diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java index 9e71fb1ab88..dac76f4ed1a 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java @@ -6,7 +6,7 @@ package org.mage.plugins.card.dl.sources; */ public interface CardImageSource { - String generateURL(Integer collectorId, String cardName, String cardSet, boolean twoFacedCard, boolean secondFace, boolean isFlipCard, boolean flippedView) throws Exception; + String generateURL(Integer collectorId, String cardName, String cardSet, boolean twoFacedCard, boolean secondFace, boolean isFlipCard, boolean isSplitCard, boolean flippedView) throws Exception; String generateTokenUrl(String name, String set); Float getAverageSize(); } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java index 00de2ec4477..29211a86f61 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java @@ -63,7 +63,7 @@ public class MagicCardsImageSource implements CardImageSource { } @Override - public String generateURL(Integer collectorId, String cardName, String cardSet, boolean twoFacedCard, boolean secondSide, boolean isFlipCard, boolean flippedView) throws Exception { + public String generateURL(Integer collectorId, String cardName, String cardSet, boolean twoFacedCard, boolean secondSide, boolean isFlipCard, boolean isSplitCard, boolean flippedView) throws Exception { if (collectorId == null || cardSet == null) { throw new Exception("Wrong parameters for image: collector id: " + collectorId + ",card set: " + cardSet); } @@ -74,6 +74,9 @@ public class MagicCardsImageSource implements CardImageSource { if (twoFacedCard) { url.append(secondSide ? "b" : "a"); } + if (isSplitCard) { + url.append("a"); + } if (isFlipCard) { if (flippedView) { // download rotated by 180 degree image url.append("b"); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java index 13c39869e68..3ec91d028e8 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java @@ -93,7 +93,7 @@ public class WizardCardsImageSource implements CardImageSource { } @Override - public String generateURL(Integer collectorId, String cardName, String cardSet, boolean twoFacedCard, boolean secondSide, boolean isFlipCard, boolean flippedView) throws Exception { + public String generateURL(Integer collectorId, String cardName, String cardSet, boolean twoFacedCard, boolean secondSide, boolean isFlipCard, boolean isSplitCard, boolean flippedView) throws Exception { if (collectorId == null || cardSet == null) { throw new Exception("Wrong parameters for image: collector id: " + collectorId + ",card set: " + cardSet); } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/CardInfo.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/CardInfo.java index 7f6e4364c5e..4c76ccd8e6e 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/CardInfo.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/CardInfo.java @@ -16,6 +16,7 @@ public class CardInfo { private boolean secondSide; private boolean flipCard; private boolean flippedSide; + private boolean splitCard; private boolean usesVariousArt; public CardInfo(String name, String set, Integer collectorId, boolean usesVariousArt, Integer type) { @@ -147,6 +148,14 @@ public class CardInfo { this.flipCard = flipCard; } + public boolean isSplitCard() { + return splitCard; + } + + public void setSplitCard(boolean splitCard) { + this.splitCard = splitCard; + } + public Integer getType() { return type; } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java index b6f6b3e8433..44c4894a6b4 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java @@ -244,6 +244,9 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab if (card.isFlipCard()) { url.setFlipCard(true); } + if (card.isSplitCard()) { + url.setSplitCard(true); + } allCardsUrls.add(url); if (card.canTransform()) { // add second side for downloading @@ -417,7 +420,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab url = cardImageSource.generateTokenUrl(card.getName(), card.getSet()); } else { url = cardImageSource.generateURL(card.getCollectorId(), card.getDownloadName(), card.getSet(), - card.isTwoFacedCard(), card.isSecondSide(), card.isFlipCard(), card.isFlippedSide()); + card.isTwoFacedCard(), card.isSecondSide(), card.isFlipCard(), card.isSplitCard(), card.isFlippedSide()); } if (url != null) { diff --git a/Mage/src/mage/abilities/keyword/FuseAbility.java b/Mage/src/mage/abilities/keyword/FuseAbility.java new file mode 100644 index 00000000000..98bfc5d4c13 --- /dev/null +++ b/Mage/src/mage/abilities/keyword/FuseAbility.java @@ -0,0 +1,66 @@ +/* +* 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.keyword; + +import mage.Constants.Zone; +import mage.abilities.SpellAbility; +import mage.abilities.costs.mana.ManaCosts; +import mage.cards.Card; + +/** + * + * @author LevelX2 + */ + +public class FuseAbility extends SpellAbility { + + public FuseAbility(Card card, ManaCosts costs) { + super(costs, "fused " + card.getName(), Zone.HAND); + } + + public FuseAbility(final FuseAbility ability) { + super(ability); + } + + @Override + public FuseAbility copy() { + return new FuseAbility(this); + } + + @Override + public String getRule(boolean all) { + return getRule(); + } + + @Override + public String getRule() { + return "Fuse (You may cast one or both halves of this card from your hand.)"; + } + +} diff --git a/Mage/src/mage/cards/Card.java b/Mage/src/mage/cards/Card.java index d88ff3b4213..b313221ec41 100644 --- a/Mage/src/mage/cards/Card.java +++ b/Mage/src/mage/cards/Card.java @@ -63,6 +63,7 @@ public interface Card extends MageObject { boolean isFaceDown(); boolean isFlipCard(); String getFlipCardName(); + boolean isSplitCard(); boolean canTransform(); Card getSecondCardFace(); diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index 452ea67194b..859b78c7497 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.java @@ -72,6 +72,7 @@ public abstract class CardImpl> extends MageObjectImpl protected Map info; protected boolean usesVariousArt = false; protected Counters counters; + protected boolean splitCard; public CardImpl(UUID ownerId, int cardNumber, String name, Rarity rarity, CardType[] cardTypes, String costs) { this(ownerId, name); @@ -123,7 +124,10 @@ public abstract class CardImpl> extends MageObjectImpl info = new HashMap(); info.putAll(card.info); } - usesVariousArt = card.usesVariousArt; + this.flipCard = card.flipCard; + this.flipCardName = card.flipCardName; + this.splitCard = card.splitCard; + this.usesVariousArt = card.usesVariousArt; this.counters = card.counters.copy(); } @@ -499,6 +503,11 @@ public abstract class CardImpl> extends MageObjectImpl return flipCard; } + @Override + public boolean isSplitCard() { + return splitCard; + } + @Override public String getFlipCardName() { return flipCardName; diff --git a/Mage/src/mage/cards/SplitCard.java b/Mage/src/mage/cards/SplitCard.java new file mode 100644 index 00000000000..3a3e85c5709 --- /dev/null +++ b/Mage/src/mage/cards/SplitCard.java @@ -0,0 +1,260 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.cards; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.Constants.Zone; +import mage.abilities.Abilities; +import mage.abilities.AbilitiesImpl; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.keyword.FuseAbility; +import mage.game.Game; +import mage.watchers.Watcher; + +/** + * + * @author LevelX2 + */ + +public abstract class SplitCard> extends CardImpl { + + public enum ActiveCardHalve { + NONE, LEFT, RIGHT + } + private Card leftHalveCard; + private Card rightHalveCard; + + private ActiveCardHalve activeCardHalve = ActiveCardHalve.NONE; + + public SplitCard(UUID ownerId, int cardNumber, String name, Rarity rarity, CardType[] cardTypes, String costs) { + super(ownerId, cardNumber, name, rarity, cardTypes, costs); + this.splitCard = true; + } + + public SplitCard(SplitCard card) { + super(card); + this.leftHalveCard = card.leftHalveCard; + this.rightHalveCard = card.rightHalveCard; + this.activeCardHalve = card.activeCardHalve; + } + + public Card createLeftHalveCard (String name, String costs) { + CardType[] cardTypes = new CardType[getCardType().size()]; + this.getCardType().toArray(cardTypes); + leftHalveCard = new leftHalveCard(this.getOwnerId(), this.getCardNumber(), name, this.rarity, cardTypes, costs); + leftHalveCard.getAbilities().setSourceId(objectId); + return leftHalveCard; + } + + public Card createRightHalveCard (String name, String costs) { + CardType[] cardTypes = new CardType[getCardType().size()]; + this.getCardType().toArray(cardTypes); + rightHalveCard = new leftHalveCard(this.getOwnerId(), this.getCardNumber(), name, this.rarity, cardTypes, costs); + rightHalveCard.getAbilities().setSourceId(objectId); + return rightHalveCard; + } + + public Card getLeftHalveCard () { + return leftHalveCard; + } + + public Card getRightHalveCard () { + return rightHalveCard; + } + + public ActiveCardHalve getActiveCardHalve() { + return activeCardHalve; + } + + @Override + public boolean cast(Game game, Constants.Zone fromZone, SpellAbility ability, UUID controllerId) { + if (super.cast(game, fromZone, ability, controllerId)) { + if (leftHalveCard.getAbilities().contains(ability)) { + activeCardHalve = ActiveCardHalve.LEFT; + } else if (rightHalveCard.getAbilities().contains(ability)) { + activeCardHalve = ActiveCardHalve.RIGHT; + } else { + activeCardHalve = ActiveCardHalve.NONE; + } + return true; + } + return false; + } + + @Override + public boolean moveToZone(Constants.Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList appliedEffects) { + if (super.moveToZone(toZone, sourceId, game, flag, appliedEffects)) { + if (!toZone.equals(Zone.STACK)) { + activeCardHalve = ActiveCardHalve.NONE; + } + return true; + } + return false; + } + + @Override + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList appliedEffects) { + if(super.moveToExile(exileId, name, sourceId, game, appliedEffects)) { + activeCardHalve = ActiveCardHalve.NONE; + return true; + } + return false; + } + + @Override + public Abilities getAbilities(){ + Abilities allAbilites = new AbilitiesImpl(); + if (activeCardHalve.equals(ActiveCardHalve.NONE) || activeCardHalve.equals(ActiveCardHalve.LEFT)) { + allAbilites.addAll(leftHalveCard.getAbilities()); + } + if (activeCardHalve.equals(ActiveCardHalve.NONE) || activeCardHalve.equals(ActiveCardHalve.RIGHT)) { + allAbilites.addAll(rightHalveCard.getAbilities()); + } + for (Ability ability: super.getAbilities()) { + if (ability instanceof FuseAbility) { + allAbilites.add(ability); + } + } + return allAbilites; + } + + @Override + public SpellAbility getSpellAbility() { + switch (activeCardHalve) { + case LEFT: + return leftHalveCard.getSpellAbility(); + case RIGHT: + return rightHalveCard.getSpellAbility(); + } + return null; + } + + @Override + public List getRules() { + List rules = new ArrayList(); + if (activeCardHalve.equals(ActiveCardHalve.NONE) || activeCardHalve.equals(ActiveCardHalve.LEFT)) { + rules.add(new StringBuilder("").append(leftHalveCard.getName()).append("").toString()); + rules.addAll(leftHalveCard.getRules()); + } + if (activeCardHalve.equals(ActiveCardHalve.NONE)) { + rules.add("
"); + } + if (activeCardHalve.equals(ActiveCardHalve.NONE) || activeCardHalve.equals(ActiveCardHalve.RIGHT)) { + rules.add(new StringBuilder("").append(rightHalveCard.getName()).append("").toString()); + rules.addAll(rightHalveCard.getRules()); + } + + for (Ability ability: super.getAbilities()) { + if (ability instanceof FuseAbility) { + rules.add("
------------------------------------------------------------"); + rules.add(ability.getRule()); + } + } + return rules; + } + + @Override + public void setControllerId(UUID controllerId) { + abilities.setControllerId(controllerId); + leftHalveCard.getAbilities().setControllerId(controllerId); + rightHalveCard.getAbilities().setControllerId(controllerId); + } + + @Override + public void setOwnerId(UUID ownerId) { + this.ownerId = ownerId; + abilities.setControllerId(ownerId); + leftHalveCard.getAbilities().setControllerId(ownerId); + leftHalveCard.setOwnerId(ownerId); + rightHalveCard.getAbilities().setControllerId(ownerId); + rightHalveCard.setOwnerId(ownerId); + + } + + @Override + public List getWatchers() { + List allWatchers = new ArrayList(); + switch (activeCardHalve) { + case LEFT: + allWatchers.addAll(leftHalveCard.getWatchers()); + break; + case RIGHT: + allWatchers.addAll(rightHalveCard.getWatchers()); + break; + } + return allWatchers; + } + + + +} + +/* + * The left side card of the split card + */ +class leftHalveCard extends CardImpl { + + public leftHalveCard(UUID ownerId, int cardNumber, String name, Rarity rarity, CardType[] cardTypes, String costs) { + super(ownerId, cardNumber, name, rarity, cardTypes, costs); + } + + public leftHalveCard(final leftHalveCard card) { + super(card); + } + + @Override + public leftHalveCard copy() { + return new leftHalveCard(this); + } +} + +/* + * The right side card of the split card + */ +class rightHalveCard extends CardImpl { + + public rightHalveCard(UUID ownerId, int cardNumber, String name, Rarity rarity, CardType[] cardTypes, String costs) { + super(ownerId, cardNumber, name, rarity, cardTypes, costs); + } + + public rightHalveCard(final rightHalveCard card) { + super(card); + } + + @Override + public rightHalveCard copy() { + return new rightHalveCard(this); + } +} diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 9d533039b23..d0cdc8cc8a9 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -337,6 +337,11 @@ public class Spell> implements StackObject, Card { return null; } + @Override + public boolean isSplitCard() { + return false; + } + @Override public boolean canTransform() { return false;