From d6f50aba14f68ac19150d09c4389d20606690e01 Mon Sep 17 00:00:00 2001 From: Sol Date: Fri, 1 Mar 2013 14:17:30 +0000 Subject: [PATCH 01/19] Recreating SplitCards branch since Agetian is having issues merging it From 9fd3aec1c5642376cb5d92f8795b8027fb95e388 Mon Sep 17 00:00:00 2001 From: Agetian Date: Sun, 3 Mar 2013 12:22:45 +0000 Subject: [PATCH 02/19] - Modifications to the combined split card face generation code. --- .../java/forge/card/cardfactory/CardFactory.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/forge/card/cardfactory/CardFactory.java b/src/main/java/forge/card/cardfactory/CardFactory.java index fbbe564cbda..1b37e77dff8 100644 --- a/src/main/java/forge/card/cardfactory/CardFactory.java +++ b/src/main/java/forge/card/cardfactory/CardFactory.java @@ -31,6 +31,7 @@ import forge.Color; import forge.card.CardRules; import forge.card.CardSplitType; import forge.card.ICardFace; +import forge.card.ability.AbilityFactory; import forge.card.cost.Cost; import forge.card.mana.ManaCost; import forge.card.replacement.ReplacementHandler; @@ -380,10 +381,19 @@ public class CardFactory { // Combined abilities -- DOESN'T DISPLAY THE ABILITY TEXT IN THE CHOICE BOX YET card.getCharacteristics().getIntrinsicAbility().clear(); for (String a : rules.getMainPart().getAbilities()) { - card.addIntrinsicAbility(a); + final SpellAbility sa = AbilityFactory.getAbility(a, card); + if (sa.hasParam("SetAsKicked")) { + sa.addOptionalAdditionalCosts("Kicker"); + } + card.addSpellAbility(sa); } for (String a : rules.getOtherPart().getAbilities()) { card.addIntrinsicAbility(a); + final SpellAbility sa = AbilityFactory.getAbility(a, card); + if (sa.hasParam("SetAsKicked")) { + sa.addOptionalAdditionalCosts("Kicker"); + } + card.addSpellAbility(sa); } // Combined text -- CURRENTLY TAKES ORACLE TEXT BECAUSE THE ABILITY TEXT DOESN'T WORK (?) From 6e7a15a863097d9caca6fa339d5fc2e088e5b721 Mon Sep 17 00:00:00 2001 From: Agetian Date: Sun, 3 Mar 2013 12:23:45 +0000 Subject: [PATCH 03/19] - Fix for the previous commit to SplitCards. --- src/main/java/forge/card/cardfactory/CardFactory.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/forge/card/cardfactory/CardFactory.java b/src/main/java/forge/card/cardfactory/CardFactory.java index 1b37e77dff8..c42176b2d27 100644 --- a/src/main/java/forge/card/cardfactory/CardFactory.java +++ b/src/main/java/forge/card/cardfactory/CardFactory.java @@ -388,7 +388,6 @@ public class CardFactory { card.addSpellAbility(sa); } for (String a : rules.getOtherPart().getAbilities()) { - card.addIntrinsicAbility(a); final SpellAbility sa = AbilityFactory.getAbility(a, card); if (sa.hasParam("SetAsKicked")) { sa.addOptionalAdditionalCosts("Kicker"); From deea6d3364a7db75fff418d56678c82dec1f92f3 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Sun, 3 Mar 2013 18:00:11 +0000 Subject: [PATCH 04/19] building abilities of combined face in a right way --- .../forge/card/cardfactory/CardFactory.java | 30 +++++++------------ .../card/cardfactory/CardFactoryUtil.java | 15 +++++----- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/src/main/java/forge/card/cardfactory/CardFactory.java b/src/main/java/forge/card/cardfactory/CardFactory.java index c42176b2d27..227b970a01b 100644 --- a/src/main/java/forge/card/cardfactory/CardFactory.java +++ b/src/main/java/forge/card/cardfactory/CardFactory.java @@ -288,9 +288,7 @@ public class CardFactory { // this is the "default" spell for permanents like creatures and artifacts if (card.isPermanent() && !card.isAura() && !card.isLand()) { - if (card.getRules().getSplitType() != CardSplitType.Split) { - card.addSpellAbility(new SpellPermanent(card)); // ignore the default spell for combined split cards - } + card.addSpellAbility(new SpellPermanent(card)); // ignore the default spell for combined split cards } CardFactoryUtil.parseKeywords(card, cardName); @@ -307,6 +305,11 @@ public class CardFactory { card.addStaticAbility(stAbs.get(i)); } } + + if ( state == CardCharacteristicName.LeftSplit || state == CardCharacteristicName.RightSplit ) + { + card.getState(CardCharacteristicName.Original).getSpellAbility().addAll(card.getCharacteristics().getSpellAbility()); + } } card.setState(CardCharacteristicName.Original); @@ -365,7 +368,6 @@ public class CardFactory { if ( st == CardSplitType.Split ) { card.setName(rules.getName()); - // BUILD COMBINED 'Original' SIDE HERE // Combined mana cost ManaCost combinedManaCost = ManaCost.combine(rules.getMainPart().getManaCost(), rules.getOtherPart().getManaCost()); card.setManaCost(combinedManaCost); @@ -378,22 +380,10 @@ public class CardFactory { combinedCardColorArr.add(combinedCardColor); card.setColor(combinedCardColorArr); - // Combined abilities -- DOESN'T DISPLAY THE ABILITY TEXT IN THE CHOICE BOX YET - card.getCharacteristics().getIntrinsicAbility().clear(); - for (String a : rules.getMainPart().getAbilities()) { - final SpellAbility sa = AbilityFactory.getAbility(a, card); - if (sa.hasParam("SetAsKicked")) { - sa.addOptionalAdditionalCosts("Kicker"); - } - card.addSpellAbility(sa); - } - for (String a : rules.getOtherPart().getAbilities()) { - final SpellAbility sa = AbilityFactory.getAbility(a, card); - if (sa.hasParam("SetAsKicked")) { - sa.addOptionalAdditionalCosts("Kicker"); - } - card.addSpellAbility(sa); - } + // Super and 'middle' types should use enums. + List coreTypes = rules.getType().getTypesBeforeDash(); + coreTypes.addAll(rules.getType().getSubTypes()); + card.setType(coreTypes); // Combined text -- CURRENTLY TAKES ORACLE TEXT BECAUSE THE ABILITY TEXT DOESN'T WORK (?) String combinedText = String.format("%s: %s\n%s: %s", rules.getMainPart().getName(), rules.getMainPart().getOracleText(), rules.getOtherPart().getName(), rules.getOtherPart().getOracleText()); diff --git a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java index 2a572f830b5..a30d9dcd13d 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java @@ -2796,16 +2796,15 @@ public class CardFactoryUtil { // ************************************************** // AbilityFactory cards final ArrayList ia = card.getIntrinsicAbilities(); - if (ia.size() > 0) { - for (int i = 0; i < ia.size(); i++) { - // System.out.println(cardName); - final SpellAbility sa = AbilityFactory.getAbility(ia.get(i), card); - if (sa.hasParam("SetAsKicked")) { - sa.addOptionalAdditionalCosts("Kicker"); - } - card.addSpellAbility(sa); + for (int i = 0; i < ia.size(); i++) { + // System.out.println(cardName); + final SpellAbility sa = AbilityFactory.getAbility(ia.get(i), card); + if (sa.hasParam("SetAsKicked")) { + sa.addOptionalAdditionalCosts("Kicker"); } + card.addSpellAbility(sa); } + } /** From 29ba518dcb00d0c933f0520a05bbdad5e5819853 Mon Sep 17 00:00:00 2001 From: Agetian Date: Sun, 3 Mar 2013 19:26:11 +0000 Subject: [PATCH 05/19] - Combined text on split cards is no longer force-created based on Oracle texts (avoids duplication of text in the card detail panel). --- src/main/java/forge/card/cardfactory/CardFactory.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/forge/card/cardfactory/CardFactory.java b/src/main/java/forge/card/cardfactory/CardFactory.java index 227b970a01b..72ad96e5984 100644 --- a/src/main/java/forge/card/cardfactory/CardFactory.java +++ b/src/main/java/forge/card/cardfactory/CardFactory.java @@ -288,7 +288,7 @@ public class CardFactory { // this is the "default" spell for permanents like creatures and artifacts if (card.isPermanent() && !card.isAura() && !card.isLand()) { - card.addSpellAbility(new SpellPermanent(card)); // ignore the default spell for combined split cards + card.addSpellAbility(new SpellPermanent(card)); } CardFactoryUtil.parseKeywords(card, cardName); @@ -385,9 +385,9 @@ public class CardFactory { coreTypes.addAll(rules.getType().getSubTypes()); card.setType(coreTypes); - // Combined text -- CURRENTLY TAKES ORACLE TEXT BECAUSE THE ABILITY TEXT DOESN'T WORK (?) - String combinedText = String.format("%s: %s\n%s: %s", rules.getMainPart().getName(), rules.getMainPart().getOracleText(), rules.getOtherPart().getName(), rules.getOtherPart().getOracleText()); - card.setText(combinedText); + // Combined text based on Oracle text - might not be necessary, temporarily disabled. + //String combinedText = String.format("%s: %s\n%s: %s", rules.getMainPart().getName(), rules.getMainPart().getOracleText(), rules.getOtherPart().getName(), rules.getOtherPart().getOracleText()); + //card.setText(combinedText); } return card; From ca1d001e44ca264ff2a5dba0269bf4bbf0325408 Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 4 Mar 2013 06:44:47 +0000 Subject: [PATCH 06/19] - Split cards now properly transform into their respective split sides when put on stack (current implementation requires the special spell ability parameter SplitSide set to LeftSplit for the first ability and to RightSplit for the second ability in the card script). - Merge: merging the latest trunk into SplitCards. --- src/main/java/forge/game/GameActionPlay.java | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/java/forge/game/GameActionPlay.java b/src/main/java/forge/game/GameActionPlay.java index ade428ec569..a8bf6a5c8bc 100644 --- a/src/main/java/forge/game/GameActionPlay.java +++ b/src/main/java/forge/game/GameActionPlay.java @@ -6,9 +6,11 @@ import java.util.List; import com.google.common.collect.Lists; import forge.Card; +import forge.CardCharacteristicName; import forge.CardColor; import forge.CardLists; import forge.CardPredicates; +import forge.card.CardSplitType; import forge.card.MagicColor; import forge.card.ability.AbilityUtils; import forge.card.ability.ApiType; @@ -363,6 +365,23 @@ public class GameActionPlay { public final void playSpellAbility(SpellAbility sa, Player activator) { sa.setActivatingPlayer(activator); + final Card source = sa.getSourceCard(); + + // Split card support + if (source.getRules().getSplitType() == CardSplitType.Split) { + if (sa.hasParam("SplitSide")) { + if (sa.getParam("SplitSide").equals("LeftSplit")) { + source.setState(CardCharacteristicName.LeftSplit); + } else if (sa.getParam("SplitSide").equals("RightSplit")) { + source.setState(CardCharacteristicName.RightSplit); + } else { + System.out.println(String.format("ERROR: Split card %s does not define the split face abilities properly.", source.getName())); + } + } else { + System.out.println(String.format("ERROR: Split card %s does not define the split face abilities properly.", source.getName())); + } + } + if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { CharmEffect.makeChoices(sa); } @@ -402,7 +421,6 @@ public class GameActionPlay { manaCost = this.getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())); } if (manaCost.isPaid() && (sa.getBeforePayMana() == null)) { - final Card source = sa.getSourceCard(); if (sa.isSpell() && !source.isCopiedSpell()) { sa.setSourceCard(game.getAction().moveToStack(source)); } From 922f67b3cca457eea43062700af1d5aeb6d68766 Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 4 Mar 2013 06:59:39 +0000 Subject: [PATCH 07/19] - Split cards correctly transform back to their full face form when going to graveyard. --- src/main/java/forge/game/GameAction.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/forge/game/GameAction.java b/src/main/java/forge/game/GameAction.java index d91fe8c86ca..61d7077f4bf 100644 --- a/src/main/java/forge/game/GameAction.java +++ b/src/main/java/forge/game/GameAction.java @@ -33,6 +33,7 @@ import forge.CardUtil; import forge.Command; import forge.CounterType; import forge.GameEntity; +import forge.card.CardSplitType; import forge.card.CardType; import forge.card.ability.effects.AttachEffect; import forge.card.cost.Cost; @@ -464,6 +465,11 @@ public class GameAction { c.getController().addPoisonCounters(1, c); } + // if a split card, convert back to its full face form before going to graveyard + if (c.getRules().getSplitType() == CardSplitType.Split) { + c.setState(CardCharacteristicName.Original); + } + // must put card in OWNER's graveyard not controller's c = this.moveTo(grave, c); From cad57311a0a62db4eb7d147de8eb3fba5a2e2846 Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 4 Mar 2013 07:03:20 +0000 Subject: [PATCH 08/19] - Split cards correctly transform back to their full face form when exiled (not sure if they can be exiled while on stack, so this is more of a fail-safe mechanism - feel free to revert if this is overkill). --- src/main/java/forge/game/GameAction.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/forge/game/GameAction.java b/src/main/java/forge/game/GameAction.java index 61d7077f4bf..510952faa43 100644 --- a/src/main/java/forge/game/GameAction.java +++ b/src/main/java/forge/game/GameAction.java @@ -710,6 +710,12 @@ public class GameAction { return c; } final PlayerZone removed = c.getOwner().getZone(ZoneType.Exile); + + // if a split card, convert back to its full face form before going to graveyard + if (c.getRules().getSplitType() == CardSplitType.Split) { + c.setState(CardCharacteristicName.Original); + } + return moveTo(removed, c); } From 0430a53105c59892b5f3927bb8caeb373fbe4f3a Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 4 Mar 2013 08:08:44 +0000 Subject: [PATCH 09/19] - Split cards correctly transform back if targeting is canceled or if mana cost is not paid. Also, consolidated the implementation of back-transformation when going to graveyard or exile (or another zone except stack). --- .../spellability/SpellAbilityRequirements.java | 14 ++++++++++++++ src/main/java/forge/game/GameAction.java | 15 +++++---------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/java/forge/card/spellability/SpellAbilityRequirements.java b/src/main/java/forge/card/spellability/SpellAbilityRequirements.java index 7dd24060d2f..e571f5c99c9 100644 --- a/src/main/java/forge/card/spellability/SpellAbilityRequirements.java +++ b/src/main/java/forge/card/spellability/SpellAbilityRequirements.java @@ -20,7 +20,9 @@ package forge.card.spellability; import java.util.ArrayList; import forge.Card; +import forge.CardCharacteristicName; import forge.Singletons; +import forge.card.CardSplitType; import forge.card.ability.AbilityUtils; import forge.card.cost.CostPayment; import forge.game.zone.Zone; @@ -149,6 +151,12 @@ public class SpellAbilityRequirements { if (this.select.isCanceled()) { // cancel ability during target choosing final Card c = this.ability.getSourceCard(); + + // split cards transform back to full form if targeting is canceled + if (c.getRules().getSplitType() == CardSplitType.Split) { + c.setState(CardCharacteristicName.Original); + } + if (this.bCasting && !c.isCopiedSpell()) { // and not a copy // add back to where it came from Singletons.getModel().getGame().getAction().moveTo(this.fromZone, c, this.zonePosition); @@ -203,6 +211,12 @@ public class SpellAbilityRequirements { Singletons.getModel().getGame().getAction().checkStateEffects(); } else if (this.payment.isCanceled()) { final Card c = this.ability.getSourceCard(); + + // split cards transform back to full form if targeting is canceled + if (c.getRules().getSplitType() == CardSplitType.Split) { + c.setState(CardCharacteristicName.Original); + } + if (this.bCasting && !c.isCopiedSpell()) { // and not a copy // add back to Previous Zone Singletons.getModel().getGame().getAction().moveTo(this.fromZone, c, this.zonePosition); diff --git a/src/main/java/forge/game/GameAction.java b/src/main/java/forge/game/GameAction.java index 510952faa43..bbfd4a16c75 100644 --- a/src/main/java/forge/game/GameAction.java +++ b/src/main/java/forge/game/GameAction.java @@ -340,6 +340,11 @@ public class GameAction { * @return a {@link forge.Card} object. */ public final Card moveTo(final Zone zoneTo, Card c) { + // if a split card is moved, convert it back to its full form before moving (unless moving to stack) + if ((c.getRules().getSplitType() == CardSplitType.Split) && (zoneTo != game.getStackZone())) { + c.setState(CardCharacteristicName.Original); + } + return moveTo(zoneTo, c, null); } @@ -465,11 +470,6 @@ public class GameAction { c.getController().addPoisonCounters(1, c); } - // if a split card, convert back to its full face form before going to graveyard - if (c.getRules().getSplitType() == CardSplitType.Split) { - c.setState(CardCharacteristicName.Original); - } - // must put card in OWNER's graveyard not controller's c = this.moveTo(grave, c); @@ -711,11 +711,6 @@ public class GameAction { } final PlayerZone removed = c.getOwner().getZone(ZoneType.Exile); - // if a split card, convert back to its full face form before going to graveyard - if (c.getRules().getSplitType() == CardSplitType.Split) { - c.setState(CardCharacteristicName.Original); - } - return moveTo(removed, c); } From 2df9e79ff78b82a8aa2f0d3187449ef716d6dd0a Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 4 Mar 2013 08:10:46 +0000 Subject: [PATCH 10/19] - Minor comment fix. --- .../java/forge/card/spellability/SpellAbilityRequirements.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/forge/card/spellability/SpellAbilityRequirements.java b/src/main/java/forge/card/spellability/SpellAbilityRequirements.java index e571f5c99c9..19359bacb24 100644 --- a/src/main/java/forge/card/spellability/SpellAbilityRequirements.java +++ b/src/main/java/forge/card/spellability/SpellAbilityRequirements.java @@ -212,7 +212,7 @@ public class SpellAbilityRequirements { } else if (this.payment.isCanceled()) { final Card c = this.ability.getSourceCard(); - // split cards transform back to full form if targeting is canceled + // split cards transform back to full form if mana cost is not paid if (c.getRules().getSplitType() == CardSplitType.Split) { c.setState(CardCharacteristicName.Original); } From c98fdc36ad756b7f5155ba67b5347847511b8df7 Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 4 Mar 2013 08:33:03 +0000 Subject: [PATCH 11/19] - Removed the necessity to use a special parameter for spell abilities of split cards. - Fixed a NPE related to back-transformation of split cards. --- .../SpellAbilityRequirements.java | 12 ++++++---- src/main/java/forge/game/GameAction.java | 6 +++-- src/main/java/forge/game/GameActionPlay.java | 23 +++++++++++-------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/main/java/forge/card/spellability/SpellAbilityRequirements.java b/src/main/java/forge/card/spellability/SpellAbilityRequirements.java index 19359bacb24..118116ab4cc 100644 --- a/src/main/java/forge/card/spellability/SpellAbilityRequirements.java +++ b/src/main/java/forge/card/spellability/SpellAbilityRequirements.java @@ -153,8 +153,10 @@ public class SpellAbilityRequirements { final Card c = this.ability.getSourceCard(); // split cards transform back to full form if targeting is canceled - if (c.getRules().getSplitType() == CardSplitType.Split) { - c.setState(CardCharacteristicName.Original); + if (c.getRules() != null) { + if (c.getRules().getSplitType() == CardSplitType.Split) { + c.setState(CardCharacteristicName.Original); + } } if (this.bCasting && !c.isCopiedSpell()) { // and not a copy @@ -213,8 +215,10 @@ public class SpellAbilityRequirements { final Card c = this.ability.getSourceCard(); // split cards transform back to full form if mana cost is not paid - if (c.getRules().getSplitType() == CardSplitType.Split) { - c.setState(CardCharacteristicName.Original); + if (c.getRules() != null) { + if (c.getRules().getSplitType() == CardSplitType.Split) { + c.setState(CardCharacteristicName.Original); + } } if (this.bCasting && !c.isCopiedSpell()) { // and not a copy diff --git a/src/main/java/forge/game/GameAction.java b/src/main/java/forge/game/GameAction.java index bbfd4a16c75..ee587c43a60 100644 --- a/src/main/java/forge/game/GameAction.java +++ b/src/main/java/forge/game/GameAction.java @@ -341,8 +341,10 @@ public class GameAction { */ public final Card moveTo(final Zone zoneTo, Card c) { // if a split card is moved, convert it back to its full form before moving (unless moving to stack) - if ((c.getRules().getSplitType() == CardSplitType.Split) && (zoneTo != game.getStackZone())) { - c.setState(CardCharacteristicName.Original); + if (c.getRules() != null) { + if ((c.getRules().getSplitType() == CardSplitType.Split) && (zoneTo != game.getStackZone())) { + c.setState(CardCharacteristicName.Original); + } } return moveTo(zoneTo, c, null); diff --git a/src/main/java/forge/game/GameActionPlay.java b/src/main/java/forge/game/GameActionPlay.java index a8bf6a5c8bc..1f7dd1be2bc 100644 --- a/src/main/java/forge/game/GameActionPlay.java +++ b/src/main/java/forge/game/GameActionPlay.java @@ -368,17 +368,20 @@ public class GameActionPlay { final Card source = sa.getSourceCard(); // Split card support - if (source.getRules().getSplitType() == CardSplitType.Split) { - if (sa.hasParam("SplitSide")) { - if (sa.getParam("SplitSide").equals("LeftSplit")) { - source.setState(CardCharacteristicName.LeftSplit); - } else if (sa.getParam("SplitSide").equals("RightSplit")) { - source.setState(CardCharacteristicName.RightSplit); - } else { - System.out.println(String.format("ERROR: Split card %s does not define the split face abilities properly.", source.getName())); + if (source.getRules() != null) { + if (source.getRules().getSplitType() == CardSplitType.Split) { + List leftSplitAbilities = source.getState(CardCharacteristicName.LeftSplit).getSpellAbility(); + List rightSplitAbilities = source.getState(CardCharacteristicName.RightSplit).getSpellAbility(); + for (SpellAbility a : leftSplitAbilities) { + if (sa == a) { + source.setState(CardCharacteristicName.LeftSplit); + } + } + for (SpellAbility a : rightSplitAbilities) { + if (sa == a) { + source.setState(CardCharacteristicName.RightSplit); + } } - } else { - System.out.println(String.format("ERROR: Split card %s does not define the split face abilities properly.", source.getName())); } } From 5671985f793e9439d2234a389d4d1d45b3fab536 Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 4 Mar 2013 08:36:33 +0000 Subject: [PATCH 12/19] - Minor modifications to playSpellAbility. --- src/main/java/forge/game/GameActionPlay.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/forge/game/GameActionPlay.java b/src/main/java/forge/game/GameActionPlay.java index 1f7dd1be2bc..ca05fff834d 100644 --- a/src/main/java/forge/game/GameActionPlay.java +++ b/src/main/java/forge/game/GameActionPlay.java @@ -375,11 +375,13 @@ public class GameActionPlay { for (SpellAbility a : leftSplitAbilities) { if (sa == a) { source.setState(CardCharacteristicName.LeftSplit); + break; } } for (SpellAbility a : rightSplitAbilities) { if (sa == a) { source.setState(CardCharacteristicName.RightSplit); + break; } } } From f0f40c8f92eab2cb2dea9b157d402f085e618e8d Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 4 Mar 2013 15:28:49 +0000 Subject: [PATCH 13/19] - Adding the Assault/Battery card script (by Max) to SplitCards so that everybody can test the current situation with split card support. --- .gitattributes | 1 + res/cardsfolder/a/assault__battery.txt | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 res/cardsfolder/a/assault__battery.txt diff --git a/.gitattributes b/.gitattributes index 4b521f71afd..b3a3a68fcb3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -552,6 +552,7 @@ res/cardsfolder/a/aspect_of_wolf.txt svneol=native#text/plain res/cardsfolder/a/assassinate.txt svneol=native#text/plain res/cardsfolder/a/assassins_blade.txt svneol=native#text/plain res/cardsfolder/a/assassins_strike.txt -text +res/cardsfolder/a/assault__battery.txt -text res/cardsfolder/a/assault_griffin.txt svneol=native#text/plain res/cardsfolder/a/assault_strobe.txt svneol=native#text/plain res/cardsfolder/a/assault_zeppelid.txt svneol=native#text/plain diff --git a/res/cardsfolder/a/assault__battery.txt b/res/cardsfolder/a/assault__battery.txt new file mode 100644 index 00000000000..e0cd9e041d4 --- /dev/null +++ b/res/cardsfolder/a/assault__battery.txt @@ -0,0 +1,21 @@ +Name:Assault +ManaCost:R +AlternateMode: Split +Types:Sorcery +A:SP$ DealDamage | Cost$ R | NumDmg$ 2 | ValidTgts$ Creature,Player | SpellDescription$ Assault deals 2 damage to target creature or player. +SetInfo:INV|Uncommon|http://magiccards.info/scans/en/in/295a.jpg +SetInfo:TSB|Uncommon +SetInfo:PCH|Uncommon +Oracle:Assault deals 2 damage to target creature or player. + +ALTERNATE + +Name:Battery +ManaCost:3 G +Types:Sorcery +A:SP$ Token | Cost$ 3 G | TokenAmount$ 1 | TokenName$ Elephant| TokenTypes$ Creature,Elephant| TokenOwner$ You | TokenColors$ Green | TokenPower$ 3 | TokenToughness$ 3 | TokenImage$ g 3 3 elephant | SpellDescription$ Put a 3/3 green Elephant creature token onto the battlefield. +SetInfo:INV|Uncommon|http://magiccards.info/scans/en/in/295b.jpg +SetInfo:PCH|Uncommon +SetInfo:TSB|Uncommon +Oracle:Put a 3/3 green Elephant creature token onto the battlefield. +End From f382f28f61a05efd38cd12781680b51644c5c215 Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 4 Mar 2013 17:37:51 +0000 Subject: [PATCH 14/19] - Updating the Assault // Battery script to the new SetInfo format. --- res/cardsfolder/a/assault__battery.txt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/res/cardsfolder/a/assault__battery.txt b/res/cardsfolder/a/assault__battery.txt index e0cd9e041d4..5c513c4fbb0 100644 --- a/res/cardsfolder/a/assault__battery.txt +++ b/res/cardsfolder/a/assault__battery.txt @@ -3,9 +3,9 @@ ManaCost:R AlternateMode: Split Types:Sorcery A:SP$ DealDamage | Cost$ R | NumDmg$ 2 | ValidTgts$ Creature,Player | SpellDescription$ Assault deals 2 damage to target creature or player. -SetInfo:INV|Uncommon|http://magiccards.info/scans/en/in/295a.jpg -SetInfo:TSB|Uncommon -SetInfo:PCH|Uncommon +SetInfo:INV Uncommon +SetInfo:TSB Uncommon +SetInfo:HOP Uncommon Oracle:Assault deals 2 damage to target creature or player. ALTERNATE @@ -14,8 +14,5 @@ Name:Battery ManaCost:3 G Types:Sorcery A:SP$ Token | Cost$ 3 G | TokenAmount$ 1 | TokenName$ Elephant| TokenTypes$ Creature,Elephant| TokenOwner$ You | TokenColors$ Green | TokenPower$ 3 | TokenToughness$ 3 | TokenImage$ g 3 3 elephant | SpellDescription$ Put a 3/3 green Elephant creature token onto the battlefield. -SetInfo:INV|Uncommon|http://magiccards.info/scans/en/in/295b.jpg -SetInfo:PCH|Uncommon -SetInfo:TSB|Uncommon Oracle:Put a 3/3 green Elephant creature token onto the battlefield. End From 8adbc48b86860e463a35f97aaa3977e427a4d73c Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 5 Mar 2013 09:54:12 +0000 Subject: [PATCH 15/19] - Initial phase of implementing Card.getCMC that supports returning either the current face CMC, or the individual left split/right split CMCs of a split card. --- src/main/java/forge/Card.java | 43 +++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index f7f3f997335..66abcc8e26e 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -37,6 +37,7 @@ import forge.CardPredicates.Presets; import forge.card.CardCharacteristics; import forge.card.CardRarity; import forge.card.CardRules; +import forge.card.CardSplitType; import forge.card.ability.AbilityUtils; import forge.card.ability.ApiType; import forge.card.cardfactory.CardFactoryUtil; @@ -233,7 +234,13 @@ public class Card extends GameEntity implements Comparable { // Soulbond pairing card private Card pairedWith = null; - + // Enumeration for CMC request types + public enum SplitCMCMode { + CurrentSideCMC, + CombinedCMC, + LeftSplitCMC, + RightSplitCMC + } /** * Instantiates a new card. @@ -9110,6 +9117,10 @@ public class Card extends GameEntity implements Comparable { * @return a int. */ public int getCMC() { + return getCMC(SplitCMCMode.CurrentSideCMC); + } + + public int getCMC(SplitCMCMode mode) { if (isToken() && !isCopiedToken()) { return 0; } @@ -9120,7 +9131,35 @@ public class Card extends GameEntity implements Comparable { if (Singletons.getModel().getGame().getCardsIn(ZoneType.Stack).contains(this) && getManaCost() != null) { xPaid = getXManaCostPaid() * getManaCost().countX(); } - return getManaCost().getCMC() + xPaid; + + int requestedCMC = 0; + + if (getRules().getSplitType() == CardSplitType.Split) { + switch(mode) { + case CurrentSideCMC: + // TODO: test if this returns combined CMC for the full face (then get rid of CombinedCMC mode?) + requestedCMC = getManaCost().getCMC() + xPaid; + break; + case LeftSplitCMC: + requestedCMC = getState(CardCharacteristicName.LeftSplit).getManaCost().getCMC() + xPaid; + break; + case RightSplitCMC: + requestedCMC = getState(CardCharacteristicName.RightSplit).getManaCost().getCMC() + xPaid; + break; + case CombinedCMC: + requestedCMC += getState(CardCharacteristicName.LeftSplit).getManaCost().getCMC(); + requestedCMC += getState(CardCharacteristicName.RightSplit).getManaCost().getCMC(); + requestedCMC += xPaid; + break; + default: + System.out.println(String.format("Illegal Split Card CMC mode %s passed to getCMC!", mode.toString())); + break; + } + } else { + requestedCMC = getManaCost().getCMC() + xPaid; + } + + return requestedCMC; } public final boolean canBeSacrificedBy(final SpellAbility source) From 643d1892d927aea4d13f39eee3829a213066b557 Mon Sep 17 00:00:00 2001 From: swordshine Date: Tue, 5 Mar 2013 10:18:19 +0000 Subject: [PATCH 16/19] - SplitCards: Added Fire//Ice for test --- .gitattributes | 1 + res/cardsfolder/a/assault__battery.txt | 2 +- res/cardsfolder/f/fire_ice.txt | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 res/cardsfolder/f/fire_ice.txt diff --git a/.gitattributes b/.gitattributes index b9e5f89fcd2..cf342a07787 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3605,6 +3605,7 @@ res/cardsfolder/f/fire_dragon.txt svneol=native#text/plain res/cardsfolder/f/fire_drake.txt svneol=native#text/plain res/cardsfolder/f/fire_elemental.txt svneol=native#text/plain res/cardsfolder/f/fire_field_ogre.txt svneol=native#text/plain +res/cardsfolder/f/fire_ice.txt -text res/cardsfolder/f/fire_imp.txt svneol=native#text/plain res/cardsfolder/f/fire_juggler.txt -text res/cardsfolder/f/fire_lit_thicket.txt svneol=native#text/plain diff --git a/res/cardsfolder/a/assault__battery.txt b/res/cardsfolder/a/assault__battery.txt index 5c513c4fbb0..fae1d1f4b26 100644 --- a/res/cardsfolder/a/assault__battery.txt +++ b/res/cardsfolder/a/assault__battery.txt @@ -2,7 +2,7 @@ Name:Assault ManaCost:R AlternateMode: Split Types:Sorcery -A:SP$ DealDamage | Cost$ R | NumDmg$ 2 | ValidTgts$ Creature,Player | SpellDescription$ Assault deals 2 damage to target creature or player. +A:SP$ DealDamage | Cost$ R | NumDmg$ 2 | ValidTgts$ Creature,Player | TgtPrompt$ Select target creature or player | SpellDescription$ Assault deals 2 damage to target creature or player. SetInfo:INV Uncommon SetInfo:TSB Uncommon SetInfo:HOP Uncommon diff --git a/res/cardsfolder/f/fire_ice.txt b/res/cardsfolder/f/fire_ice.txt new file mode 100644 index 00000000000..5ae8a3319b7 --- /dev/null +++ b/res/cardsfolder/f/fire_ice.txt @@ -0,0 +1,19 @@ +Name:Fire +ManaCost:1 R +AlternateMode: Split +Types:Instant +A:SP$ DealDamage | Cost$ 1 R | ValidTgts$ Creature,Player | TgtPrompt$ Select target creature or player to distribute damage to | NumDmg$ 2 | TargetMin$ 1 | TargetMax$ 2 | DividedAsYouChoose$ 2 | SpellDescription$ Fire deals 2 damage divided as you choose among one or two target creatures and/or players. +SetInfo:APC Uncommon x2 +SetInfo:COM Uncommon +SetInfo:DDJ Uncommon +Oracle:Fire deals 2 damage divided as you choose among one or two target creatures and/or players. + +ALTERNATE + +Name:Ice +ManaCost:1 U +Types:Instant +A:SP$ Tap | Cost$ 1 U | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | SubAbility$ DBDraw | SpellDescription$ Tap target permanent. Draw a card. +SVar:DBDraw:DB$ Draw | NumCards$ 1 +Oracle:Tap target permanent.\nDraw a card. +End From 1d7e80d6752c9551e9be53c6cb0be752caa82508 Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 5 Mar 2013 13:00:49 +0000 Subject: [PATCH 17/19] - A little fix for the implementation of split card CMC check in Card.hasProperty. --- src/main/java/forge/Card.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index 7491b7454f0..acb185935a5 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -7142,7 +7142,7 @@ public class Card extends GameEntity implements Comparable { y = this.getNetDefense(); } else if (property.startsWith("cmc")) { rhs = property.substring(5); - if (getRules() != null && getRules().getSplitType() == CardSplitType.Split) { + if (getRules() != null && getRules().getSplitType() == CardSplitType.Split && getCurState() == CardCharacteristicName.Original) { y = getState(CardCharacteristicName.LeftSplit).getManaCost().getCMC(); y2 = getState(CardCharacteristicName.RightSplit).getManaCost().getCMC(); } else { From d6f16061edc99a6661d649de08e3cedddc5710dd Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 5 Mar 2013 13:30:21 +0000 Subject: [PATCH 18/19] - Fixed a bug that caused copies of split card spells (e.g. from Isochron Scepter) not to go on stack correctly. Please revise, I'm not sure if there may be other cases like that which are not yet accounted for. --- src/main/java/forge/game/GameActionPlay.java | 43 +++++++++++--------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/main/java/forge/game/GameActionPlay.java b/src/main/java/forge/game/GameActionPlay.java index ca05fff834d..49e78212e9d 100644 --- a/src/main/java/forge/game/GameActionPlay.java +++ b/src/main/java/forge/game/GameActionPlay.java @@ -366,26 +366,9 @@ public class GameActionPlay { sa.setActivatingPlayer(activator); final Card source = sa.getSourceCard(); - + // Split card support - if (source.getRules() != null) { - if (source.getRules().getSplitType() == CardSplitType.Split) { - List leftSplitAbilities = source.getState(CardCharacteristicName.LeftSplit).getSpellAbility(); - List rightSplitAbilities = source.getState(CardCharacteristicName.RightSplit).getSpellAbility(); - for (SpellAbility a : leftSplitAbilities) { - if (sa == a) { - source.setState(CardCharacteristicName.LeftSplit); - break; - } - } - for (SpellAbility a : rightSplitAbilities) { - if (sa == a) { - source.setState(CardCharacteristicName.RightSplit); - break; - } - } - } - } + setSplitCardState(source, sa); if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { CharmEffect.makeChoices(sa); @@ -555,4 +538,26 @@ public class GameActionPlay { return usableColors; } + + private void setSplitCardState(final Card source, SpellAbility sa) { + // Split card support + if (source.getRules() != null) { + if (source.getRules().getSplitType() == CardSplitType.Split) { + List leftSplitAbilities = source.getState(CardCharacteristicName.LeftSplit).getSpellAbility(); + List rightSplitAbilities = source.getState(CardCharacteristicName.RightSplit).getSpellAbility(); + for (SpellAbility a : leftSplitAbilities) { + if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) { + source.setState(CardCharacteristicName.LeftSplit); + break; + } + } + for (SpellAbility a : rightSplitAbilities) { + if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) { + source.setState(CardCharacteristicName.RightSplit); + break; + } + } + } + } + } } From 9e626136145c8297633ee94dd3e96cc8021798db Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 5 Mar 2013 14:17:33 +0000 Subject: [PATCH 19/19] - Corrected the Fire // Ice setinfo. --- res/cardsfolder/f/fire_ice.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/cardsfolder/f/fire_ice.txt b/res/cardsfolder/f/fire_ice.txt index 5ae8a3319b7..f3ef0303faf 100644 --- a/res/cardsfolder/f/fire_ice.txt +++ b/res/cardsfolder/f/fire_ice.txt @@ -3,7 +3,7 @@ ManaCost:1 R AlternateMode: Split Types:Instant A:SP$ DealDamage | Cost$ 1 R | ValidTgts$ Creature,Player | TgtPrompt$ Select target creature or player to distribute damage to | NumDmg$ 2 | TargetMin$ 1 | TargetMax$ 2 | DividedAsYouChoose$ 2 | SpellDescription$ Fire deals 2 damage divided as you choose among one or two target creatures and/or players. -SetInfo:APC Uncommon x2 +SetInfo:APC Uncommon SetInfo:COM Uncommon SetInfo:DDJ Uncommon Oracle:Fire deals 2 damage divided as you choose among one or two target creatures and/or players.