From f9e088b51dcc1628fb4449dfe7e7ce9507b71de5 Mon Sep 17 00:00:00 2001 From: Mark Langen Date: Tue, 6 Sep 2016 17:03:28 -0600 Subject: [PATCH 01/12] Card Rendering name & type line fixes * Changed Name and Type line rendering to use Arial / Arial Narrow instead of Beleren. At small font sizes, those fonts are much more readable. * The P/T box still uses the Beleren font, as the numbers in that font are quite readable even at small sizes. * Changed the name / type lines to switch between Arial and Arial Narrow depending on whether there is space available using Arial or not. --- .../mage/card/arcane/ModernCardRenderer.java | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java index 7e0a1d9d272..82f3bb71401 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java @@ -165,6 +165,7 @@ public class ModernCardRenderer extends CardRenderer { protected int boxTextHeight; protected int boxTextOffset; protected Font boxTextFont; + protected Font boxTextFontNarrow; // How large is the P/T text, and how far is it down the boxes protected int ptTextHeight; @@ -211,11 +212,16 @@ public class ModernCardRenderer extends CardRenderer { // Box text height boxTextHeight = getTextHeightForBoxHeight(boxHeight); boxTextOffset = (boxHeight - boxTextHeight) / 2; - boxTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, boxTextHeight); - + // Not using Beleren for now because it looks bad at small font sizes. Maybe we want to in the future? + //boxTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, boxTextHeight); + boxTextFont = new Font("Arial", Font.PLAIN, boxTextHeight); + boxTextFontNarrow = new Font("Arial Narrow", Font.PLAIN, boxTextHeight); + + // Box text height ptTextHeight = getPTTextHeightForLineHeight(boxHeight); ptTextOffset = (boxHeight - ptTextHeight) / 2; + // Beleren font does work well for numbers though ptTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, ptTextHeight); } @@ -417,7 +423,14 @@ public class ModernCardRenderer extends CardRenderer { AttributedString str = new AttributedString(nameStr); str.addAttribute(TextAttribute.FONT, boxTextFont); TextMeasurer measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext()); - TextLayout layout = measure.getLayout(0, measure.getLineBreakIndex(0, availableWidth)); + int breakIndex = measure.getLineBreakIndex(0, availableWidth); + if (breakIndex < nameStr.length()) { + str = new AttributedString(nameStr); + str.addAttribute(TextAttribute.FONT, boxTextFontNarrow); + measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext()); + breakIndex = measure.getLineBreakIndex(0, availableWidth); + } + TextLayout layout = measure.getLayout(0, breakIndex); g.setColor(getBoxTextColor()); layout.draw(g, x, y + boxTextOffset + boxTextHeight - 1); @@ -455,7 +468,14 @@ public class ModernCardRenderer extends CardRenderer { AttributedString str = new AttributedString(types); str.addAttribute(TextAttribute.FONT, boxTextFont); TextMeasurer measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext()); - TextLayout layout = measure.getLayout(0, measure.getLineBreakIndex(0, availableWidth)); + int breakIndex = measure.getLineBreakIndex(0, availableWidth); + if (breakIndex < types.length()) { + str = new AttributedString(types); + str.addAttribute(TextAttribute.FONT, boxTextFontNarrow); + measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext()); + breakIndex = measure.getLineBreakIndex(0, availableWidth); + } + TextLayout layout = measure.getLayout(0, breakIndex); g.setColor(getBoxTextColor()); layout.draw(g, x, y + boxTextOffset + boxTextHeight - 1); } From 0ea9d33211299d3dee998296875c76b55664beb8 Mon Sep 17 00:00:00 2001 From: Mark Langen Date: Tue, 6 Sep 2016 18:15:37 -0600 Subject: [PATCH 02/12] Fixed card highlighting * Changed CardPanelRenderImpl to correctly invalidate its render when its panel has its isChoosable / isSelected override set. Before things like selecting cards in a draft view would not visibly have an effect as the render wasn't invalidated. --- .../mage/card/arcane/CardPanelRenderImpl.java | 18 ++++++++++++++++++ .../mage/card/arcane/ModernCardRenderer.java | 13 ++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java index e84d2aec7c9..43a467d92f0 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java @@ -377,6 +377,24 @@ public class CardPanelRenderImpl extends CardPanel { return ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename)); } } + + @Override + public void setSelected(boolean selected) { + if (selected != isSelected()) { + super.setSelected(selected); + // Invalidate our render + cardImage = null; + } + } + + @Override + public void setChoosable(boolean choosable) { + if (choosable != isChoosable()) { + super.setChoosable(choosable); + // Invalidate our render + cardImage = null; + } + } @Override public Image getImage() { diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java index 82f3bb71401..9f9fbec7f49 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java @@ -227,10 +227,6 @@ public class ModernCardRenderer extends CardRenderer { @Override protected void drawBorder(Graphics2D g) { - // Draw border as one rounded rectangle - g.setColor(Color.black); - g.fillRoundRect(0, 0, cardWidth, cardHeight, cornerRadius, cornerRadius); - // Selection Borders Color borderColor; if (isSelected) { @@ -242,8 +238,14 @@ public class ModernCardRenderer extends CardRenderer { } else if (cardView instanceof PermanentView && ((PermanentView) cardView).isCanAttack()) { borderColor = new Color(0, 0, 255, 230); } else { - borderColor = null; + borderColor = Color.BLACK; } + + // Draw border as one rounded rectangle + g.setColor(borderColor); + g.fillRoundRect(0, 0, cardWidth, cardHeight, cornerRadius, cornerRadius); + + /* // Separate selection highlight border from card itself. Not used right now if (borderColor != null) { float hwidth = borderWidth / 2.0f; Graphics2D g2 = (Graphics2D) g.create(); @@ -257,6 +259,7 @@ public class ModernCardRenderer extends CardRenderer { g2.draw(rect); g2.dispose(); } + */ } @Override From b549dfe0dc0cf7306bbb67e56f5dbdcba0033ebf Mon Sep 17 00:00:00 2001 From: Mark Langen Date: Tue, 6 Sep 2016 21:50:04 -0600 Subject: [PATCH 03/12] Added frameStyle Characteristic for cards * Added FrameStyle Enum containing a list of styles that cards can be rendered in. * Added getFrameStyle() getter to Card interface. * Implemented getFrameStyle() for various concrete implementations of Card. --- Mage/src/main/java/mage/MageObject.java | 3 + Mage/src/main/java/mage/MageObjectImpl.java | 9 +++ Mage/src/main/java/mage/cards/FrameStyle.java | 58 +++++++++++++++++++ .../main/java/mage/cards/mock/MockCard.java | 2 + .../java/mage/cards/repository/CardInfo.java | 8 +++ .../mage/cards/repository/CardRepository.java | 6 +- .../java/mage/game/command/Commander.java | 6 ++ .../main/java/mage/game/command/Emblem.java | 8 +++ .../mage/game/permanent/PermanentCard.java | 1 + .../mage/game/permanent/PermanentToken.java | 1 + Mage/src/main/java/mage/game/stack/Spell.java | 9 +++ .../java/mage/game/stack/StackAbility.java | 7 +++ 12 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 Mage/src/main/java/mage/cards/FrameStyle.java diff --git a/Mage/src/main/java/mage/MageObject.java b/Mage/src/main/java/mage/MageObject.java index db9ed97dee6..a0d9c5bc0ce 100644 --- a/Mage/src/main/java/mage/MageObject.java +++ b/Mage/src/main/java/mage/MageObject.java @@ -7,6 +7,7 @@ import mage.abilities.Abilities; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; +import mage.cards.FrameStyle; import mage.constants.CardType; import mage.game.Game; @@ -37,6 +38,8 @@ public interface MageObject extends MageItem, Serializable { ObjectColor getColor(Game game); ObjectColor getFrameColor(Game game); + + FrameStyle getFrameStyle(); ManaCosts getManaCost(); diff --git a/Mage/src/main/java/mage/MageObjectImpl.java b/Mage/src/main/java/mage/MageObjectImpl.java index 80b3d7fd8d2..daea728b079 100644 --- a/Mage/src/main/java/mage/MageObjectImpl.java +++ b/Mage/src/main/java/mage/MageObjectImpl.java @@ -39,6 +39,7 @@ import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.keyword.ChangelingAbility; import mage.abilities.mana.ManaAbility; +import mage.cards.FrameStyle; import mage.constants.CardType; import mage.game.Game; import mage.util.CardUtil; @@ -52,6 +53,7 @@ public abstract class MageObjectImpl implements MageObject { protected ManaCosts manaCost; protected ObjectColor color; protected ObjectColor frameColor; + protected FrameStyle frameStyle; protected List cardType = new ArrayList<>(); protected List subtype = new ArrayList<>(); protected List supertype = new ArrayList<>(); @@ -71,6 +73,7 @@ public abstract class MageObjectImpl implements MageObject { toughness = new MageInt(0); color = new ObjectColor(); frameColor = new ObjectColor(); + frameStyle = FrameStyle.M15_NORMAL; manaCost = new ManaCostsImpl<>(""); abilities = new AbilitiesImpl<>(); } @@ -82,6 +85,7 @@ public abstract class MageObjectImpl implements MageObject { text = object.text; color = object.color.copy(); frameColor = object.frameColor.copy(); + frameStyle = object.frameStyle; power = object.power.copy(); toughness = object.toughness.copy(); abilities = object.abilities.copy(); @@ -221,6 +225,11 @@ public abstract class MageObjectImpl implements MageObject { } } + @Override + public FrameStyle getFrameStyle() { + return frameStyle; + } + @Override public ManaCosts getManaCost() { return manaCost; diff --git a/Mage/src/main/java/mage/cards/FrameStyle.java b/Mage/src/main/java/mage/cards/FrameStyle.java new file mode 100644 index 00000000000..4a8c4f4962b --- /dev/null +++ b/Mage/src/main/java/mage/cards/FrameStyle.java @@ -0,0 +1,58 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.cards; + +/** + * + * @author StravantUser + */ +public enum FrameStyle { + /** + * The default card frame, normal M15 card frames + */ + M15_NORMAL(BorderType.M15, false), + + /** + * Battle for Zendkiar full art basic lands + */ + BFZ_FULL_ART_BASIC(BorderType.M15, true); + + /** + * General type of card + */ + public enum BorderType { + /** + * Old border cards + */ + OLD, + + /** + * Modern border cards (8th -> Theros) + */ + MOD, + + /** + * M15 border cards (M14 -> current) + */ + M15 + } + + private BorderType borderType; + private boolean isFullArt; + + public BorderType getBorderType() { + return borderType; + } + + public boolean isFullArt() { + return isFullArt; + } + + FrameStyle(BorderType borderType, boolean isFullArt) { + this.borderType = borderType; + this.isFullArt = isFullArt; + } +} diff --git a/Mage/src/main/java/mage/cards/mock/MockCard.java b/Mage/src/main/java/mage/cards/mock/MockCard.java index 7a0d375d972..593a6fb5387 100644 --- a/Mage/src/main/java/mage/cards/mock/MockCard.java +++ b/Mage/src/main/java/mage/cards/mock/MockCard.java @@ -30,6 +30,7 @@ public class MockCard extends CardImpl { this.subtype = card.getSubTypes(); this.supertype = card.getSupertypes(); + this.usesVariousArt = card.usesVariousArt(); this.manaCost = new ManaCostsImpl(join(card.getManaCosts())); @@ -37,6 +38,7 @@ public class MockCard extends CardImpl { this.color = card.getColor(); this.frameColor = card.getFrameColor(); + this.frameStyle = card.getFrameStyle(); this.splitCard = card.isSplitCard(); this.flipCard = card.isFlipCard(); diff --git a/Mage/src/main/java/mage/cards/repository/CardInfo.java b/Mage/src/main/java/mage/cards/repository/CardInfo.java index a9ead5ffcc9..cf6f5423282 100644 --- a/Mage/src/main/java/mage/cards/repository/CardInfo.java +++ b/Mage/src/main/java/mage/cards/repository/CardInfo.java @@ -36,6 +36,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import mage.cards.FrameStyle; import mage.constants.CardType; import mage.constants.Rarity; import mage.ObjectColor; @@ -100,6 +101,8 @@ public class CardInfo { @DatabaseField protected String frameColor; @DatabaseField + protected String frameStyle; + @DatabaseField protected boolean splitCard; @DatabaseField protected boolean splitCardHalf; @@ -138,6 +141,7 @@ public class CardInfo { this.secondSideName = secondSide.getName(); } + this.frameStyle = card.getFrameStyle().toString(); this.frameColor = card.getFrameColor(null).toString(); this.blue = card.getColor(null).isBlue(); this.black = card.getColor(null).isBlack(); @@ -227,6 +231,10 @@ public class CardInfo { return new ObjectColor(frameColor); } + public FrameStyle getFrameStyle() { + return FrameStyle.valueOf(this.frameStyle); + } + private String joinList(List items) { StringBuilder sb = new StringBuilder(); for (Object item : items) { diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 278d9ea027c..855323a3d5d 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -62,16 +62,16 @@ public enum CardRepository { private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE"; private static final String VERSION_ENTITY_NAME = "card"; // raise this if db structure was changed - private static final long CARD_DB_VERSION = 46; + private static final long CARD_DB_VERSION = 47; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 57; + private static final long CARD_CONTENT_VERSION = 58; private Dao cardDao; private Set classNames; private final TreeSet landTypes = new TreeSet(); - private CardRepository() { + CardRepository() { File file = new File("db"); if (!file.exists()) { file.mkdirs(); diff --git a/Mage/src/main/java/mage/game/command/Commander.java b/Mage/src/main/java/mage/game/command/Commander.java index 2805caeb80c..3831292c623 100644 --- a/Mage/src/main/java/mage/game/command/Commander.java +++ b/Mage/src/main/java/mage/game/command/Commander.java @@ -39,6 +39,7 @@ import mage.abilities.common.CastCommanderAbility; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.cards.Card; +import mage.cards.FrameStyle; import mage.constants.CardType; import mage.game.Game; import mage.util.GameLog; @@ -150,6 +151,11 @@ public class Commander implements CommandObject { return card.getFrameColor(game); } + @Override + public FrameStyle getFrameStyle() { + return card.getFrameStyle(); + } + @Override public ManaCosts getManaCost() { return card.getManaCost(); diff --git a/Mage/src/main/java/mage/game/command/Emblem.java b/Mage/src/main/java/mage/game/command/Emblem.java index 6f9f10a864b..eb9acc3b3a0 100644 --- a/Mage/src/main/java/mage/game/command/Emblem.java +++ b/Mage/src/main/java/mage/game/command/Emblem.java @@ -38,6 +38,7 @@ import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.cards.FrameStyle; import mage.constants.CardType; import mage.game.Game; import mage.util.GameLog; @@ -55,6 +56,7 @@ public class Emblem implements CommandObject { private UUID id; private UUID controllerId; private UUID sourceId; + private FrameStyle frameStyle; private Abilities abilites = new AbilitiesImpl<>(); private String expansionSetCodeForImage = null; @@ -65,11 +67,17 @@ public class Emblem implements CommandObject { public Emblem(final Emblem emblem) { this.id = emblem.id; this.name = emblem.name; + this.frameStyle = emblem.frameStyle; this.controllerId = emblem.controllerId; this.sourceId = emblem.sourceId; this.abilites = emblem.abilites.copy(); } + @Override + public FrameStyle getFrameStyle() { + return frameStyle; + } + @Override public void assignNewId() { this.id = UUID.randomUUID(); diff --git a/Mage/src/main/java/mage/game/permanent/PermanentCard.java b/Mage/src/main/java/mage/game/permanent/PermanentCard.java index bb583cd2921..23eb2800a76 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentCard.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentCard.java @@ -119,6 +119,7 @@ public class PermanentCard extends PermanentImpl { this.cardType.addAll(card.getCardType()); this.color = card.getColor(null).copy(); this.frameColor = card.getFrameColor(null).copy(); + this.frameStyle = card.getFrameStyle(); this.manaCost = card.getManaCost().copy(); if (card instanceof PermanentCard) { this.maxLevelCounters = ((PermanentCard) card).maxLevelCounters; diff --git a/Mage/src/main/java/mage/game/permanent/PermanentToken.java b/Mage/src/main/java/mage/game/permanent/PermanentToken.java index e95fc3c0ca6..7c730b61fab 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentToken.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentToken.java @@ -83,6 +83,7 @@ public class PermanentToken extends PermanentImpl { this.cardType = token.getCardType(); this.color = token.getColor(game).copy(); this.frameColor = token.getFrameColor(game); + this.frameStyle = token.getFrameStyle(); this.power.modifyBaseValue(token.getPower().getBaseValueModified()); this.toughness.modifyBaseValue(token.getToughness().getBaseValueModified()); this.supertype = token.getSupertype(); diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index 85e4b2bb860..7d3d7db703b 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -46,6 +46,7 @@ import mage.abilities.keyword.BestowAbility; import mage.abilities.keyword.MorphAbility; import mage.cards.Card; import mage.cards.CardsImpl; +import mage.cards.FrameStyle; import mage.cards.SplitCard; import mage.constants.CardType; import mage.constants.Outcome; @@ -77,6 +78,7 @@ public class Spell extends StackObjImpl implements Card { private final Card card; private final ObjectColor color; private final ObjectColor frameColor; + private final FrameStyle frameStyle; private final SpellAbility ability; private final Zone fromZone; private final UUID id; @@ -90,6 +92,7 @@ public class Spell extends StackObjImpl implements Card { this.card = card; this.color = card.getColor(null).copy(); this.frameColor = card.getFrameColor(null).copy(); + this.frameStyle = card.getFrameStyle(); id = ability.getId(); this.ability = ability; this.ability.setControllerId(controllerId); @@ -131,6 +134,7 @@ public class Spell extends StackObjImpl implements Card { this.faceDown = spell.faceDown; this.color = spell.color.copy(); this.frameColor = spell.color.copy(); + this.frameStyle = spell.frameStyle; } public boolean activate(Game game, boolean noMana) { @@ -492,6 +496,11 @@ public class Spell extends StackObjImpl implements Card { return frameColor; } + @Override + public FrameStyle getFrameStyle() { + return frameStyle; + } + @Override public ManaCosts getManaCost() { return card.getManaCost(); diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index 824787d22a9..17e4bb29106 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -49,6 +49,7 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; import mage.cards.Card; +import mage.cards.FrameStyle; import mage.constants.AbilityType; import mage.constants.AbilityWord; import mage.constants.CardType; @@ -198,6 +199,12 @@ public class StackAbility extends StackObjImpl implements Ability { return ability.getSourceObject(game).getFrameColor(game); } + @Override + public FrameStyle getFrameStyle() { + // Abilities all use the same frame + return FrameStyle.M15_NORMAL; + } + @Override public ManaCosts getManaCost() { return emptyCost; From f0a1938b3e6c689e4a795a55bdbd912fe5613e25 Mon Sep 17 00:00:00 2001 From: Mark Langen Date: Wed, 7 Sep 2016 02:20:51 -0600 Subject: [PATCH 04/12] Full art Land rendering * Added "frameStyle" tagging to relevant full art lands (ZEN, BFZ, UNG, UHG) * Added support for rendering based off of frameStyle * Outstanding bug that frameStyle doesn't seem to be replicated exactly properly --- .../mage/card/arcane/ModernCardRenderer.java | 64 +++++++++++++++---- Mage.Common/src/mage/view/CardView.java | 16 ++++- .../mage/sets/battleforzendikar/Forest10.java | 3 + .../mage/sets/battleforzendikar/Forest6.java | 3 + .../mage/sets/battleforzendikar/Forest7.java | 3 + .../mage/sets/battleforzendikar/Forest8.java | 3 + .../mage/sets/battleforzendikar/Forest9.java | 3 + .../mage/sets/battleforzendikar/Island10.java | 3 + .../mage/sets/battleforzendikar/Island6.java | 3 + .../mage/sets/battleforzendikar/Island7.java | 3 + .../mage/sets/battleforzendikar/Island8.java | 3 + .../mage/sets/battleforzendikar/Island9.java | 3 + .../sets/battleforzendikar/Mountain10.java | 3 + .../sets/battleforzendikar/Mountain6.java | 3 + .../sets/battleforzendikar/Mountain7.java | 3 + .../sets/battleforzendikar/Mountain8.java | 3 + .../sets/battleforzendikar/Mountain9.java | 3 + .../mage/sets/battleforzendikar/Plains10.java | 3 + .../mage/sets/battleforzendikar/Plains6.java | 3 + .../mage/sets/battleforzendikar/Plains7.java | 3 + .../mage/sets/battleforzendikar/Plains8.java | 3 + .../mage/sets/battleforzendikar/Plains9.java | 3 + .../mage/sets/battleforzendikar/Swamp10.java | 3 + .../mage/sets/battleforzendikar/Swamp6.java | 3 + .../mage/sets/battleforzendikar/Swamp7.java | 3 + .../mage/sets/battleforzendikar/Swamp8.java | 3 + .../mage/sets/battleforzendikar/Swamp9.java | 3 + Mage.Sets/src/mage/sets/unglued/Forest.java | 3 + Mage.Sets/src/mage/sets/unglued/Island.java | 3 + Mage.Sets/src/mage/sets/unglued/Mountain.java | 3 + Mage.Sets/src/mage/sets/unglued/Plains.java | 3 + Mage.Sets/src/mage/sets/unglued/Swamp.java | 3 + Mage.Sets/src/mage/sets/unhinged/Forest.java | 3 + Mage.Sets/src/mage/sets/unhinged/Island.java | 3 + .../src/mage/sets/unhinged/Mountain.java | 3 + Mage.Sets/src/mage/sets/unhinged/Plains.java | 3 + Mage.Sets/src/mage/sets/unhinged/Swamp.java | 3 + Mage.Sets/src/mage/sets/zendikar/Forest1.java | 3 + Mage.Sets/src/mage/sets/zendikar/Forest2.java | 3 + Mage.Sets/src/mage/sets/zendikar/Forest3.java | 3 + Mage.Sets/src/mage/sets/zendikar/Forest4.java | 3 + Mage.Sets/src/mage/sets/zendikar/Island1.java | 3 + Mage.Sets/src/mage/sets/zendikar/Island2.java | 3 + Mage.Sets/src/mage/sets/zendikar/Island3.java | 3 + Mage.Sets/src/mage/sets/zendikar/Island4.java | 3 + .../src/mage/sets/zendikar/Mountain1.java | 3 + .../src/mage/sets/zendikar/Mountain2.java | 3 + .../src/mage/sets/zendikar/Mountain3.java | 3 + .../src/mage/sets/zendikar/Mountain4.java | 3 + Mage.Sets/src/mage/sets/zendikar/Plains1.java | 3 + Mage.Sets/src/mage/sets/zendikar/Plains2.java | 3 + Mage.Sets/src/mage/sets/zendikar/Plains3.java | 3 + Mage.Sets/src/mage/sets/zendikar/Plains4.java | 3 + Mage.Sets/src/mage/sets/zendikar/Swamp1.java | 3 + Mage.Sets/src/mage/sets/zendikar/Swamp2.java | 3 + Mage.Sets/src/mage/sets/zendikar/Swamp3.java | 3 + Mage.Sets/src/mage/sets/zendikar/Swamp4.java | 3 + Mage/src/main/java/mage/cards/FrameStyle.java | 23 ++++++- .../mage/cards/repository/CardRepository.java | 2 +- 59 files changed, 254 insertions(+), 16 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java index 9f9fbec7f49..d43377b31a5 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java @@ -20,6 +20,7 @@ import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.font.TextMeasurer; +import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; @@ -32,6 +33,7 @@ import java.util.Collection; import java.util.List; import javax.swing.ImageIcon; import mage.ObjectColor; +import mage.cards.FrameStyle; import mage.client.dialog.PreferencesDialog; import mage.constants.CardType; import mage.view.CardView; @@ -159,6 +161,7 @@ public class ModernCardRenderer extends CardRenderer { // How far down the card is the type line placed? protected static float TYPE_LINE_Y_FRAC = 0.57f; // x cardHeight protected static float TYPE_LINE_Y_FRAC_TOKEN = 0.70f; + protected static float TYPE_LINE_Y_FRAC_FULL_ART = 0.74f; protected int typeLineY; // How large is the box text, and how far is it down the boxes @@ -203,11 +206,7 @@ public class ModernCardRenderer extends CardRenderer { BOX_HEIGHT_FRAC * cardHeight); // Type line at - if (cardView.isToken()) { - typeLineY = (int) (TYPE_LINE_Y_FRAC_TOKEN * cardHeight); - } else { - typeLineY = (int) (TYPE_LINE_Y_FRAC * cardHeight); - } + typeLineY = (int)(getTypeLineYFrac() * cardHeight); // Box text height boxTextHeight = getTextHeightForBoxHeight(boxHeight); @@ -235,7 +234,7 @@ public class ModernCardRenderer extends CardRenderer { borderColor = new Color(250, 250, 0, 230); } else if (cardView.isPlayable()) { borderColor = new Color(153, 102, 204, 200); - } else if (cardView instanceof PermanentView && ((PermanentView) cardView).isCanAttack()) { + } else if (cardView.isCanAttack()) { borderColor = new Color(0, 0, 255, 230); } else { borderColor = Color.BLACK; @@ -292,18 +291,58 @@ public class ModernCardRenderer extends CardRenderer { } } + /** + * Get the region to slice out of a source art image for the card + * @return + */ + private Rectangle2D getArtRect() { + Rectangle2D rect; + if (cardView.getFrameStyle().isFullArt()) { + rect = new Rectangle2D.Float(.079f, .11f, .84f, .63f); + } else { + rect = new Rectangle2D.Float(.079f, .11f, .84f, .42f); + } + return rect; + } + + private float getTypeLineYFrac() { + if (cardView.isToken()) { + return TYPE_LINE_Y_FRAC; + } else if (cardView.getFrameStyle().isFullArt()) { + return TYPE_LINE_Y_FRAC_FULL_ART; + } else { + return TYPE_LINE_Y_FRAC; + } + } + @Override protected void drawArt(Graphics2D g) { if (artImage != null && !cardView.isFaceDown()) { - int imgWidth = artImage.getWidth(); - int imgHeight = artImage.getHeight(); + Rectangle2D artRect = getArtRect(); + + // Perform a process to make sure that the art is scaled uniformly to fill the frame, cutting + // off the minimum amount necessary to make it completely fill the frame without "squashing" it. + double fullCardImgWidth = artImage.getWidth(); + double fullCardImgHeight = artImage.getHeight(); + double artWidth = artRect.getWidth() * fullCardImgWidth; + double artHeight = artRect.getHeight() * fullCardImgHeight; + double targetWidth = contentWidth - 2; + double targetHeight = typeLineY - totalContentInset - boxHeight; + double targetAspect = targetWidth / targetHeight; + if (targetAspect * artHeight < artWidth) { + // Trim off some width + artWidth = targetAspect * artHeight; + } else { + // Trim off some height + artHeight = artWidth / targetAspect; + } BufferedImage subImg = artImage.getSubimage( - (int) (.079 * imgWidth), (int) (.11 * imgHeight), - (int) (.84 * imgWidth), (int) (.42 * imgHeight)); + (int)(artRect.getX() * fullCardImgWidth), (int)(artRect.getY() * fullCardImgHeight), + (int)artWidth, (int)artHeight); g.drawImage(subImg, totalContentInset + 1, totalContentInset + boxHeight, - contentWidth - 2, typeLineY - totalContentInset - boxHeight, + (int)targetWidth, (int)targetHeight, null); } } @@ -664,7 +703,6 @@ public class ModernCardRenderer extends CardRenderer { attributedRules.add(attributed); remaining -= drawSingleRule(g, attributed, rule, 0, 0, w, remaining, false); if (remaining < 0) { - useSmallFont = true; break; } } @@ -676,7 +714,7 @@ public class ModernCardRenderer extends CardRenderer { if (remaining <= 0) { spacing = 0; } else { - spacing = (int) (remaining / (hasKeywords + spacing = (int) (((float)remaining) / (hasKeywords ? (textboxRules.size() + 2) : (textboxRules.size() + 1))); } diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index 18ef48839e9..aadc38d4ca7 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -36,6 +36,7 @@ import mage.abilities.Mode; import mage.abilities.SpellAbility; import mage.abilities.costs.mana.ManaCosts; import mage.cards.Card; +import mage.cards.FrameStyle; import mage.cards.SplitCard; import mage.constants.AbilityType; import mage.constants.CardType; @@ -74,6 +75,7 @@ public class CardView extends SimpleCardView { protected List superTypes; protected ObjectColor color; protected ObjectColor frameColor; + protected FrameStyle frameStyle; protected List manaCost; protected int convertedManaCost; protected Rarity rarity; @@ -334,7 +336,10 @@ public class CardView extends SimpleCardView { } // Frame color - this.frameColor = card.getFrameColor(game); + this.frameColor = card.getFrameColor(game); + + // Frame style + this.frameStyle = card.getFrameStyle(); // Get starting loyalty this.startingLoyalty = "" + card.getStartingLoyalty(); @@ -384,6 +389,8 @@ public class CardView extends SimpleCardView { } // Frame color this.frameColor = object.getFrameColor(null); + // Frame style + this.frameStyle = object.getFrameStyle(); // Starting loyalty. Must be extracted from an ability this.startingLoyalty = "" + object.getStartingLoyalty(); } @@ -401,6 +408,7 @@ public class CardView extends SimpleCardView { this.displayName = name; this.rules = emblem.getRules(); // emblem images are always with common (black) symbol + this.frameStyle = FrameStyle.M15_NORMAL; this.expansionSetCode = emblem.getExpansionSetCode(); this.rarity = Rarity.COMMON; } @@ -426,6 +434,7 @@ public class CardView extends SimpleCardView { this.superTypes = new ArrayList<>(); this.color = new ObjectColor(); this.frameColor = new ObjectColor(); + this.frameStyle = FrameStyle.M15_NORMAL; this.manaCost = new ArrayList<>(); this.convertedManaCost = 0; @@ -472,6 +481,7 @@ public class CardView extends SimpleCardView { this.superTypes = token.getSupertype(); this.color = token.getColor(null); this.frameColor = token.getFrameColor(null); + this.frameStyle = token.getFrameStyle(); this.manaCost = token.getManaCost().getSymbols(); this.rarity = Rarity.NA; this.type = token.getTokenType(); @@ -559,6 +569,10 @@ public class CardView extends SimpleCardView { return frameColor; } + public FrameStyle getFrameStyle() { + return frameStyle; + } + public List getManaCost() { return manaCost; } diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Forest10.java b/Mage.Sets/src/mage/sets/battleforzendikar/Forest10.java index 23bcb9ceaf6..26591a9a751 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Forest10.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Forest10.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Forest10 extends mage.cards.basiclands.Forest { public Forest10(UUID ownerId) { super(ownerId, "274b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Forest10(final Forest10 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Forest6.java b/Mage.Sets/src/mage/sets/battleforzendikar/Forest6.java index 071eb8bd523..0c43ccd9b94 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Forest6.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Forest6.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Forest6 extends mage.cards.basiclands.Forest { public Forest6(UUID ownerId) { super(ownerId, "270b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Forest6(final Forest6 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Forest7.java b/Mage.Sets/src/mage/sets/battleforzendikar/Forest7.java index e29564f4de8..bce2002c3e1 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Forest7.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Forest7.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Forest7 extends mage.cards.basiclands.Forest { public Forest7(UUID ownerId) { super(ownerId, "271b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Forest7(final Forest7 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Forest8.java b/Mage.Sets/src/mage/sets/battleforzendikar/Forest8.java index 2d94070106b..e868b1aa790 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Forest8.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Forest8.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Forest8 extends mage.cards.basiclands.Forest { public Forest8(UUID ownerId) { super(ownerId, "272b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Forest8(final Forest8 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Forest9.java b/Mage.Sets/src/mage/sets/battleforzendikar/Forest9.java index a705c9921e9..f573b6c4fd9 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Forest9.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Forest9.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Forest9 extends mage.cards.basiclands.Forest { public Forest9(UUID ownerId) { super(ownerId, "273b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Forest9(final Forest9 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Island10.java b/Mage.Sets/src/mage/sets/battleforzendikar/Island10.java index 05f385c2b9a..5f0256baaca 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Island10.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Island10.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Island10 extends mage.cards.basiclands.Island { public Island10(UUID ownerId) { super(ownerId, "259b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Island10(final Island10 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Island6.java b/Mage.Sets/src/mage/sets/battleforzendikar/Island6.java index 1119555f32b..f290b4f236c 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Island6.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Island6.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Island6 extends mage.cards.basiclands.Island { public Island6(UUID ownerId) { super(ownerId, "255b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Island6(final Island6 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Island7.java b/Mage.Sets/src/mage/sets/battleforzendikar/Island7.java index 7547fa7be83..bb4a6550b5f 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Island7.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Island7.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Island7 extends mage.cards.basiclands.Island { public Island7(UUID ownerId) { super(ownerId, "256b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Island7(final Island7 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Island8.java b/Mage.Sets/src/mage/sets/battleforzendikar/Island8.java index b8aad3f54ef..67011f5b88a 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Island8.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Island8.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Island8 extends mage.cards.basiclands.Island { public Island8(UUID ownerId) { super(ownerId, "257b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Island8(final Island8 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Island9.java b/Mage.Sets/src/mage/sets/battleforzendikar/Island9.java index 522a3b4e37c..cb30559c286 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Island9.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Island9.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Island9 extends mage.cards.basiclands.Island { public Island9(UUID ownerId) { super(ownerId, "258b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Island9(final Island9 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Mountain10.java b/Mage.Sets/src/mage/sets/battleforzendikar/Mountain10.java index 1a62598d04e..a24673020c4 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Mountain10.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Mountain10.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Mountain10 extends mage.cards.basiclands.Mountain { public Mountain10(UUID ownerId) { super(ownerId, "269b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Mountain10(final Mountain10 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Mountain6.java b/Mage.Sets/src/mage/sets/battleforzendikar/Mountain6.java index 921cbeaf36f..a87ab4f8763 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Mountain6.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Mountain6.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Mountain6 extends mage.cards.basiclands.Mountain { public Mountain6(UUID ownerId) { super(ownerId, "265b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Mountain6(final Mountain6 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Mountain7.java b/Mage.Sets/src/mage/sets/battleforzendikar/Mountain7.java index 1c23f5e64e6..736c1c89727 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Mountain7.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Mountain7.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Mountain7 extends mage.cards.basiclands.Mountain { public Mountain7(UUID ownerId) { super(ownerId, "266b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Mountain7(final Mountain7 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Mountain8.java b/Mage.Sets/src/mage/sets/battleforzendikar/Mountain8.java index 755f49ea6cb..993a7eda3a4 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Mountain8.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Mountain8.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Mountain8 extends mage.cards.basiclands.Mountain { public Mountain8(UUID ownerId) { super(ownerId, "267b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Mountain8(final Mountain8 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Mountain9.java b/Mage.Sets/src/mage/sets/battleforzendikar/Mountain9.java index 8713dfa46f2..8a84c352743 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Mountain9.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Mountain9.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Mountain9 extends mage.cards.basiclands.Mountain { public Mountain9(UUID ownerId) { super(ownerId, "268b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Mountain9(final Mountain9 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Plains10.java b/Mage.Sets/src/mage/sets/battleforzendikar/Plains10.java index ac9c617c3cf..fd7da2141f2 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Plains10.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Plains10.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Plains10 extends mage.cards.basiclands.Plains { public Plains10(UUID ownerId) { super(ownerId, "254b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Plains10(final Plains10 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Plains6.java b/Mage.Sets/src/mage/sets/battleforzendikar/Plains6.java index ed3ec52d2bc..ea8c621347e 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Plains6.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Plains6.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Plains6 extends mage.cards.basiclands.Plains { public Plains6(UUID ownerId) { super(ownerId, "250b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Plains6(final Plains6 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Plains7.java b/Mage.Sets/src/mage/sets/battleforzendikar/Plains7.java index a054d77cd4e..18dc050daf1 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Plains7.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Plains7.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Plains7 extends mage.cards.basiclands.Plains { public Plains7(UUID ownerId) { super(ownerId, "251b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Plains7(final Plains7 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Plains8.java b/Mage.Sets/src/mage/sets/battleforzendikar/Plains8.java index 6487b287144..593eed20866 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Plains8.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Plains8.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Plains8 extends mage.cards.basiclands.Plains { public Plains8(UUID ownerId) { super(ownerId, "252b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Plains8(final Plains8 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Plains9.java b/Mage.Sets/src/mage/sets/battleforzendikar/Plains9.java index 4ee62071825..74e3a5f1ffe 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Plains9.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Plains9.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Plains9 extends mage.cards.basiclands.Plains { public Plains9(UUID ownerId) { super(ownerId, "253b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Plains9(final Plains9 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Swamp10.java b/Mage.Sets/src/mage/sets/battleforzendikar/Swamp10.java index 60b17fd3189..8985a774f69 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Swamp10.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Swamp10.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Swamp10 extends mage.cards.basiclands.Swamp { public Swamp10(UUID ownerId) { super(ownerId, "264b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Swamp10(final Swamp10 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Swamp6.java b/Mage.Sets/src/mage/sets/battleforzendikar/Swamp6.java index 165f8ae6065..f9807246c45 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Swamp6.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Swamp6.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Swamp6 extends mage.cards.basiclands.Swamp { public Swamp6(UUID ownerId) { super(ownerId, "260b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Swamp6(final Swamp6 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Swamp7.java b/Mage.Sets/src/mage/sets/battleforzendikar/Swamp7.java index e54203cdc35..38a79c536b7 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Swamp7.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Swamp7.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Swamp7 extends mage.cards.basiclands.Swamp { public Swamp7(UUID ownerId) { super(ownerId, "261b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Swamp7(final Swamp7 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Swamp8.java b/Mage.Sets/src/mage/sets/battleforzendikar/Swamp8.java index 0bfd1222dd1..8cf2d4c9095 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Swamp8.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Swamp8.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Swamp8 extends mage.cards.basiclands.Swamp { public Swamp8(UUID ownerId) { super(ownerId, "262b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Swamp8(final Swamp8 card) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/Swamp9.java b/Mage.Sets/src/mage/sets/battleforzendikar/Swamp9.java index 93d9cb9b3c2..40e71315231 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/Swamp9.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/Swamp9.java @@ -27,6 +27,8 @@ */ package mage.sets.battleforzendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Swamp9 extends mage.cards.basiclands.Swamp { public Swamp9(UUID ownerId) { super(ownerId, "263b"); this.expansionSetCode = "BFZ"; + this.frameStyle = FrameStyle.BFZ_FULL_ART_BASIC; } public Swamp9(final Swamp9 card) { diff --git a/Mage.Sets/src/mage/sets/unglued/Forest.java b/Mage.Sets/src/mage/sets/unglued/Forest.java index 0a2e9c6efcd..af36707085d 100644 --- a/Mage.Sets/src/mage/sets/unglued/Forest.java +++ b/Mage.Sets/src/mage/sets/unglued/Forest.java @@ -28,6 +28,8 @@ package mage.sets.unglued; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Forest extends mage.cards.basiclands.Forest { public Forest(UUID ownerId) { super(ownerId, 88); this.expansionSetCode = "UGL"; + this.frameStyle = FrameStyle.UGL_FULL_ART_BASIC; } public Forest(final Forest card) { diff --git a/Mage.Sets/src/mage/sets/unglued/Island.java b/Mage.Sets/src/mage/sets/unglued/Island.java index 920b04f02fb..41fc841572b 100644 --- a/Mage.Sets/src/mage/sets/unglued/Island.java +++ b/Mage.Sets/src/mage/sets/unglued/Island.java @@ -28,6 +28,8 @@ package mage.sets.unglued; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Island extends mage.cards.basiclands.Island { public Island(UUID ownerId) { super(ownerId, 85); this.expansionSetCode = "UGL"; + this.frameStyle = FrameStyle.UGL_FULL_ART_BASIC; } public Island(final Island card) { diff --git a/Mage.Sets/src/mage/sets/unglued/Mountain.java b/Mage.Sets/src/mage/sets/unglued/Mountain.java index d5d44f093d2..bbae44704a7 100644 --- a/Mage.Sets/src/mage/sets/unglued/Mountain.java +++ b/Mage.Sets/src/mage/sets/unglued/Mountain.java @@ -28,6 +28,8 @@ package mage.sets.unglued; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Mountain extends mage.cards.basiclands.Mountain { public Mountain(UUID ownerId) { super(ownerId, 87); this.expansionSetCode = "UGL"; + this.frameStyle = FrameStyle.UGL_FULL_ART_BASIC; } public Mountain(final Mountain card) { diff --git a/Mage.Sets/src/mage/sets/unglued/Plains.java b/Mage.Sets/src/mage/sets/unglued/Plains.java index 227e3382501..8d2d55c6e11 100644 --- a/Mage.Sets/src/mage/sets/unglued/Plains.java +++ b/Mage.Sets/src/mage/sets/unglued/Plains.java @@ -28,6 +28,8 @@ package mage.sets.unglued; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Plains extends mage.cards.basiclands.Plains { public Plains(UUID ownerId) { super(ownerId, 84); this.expansionSetCode = "UGL"; + this.frameStyle = FrameStyle.UGL_FULL_ART_BASIC; } public Plains(final Plains card) { diff --git a/Mage.Sets/src/mage/sets/unglued/Swamp.java b/Mage.Sets/src/mage/sets/unglued/Swamp.java index 9b697185af2..93ddbcddb88 100644 --- a/Mage.Sets/src/mage/sets/unglued/Swamp.java +++ b/Mage.Sets/src/mage/sets/unglued/Swamp.java @@ -28,6 +28,8 @@ package mage.sets.unglued; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Swamp extends mage.cards.basiclands.Swamp { public Swamp(UUID ownerId) { super(ownerId, 86); this.expansionSetCode = "UGL"; + this.frameStyle = FrameStyle.UGL_FULL_ART_BASIC; } public Swamp(final Swamp card) { diff --git a/Mage.Sets/src/mage/sets/unhinged/Forest.java b/Mage.Sets/src/mage/sets/unhinged/Forest.java index f13f00a0689..790991118b5 100644 --- a/Mage.Sets/src/mage/sets/unhinged/Forest.java +++ b/Mage.Sets/src/mage/sets/unhinged/Forest.java @@ -28,6 +28,8 @@ package mage.sets.unhinged; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -38,6 +40,7 @@ public class Forest extends mage.cards.basiclands.Forest { public Forest(UUID ownerId) { super(ownerId, 140); this.expansionSetCode = "UNH"; + this.frameStyle = FrameStyle.UNH_FULL_ART_BASIC; } public Forest(final Forest card) { diff --git a/Mage.Sets/src/mage/sets/unhinged/Island.java b/Mage.Sets/src/mage/sets/unhinged/Island.java index 9890a84206e..24c3163b25e 100644 --- a/Mage.Sets/src/mage/sets/unhinged/Island.java +++ b/Mage.Sets/src/mage/sets/unhinged/Island.java @@ -28,6 +28,8 @@ package mage.sets.unhinged; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Island extends mage.cards.basiclands.Island { public Island(UUID ownerId) { super(ownerId, 137); this.expansionSetCode = "UNH"; + this.frameStyle = FrameStyle.UNH_FULL_ART_BASIC; } public Island(final Island card) { diff --git a/Mage.Sets/src/mage/sets/unhinged/Mountain.java b/Mage.Sets/src/mage/sets/unhinged/Mountain.java index 38b666a6ac7..a75fd46a4e4 100644 --- a/Mage.Sets/src/mage/sets/unhinged/Mountain.java +++ b/Mage.Sets/src/mage/sets/unhinged/Mountain.java @@ -28,6 +28,8 @@ package mage.sets.unhinged; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Mountain extends mage.cards.basiclands.Mountain { public Mountain(UUID ownerId) { super(ownerId, 139); this.expansionSetCode = "UNH"; + this.frameStyle = FrameStyle.UNH_FULL_ART_BASIC; } public Mountain(final Mountain card) { diff --git a/Mage.Sets/src/mage/sets/unhinged/Plains.java b/Mage.Sets/src/mage/sets/unhinged/Plains.java index 95299023e48..a6d7a8c2953 100644 --- a/Mage.Sets/src/mage/sets/unhinged/Plains.java +++ b/Mage.Sets/src/mage/sets/unhinged/Plains.java @@ -28,6 +28,8 @@ package mage.sets.unhinged; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Plains extends mage.cards.basiclands.Plains { public Plains(UUID ownerId) { super(ownerId, 136); this.expansionSetCode = "UNH"; + this.frameStyle = FrameStyle.UNH_FULL_ART_BASIC; } public Plains(final Plains card) { diff --git a/Mage.Sets/src/mage/sets/unhinged/Swamp.java b/Mage.Sets/src/mage/sets/unhinged/Swamp.java index 046793432c6..3d834dddb21 100644 --- a/Mage.Sets/src/mage/sets/unhinged/Swamp.java +++ b/Mage.Sets/src/mage/sets/unhinged/Swamp.java @@ -28,6 +28,8 @@ package mage.sets.unhinged; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Swamp extends mage.cards.basiclands.Swamp { public Swamp(UUID ownerId) { super(ownerId, 138); this.expansionSetCode = "UNH"; + this.frameStyle = FrameStyle.UNH_FULL_ART_BASIC; } public Swamp(final Swamp card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Forest1.java b/Mage.Sets/src/mage/sets/zendikar/Forest1.java index e652ff9ecc2..6c27a7c2058 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Forest1.java +++ b/Mage.Sets/src/mage/sets/zendikar/Forest1.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Forest1 extends mage.cards.basiclands.Forest { public Forest1(UUID ownerId) { super(ownerId, 246); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Forest1(final Forest1 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Forest2.java b/Mage.Sets/src/mage/sets/zendikar/Forest2.java index 85e7a205ce5..71aa0d39b60 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Forest2.java +++ b/Mage.Sets/src/mage/sets/zendikar/Forest2.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Forest2 extends mage.cards.basiclands.Forest { public Forest2(UUID ownerId) { super(ownerId, 247); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Forest2(final Forest2 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Forest3.java b/Mage.Sets/src/mage/sets/zendikar/Forest3.java index 945157ad0c2..bff8bb8b79b 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Forest3.java +++ b/Mage.Sets/src/mage/sets/zendikar/Forest3.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Forest3 extends mage.cards.basiclands.Forest { public Forest3(UUID ownerId) { super(ownerId, 248); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Forest3(final Forest3 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Forest4.java b/Mage.Sets/src/mage/sets/zendikar/Forest4.java index d27e5503d85..2b649c0a816 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Forest4.java +++ b/Mage.Sets/src/mage/sets/zendikar/Forest4.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Forest4 extends mage.cards.basiclands.Forest { public Forest4(UUID ownerId) { super(ownerId, 249); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Forest4(final Forest4 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Island1.java b/Mage.Sets/src/mage/sets/zendikar/Island1.java index 07cae71f787..2c6fc05c0bb 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Island1.java +++ b/Mage.Sets/src/mage/sets/zendikar/Island1.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Island1 extends mage.cards.basiclands.Island { public Island1(UUID ownerId) { super(ownerId, 234); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Island1(final Island1 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Island2.java b/Mage.Sets/src/mage/sets/zendikar/Island2.java index e048d0a5c0b..b2a8ebd5552 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Island2.java +++ b/Mage.Sets/src/mage/sets/zendikar/Island2.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Island2 extends mage.cards.basiclands.Island { public Island2(UUID ownerId) { super(ownerId, 235); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Island2(final Island2 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Island3.java b/Mage.Sets/src/mage/sets/zendikar/Island3.java index 927af5ca216..dfe83bc105a 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Island3.java +++ b/Mage.Sets/src/mage/sets/zendikar/Island3.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Island3 extends mage.cards.basiclands.Island { public Island3(UUID ownerId) { super(ownerId, 236); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Island3(final Island3 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Island4.java b/Mage.Sets/src/mage/sets/zendikar/Island4.java index 7d8fca5d2e9..85958159a43 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Island4.java +++ b/Mage.Sets/src/mage/sets/zendikar/Island4.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Island4 extends mage.cards.basiclands.Island { public Island4(UUID ownerId) { super(ownerId, 237); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Island4(final Island4 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Mountain1.java b/Mage.Sets/src/mage/sets/zendikar/Mountain1.java index db56ae4753c..11c3fd8752a 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Mountain1.java +++ b/Mage.Sets/src/mage/sets/zendikar/Mountain1.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Mountain1 extends mage.cards.basiclands.Mountain { public Mountain1(UUID ownerId) { super(ownerId, 242); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Mountain1(final Mountain1 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Mountain2.java b/Mage.Sets/src/mage/sets/zendikar/Mountain2.java index 481fd4a3d51..14d8ca24b2d 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Mountain2.java +++ b/Mage.Sets/src/mage/sets/zendikar/Mountain2.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Mountain2 extends mage.cards.basiclands.Mountain { public Mountain2(UUID ownerId) { super(ownerId, 243); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Mountain2(final Mountain2 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Mountain3.java b/Mage.Sets/src/mage/sets/zendikar/Mountain3.java index 84127eee56a..56afde0702e 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Mountain3.java +++ b/Mage.Sets/src/mage/sets/zendikar/Mountain3.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Mountain3 extends mage.cards.basiclands.Mountain { public Mountain3(UUID ownerId) { super(ownerId, 244); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Mountain3(final Mountain3 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Mountain4.java b/Mage.Sets/src/mage/sets/zendikar/Mountain4.java index 7cc370f32a7..099dd3f474e 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Mountain4.java +++ b/Mage.Sets/src/mage/sets/zendikar/Mountain4.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Mountain4 extends mage.cards.basiclands.Mountain { public Mountain4(UUID ownerId) { super(ownerId, 245); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Mountain4(final Mountain4 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Plains1.java b/Mage.Sets/src/mage/sets/zendikar/Plains1.java index 54057b9cd0d..80bbbe61a8a 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Plains1.java +++ b/Mage.Sets/src/mage/sets/zendikar/Plains1.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Plains1 extends mage.cards.basiclands.Plains { public Plains1(UUID ownerId) { super(ownerId, 230); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Plains1(final Plains1 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Plains2.java b/Mage.Sets/src/mage/sets/zendikar/Plains2.java index 4411aa944f0..f0c7c15c029 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Plains2.java +++ b/Mage.Sets/src/mage/sets/zendikar/Plains2.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Plains2 extends mage.cards.basiclands.Plains { public Plains2(UUID ownerId) { super(ownerId, 231); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Plains2(final Plains2 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Plains3.java b/Mage.Sets/src/mage/sets/zendikar/Plains3.java index 61dcf9a75c4..837d14d639f 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Plains3.java +++ b/Mage.Sets/src/mage/sets/zendikar/Plains3.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Plains3 extends mage.cards.basiclands.Plains { public Plains3(UUID ownerId) { super(ownerId, 232); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Plains3(final Plains3 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Plains4.java b/Mage.Sets/src/mage/sets/zendikar/Plains4.java index 550a8724195..67e4a4cb6c8 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Plains4.java +++ b/Mage.Sets/src/mage/sets/zendikar/Plains4.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Plains4 extends mage.cards.basiclands.Plains { public Plains4(UUID ownerId) { super(ownerId, 233); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Plains4(final Plains4 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Swamp1.java b/Mage.Sets/src/mage/sets/zendikar/Swamp1.java index 4c874ddcdf1..391e4886720 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Swamp1.java +++ b/Mage.Sets/src/mage/sets/zendikar/Swamp1.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Swamp1 extends mage.cards.basiclands.Swamp { public Swamp1(UUID ownerId) { super(ownerId, 238); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Swamp1(final Swamp1 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Swamp2.java b/Mage.Sets/src/mage/sets/zendikar/Swamp2.java index db4208b5758..c4653c9831c 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Swamp2.java +++ b/Mage.Sets/src/mage/sets/zendikar/Swamp2.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Swamp2 extends mage.cards.basiclands.Swamp { public Swamp2(UUID ownerId) { super(ownerId, 239); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Swamp2(final Swamp2 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Swamp3.java b/Mage.Sets/src/mage/sets/zendikar/Swamp3.java index 4f347cdcbbd..123bd36470d 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Swamp3.java +++ b/Mage.Sets/src/mage/sets/zendikar/Swamp3.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Swamp3 extends mage.cards.basiclands.Swamp { public Swamp3(UUID ownerId) { super(ownerId, 240); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Swamp3(final Swamp3 card) { diff --git a/Mage.Sets/src/mage/sets/zendikar/Swamp4.java b/Mage.Sets/src/mage/sets/zendikar/Swamp4.java index ffa875496b6..5cd24edba4e 100644 --- a/Mage.Sets/src/mage/sets/zendikar/Swamp4.java +++ b/Mage.Sets/src/mage/sets/zendikar/Swamp4.java @@ -28,6 +28,8 @@ package mage.sets.zendikar; +import mage.cards.FrameStyle; + import java.util.UUID; /** @@ -39,6 +41,7 @@ public class Swamp4 extends mage.cards.basiclands.Swamp { public Swamp4(UUID ownerId) { super(ownerId, 241); this.expansionSetCode = "ZEN"; + this.frameStyle = FrameStyle.ZEN_FULL_ART_BASIC; } public Swamp4(final Swamp4 card) { diff --git a/Mage/src/main/java/mage/cards/FrameStyle.java b/Mage/src/main/java/mage/cards/FrameStyle.java index 4a8c4f4962b..52573fe4491 100644 --- a/Mage/src/main/java/mage/cards/FrameStyle.java +++ b/Mage/src/main/java/mage/cards/FrameStyle.java @@ -18,12 +18,33 @@ public enum FrameStyle { /** * Battle for Zendkiar full art basic lands */ - BFZ_FULL_ART_BASIC(BorderType.M15, true); + BFZ_FULL_ART_BASIC(BorderType.M15, true), + + /** + * Zenkikar full art lands + */ + ZEN_FULL_ART_BASIC(BorderType.MOD, true), + + /** + * Unhinged full art lands + */ + UNH_FULL_ART_BASIC(BorderType.SPC, true), + + /** + * Unglued full art lands + */ + UGL_FULL_ART_BASIC(BorderType.SPC, true); /** * General type of card */ public enum BorderType { + /** + * Various specialty borders + * EG: Unhinged, Unglued + */ + SPC, + /** * Old border cards */ diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 855323a3d5d..3513f0d6ba6 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -64,7 +64,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 47; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 58; + private static final long CARD_CONTENT_VERSION = 59; private Dao cardDao; private Set classNames; From a638625c7746630921bea202025bf83d8e04a7a7 Mon Sep 17 00:00:00 2001 From: Mark Langen Date: Wed, 7 Sep 2016 17:35:05 -0600 Subject: [PATCH 05/12] Fixed full-arts seemingly not replicating properly * The problem was that they key for caching rendered cards did not take into account the full art / not full artness of the cards, so when someone has both full art and non-full art variants of a land from the same set it one would override the other. --- .../main/java/org/mage/card/arcane/CardPanelRenderImpl.java | 4 ++++ .../main/java/org/mage/card/arcane/ModernCardRenderer.java | 5 +++-- Mage.Common/src/mage/view/CardView.java | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java index 43a467d92f0..97ab5c06d92 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java @@ -66,6 +66,9 @@ public class CardPanelRenderImpl extends CardPanel { if (!a.getExpansionSetCode().equals(b.getExpansionSetCode())) { return false; } + if (a.getFrameStyle() != b.getFrameStyle()) { + return false; + } if (a.getCounters() == null) { if (b.getCounters() != null) { return false; @@ -121,6 +124,7 @@ public class CardPanelRenderImpl extends CardPanel { sb.append((char) (this.view.isPlayable() ? 1 : 0)); sb.append((char) (this.view.isCanAttack() ? 1 : 0)); sb.append((char) (this.view.isFaceDown() ? 1 : 0)); + sb.append((char) this.view.getFrameStyle().ordinal()); if (this.view instanceof PermanentView) { sb.append((char) (((PermanentView) this.view).hasSummoningSickness() ? 1 : 0)); sb.append((char) (((PermanentView) this.view).getDamage())); diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java index d43377b31a5..be9c04cd461 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java @@ -206,6 +206,7 @@ public class ModernCardRenderer extends CardRenderer { BOX_HEIGHT_FRAC * cardHeight); // Type line at + LOGGER.info("Draw, " + cardView.getFrameStyle() + ", " + cardView.getFrameStyle().isFullArt()); typeLineY = (int)(getTypeLineYFrac() * cardHeight); // Box text height @@ -297,7 +298,7 @@ public class ModernCardRenderer extends CardRenderer { */ private Rectangle2D getArtRect() { Rectangle2D rect; - if (cardView.getFrameStyle().isFullArt()) { + if (cardView.getFrameStyle().isFullArt() || cardView.isToken()) { rect = new Rectangle2D.Float(.079f, .11f, .84f, .63f); } else { rect = new Rectangle2D.Float(.079f, .11f, .84f, .42f); @@ -307,7 +308,7 @@ public class ModernCardRenderer extends CardRenderer { private float getTypeLineYFrac() { if (cardView.isToken()) { - return TYPE_LINE_Y_FRAC; + return TYPE_LINE_Y_FRAC_TOKEN; } else if (cardView.getFrameStyle().isFullArt()) { return TYPE_LINE_Y_FRAC_FULL_ART; } else { diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index aadc38d4ca7..7d1c2fd288c 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -30,6 +30,7 @@ package mage.view; import java.util.ArrayList; import java.util.List; import java.util.UUID; + import mage.MageObject; import mage.ObjectColor; import mage.abilities.Mode; @@ -54,6 +55,7 @@ import mage.game.stack.Spell; import mage.game.stack.StackAbility; import mage.target.Target; import mage.target.Targets; +import org.apache.log4j.Logger; /** * @author BetaSteward_at_googlemail.com From 26b98d1afb8dacb862e726456837c1a2106cd5ad Mon Sep 17 00:00:00 2001 From: Mark Langen Date: Wed, 7 Sep 2016 22:35:14 -0600 Subject: [PATCH 06/12] Added more card text sizes. And other small fixes. * Changed card rules text rendering to use 5 total possible text sizes to better support HD+ display resolutions. * Made a P/T box be shown on vehicles. * Small bugfixes, fixing crashes when characteristics like type line or name are missing for whatever reason. --- .../mage/card/arcane/ModernCardRenderer.java | 211 +++++++++--------- 1 file changed, 108 insertions(+), 103 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java index be9c04cd461..e995f4d8174 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java @@ -21,8 +21,8 @@ import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.font.TextMeasurer; import java.awt.geom.Rectangle2D; -import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; +import java.awt.image.RasterFormatException; import java.io.IOException; import java.net.URL; import java.text.AttributedCharacterIterator; @@ -33,7 +33,6 @@ import java.util.Collection; import java.util.List; import javax.swing.ImageIcon; import mage.ObjectColor; -import mage.cards.FrameStyle; import mage.client.dialog.PreferencesDialog; import mage.constants.CardType; import mage.view.CardView; @@ -164,6 +163,9 @@ public class ModernCardRenderer extends CardRenderer { protected static float TYPE_LINE_Y_FRAC_FULL_ART = 0.74f; protected int typeLineY; + // Possible sizes of rules text font + protected static int[] RULES_TEXT_FONT_SIZES = {24, 18, 15, 12, 9}; + // How large is the box text, and how far is it down the boxes protected int boxTextHeight; protected int boxTextOffset; @@ -206,7 +208,6 @@ public class ModernCardRenderer extends CardRenderer { BOX_HEIGHT_FRAC * cardHeight); // Type line at - LOGGER.info("Draw, " + cardView.getFrameStyle() + ", " + cardView.getFrameStyle().isFullArt()); typeLineY = (int)(getTypeLineYFrac() * cardHeight); // Box text height @@ -337,14 +338,18 @@ public class ModernCardRenderer extends CardRenderer { // Trim off some height artHeight = artWidth / targetAspect; } - BufferedImage subImg - = artImage.getSubimage( - (int)(artRect.getX() * fullCardImgWidth), (int)(artRect.getY() * fullCardImgHeight), - (int)artWidth, (int)artHeight); - g.drawImage(subImg, - totalContentInset + 1, totalContentInset + boxHeight, - (int)targetWidth, (int)targetHeight, - null); + try { + BufferedImage subImg + = artImage.getSubimage( + (int) (artRect.getX() * fullCardImgWidth), (int) (artRect.getY() * fullCardImgHeight), + (int) artWidth, (int) artHeight); + g.drawImage(subImg, + totalContentInset + 1, totalContentInset + boxHeight, + (int) targetWidth, (int) targetHeight, + null); + } catch (RasterFormatException e) { + // At very small card sizes we may encounter a problem with rounding error making the rect not fit + } } } @@ -463,19 +468,23 @@ public class ModernCardRenderer extends CardRenderer { } else { nameStr = cardView.getName(); } - AttributedString str = new AttributedString(nameStr); - str.addAttribute(TextAttribute.FONT, boxTextFont); - TextMeasurer measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext()); - int breakIndex = measure.getLineBreakIndex(0, availableWidth); - if (breakIndex < nameStr.length()) { - str = new AttributedString(nameStr); - str.addAttribute(TextAttribute.FONT, boxTextFontNarrow); - measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext()); - breakIndex = measure.getLineBreakIndex(0, availableWidth); + if (!nameStr.isEmpty()) { + AttributedString str = new AttributedString(nameStr); + str.addAttribute(TextAttribute.FONT, boxTextFont); + TextMeasurer measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext()); + int breakIndex = measure.getLineBreakIndex(0, availableWidth); + if (breakIndex < nameStr.length()) { + str = new AttributedString(nameStr); + str.addAttribute(TextAttribute.FONT, boxTextFontNarrow); + measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext()); + breakIndex = measure.getLineBreakIndex(0, availableWidth); + } + if (breakIndex > 0) { + TextLayout layout = measure.getLayout(0, breakIndex); + g.setColor(getBoxTextColor()); + layout.draw(g, x, y + boxTextOffset + boxTextHeight - 1); + } } - TextLayout layout = measure.getLayout(0, breakIndex); - g.setColor(getBoxTextColor()); - layout.draw(g, x, y + boxTextOffset + boxTextHeight - 1); // Draw the mana symbols if (!cardView.isAbility() && !cardView.isFaceDown()) { @@ -518,9 +527,11 @@ public class ModernCardRenderer extends CardRenderer { measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext()); breakIndex = measure.getLineBreakIndex(0, availableWidth); } - TextLayout layout = measure.getLayout(0, breakIndex); - g.setColor(getBoxTextColor()); - layout.draw(g, x, y + boxTextOffset + boxTextHeight - 1); + if (breakIndex > 0) { + TextLayout layout = measure.getLayout(0, breakIndex); + g.setColor(getBoxTextColor()); + layout.draw(g, x, y + boxTextOffset + boxTextHeight - 1); + } } } @@ -538,7 +549,7 @@ public class ModernCardRenderer extends CardRenderer { int partWidth = (int) Math.max(30, 0.20f * cardWidth); // Is it a creature? - if (cardView.getCardTypes().contains(CardType.CREATURE)) { + if (cardView.getCardTypes().contains(CardType.CREATURE) || cardView.getSubTypes().contains("Vehicle")) { int x = cardWidth - borderWidth - partWidth; // Draw PT box @@ -563,12 +574,7 @@ public class ModernCardRenderer extends CardRenderer { g.drawString(ptText, x + (partWidth - ptTextWidth) / 2, curY - ptTextOffset - 1); - // Does it have damage on it? - if ((cardView instanceof PermanentView) && ((PermanentView) cardView).getDamage() > 0) { - // Show marked damage - - } - + // Advance curY -= boxHeight; } @@ -646,94 +652,92 @@ public class ModernCardRenderer extends CardRenderer { // Draw the card's textbox in a given rect protected boolean loyaltyAbilityColorToggle = false; - protected void drawRulesText(Graphics2D g, int x, int y, int w, int h) { - // Initial font size to try to render at - Font font = new Font("Arial", Font.PLAIN, 12); - Font fontItalic = new Font("Arial", Font.ITALIC, 12); + private class RuleLayout { + public List attributedRules; + public int remainingHeight; + public boolean fits; + public Font font; + public Font fontItalic; + } - // Handle the keyword rules - boolean hasKeywords = !textboxKeywords.isEmpty(); - String keywordRulesString = getKeywordRulesString(); - AttributedString keywordRulesAttributed = new AttributedString(keywordRulesString); - if (hasKeywords) { - keywordRulesAttributed.addAttribute(TextAttribute.FONT, font); - } + /** + * Figure out if a given text size will work for laying out the rules in a card textbox + */ + protected RuleLayout layoutRules(Graphics2D g, List rules, int w, int h, int fontSize) { + // The fonts to try + Font font = new Font("Arial", Font.PLAIN, fontSize); + Font fontItalic = new Font("Arial", Font.ITALIC, fontSize); - // Get the total height + // Get the total height of the rules List attributedRules = new ArrayList<>(); - boolean useSmallFont = false; + boolean fits = true; int remaining = h; - { - if (hasKeywords) { - remaining -= drawSingleRule(g, keywordRulesAttributed, null, 0, 0, w, remaining, false); - } - for (TextboxRule rule : textboxRules) { - AttributedString attributed = rule.generateAttributedString(font, fontItalic); - attributedRules.add(attributed); - remaining -= drawSingleRule(g, attributed, rule, 0, 0, w, remaining, false); - if (remaining < 0) { - useSmallFont = true; - break; - } + for (TextboxRule rule : rules) { + AttributedString attributed = rule.generateAttributedString(font, fontItalic); + attributedRules.add(attributed); + remaining -= drawSingleRule(g, attributed, rule, 0, 0, w, remaining, /*doDraw=*/false); + if (remaining < 0) { + fits = false; + break; } } - // If there wasn't enough room, try using a smaller font - if (useSmallFont) { - font = new Font("Arial", Font.PLAIN, 9); - fontItalic = new Font("Arial", Font.ITALIC, 9); - if (hasKeywords) { - keywordRulesAttributed = new AttributedString(keywordRulesString); - keywordRulesAttributed.addAttribute(TextAttribute.FONT, font); - } + // Return the information + RuleLayout layout = new RuleLayout(); + layout.attributedRules = attributedRules; + layout.remainingHeight = remaining; + layout.fits = fits; + layout.font = font; + layout.fontItalic = fontItalic; + return layout; + } - // Clear out the attributed rules and reatribute them with the new font size - attributedRules.clear(); - for (TextboxRule rule : textboxRules) { - AttributedString attributed = rule.generateAttributedString(font, fontItalic); - attributedRules.add(attributed); - } + protected void drawRulesText(Graphics2D g, int x, int y, int w, int h) { + // Gather all rules to render + List allRules = new ArrayList<>(textboxRules); - // Get the new spacing for the small text - remaining = h; - if (hasKeywords) { - remaining -= drawSingleRule(g, keywordRulesAttributed, null, 0, 0, w, remaining, false); - } - for (TextboxRule rule : textboxRules) { - AttributedString attributed = rule.generateAttributedString(font, fontItalic); - attributedRules.add(attributed); - remaining -= drawSingleRule(g, attributed, rule, 0, 0, w, remaining, false); - if (remaining < 0) { - break; - } + // Add the keyword rule if there are any keywords + if (!textboxKeywords.isEmpty()) { + String keywordRulesString = getKeywordRulesString(); + TextboxRule keywordsRule = new TextboxRule(keywordRulesString, new ArrayList()); + allRules.add(keywordsRule); + } + + // Go through possible font sizes in descending order to find the best fit + RuleLayout bestLayout = null; + for (int fontSize: RULES_TEXT_FONT_SIZES) { + bestLayout = layoutRules(g, allRules, w, h, fontSize); + + // Stop, we found a good fit + if (bestLayout.fits) { + break; } } - // Do we have room for additional spacing between the parts of text? - // If so, calculate the spacing based on how much space was left over - int spacing; - if (remaining <= 0) { - spacing = 0; + // Nothing to draw + if (bestLayout == null) { + return; + } + + // Do we have room for additional padding between the parts of text? + // If so, calculate the padding based on how much space was left over + int padding; + if (bestLayout.fits) { + padding = (int) (((float)bestLayout.remainingHeight) / (1 + allRules.size())); } else { - spacing = (int) (((float)remaining) / (hasKeywords - ? (textboxRules.size() + 2) - : (textboxRules.size() + 1))); + // When the text doesn't fit to begin with there's no room for padding + padding = 0; } // Do the actual draw loyaltyAbilityColorToggle = false; g.setColor(Color.black); - int curY = y + spacing; - if (hasKeywords) { - int adv = drawSingleRule(g, keywordRulesAttributed, null, x, curY, w, h, true); - curY += adv + spacing; - h -= adv; - } - for (int i = 0; i < textboxRules.size(); ++i) { - TextboxRule rule = textboxRules.get(i); - AttributedString attributedRule = attributedRules.get(i); + int curY = y + padding; + for (int i = 0; i < bestLayout.attributedRules.size(); ++i) { + AttributedString attributedRule = bestLayout.attributedRules.get(i); + TextboxRule rule = allRules.get(i); int adv = drawSingleRule(g, attributedRule, rule, x, curY, w, h, true); - curY += adv + spacing; + curY += adv + padding; h -= adv; if (h < 0) { break; @@ -772,7 +776,8 @@ public class ModernCardRenderer extends CardRenderer { AttributedCharacterIterator newLineCheck = text.getIterator(); while (measure.getPosition() < textIter.getEndIndex()) { // Advance iterator to next line break - char ch = newLineCheck.setIndex(measure.getPosition()); + newLineCheck.setIndex(measure.getPosition()); + char ch; while ((ch = newLineCheck.next()) != CharacterIterator.DONE) { if (ch == '\n') { break; From 67f29124f86602175ad8b2c1356015c64a3d5eb3 Mon Sep 17 00:00:00 2001 From: emerald000 Date: Thu, 8 Sep 2016 02:10:26 -0400 Subject: [PATCH 07/12] [KLD] Added 15 artifacts. Aetherflux Reservoir, Aetherworks Marvel, Animation Module, Cogworker's Puzzleknot, Decoction Module, Demolition Stomper, Fabrication Module, Fireforger's Puzzleknot, Fleetwheel Cruiser, Ghirapur Orrery, Glassblower's Puzzleknot, Inventor's Goggles, Metalspinner's Puzzleknot, Ovalchase Dragster and Skysovereign, Consul Flagship. --- .../sets/kaladesh/AetherfluxReservoir.java | 99 +++++++++ .../mage/sets/kaladesh/AetherworksMarvel.java | 121 ++++++++++ .../mage/sets/kaladesh/AnimationModule.java | 206 ++++++++++++++++++ .../sets/kaladesh/CogworkersPuzzleknot.java | 70 ++++++ .../mage/sets/kaladesh/DecoctionModule.java | 72 ++++++ .../mage/sets/kaladesh/DemolitionStomper.java | 76 +++++++ .../mage/sets/kaladesh/FabricationModule.java | 110 ++++++++++ .../sets/kaladesh/FireforgersPuzzleknot.java | 77 +++++++ .../mage/sets/kaladesh/FleetwheelCruiser.java | 84 +++++++ .../mage/sets/kaladesh/GhirapurOrrery.java | 90 ++++++++ .../sets/kaladesh/GlassblowersPuzzleknot.java | 78 +++++++ .../mage/sets/kaladesh/InventorsGoggles.java | 82 +++++++ .../kaladesh/MetalspinnersPuzzleknot.java | 78 +++++++ .../mage/sets/kaladesh/OvalchaseDragster.java | 70 ++++++ .../kaladesh/SkysovereignConsulFlagship.java | 122 +++++++++++ .../abilities/costs/common/PayEnergyCost.java | 85 ++++++++ .../java/mage/abilities/effects/Effects.java | 6 +- .../abilities/keyword/FabricateAbility.java | 16 +- 18 files changed, 1524 insertions(+), 18 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/kaladesh/AetherfluxReservoir.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/AetherworksMarvel.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/AnimationModule.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/CogworkersPuzzleknot.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/DecoctionModule.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/DemolitionStomper.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/FabricationModule.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/FireforgersPuzzleknot.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/FleetwheelCruiser.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/GhirapurOrrery.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/GlassblowersPuzzleknot.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/MetalspinnersPuzzleknot.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/OvalchaseDragster.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/SkysovereignConsulFlagship.java create mode 100644 Mage/src/main/java/mage/abilities/costs/common/PayEnergyCost.java diff --git a/Mage.Sets/src/mage/sets/kaladesh/AetherfluxReservoir.java b/Mage.Sets/src/mage/sets/kaladesh/AetherfluxReservoir.java new file mode 100644 index 00000000000..6c00b0278c7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/AetherfluxReservoir.java @@ -0,0 +1,99 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.target.common.TargetCreatureOrPlayer; +import mage.watchers.common.CastSpellLastTurnWatcher; + +/** + * + * @author emerald000 + */ +public class AetherfluxReservoir extends CardImpl { + + public AetherfluxReservoir(UUID ownerId) { + super(ownerId, 192, "Aetherflux Reservoir", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "KLD"; + + // Whenever you cast a spell, you gain 1 life for each spell you've cast this turn. + this.addAbility(new SpellCastControllerTriggeredAbility(new GainLifeEffect(new AetherfluxReservoirDynamicValue()), false)); + + // Pay 50 life: Aetherflux Reservoir deals 50 damage to target creature or player. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(50), new PayLifeCost(50)); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public AetherfluxReservoir(final AetherfluxReservoir card) { + super(card); + } + + @Override + public AetherfluxReservoir copy() { + return new AetherfluxReservoir(this); + } +} + +class AetherfluxReservoirDynamicValue implements DynamicValue { + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName()); + return watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(sourceAbility.getControllerId()); + } + + @Override + public AetherfluxReservoirDynamicValue copy() { + return new AetherfluxReservoirDynamicValue(); + } + + @Override + public String toString() { + return "1"; + } + + @Override + public String getMessage() { + return "spell you've cast this turn"; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/kaladesh/AetherworksMarvel.java b/Mage.Sets/src/mage/sets/kaladesh/AetherworksMarvel.java new file mode 100644 index 00000000000..8d32bf3291f --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/AetherworksMarvel.java @@ -0,0 +1,121 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.PayEnergyCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterNonlandCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author emerald000 + */ +public class AetherworksMarvel extends CardImpl { + + public AetherworksMarvel(UUID ownerId) { + super(ownerId, 193, "Aetherworks Marvel", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "KLD"; + this.supertype.add("Legendary"); + + // Whenever a permanent you control is put into a graveyard, you get {E}. + this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility(new GetEnergyCountersControllerEffect(1), false, new FilterPermanent("a permanent"), false)); + + // {T}, Pay {E}{E}{E}{E}{E}{E}: Look at the top six cards of your library. You may cast a card from among them without paying its mana cost. Put the rest on the bottom of your library in a random order. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AetherworksMarvelEffect(), new TapSourceCost()); + ability.addCost(new PayEnergyCost(6)); + this.addAbility(ability); + } + + public AetherworksMarvel(final AetherworksMarvel card) { + super(card); + } + + @Override + public AetherworksMarvel copy() { + return new AetherworksMarvel(this); + } +} + +class AetherworksMarvelEffect extends OneShotEffect { + + AetherworksMarvelEffect() { + super(Outcome.PlayForFree); + this.staticText = "Look at the top six cards of your library. You may cast a card from among them without paying its mana cost. Put the rest on the bottom of your library in a random order"; + } + + AetherworksMarvelEffect(final AetherworksMarvelEffect effect) { + super(effect); + } + + @Override + public AetherworksMarvelEffect copy() { + return new AetherworksMarvelEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Set cardsSet = controller.getLibrary().getTopCards(game, 6); + Cards cards = new CardsImpl(); + for (Card card : cardsSet) { + cards.add(card); + } + TargetCard target = new TargetCardInLibrary(0, 1, new FilterNonlandCard("card to cast without paying its mana cost")); + if (controller.choose(Outcome.PlayForFree, cards, target, game)) { + Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); + if (card != null && controller.cast(card.getSpellAbility(), game, true)) { + cards.remove(card); + } + } + controller.putCardsOnBottomOfLibrary(cards, game, source, false); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/AnimationModule.java b/Mage.Sets/src/mage/sets/kaladesh/AnimationModule.java new file mode 100644 index 00000000000..46b13be0d47 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/AnimationModule.java @@ -0,0 +1,206 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.cards.CardImpl; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.Counter; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.ServoToken; +import mage.players.Player; +import mage.target.common.TargetPermanentOrPlayer; + +/** + * + * @author emerald000 + */ +public class AnimationModule extends CardImpl { + + public AnimationModule(UUID ownerId) { + super(ownerId, 194, "Animation Module", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{1}"); + this.expansionSetCode = "KLD"; + + // Whenever one or more +1/+1 counters are placed on a permanent you control, you may pay {1}. If you do, create a 1/1 colorless Servo artifact creature token. + this.addAbility(new AnimationModuleTriggeredAbility()); + + // {3}, {T}: Choose a counter on target permanent or player. Give that permanent or player another counter of that kind. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AnimationModuleEffect(), new GenericManaCost(3)); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetPermanentOrPlayer()); + this.addAbility(ability); + } + + public AnimationModule(final AnimationModule card) { + super(card); + } + + @Override + public AnimationModule copy() { + return new AnimationModule(this); + } +} + +class AnimationModuleTriggeredAbility extends TriggeredAbilityImpl { + + AnimationModuleTriggeredAbility() { + super(Zone.BATTLEFIELD, new DoIfCostPaid(new CreateTokenEffect(new ServoToken()), new GenericManaCost(1)), false); + } + + AnimationModuleTriggeredAbility(final AnimationModuleTriggeredAbility ability) { + super(ability); + } + + @Override + public AnimationModuleTriggeredAbility copy() { + return new AnimationModuleTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.COUNTERS_ADDED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getData().equals(CounterType.P1P1.getName())) { + Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); + if (permanent == null) { + permanent = game.getPermanentEntering(event.getTargetId()); + } + return permanent != null && permanent.getControllerId().equals(this.getControllerId()); + } + return false; + } + + @Override + public String getRule() { + return "Whenever one or more +1/+1 counters are placed on a permanent you control, you may pay {1}. If you do, create a 1/1 colorless Servo artifact creature token."; + } +} + +class AnimationModuleEffect extends OneShotEffect { + + AnimationModuleEffect() { + super(Outcome.Neutral); + this.staticText = "Choose a counter on target permanent or player. Give that permanent or player another counter of that kind"; + } + + AnimationModuleEffect(final AnimationModuleEffect effect) { + super(effect); + } + + @Override + public AnimationModuleEffect copy() { + return new AnimationModuleEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (permanent != null) { + if (permanent.getCounters(game).size() > 0) { + if (permanent.getCounters(game).size() == 1) { + for (Counter counter : permanent.getCounters(game).values()) { + Counter newCounter = new Counter(counter.getName()); + permanent.addCounters(newCounter, game); + } + } + else { + Choice choice = new ChoiceImpl(true); + Set choices = new HashSet<>(permanent.getCounters(game).size()); + for (Counter counter : permanent.getCounters(game).values()) { + choices.add(counter.getName()); + } + choice.setChoices(choices); + choice.setMessage("Choose a counter"); + controller.choose(Outcome.Benefit, choice, game); + for (Counter counter : permanent.getCounters(game).values()) { + if (counter.getName().equals(choice.getChoice())) { + Counter newCounter = new Counter(counter.getName()); + permanent.addCounters(newCounter, game); + break; + } + } + } + } + } + else { + Player player = game.getPlayer(this.getTargetPointer().getFirst(game, source)); + if (player != null) { + if (player.getCounters().size() > 0) { + if (player.getCounters().size() == 1) { + for (Counter counter : player.getCounters().values()) { + Counter newCounter = new Counter(counter.getName()); + player.addCounters(newCounter, game); + } + } + else { + Choice choice = new ChoiceImpl(true); + Set choices = new HashSet<>(player.getCounters().size()); + for (Counter counter : player.getCounters().values()) { + choices.add(counter.getName()); + } + choice.setChoices(choices); + choice.setMessage("Choose a counter"); + controller.choose(Outcome.Benefit, choice, game); + for (Counter counter : player.getCounters().values()) { + if (counter.getName().equals(choice.getChoice())) { + Counter newCounter = new Counter(counter.getName()); + player.addCounters(newCounter, game); + break; + } + } + } + } + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/CogworkersPuzzleknot.java b/Mage.Sets/src/mage/sets/kaladesh/CogworkersPuzzleknot.java new file mode 100644 index 00000000000..49bb8198e17 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/CogworkersPuzzleknot.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.permanent.token.ServoToken; + +/** + * + * @author emerald000 + */ +public class CogworkersPuzzleknot extends CardImpl { + + public CogworkersPuzzleknot(UUID ownerId) { + super(ownerId, 201, "Cogworker's Puzzleknot", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "KLD"; + + // When Cogworker's Puzzleknot enters the battlefield, create a 1/1 colorless Servo artifact creature token. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ServoToken()))); + + // {1}{W}, Sacrifice Cogworker's Puzzleknot: Create a 1/1 colorless Servo artifact creature token. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new ServoToken()), new ManaCostsImpl<>("{1}{W}")); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public CogworkersPuzzleknot(final CogworkersPuzzleknot card) { + super(card); + } + + @Override + public CogworkersPuzzleknot copy() { + return new CogworkersPuzzleknot(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/DecoctionModule.java b/Mage.Sets/src/mage/sets/kaladesh/DecoctionModule.java new file mode 100644 index 00000000000..2d5991a38f8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/DecoctionModule.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class DecoctionModule extends CardImpl { + + public DecoctionModule(UUID ownerId) { + super(ownerId, 205, "Decoction Module", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "KLD"; + + // Whenever a creature enters the battlefield under your control, you get {E}. + this.addAbility(new CreatureEntersBattlefieldTriggeredAbility(new GetEnergyCountersControllerEffect(1))); + + // {4}, {T}: Return target creature you control to its owner's hand. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + } + + public DecoctionModule(final DecoctionModule card) { + super(card); + } + + @Override + public DecoctionModule copy() { + return new DecoctionModule(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/DemolitionStomper.java b/Mage.Sets/src/mage/sets/kaladesh/DemolitionStomper.java new file mode 100644 index 00000000000..0657f8b016c --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/DemolitionStomper.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleEvasionAbility; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.abilities.keyword.CrewAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.Filter; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; + +/** + * + * @author emerald000 + */ +public class DemolitionStomper extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with power 2 or less"); + static { + filter.add(new PowerPredicate(Filter.ComparisonType.LessThan, 3)); + } + + public DemolitionStomper(UUID ownerId) { + super(ownerId, 206, "Demolition Stomper", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{6}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Vehicle"); + this.power = new MageInt(10); + this.toughness = new MageInt(7); + + // Demolition Stomper can't be blocked by creatures with power 2 or less. + this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield))); + + // Crew 5 + this.addAbility(new CrewAbility(5)); + } + + public DemolitionStomper(final DemolitionStomper card) { + super(card); + } + + @Override + public DemolitionStomper copy() { + return new DemolitionStomper(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/FabricationModule.java b/Mage.Sets/src/mage/sets/kaladesh/FabricationModule.java new file mode 100644 index 00000000000..13e39412e1c --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/FabricationModule.java @@ -0,0 +1,110 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class FabricationModule extends CardImpl { + + public FabricationModule(UUID ownerId) { + super(ownerId, 211, "Fabrication Module", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{3}"); + this.expansionSetCode = "KLD"; + + // Whenever you get one or more {E}, put a +1/+1 counter on target creature you control. + Ability ability = new FabricationModuleTriggeredAbility(); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + + // {4}, {T}: You get {E}. + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GetEnergyCountersControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public FabricationModule(final FabricationModule card) { + super(card); + } + + @Override + public FabricationModule copy() { + return new FabricationModule(this); + } +} + +class FabricationModuleTriggeredAbility extends TriggeredAbilityImpl { + + FabricationModuleTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false); + } + + FabricationModuleTriggeredAbility(final FabricationModuleTriggeredAbility ability) { + super(ability); + } + + @Override + public FabricationModuleTriggeredAbility copy() { + return new FabricationModuleTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.COUNTERS_ADDED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getData().equals(CounterType.ENERGY.getName())) { + return event.getTargetId() == this.getControllerId(); + } + return false; + } + + @Override + public String getRule() { + return "Whenever you get one or more {E}, put a +1/+1 counter on target creature you control."; + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/FireforgersPuzzleknot.java b/Mage.Sets/src/mage/sets/kaladesh/FireforgersPuzzleknot.java new file mode 100644 index 00000000000..672a1d4084e --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/FireforgersPuzzleknot.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author emerald000 + */ +public class FireforgersPuzzleknot extends CardImpl { + + public FireforgersPuzzleknot(UUID ownerId) { + super(ownerId, 213, "Fireforger's Puzzleknot", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "KLD"; + + // When Fireforger's Puzzleknot enters the battlefield, it deals 1 damage to target creature or player. + Effect effect = new DamageTargetEffect(1); + effect.setText("it deals 1 damage to target creature or player"); + Ability ability = new EntersBattlefieldTriggeredAbility(effect); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + + // {2}{R}, Sacrifice Fireforger's Puzzleknot: It deals 1 damage to target creature or player. + effect.setText("It deals 1 damage to target creature or player"); + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl<>("{2}{R}")); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public FireforgersPuzzleknot(final FireforgersPuzzleknot card) { + super(card); + } + + @Override + public FireforgersPuzzleknot copy() { + return new FireforgersPuzzleknot(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/FleetwheelCruiser.java b/Mage.Sets/src/mage/sets/kaladesh/FleetwheelCruiser.java new file mode 100644 index 00000000000..1a3d51dacad --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/FleetwheelCruiser.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect; +import mage.abilities.keyword.CrewAbility; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author emerald000 + */ +public class FleetwheelCruiser extends CardImpl { + + public FleetwheelCruiser(UUID ownerId) { + super(ownerId, 214, "Fleetwheel Cruiser", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Vehicle"); + this.power = new MageInt(5); + this.toughness = new MageInt(3); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // When Fleetwheel Cruiser enters the battlefield, it becomes an artifact creature until the end of turn. + Effect effect = new AddCardTypeSourceEffect(CardType.ARTIFACT, Duration.EndOfTurn); + effect.setText("it becomes an artifact"); + Ability ability = new EntersBattlefieldTriggeredAbility(effect); + effect = new AddCardTypeSourceEffect(CardType.CREATURE, Duration.EndOfTurn); + effect.setText(" creature until end of turn"); + ability.addEffect(effect); + this.addAbility(ability); + + // Crew 2 + this.addAbility(new CrewAbility(2)); + } + + public FleetwheelCruiser(final FleetwheelCruiser card) { + super(card); + } + + @Override + public FleetwheelCruiser copy() { + return new FleetwheelCruiser(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/GhirapurOrrery.java b/Mage.Sets/src/mage/sets/kaladesh/GhirapurOrrery.java new file mode 100644 index 00000000000..5f5a2a89afa --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/GhirapurOrrery.java @@ -0,0 +1,90 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.IntCompareCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.DrawCardTargetEffect; +import mage.abilities.effects.common.continuous.PlayAdditionalLandsAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author emerald000 + */ +public class GhirapurOrrery extends CardImpl { + + public GhirapurOrrery(UUID ownerId) { + super(ownerId, 216, "Ghirapur Orrery", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "KLD"; + + // Each player may play an additional land on each of his or her turns. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PlayAdditionalLandsAllEffect())); + + // At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards. + this.addAbility(new ConditionalTriggeredAbility( + new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DrawCardTargetEffect(3), TargetController.ANY, false, true), + new GhirapurOrreryCondition(), + "At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards.")); + } + + public GhirapurOrrery(final GhirapurOrrery card) { + super(card); + } + + @Override + public GhirapurOrrery copy() { + return new GhirapurOrrery(this); + } +} + +class GhirapurOrreryCondition extends IntCompareCondition { + + GhirapurOrreryCondition() { + super(ComparisonType.Equal, 0); + } + + @Override + protected int getInputValue(Game game, Ability source) { + Player activePlayer = game.getPlayer(game.getActivePlayerId()); + if (activePlayer != null) { + return activePlayer.getHand().size(); + } + return 0; + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/GlassblowersPuzzleknot.java b/Mage.Sets/src/mage/sets/kaladesh/GlassblowersPuzzleknot.java new file mode 100644 index 00000000000..c1f46366a7d --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/GlassblowersPuzzleknot.java @@ -0,0 +1,78 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author emerald000 + */ +public class GlassblowersPuzzleknot extends CardImpl { + + public GlassblowersPuzzleknot(UUID ownerId) { + super(ownerId, 217, "Glassblower's Puzzleknot", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "KLD"; + + // When Glassblower's Puzzleknot enters the battlefield, scry 2, then you get {E}{E}. + Effect scryEffect = new ScryEffect(2); + scryEffect.setText("scry 2"); + Ability ability = new EntersBattlefieldTriggeredAbility(scryEffect); + Effect energyEffect = new GetEnergyCountersControllerEffect(2); + energyEffect.setText(", then you get {E}{E}"); + ability.addEffect(energyEffect); + this.addAbility(ability); + + // {2}{U}, Sacrifice Glassblower's Puzzleknot: Scry 2, then you get {E}{E}. + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, scryEffect, new ManaCostsImpl<>("{2}{U}")); + ability.addCost(new SacrificeSourceCost()); + ability.addEffect(energyEffect); + this.addAbility(ability); + } + + public GlassblowersPuzzleknot(final GlassblowersPuzzleknot card) { + super(card); + } + + @Override + public GlassblowersPuzzleknot copy() { + return new GlassblowersPuzzleknot(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java b/Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java new file mode 100644 index 00000000000..630766e4ab7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/InventorsGoggles.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SetTargetPointer; +import mage.constants.Zone; +import mage.filter.FilterPermanent; + +/** + * + * @author emerald000 + */ +public class InventorsGoggles extends CardImpl { + + public InventorsGoggles(UUID ownerId) { + super(ownerId, 218, "Inventor's Goggles", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{1}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Equipment"); + + // Equipped creature gets +1/+2. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 2, Duration.WhileOnBattlefield))); + + // Whenever an Artificer enters the battlefield under your control, you may attach Inventor's Goggles to it. + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, + new AttachEffect(Outcome.BoostCreature, "attach {this} to it"), + new FilterPermanent("Artificer", "Artificer"), + true, + SetTargetPointer.PERMANENT, + null, + true)); + + // Equip {2} + this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2))); + } + + public InventorsGoggles(final InventorsGoggles card) { + super(card); + } + + @Override + public InventorsGoggles copy() { + return new InventorsGoggles(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/MetalspinnersPuzzleknot.java b/Mage.Sets/src/mage/sets/kaladesh/MetalspinnersPuzzleknot.java new file mode 100644 index 00000000000..cf2235e0fdd --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/MetalspinnersPuzzleknot.java @@ -0,0 +1,78 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.LoseLifeSourceControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author emerald000 + */ +public class MetalspinnersPuzzleknot extends CardImpl { + + public MetalspinnersPuzzleknot(UUID ownerId) { + super(ownerId, 221, "Metalspinner's Puzzleknot", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "KLD"; + + // When Metalspinner's Puzzleknot enters the battlefield, you draw a card and you lose 1 life. + Effect drawEffect = new DrawCardSourceControllerEffect(1); + drawEffect.setText("you draw a card"); + Ability ability = new EntersBattlefieldTriggeredAbility(drawEffect); + Effect lifeEffect = new LoseLifeSourceControllerEffect(1); + lifeEffect.setText("and you lose 1 life"); + ability.addEffect(lifeEffect); + this.addAbility(ability); + + // {2}{B}, Sacrifice Metalspinner's Puzzleknot: You draw a card and you lose 1 life. + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, drawEffect, new ManaCostsImpl<>("{2}{B}")); + ability.addCost(new SacrificeSourceCost()); + ability.addEffect(lifeEffect); + this.addAbility(ability); + } + + public MetalspinnersPuzzleknot(final MetalspinnersPuzzleknot card) { + super(card); + } + + @Override + public MetalspinnersPuzzleknot copy() { + return new MetalspinnersPuzzleknot(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/OvalchaseDragster.java b/Mage.Sets/src/mage/sets/kaladesh/OvalchaseDragster.java new file mode 100644 index 00000000000..452a0dd3705 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/OvalchaseDragster.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.CrewAbility; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author emerald000 + */ +public class OvalchaseDragster extends CardImpl { + + public OvalchaseDragster(UUID ownerId) { + super(ownerId, 225, "Ovalchase Dragster", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Vehicle"); + this.power = new MageInt(6); + this.toughness = new MageInt(1); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Crew 1 + this.addAbility(new CrewAbility(1)); + } + + public OvalchaseDragster(final OvalchaseDragster card) { + super(card); + } + + @Override + public OvalchaseDragster copy() { + return new OvalchaseDragster(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/SkysovereignConsulFlagship.java b/Mage.Sets/src/mage/sets/kaladesh/SkysovereignConsulFlagship.java new file mode 100644 index 00000000000..6b414084b98 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/SkysovereignConsulFlagship.java @@ -0,0 +1,122 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.CrewAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.target.common.TargetCreatureOrPlaneswalker; + +/** + * + * @author emerald000 + */ +public class SkysovereignConsulFlagship extends CardImpl { + + private static final FilterCreatureOrPlaneswalkerPermanent filter = new FilterCreatureOrPlaneswalkerPermanent("creature or planeswalker an opponent controls"); + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public SkysovereignConsulFlagship(UUID ownerId) { + super(ownerId, 234, "Skysovereign, Consul Flagship", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT}, "{5}"); + this.expansionSetCode = "KLD"; + this.supertype.add("Legendary"); + this.subtype.add("Vehicle"); + this.power = new MageInt(6); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever Skysovereign, Consul Flagship enters the battlefield or attacks, it deals 3 damage to target creature or planeswalker an opponent controls. + Ability ability = new SkysovereignConsulFlagshipTriggeredAbility(); + ability.addTarget(new TargetCreatureOrPlaneswalker(1, 1, filter, false)); + this.addAbility(ability); + + // Crew 3 + this.addAbility(new CrewAbility(3)); + } + + public SkysovereignConsulFlagship(final SkysovereignConsulFlagship card) { + super(card); + } + + @Override + public SkysovereignConsulFlagship copy() { + return new SkysovereignConsulFlagship(this); + } +} + +class SkysovereignConsulFlagshipTriggeredAbility extends TriggeredAbilityImpl { + + SkysovereignConsulFlagshipTriggeredAbility() { + super(Zone.BATTLEFIELD, new DamageTargetEffect(3), false); + } + + SkysovereignConsulFlagshipTriggeredAbility(final SkysovereignConsulFlagshipTriggeredAbility ability) { + super(ability); + } + + @Override + public SkysovereignConsulFlagshipTriggeredAbility copy() { + return new SkysovereignConsulFlagshipTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.ATTACKER_DECLARED || event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == EventType.ATTACKER_DECLARED && event.getSourceId().equals(this.getSourceId())) { + return true; + } + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD && event.getTargetId().equals(this.getSourceId()); + } + + @Override + public String getRule() { + return "Whenever {this} enters the battlefield or attacks, it deals 3 damage to target creature or planeswalker an opponent controls."; + } +} diff --git a/Mage/src/main/java/mage/abilities/costs/common/PayEnergyCost.java b/Mage/src/main/java/mage/abilities/costs/common/PayEnergyCost.java new file mode 100644 index 00000000000..f5156f5a35f --- /dev/null +++ b/Mage/src/main/java/mage/abilities/costs/common/PayEnergyCost.java @@ -0,0 +1,85 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.abilities.costs.common; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.counters.CounterType; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author emerald000 + */ +public class PayEnergyCost extends CostImpl { + + private final int amount; + + public PayEnergyCost(int amount) { + this.amount = amount; + setText(); + } + + public PayEnergyCost(PayEnergyCost cost) { + super(cost); + this.amount = cost.amount; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + Player player = game.getPlayer(controllerId); + return player != null && player.getCounters().getCount(CounterType.ENERGY) >= amount; + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { + Player player = game.getPlayer(controllerId); + if (player != null) { + player.getCounters().removeCounter(CounterType.ENERGY, amount); + paid = true; + } + return paid; + } + + @Override + public PayEnergyCost copy() { + return new PayEnergyCost(this); + } + + private void setText() { + StringBuilder sb = new StringBuilder("Pay "); + for (int i = 0; i < amount; i++) { + sb.append("{E}"); + } + this.text = sb.toString(); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/Effects.java b/Mage/src/main/java/mage/abilities/effects/Effects.java index 36a78daa694..9f207eeeca0 100644 --- a/Mage/src/main/java/mage/abilities/effects/Effects.java +++ b/Mage/src/main/java/mage/abilities/effects/Effects.java @@ -65,12 +65,12 @@ public class Effects extends ArrayList { StringBuilder sbText = new StringBuilder(); String lastRule = null; for (Effect effect: this) { - String endString = ""; + String endString = ""; String nextRule = effect.getText(mode); if (nextRule != null) { if (nextRule.startsWith("and ") || nextRule.startsWith("with ")) { endString = " "; - } else if (nextRule.startsWith(",")) { + } else if (nextRule.startsWith(",") || nextRule.startsWith(" ")) { endString = ""; } else if (lastRule != null && lastRule.length()> 3) { if (!lastRule.endsWith(".") && !lastRule.endsWith("
")) { @@ -84,7 +84,7 @@ public class Effects extends ArrayList { } lastRule = nextRule; } - if (lastRule != null && lastRule.length()> 3 && + if (lastRule != null && lastRule.length()> 3 && !lastRule.endsWith(".") && !lastRule.endsWith("\"") && !lastRule.startsWith("Level ") && diff --git a/Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java b/Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java index d60250a2ffe..5fe9c105880 100644 --- a/Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java @@ -27,17 +27,15 @@ */ package mage.abilities.keyword; -import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; -import mage.constants.CardType; import mage.constants.Outcome; import mage.counters.CounterType; import mage.game.Game; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.ServoToken; import mage.players.Player; import mage.util.CardUtil; @@ -105,15 +103,3 @@ class FabricateEffect extends OneShotEffect { return false; } } - -class ServoToken extends Token { - - ServoToken() { - super("Servo", "1/1 colorless Servo artifact creature token"); - cardType.add(CardType.ARTIFACT); - cardType.add(CardType.CREATURE); - subtype.add("Servo"); - power = new MageInt(1); - toughness = new MageInt(1); - } -} From 8cd3ec11359d0eb385279be390542c9a1fc9259f Mon Sep 17 00:00:00 2001 From: spjspj Date: Thu, 8 Sep 2016 17:09:47 +1000 Subject: [PATCH 08/12] spjspj - Implement Paradoxical Outcome (KLD) (done with addition to SweepEffect) --- .../sets/kaladesh/ParadoxicalOutcome.java | 72 +++++++++++++++++++ .../effects/keyword/SweepEffect.java | 22 +++++- 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/kaladesh/ParadoxicalOutcome.java diff --git a/Mage.Sets/src/mage/sets/kaladesh/ParadoxicalOutcome.java b/Mage.Sets/src/mage/sets/kaladesh/ParadoxicalOutcome.java new file mode 100644 index 00000000000..6c36ba2842a --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/ParadoxicalOutcome.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.kaladesh; + +import java.util.UUID; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.SweepNumber; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.keyword.SweepEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.TokenPredicate; + +/** + * + * @author spjspj + */ +public class ParadoxicalOutcome extends CardImpl { + + public ParadoxicalOutcome(UUID ownerId) { + super(ownerId, 60, "Paradoxical Outcome", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{3}{U}"); + this.expansionSetCode = "KLD"; + + // Return any number of target nonland, nontoken permanents you control to their owners' hands. Draw a card for each card returned to your hand this way. + FilterPermanent filter = new FilterControlledPermanent(new StringBuilder("any number of of target nonland, nontoken permanents you control").toString()); + filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); + filter.add(Predicates.not(new TokenPredicate())); + + this.getSpellAbility().addEffect(new SweepEffect(filter, "nonland, nontoken permanents ")); + DynamicValue paradoxicalOutcomeValue = new SweepNumber("nonland, nontoken permanents ", false); + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(paradoxicalOutcomeValue)); + } + + public ParadoxicalOutcome(final ParadoxicalOutcome card) { + super(card); + } + + @Override + public ParadoxicalOutcome copy() { + return new ParadoxicalOutcome(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java index 229b7d8bea1..dc047692ebc 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java @@ -32,6 +32,7 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.CardsImpl; import mage.constants.Outcome; import mage.constants.Zone; +import mage.filter.Filter; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.predicate.mageobject.SubtypePredicate; @@ -48,16 +49,27 @@ import mage.util.CardUtil; public class SweepEffect extends OneShotEffect { private final String sweepSubtype; + private FilterPermanent setFilter = null; public SweepEffect(String sweepSubtype) { super(Outcome.Benefit); this.sweepSubtype = sweepSubtype; this.staticText = "Sweep - Return any number of " + sweepSubtype + (sweepSubtype.endsWith("s") ? "" : "s") + " you control to their owner's hand"; } + + public SweepEffect(FilterPermanent filter, String text) { + super(Outcome.Benefit); + this.sweepSubtype = text; + this.staticText = "Return any number of " + text + " you control to their owner's hand"; + this.setFilter = filter; + } + + public SweepEffect(final SweepEffect effect) { super(effect); this.sweepSubtype = effect.sweepSubtype; + this.setFilter = effect.setFilter; } @Override @@ -69,8 +81,14 @@ public class SweepEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - FilterPermanent filter = new FilterControlledLandPermanent(new StringBuilder("any number of ").append(sweepSubtype).append("s you control").toString()); - filter.add(new SubtypePredicate(sweepSubtype)); + FilterPermanent filter; + if (setFilter == null) { + filter = new FilterControlledLandPermanent(new StringBuilder("any number of ").append(sweepSubtype).append("s you control").toString()); + filter.add(new SubtypePredicate(sweepSubtype)); + } else { + filter = setFilter; + } + Target target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); if (controller.chooseTarget(outcome, target, source, game)) { game.getState().setValue(CardUtil.getCardZoneString("sweep", source.getSourceId(), game), target.getTargets().size()); From 1c49100d7505e69a8e0c251020471457e379e634 Mon Sep 17 00:00:00 2001 From: spjspj Date: Thu, 8 Sep 2016 17:31:42 +1000 Subject: [PATCH 09/12] spjspj - Implement Paradoxical Outcome (KLD) - shroud wasn't being followed --- Mage.Sets/src/mage/sets/kaladesh/ParadoxicalOutcome.java | 2 +- .../java/mage/abilities/effects/keyword/SweepEffect.java | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/ParadoxicalOutcome.java b/Mage.Sets/src/mage/sets/kaladesh/ParadoxicalOutcome.java index 6c36ba2842a..d03487a6fe8 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/ParadoxicalOutcome.java +++ b/Mage.Sets/src/mage/sets/kaladesh/ParadoxicalOutcome.java @@ -56,7 +56,7 @@ public class ParadoxicalOutcome extends CardImpl { filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); filter.add(Predicates.not(new TokenPredicate())); - this.getSpellAbility().addEffect(new SweepEffect(filter, "nonland, nontoken permanents ")); + this.getSpellAbility().addEffect(new SweepEffect(filter, "nonland, nontoken permanents ", false)); DynamicValue paradoxicalOutcomeValue = new SweepNumber("nonland, nontoken permanents ", false); this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(paradoxicalOutcomeValue)); } diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java index dc047692ebc..f46f6b7f2cf 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java @@ -50,6 +50,7 @@ public class SweepEffect extends OneShotEffect { private final String sweepSubtype; private FilterPermanent setFilter = null; + private boolean notTarget = true; public SweepEffect(String sweepSubtype) { super(Outcome.Benefit); @@ -57,11 +58,12 @@ public class SweepEffect extends OneShotEffect { this.staticText = "Sweep - Return any number of " + sweepSubtype + (sweepSubtype.endsWith("s") ? "" : "s") + " you control to their owner's hand"; } - public SweepEffect(FilterPermanent filter, String text) { + public SweepEffect(FilterPermanent filter, String text, boolean notTarget) { super(Outcome.Benefit); this.sweepSubtype = text; this.staticText = "Return any number of " + text + " you control to their owner's hand"; this.setFilter = filter; + this.notTarget = notTarget; } @@ -70,6 +72,7 @@ public class SweepEffect extends OneShotEffect { super(effect); this.sweepSubtype = effect.sweepSubtype; this.setFilter = effect.setFilter; + this.notTarget = effect.notTarget; } @Override @@ -89,7 +92,7 @@ public class SweepEffect extends OneShotEffect { filter = setFilter; } - Target target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); + Target target = new TargetPermanent(0, Integer.MAX_VALUE, filter, notTarget); if (controller.chooseTarget(outcome, target, source, game)) { game.getState().setValue(CardUtil.getCardZoneString("sweep", source.getSourceId(), game), target.getTargets().size()); controller.moveCards(new CardsImpl(target.getTargets()), Zone.HAND, source, game); From 0af787180497bc39a85729bd27e183ae2ca5824b Mon Sep 17 00:00:00 2001 From: emerald000 Date: Thu, 8 Sep 2016 09:09:32 -0400 Subject: [PATCH 10/12] TestPlayer should not scry down cards at the start of the game. --- Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 5ede5fff409..87aa6bd6611 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -2118,6 +2118,10 @@ public class TestPlayer implements Player { @Override public boolean scry(int value, Ability source, Game game) { + // Don't scry at the start of the game. + if (game.getTurnNum() == 1 && game.getStep() == null) { + return false; + } return computerPlayer.scry(value, source, game); } From 21baa144046c77b77405d0579b5895d1fc5d1ec1 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 8 Sep 2016 17:15:40 +0200 Subject: [PATCH 11/12] * Fixed a problem with token P/T reset (fixes the problem with Tree of Perdition and Soul Separator). --- Mage.Sets/src/mage/sets/eldritchmoon/SoulSeparator.java | 6 +++--- .../common/PutTokenOntoBattlefieldCopyTargetEffect.java | 4 ++-- Mage/src/main/java/mage/game/permanent/PermanentToken.java | 7 +++++-- Mage/src/main/java/mage/players/Library.java | 2 -- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/SoulSeparator.java b/Mage.Sets/src/mage/sets/eldritchmoon/SoulSeparator.java index 96577bcd9d3..811755bf5ff 100644 --- a/Mage.Sets/src/mage/sets/eldritchmoon/SoulSeparator.java +++ b/Mage.Sets/src/mage/sets/eldritchmoon/SoulSeparator.java @@ -57,8 +57,8 @@ public class SoulSeparator extends CardImpl { super(ownerId, 199, "Soul Separator", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{3}"); this.expansionSetCode = "EMN"; - // {5}, {T}, Sacrifice Soul Separator: Exile target creature card from your graveyard. - // Put a token onto the battlefield that's a copy of that card except it's 1/1, it's a Spirit in addition to its other types, and it has flying. + // {5}, {T}, Sacrifice Soul Separator: Exile target creature card from your graveyard. + // Put a token onto the battlefield that's a copy of that card except it's 1/1, it's a Spirit in addition to its other types, and it has flying. // Put a black Zombie creature token onto the battlefield with power equal to that card's power and toughness equal that card's toughness. PutTokenOntoBattlefieldCopyTargetEffect copyEffect = new PutTokenOntoBattlefieldCopyTargetEffect(null, null, false, 1, false, false, null, 1, 1, true); copyEffect.setAdditionalSubType("Spirit"); @@ -85,7 +85,7 @@ class SoulSeparatorEffect extends OneShotEffect { public SoulSeparatorEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "Put a black Zombie creature token onto the battlefield with power equal to that card's power and toughness equal that card's toughness."; + this.staticText = "Put a black Zombie creature token onto the battlefield with power equal to that card's power and toughness equal that card's toughness"; } public SoulSeparatorEffect(final SoulSeparatorEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutTokenOntoBattlefieldCopyTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutTokenOntoBattlefieldCopyTargetEffect.java index 43d7439afbd..0a55983042f 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PutTokenOntoBattlefieldCopyTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PutTokenOntoBattlefieldCopyTargetEffect.java @@ -193,10 +193,10 @@ public class PutTokenOntoBattlefieldCopyTargetEffect extends OneShotEffect { token.addAbility(FlyingAbility.getInstance()); } if (tokenPower != Integer.MIN_VALUE) { - token.setPower(tokenPower); + token.getPower().modifyBaseValue(tokenPower); } if (tokenToughness != Integer.MIN_VALUE) { - token.setToughness(tokenToughness); + token.getToughness().modifyBaseValue(tokenToughness); } if (additionalSubType != null && !token.getSubtype(game).contains(additionalSubType)) { token.getSubtype(game).add(additionalSubType); diff --git a/Mage/src/main/java/mage/game/permanent/PermanentToken.java b/Mage/src/main/java/mage/game/permanent/PermanentToken.java index 7c730b61fab..921140e32f7 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentToken.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentToken.java @@ -49,6 +49,8 @@ public class PermanentToken extends PermanentImpl { this.token = token.copy(); this.token.getAbilities().newId(); // neccessary if token has ability like DevourAbility() this.token.getAbilities().setSourceId(objectId); + this.power.modifyBaseValue(token.getPower().getBaseValueModified()); + this.toughness.modifyBaseValue(token.getToughness().getBaseValueModified()); this.copyFromToken(this.token, game, false); // needed to have at this time (e.g. for subtypes for entersTheBattlefield replacement effects) } @@ -62,6 +64,9 @@ public class PermanentToken extends PermanentImpl { public void reset(Game game) { copyFromToken(token, game, true); super.reset(game); + // Because the P/T objects have there own base value for reset we have to take it from there instead of from the basic token object + this.power.resetToBaseValue(); + this.toughness.resetToBaseValue(); } private void copyFromToken(Token token, Game game, boolean reset) { @@ -84,8 +89,6 @@ public class PermanentToken extends PermanentImpl { this.color = token.getColor(game).copy(); this.frameColor = token.getFrameColor(game); this.frameStyle = token.getFrameStyle(); - this.power.modifyBaseValue(token.getPower().getBaseValueModified()); - this.toughness.modifyBaseValue(token.getToughness().getBaseValueModified()); this.supertype = token.getSupertype(); this.subtype = token.getSubtype(game); this.tokenDescriptor = token.getTokenDescriptor(); diff --git a/Mage/src/main/java/mage/players/Library.java b/Mage/src/main/java/mage/players/Library.java index 157a986bba6..f8a4d2bae4b 100644 --- a/Mage/src/main/java/mage/players/Library.java +++ b/Mage/src/main/java/mage/players/Library.java @@ -38,7 +38,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Random; import java.util.Set; import java.util.UUID; import mage.cards.Card; @@ -53,7 +52,6 @@ import mage.util.RandomUtil; */ public class Library implements Serializable { - private boolean emptyDraw; private final Deque library = new ArrayDeque<>(); private final UUID playerId; From aaab087c913b1bd9c6342043092c64c0e866c63d Mon Sep 17 00:00:00 2001 From: fireshoes Date: Thu, 8 Sep 2016 10:39:07 -0500 Subject: [PATCH 12/12] [KLD] Updated mtg-cards-data.txt with 9/8 spoilers. --- Utils/mtg-cards-data.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index d770dbac957..4f69079509f 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -29657,11 +29657,13 @@ Hanweir Battlements|Eldritch Moon|204|R||Land|||{T}: Add {C} to your mana pool.$ Nephalia Academy|Eldritch Moon|205|U||Land|||If a spell or ability an opponent controls causes you to discard a card, you may reveal that card and put it on top of your library instead of putting it anywhere else.${T}: Add {C} to your mana pool.| Aerial Responder|Kaladesh|2|U|{1}{W}{W}|Creature - Dwarf Soldier|2|3|Flying, vigilance, lifelink| Aetherstorm Roc|Kaladesh|3|R|{2}{W}{W}|Creature - Bird|3|3|Flying$Whenever Aetherstorm Roc or another creature enters the battlefield under your control, you get {E} (an energy counter).$Whenever Aetherstorm Roc attacks, you may pay {E}{E}. If you do, put a +1/+1 creature on it and tap up to one target creature defending player controls.| +Angel of Invention|Kaladesh|4|M|{3}{W}{W}|Creature - Angel|2|1|Flying, vigilance, lifelink$Fabricate 2 (When this creature enters the battlefield, put two +1/+1 counters on it or create two 1/1 colorless Servo artifact creature tokens.)$Other creatures you control get +1/+1.| Cataclysmic Gearhulk|Kaladesh|9|M|{3}{W}{W}|Artifact Creature - Construct|4|5|Vigilance$When Cataclysmic Gearhulk enters the battlefield, each player chooses from among the non-land permanents he or she controls an artifact, a creature, an enchantment, and a planeswalker, then sacrifices the rest.| Glint-Sleeve Artisan|Kaladesh|17|C|{2}{W}|Creature - Dwarf Artificer|2|2|Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| Master Trinketcrafter|Kaladesh|21|R|{2}{W}|Creature - Dwarf Artificer|3|2|Servo and Thopter creatures you control get +1/+1.${3}{W}: Create a 1/1 colorless Servo artifact creature token.| Propeller Pioneer|Kaladesh|24|C|{3}{W}|Creature - Human Artificer|2|1|Flying$Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| Tasseled Dromedary|Kaladesh|30|C|{W}|Creature - Camel|0|4|| +Thriving Ibex|Kaladesh|31|C|{3}{W}|Creature - Goat|2|4|When Thriving Ibex enters the battlefield, you get {E}{E} (two energy counters).$Whenever Thriving Ibex attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it.| Wispweaver Angel|Kaladesh|35|U|{4}{W}{W}|Creature - Angel|4|4|Flying$When Wispweaver Angel enters the battlefield, you may exile another target creature you control, then return that card to the battlefield under its owner's control.| Aether Tradewinds|Kaladesh|38|C|{2}{U}|Instant|||Return target permanent you control and target permanent you don't control to their owners' hands.| Ceremonious Rejection|Kaladesh|40|U|{U}|Instant|||Counter target colorless spell.| @@ -29669,6 +29671,8 @@ Curio Vendor|Kaladesh|42|C|{1}{U}|Creature - Vedalken|2|1|| Metallurgic Summonings|Kaladesh|56|M|{3}{U}{U}|Enchantment|||Whenever you cast an instant or sorcery spell, create an X/X colorless Construct artifact creature token, where X is that spell's converted mana cost.${3}{U}{U}, Exile Metallurgic Summons: Return all instant and sorcery cards from your graveyard to your hand. Activate this ability only if you control six or more artifacts.| Paradoxical Outcome|Kaladesh|60|R|{3}{U}|Instant|||Return any number of target nonland, nontoken permanents you control to their owners' hands. Draw a card for each card return to your hand this way.| Saheeli's Artistry|Kaladesh|62|R|{4}{U}{U}|Sorcery|||Choose one or both —$• Create a token that's a copy of target artifact.$• Create a token that's a copy of target creature, except that it's an artifact in addition to its other types.| +Shrewd Negotiation|Kaladesh|64|U|{4}{U}|Sorcery|||Exchange control of target artifact you control and target artifact or creature you don't control.| +Thriving Turtle|Kaladesh|66|C|{U}|Creature - Turtle|0|3|When Thriving Turtle enters the battlefield, you get {E}{E} (two energy counters).$Whenever Thriving Turtle attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it.| Torrential Gearhulk|Kaladesh|67|M|{4}{U}{U}|Artifact Creature - Construct|5|6|Flash$When Torrential Gearhulk enters the battlefield, you may cast target instant card from your graveyard without paying its mana cost. If that card would be put into your graveyard this turn, exile it instead.| Demon of Dark Schemes|Kaladesh|73|M|{3}{B}{B}{B}|Creature - Demon|5|5|Flying$When Demon of Dark Schemes enters the battlefield, all other creatures get -2/-2 until end of turn.$Whenever another creature dies, you get {E} (an energy counter).${2}{B}, Pay {E}{E}{E}{E}: Put target creature card from a graveyard onto the battlefiend tapped under your control.| Die Young|Kaladesh|76|C|{1}{B}|Sorcery|||Choose target creature. You get {E}{E} (two energy counters), then you may pay any amount of {E}. The creature gets -1/-1 until end of turn for each {E} paid this way.| @@ -29676,12 +29680,15 @@ Essence Extraction|Kaladesh|80|U|{1}{B}{B}|Instant|||Essence Extraction deals 3 Fortuitous Find|Kaladesh|81|C|{2}{B}|Sorcery|||Choose one or both — Return target artifact card from your graveyard to your hand.; or Return target creature card from your graveyard to your hand.| Gonti, Lord of Luxury|Kaladesh|84|R|{2}{B}{B}|Legendary Creature - Aetherborn Rogue|2|3|Deathtouch$When Gonti, Lord of Luxury enters the battlefield, look at the top four cards of target opponent's library, exile one of them face down, then put the rest on the bottom of that library in a random order. For as long as that card remains exiled, you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it.| Live Fast|Kaladesh|87|C|{2}{B}|Sorcery|||You draw two cards, lose 2 life, and gain {E}{E} (two energy counters).| +Lost Legacy|Kaladesh|88|R|{1}{B}{B}|Sorcery|||Name a nonartifact, nonland card. Search target player's graveyard, hand, and library for any number of cards with that name and exile them. That player shuffles his or her library, then draws a card for each card exiled from hand this way.| Morbid Curiosity|Kaladesh|94|U|{1}{B}{B}|Sorcery|||As an additional cost to cast Morbid Curiosity, sacrifice an artifact or creature.$Draw cards equal to the converted mana cost of the sacrificed permanent.| Noxious Gearhulk|Kaladesh|96|M|{4}{B}{B}|Artifact Creature - Construct|5|4|Menace$When Noxious Gearhulk enters the battlefield, you may destroy another target creature. If a creature is destroyed this way, you gain life equal to its toughness.| Ovalchase Daredevil|Kaladesh|97|U|{3}{B}|Creature - Human Pilot|4|2|Whenever an artifact enters the battlefield under your control, you may return Ovalchase Daredevil from your graveyard to your hand.| +Thriving Rats|Kaladesh|102|C|{1}{B}|Creature - Rat|1|2|When Thriving Rats enters the battlefield, you get {E}{E} (two energy counters(.$Whenever Thriving Rats attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it.| Chandra, Torch of Defiance|Kaladesh|110|M|{2}{R}{R}|Planeswalker - Chandra|||+1: Exile the top card of your library. You may cast that card. If you don't, Chandra, Torch of Defiance deals 2 damage to each opponent.$+1: Add {R}{R} to your mana pool.$-3: Chandra, Torch of Defiance deals 4 damage to target creature.$-7: You get an emblem with "Whenever you cast a spell, this emblem deals 5 damage to target creature or player."| Furious Reprisal|Kaladesh|115|U|{3}{R}|Sorcery|||Furious Reprisal deals 2 damage to each of two target creatures and/or players.| Harnessed Lightning|Kaladesh|117|U|{1}{R}|Instant|||Choose target creature. You get {E}{E}{E} (three energy counters), then you may pay any amount of {E}. Harnessed Lightning deals that much damage to that creature.| +Incendiary Sabotage|Kaladesh|119|U|{2}{R}{R}|Instant|||As an additional cost to cast Incendiary Sabotage, sacrifice an artifact.$Incendiary Sabotage deals 3 damage to each creature.| Lathnu Hellion|Kaladesh|121|R|{2}{R}|Creature - Hellion|4|4|Haste$When Lathnu Hellion enters the battlefield, you get {E}{E} (two energy counters).$At the beginning of your end step, sacrifice Lathnu Hellion unless you pay {E}{E}.| Madcap Experiment|Kaladesh|122|R|{3}{R}|Sorcery|||Reveal cards from the top of your library until you reveal an artifact card. Put that card onto the battlefield and the rest on the bottom of your library in a random order. Madcap Experiment deals damage to you equal to the number of cards revealed this way.| Pia Nalaar|Kaladesh|124|R|{2}{R}|Legendary Creature - Human Artificer|2|2|When Pia Nalaar enters the battlefield, create a 1/1 colorless Thopter artifact creature token with flying.${1}{R}: Target artifact creature gets +1/+0 until end of turn.${1}, Sacrifice an artifact: Target creature can't block this turn.| @@ -29690,6 +29697,7 @@ Speedway Fanatic|Kaladesh|132|U|{1}{R}|Creature - Human Pilot|2|1|Haste$Whenever Start Your Engines|Kaladesh|135|U|{3}{R}|Sorcery|||Vehicles you control becomes artifact creatures until end of turn. Creatures you control get +2/+0 until end of turn.| Territorial Devourer|Kaladesh|136|R|{3}{R}|Creature - Gremlin|2|2|Trample $Whenever you gain one or more {E} (energy counters), Territorial Devourer gets +2/+2 until end of turn.| Terror of the Fairgrounds|Kaladesh|137|C|{3}{R}|Creature - Gremlin|5|2|| +Thriving Grubs|Kaladesh|138|C|{1}{R}|Creature - Gremlin|2|1|When Thriving Grubs enters the battlefield, you get {E}{E} (two energy counters).$Whenever Thriving Grubs attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it.| Arborback Stomper|Kaladesh|142|U|{3}{G}{G}|Creature - Beast|5|4|Trample$When Arborback Stomper enters the battlefield, you gain 5 life.| Architect of the Untamed|Kaladesh|143|R|{2}{G}|Creature - Elf Artificer Druid|2|3|Whenever a land enters the battlefiend under your control, you get {E} (an energy counter).$Pay {E}{E}{E}{E}{E}{E}{E}{E}: Create a 6/6 colorless Beast artifact creature token.| Armorcraft Judge|Kaladesh|144|U|{3}{G}|Creature - Elf Artificer|3|3|When Armorcraft Judge enters the battlefield, draw a card for each creature you control with a +1/+1 counter on it.| @@ -29699,8 +29707,11 @@ Ghirapur Guide|Kaladesh|156|U|{2}{G}|Creature - Elf Scout|3|2|{2}{G}: Target cre Larger Than Life|Kaladesh|160|C|{1}{G}|Sorcery|||Target creature gets +4/+4 and gains trample until end of turn.| Longtusk Cub|Kaladesh|161|U|{1}{G}|Creature - Cat|2|2|Whenever Longtusk Cub deals combat damage to a player, you get {E}{E} (two energy counters).$Pay {E}{E}: Put a +1/+1 counter on Longtusk Cub.| Nissa, Vital Force|Kaladesh|163|M|{3}{G}{G}|Planeswalker - Nissa|||+1: Untap target land you control. Until your next turn, it becomes a 5/5 Elemental creature with haste. It's still a land.$-3: Return target permanent card from your graveyard to your hand.$-6: You get an emblem with "Whenever a land enters the battlefield under your control, you may draw a card."| +Thriving Rhino|Kaladesh|171|C|{2}{G}|Creature - Rhino|2|3|When Thriving Rhino enters the battlefield, you get {E}{E} (two energy counters).$Whenever Thriving Rhino attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it.| Verdurous Gearhulk|Kaladesh|172|M|{3}{G}{G}|Artifact Creature - Construct|4|4|Trample$When Verdurous Gearhulk enters the battlefield, distribute four +1/+1 counters among any number of target creatures you control.| +Wildest Dreams|Kaladesh|174|R|{X}{X}{G}|Sorcery|||Return X target cards from your graveyard to your hand.$Exile Wildest Dreams.| Depala, Pilot Exemplar|Kaladesh|178|R|{1}{R}{W}|Legendary Creature - Dwarf Pilot|3|3|Other Dwarves you control get +1/+1.$Each Vehicle you control gets +1/+1 as long as it's a creature.$Whenever Depala, Pilot Exemplar becomes tapped, you may pay {X}. If you do, reveal the top X cards of your library, put all Dwarf and Vehicle cards from among them into your hand, then put the rest on the bottom of your library in a random order.| +Kambal, Consul of Allocation|Kaladesh|183|R|{1}{W}{B}|Legendary Creature - Human Advisor|2|3|Whenever an opponent casts a noncreature spell, that player loses 2 life and you gain 2 life.| Rashmi, Eternities Crafter|Kaladesh|184|M|{2}{G}{U}|Legendary Creature - Elf Druid|2|3|Whenever you cast your first spell each turn, reveal the top card of your library. If it's a nonland card with converted mana cost less than that spell's, you may cast it without paying its mana cost. If you don't cast the revealed card, put it into your hand. | Saheeli Rai|Kaladesh|186|M|{1}{U}{R}|Planeswalker - Saheeli|3|+1: Scry 1. Saheeli Rai deals 1 damage to each opponent.$-2: Create a token that's a copy of target artifact or creature you control, except it's an artifact in addition to its other types. That token gains haste. Exile it at the beginning of the next end step.$-7: Search your library for up to three artifact cards with different names, put them onto the battlefield, then shuffle your library.| Voltaic Brawler|Kaladesh|189|U|{R}{G}|Creature - Human Warrior|3|2|When Voltaic Brawler enters the battlefield, you get {E}{E} (two energy counters).$Whenever Voltaic Brawler attacks, you may pay {E}. If you do, it gets +1/+1 and gains trample until end of turn.| @@ -29709,6 +29720,7 @@ Aetherworks Marvel|Kaladesh|193|M|{4}|Legendary Artifact|||Whenever a permanent Animation Module|Kaladesh|194|R|{1}|Artifact|||Whenever one or more +1/+1 counters are placed on a permanent you control, you may pay {1}. If you do, create a 1/1 colorless Servo artifact creature token.${3}, {T}: Choose a counter on target permanent or player. Give that permanent or player another counter of that kind.| Bomat Bazaar Barge|Kaladesh|198|U|{4}|Artifact - Vehicle|5|5|When Bomat Bazaar Barge enters the battlefield, draw a card.$Crew 3 (Tap any number of creatures you control with total power 3 or more: This Vehicle becomes an artifact creature until end of turn.)| Cogworker's Puzzleknot|Kaladesh|201|C|{2}|Artifact|||When Cogworker's Puzzleknot enters the battlefield, create a 1/1 colorless Servo artifact creature token.${1}{W}, Sacrifice Cogworker's Puzzleknot: Create a 1/1 colorless Servo artifact creature token.| +Cultivator's Caravan|Kaladesh|203|R|{3}|Artifact - Vehicle|5|5|{T}: Add one mana of any color to your mana pool.$Crew 3 (Tap any number of creatures you control with total power 3 or more: This Vehicle becomes an artifact creature until end of turn.)| Decoction Module|Kaladesh|205|U|{2}|Artifact|||Whenever a creature enters the battlefield under your control, you get {E} (an energy counter).${4}, {T}: Return target creature you control to its owner's hand.| Demolition Stomper|Kaladesh|206|U|{6}|Artifact - Vehicle|10|7|Demolition Stomper can't be blocked by creature with power 2 or less.$Crew 5 (Tap any number of creatures you control with total power 5 or more: This Vehicle becomes an artifact creature until end of turn.)| Fabrication Module|Kaladesh|211|U|{3}|Artifact|||Whenever you get one or more {E} (energy counters), put a +1/+1 counter on target creature you control.${4}, {T}: You get {E}.| @@ -29718,6 +29730,7 @@ Fleetwheel Cruiser|Kaladesh|214|R|{4}|Artifact - Vehicle|5|3|Trample, Haste $Wh Ghirapur Orrery|Kaladesh|216|R|{4}|Artifact|||Each player may play an additional land on each of his or her turns.$At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards.| Glassblower's Puzzleknot|Kaladesh|217|C|{2}|Artifact|||When Glassblower's Puzzleknot enters the battlefield, scry 2, then you get {E}{E}. (You get two energy counters. To scry 2, look at the top two cards of you library, then put any number of them on the bottom of your library and the rest on top in any order.)${2}{U}, Sacrifice Glassblower's Puzzleknot: Scry 2, then you get {E}{E}.| Inventor's Goggles|Kaladesh|218|C|{1}|Artifact - Equipment|||Equipped creature gets +1/+2.$Whenever an Artificer enters the battlefield under your control, you may attach Inventor's Goggles to it.$Equip {2} ({2}: Attach to target creature you control. Equip only as a sorcery)| +Key to the City|Kaladesh|220|R|{2}|Artifact|||{T}, Discard a card: Up to one target creature can't be blocked this turn.$Whenever Key to the City becomes untapped, you may pay {2}. If you do, draw a card.| Metalspinner's Puzzleknot|Kaladesh|221|C|{2}|Artifact|||When Metalspinner's Puzzleknot enters the battlefield, you draw a card and you lose 1 life.${2}{B}, Sacrifice Metalspinner's Puzzleknot: You draw a card and you lose 1 life.| Ovalchase Dragster|Kaladesh|225|U|{4}|Artifact - Vehicle|6|1|Trample, haste$Crew 1 (Tap any number of creatures you control with total power 1 or more: This Vehicle becomes an artifact creature until end of turn.)| Panharmonicon|Kaladesh|226|R|{4}|Artifact|||If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.| @@ -29725,6 +29738,7 @@ Sky Skiff|Kaladesh|233|C|{2}|Artifact - Vehicle|2|3|Flying$Crew 1 (Tap any nu Skysovereign, Consul Flagship|Kaladesh|234|M|{5}|Legendary Artifact - Vehicle|6|5|Flying$Whenever Skysovereign, Consul Flagship enters the battlefield or attacks, it deals 3 damage to target creature or planeswalker an opponent controls.$Crew 3 (Tap any number of creatures you control with total power 3 or more: This Vehicle becomes an artifact creature until end of turn.)| Whirlermaker|Kaladesh|239|U|{3}|Artifact|||{4}, {T}: Create a 1/1 colorless Thopter artifact creature token with flying.| Woodweaver's Puzzleknot|Kaladesh|240|C|{2}|Artifact|||When Woodweaver's Puzzleknot enters the battlefield, you gain 3 life and get {E}{E}{E} (three energy counters).${2}{G}, Sacrifice Woodweaver's Puzzleknot: You gain 3 life and get {E}{E}{E}.| +Aether Hub|Kaladesh|242|U||Land|||When Aether Hub enters the battlefield, you get {E} (an energy counter).${T}: Add {C} to your mana pool.${T}, Pay {E}: Add one mana of any color to your mana pool.| Blooming Marsh|Kaladesh|243|R||Land|||Blooming Marsh enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {B} or {G} to your mana pool.| Botanical Sanctum|Kaladesh|244|R||Land|||Botanical Sanctum enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {G} or {U} to your mana pool.| Concealed Courtyard|Kaladesh|245|R||Land|||Concealed Courtyard enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {W} or {B} to your mana pool.|