From ea04892ea0b110957b9cc251c19b83c2920c0af7 Mon Sep 17 00:00:00 2001 From: Sol Date: Wed, 6 Mar 2013 04:59:48 +0000 Subject: [PATCH 01/40] - Change CardDetailPanel to use Card.getManaDisplay() to show split cards cost separately --- src/main/java/forge/Card.java | 16 ++++++++++++++++ src/main/java/forge/gui/CardDetailPanel.java | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index acb185935a5..6e6f8eb35ba 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -1631,6 +1631,22 @@ public class Card extends GameEntity implements Comparable { public final ManaCost getManaCost() { return this.getCharacteristics().getManaCost(); } + + /** + *

+ * Display for the field manaCost. + *

+ * + * @return a {@link java.lang.String} object. + */ + public final String getManaDisplay() { + // If this is a split card, display mana as X / Y. Otherwise, Display it as normal + if (this.getRules() != null && this.getRules().getSplitType() == CardSplitType.Split) { + return String.format("%s / %s", this.getState(CardCharacteristicName.LeftSplit).getManaCost(), + this.getState(CardCharacteristicName.RightSplit).getManaCost()); + } + return this.getCharacteristics().getManaCost().toString(); + } /** *

diff --git a/src/main/java/forge/gui/CardDetailPanel.java b/src/main/java/forge/gui/CardDetailPanel.java index 88bc82ebe13..123207c1b0d 100644 --- a/src/main/java/forge/gui/CardDetailPanel.java +++ b/src/main/java/forge/gui/CardDetailPanel.java @@ -205,7 +205,7 @@ public class CardDetailPanel extends FPanel { if (card.getManaCost().toString().equals("") || card.isLand()) { this.nameCostLabel.setText(card.getName()); } else { - this.nameCostLabel.setText(card.getName() + " - " + card.getManaCost()); + this.nameCostLabel.setText(card.getName() + " - " + card.getManaDisplay()); } this.typeLabel.setText(GuiDisplayUtil.formatCardType(card)); From e868f8d5ed55884f1460706c9cb173bc4f6efcac Mon Sep 17 00:00:00 2001 From: Sol Date: Wed, 6 Mar 2013 05:04:13 +0000 Subject: [PATCH 02/40] - Fix dev mode description in popup for adding card to hand --- src/main/java/forge/gui/GuiDisplayUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/forge/gui/GuiDisplayUtil.java b/src/main/java/forge/gui/GuiDisplayUtil.java index cd601122daa..20418b3766d 100644 --- a/src/main/java/forge/gui/GuiDisplayUtil.java +++ b/src/main/java/forge/gui/GuiDisplayUtil.java @@ -672,7 +672,7 @@ public final class GuiDisplayUtil { */ public static void devModeCardToHand() { final List players = Singletons.getModel().getGame().getPlayers(); - final Player p = GuiChoose.oneOrNone("Put card in play for which player?", players); + final Player p = GuiChoose.oneOrNone("Put card in hand for which player?", players); if (null == p) { return; } From fb838d9736ffd41639e53af13d12a5ba1031010b Mon Sep 17 00:00:00 2001 From: swordshine Date: Wed, 6 Mar 2013 06:08:45 +0000 Subject: [PATCH 03/40] - Added a few split cards --- .gitattributes | 6 ++++++ res/cardsfolder/d/dead_gone.txt | 16 ++++++++++++++++ res/cardsfolder/i/illusion_reality.txt | 17 +++++++++++++++++ res/cardsfolder/l/life_death.txt | 19 +++++++++++++++++++ res/cardsfolder/p/pure_simple.txt | 16 ++++++++++++++++ res/cardsfolder/r/rough_tumble.txt | 16 ++++++++++++++++ res/cardsfolder/s/supply_demand.txt | 17 +++++++++++++++++ 7 files changed, 107 insertions(+) create mode 100644 res/cardsfolder/d/dead_gone.txt create mode 100644 res/cardsfolder/i/illusion_reality.txt create mode 100644 res/cardsfolder/l/life_death.txt create mode 100644 res/cardsfolder/p/pure_simple.txt create mode 100644 res/cardsfolder/r/rough_tumble.txt create mode 100644 res/cardsfolder/s/supply_demand.txt diff --git a/.gitattributes b/.gitattributes index cf342a07787..087b00363da 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2372,6 +2372,7 @@ res/cardsfolder/d/day_of_the_dragons.txt svneol=native#text/plain res/cardsfolder/d/daybreak_coronet.txt -text res/cardsfolder/d/daybreak_ranger_nightfall_predator.txt -text res/cardsfolder/d/daze.txt svneol=native#text/plain +res/cardsfolder/d/dead_gone.txt -text res/cardsfolder/d/dead_iron_sledge.txt svneol=native#text/plain res/cardsfolder/d/dead_reckoning.txt -text svneol=unset#text/plain res/cardsfolder/d/dead_reveler.txt -text @@ -5117,6 +5118,7 @@ res/cardsfolder/i/ill_gotten_gains.txt svneol=native#text/plain res/cardsfolder/i/illness_in_the_ranks.txt -text res/cardsfolder/i/illuminated_wings.txt svneol=native#text/plain res/cardsfolder/i/illumination.txt svneol=native#text/plain +res/cardsfolder/i/illusion_reality.txt -text res/cardsfolder/i/illusionary_forces.txt svneol=native#text/plain res/cardsfolder/i/illusionary_servant.txt svneol=native#text/plain res/cardsfolder/i/illusionary_wall.txt svneol=native#text/plain @@ -5995,6 +5997,7 @@ res/cardsfolder/l/lieutenant_kirtar.txt svneol=native#text/plain res/cardsfolder/l/life_and_limb.txt svneol=native#text/plain res/cardsfolder/l/life_burst.txt svneol=native#text/plain res/cardsfolder/l/life_chisel.txt svneol=native#text/plain +res/cardsfolder/l/life_death.txt -text res/cardsfolder/l/life_from_the_loam.txt svneol=native#text/plain res/cardsfolder/l/life_matrix.txt -text svneol=unset#text/plain res/cardsfolder/l/lifeblood.txt svneol=native#text/plain @@ -8063,6 +8066,7 @@ res/cardsfolder/p/puppeteer_clique.txt svneol=native#text/plain res/cardsfolder/p/puppets_verdict.txt -text res/cardsfolder/p/pure_intentions.txt -text svneol=unset#text/plain res/cardsfolder/p/pure_reflection.txt -text +res/cardsfolder/p/pure_simple.txt -text res/cardsfolder/p/purelace.txt -text res/cardsfolder/p/puresight_merrow.txt svneol=native#text/plain res/cardsfolder/p/puresteel_paladin.txt -text @@ -8751,6 +8755,7 @@ res/cardsfolder/r/rotting_fensnake.txt -text res/cardsfolder/r/rotting_giant.txt -text res/cardsfolder/r/rotting_legion.txt svneol=native#text/plain res/cardsfolder/r/rotting_rats.txt svneol=native#text/plain +res/cardsfolder/r/rough_tumble.txt -text res/cardsfolder/r/roughshod_mentor.txt svneol=native#text/plain res/cardsfolder/r/rouse.txt svneol=native#text/plain res/cardsfolder/r/rowan_treefolk.txt svneol=native#text/plain @@ -10449,6 +10454,7 @@ res/cardsfolder/s/suntail_hawk.txt svneol=native#text/plain res/cardsfolder/s/suntouched_myr.txt svneol=native#text/plain res/cardsfolder/s/sunweb.txt svneol=native#text/plain res/cardsfolder/s/superior_numbers.txt -text svneol=unset#text/plain +res/cardsfolder/s/supply_demand.txt -text res/cardsfolder/s/suppress.txt -text svneol=unset#text/plain res/cardsfolder/s/suppression_field.txt -text res/cardsfolder/s/supreme_exemplar.txt svneol=native#text/plain diff --git a/res/cardsfolder/d/dead_gone.txt b/res/cardsfolder/d/dead_gone.txt new file mode 100644 index 00000000000..29fe56be504 --- /dev/null +++ b/res/cardsfolder/d/dead_gone.txt @@ -0,0 +1,16 @@ +Name:Dead +ManaCost:R +AlternateMode: Split +Types:Instant +A:SP$ DealDamage | Cost$ R | ValidTgts$ Creature | NumDmg$ 2 | SpellDescription$ Dead deals 2 damage to target creature. +SetInfo:PLC Common +Oracle:Dead deals 2 damage to target creature. + +ALTERNATE + +Name:Gone +ManaCost:2 R +Types:Instant +A:SP$ ChangeZone | Cost$ 2 R | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Select target creature you don't control | Origin$ Battlefield | Destination$ Hand | SpellDescription$ Return target creature you don't control to its owner's hand. +Oracle:Return target creature you don't control to its owner's hand. +End \ No newline at end of file diff --git a/res/cardsfolder/i/illusion_reality.txt b/res/cardsfolder/i/illusion_reality.txt new file mode 100644 index 00000000000..b471b904652 --- /dev/null +++ b/res/cardsfolder/i/illusion_reality.txt @@ -0,0 +1,17 @@ +Name:Illusion +ManaCost:U +AlternateMode: Split +Types:Instant +A:SP$ ChooseColor | Cost$ U | Defined$ You | SubAbility$ Animate | SpellDescription$ Target spell or permanent becomes the color of your choice until end of turn. +SVar:Animate:DB$ Animate | ValidTgts$ Card | TgtPrompt$ Select target spell or permanent to change the color of | TgtZone$ Stack,Battlefield | Colors$ ChosenColor | OverwriteColors$ True +SetInfo:APC Uncommon +Oracle:Target spell or permanent becomes the color of your choice until end of turn. + +ALTERNATE + +Name:Reality +ManaCost:2 G +Types:Instant +A:SP$ Destroy | Cost$ 2 G | ValidTgts$ Artifact | TgtPrompt$ Select target artifact | SpellDescription$ Destroy target artifact. +Oracle:Destroy target artifact. +End \ No newline at end of file diff --git a/res/cardsfolder/l/life_death.txt b/res/cardsfolder/l/life_death.txt new file mode 100644 index 00000000000..c07ea97d638 --- /dev/null +++ b/res/cardsfolder/l/life_death.txt @@ -0,0 +1,19 @@ +Name:Life +ManaCost:G +AlternateMode: Split +Types:Sorcery +A:SP$ AnimateAll | Cost$ G | Power$ 1 | Toughness$ 1 | Types$ Creature | ValidCards$ Land.YouCtrl | SpellDescription$ All lands you control become 1/1 creatures until end of turn. They're still lands. +SetInfo:APC Uncommon +SetInfo:DDJ Uncommon +Oracle:All lands you control become 1/1 creatures until end of turn. They're still lands. + +ALTERNATE + +Name:Death +ManaCost:1 B +Types:Sorcery +A:SP$ ChangeZone | Cost$ 1 B | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn | TgtPrompt$ Choose target creature card in your graveyard | GainControl$ True | SubAbility$ DBLoseLifeYou | SpellDescription$ Return target creature card from your graveyard to the battlefield. You lose life equal to its converted mana cost. +SVar:DBLoseLifeYou:DB$ LoseLife | Defined$ You | LifeAmount$ X | References$ X +SVar:X:Targeted$CardManaCost +Oracle:Return target creature card from your graveyard to the battlefield. You lose life equal to its converted mana cost. +End \ No newline at end of file diff --git a/res/cardsfolder/p/pure_simple.txt b/res/cardsfolder/p/pure_simple.txt new file mode 100644 index 00000000000..b3b8c7ebebe --- /dev/null +++ b/res/cardsfolder/p/pure_simple.txt @@ -0,0 +1,16 @@ +Name:Pure +ManaCost:1 R G +AlternateMode: Split +Types:Sorcery +A:SP$ Destroy | Cost$ 1 R G | ValidTgts$ Permanent.MultiColor | TgtPrompt$ Select target multicolored permanent | SpellDescription$ Destroy target multicolored permanent. +SetInfo:DIS Uncommon +Oracle:Destroy target multicolored permanent. + +ALTERNATE + +Name:Simple +ManaCost:1 W G +Types:Sorcery +A:SP$ DestroyAll | Cost$ 1 W G | ValidCards$ Aura,Equipment | SpellDescription$ Destroy all Auras and Equipment. +Oracle:Destroy all Auras and Equipment. +End \ No newline at end of file diff --git a/res/cardsfolder/r/rough_tumble.txt b/res/cardsfolder/r/rough_tumble.txt new file mode 100644 index 00000000000..2c32d97a5bc --- /dev/null +++ b/res/cardsfolder/r/rough_tumble.txt @@ -0,0 +1,16 @@ +Name:Rough +ManaCost:1 R +AlternateMode: Split +Types:Sorcery +A:SP$ DamageAll | Cost$ 1 R | ValidCards$ Creature.withoutFlying | NumDmg$ 2 | SpellDescription$ Rough deals 2 damage to each creature without flying. +SetInfo:PLC Uncommon +Oracle:Rough deals 2 damage to each creature without flying. + +ALTERNATE + +Name:Tumble +ManaCost:5 R +Types:Sorcery +A:SP$ DamageAll | Cost$ 5 R | ValidCards$ Creature.withFlying | NumDmg$ 6 | SpellDescription$ Tumble deals 6 damage to each creature with flying. +Oracle:Tumble deals 6 damage to each creature with flying. +End \ No newline at end of file diff --git a/res/cardsfolder/s/supply_demand.txt b/res/cardsfolder/s/supply_demand.txt new file mode 100644 index 00000000000..b282572319e --- /dev/null +++ b/res/cardsfolder/s/supply_demand.txt @@ -0,0 +1,17 @@ +Name:Supply +ManaCost:X W G +AlternateMode: Split +Types:Sorcery +A:SP$ Token | Cost$ X W G | TokenAmount$ X | References$ X | TokenName$ Saproling | TokenTypes$ Creature,Saproling | TokenOwner$ You | TokenColors$ Green | TokenPower$ 1 | TokenToughness$ 1 | SpellDescription$ Put X 1/1 green Saproling creature tokens onto the battlefield. +SVar:X:Count$xPaid +SetInfo:DIS Uncommon +Oracle:Put X 1/1 green Saproling creature tokens onto the battlefield. + +ALTERNATE + +Name:Demand +ManaCost:1 W U +Types:Sorcery +A:SP$ ChangeZone | Cost$ 1 W U | Origin$ Library | Destination$ Hand | ChangeType$ Card.MultiColor | ChangeNum$ 1 | SpellDescription$ Search your library for a multicolored card, reveal it, and put it into your hand. Then shuffle your library. +Oracle:Search your library for a multicolored card, reveal it, and put it into your hand. Then shuffle your library. +End \ No newline at end of file From 74643082d873b817c519ded0557882b1d40ad4ec Mon Sep 17 00:00:00 2001 From: Agetian Date: Wed, 6 Mar 2013 06:11:13 +0000 Subject: [PATCH 04/40] - Experimental fix for the Picture URL not being processed correctly for split cards when downloading card images (can't test because for some reason the LQ picture downloader crashes for me, even without this fix in its stock trunk form). --- .../java/forge/gui/download/GuiDownloadPicturesLQ.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java index f4ad0762fc2..f38fd6b65ec 100644 --- a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java +++ b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java @@ -67,7 +67,14 @@ public class GuiDownloadPicturesLQ extends GuiDownloader { for (final IPaperCard c : CardDb.instance().getUniqueCards()) { //System.out.println(c.getName()); CardRules cardRules = c.getRules(); - this.createDLObjects(cardRules.getPictureUrl(), cardRules.getMainPart().getName()); + String cardName = ""; + if (cardRules.getSplitType() == CardSplitType.Split) { + cardName = String.format("%s%s", cardRules.getMainPart().getName() + cardRules.getOtherPart().getName()); + System.out.println(cardName); + } else { + cardName = cardRules.getMainPart().getName(); + } + this.createDLObjects(cardRules.getPictureUrl(), cardName); ICardCharacteristics secondSide = cardRules.getOtherPart(); if (secondSide != null && cardRules.getSplitType() == CardSplitType.Transform) { From c045cbe93cda8e66b32b0959e5251031473f9b74 Mon Sep 17 00:00:00 2001 From: Agetian Date: Wed, 6 Mar 2013 07:01:30 +0000 Subject: [PATCH 05/40] - Reverted the last experimental fix due to a crash. Will recommit soon. --- .../java/forge/gui/download/GuiDownloadPicturesLQ.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java index f38fd6b65ec..f4ad0762fc2 100644 --- a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java +++ b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java @@ -67,14 +67,7 @@ public class GuiDownloadPicturesLQ extends GuiDownloader { for (final IPaperCard c : CardDb.instance().getUniqueCards()) { //System.out.println(c.getName()); CardRules cardRules = c.getRules(); - String cardName = ""; - if (cardRules.getSplitType() == CardSplitType.Split) { - cardName = String.format("%s%s", cardRules.getMainPart().getName() + cardRules.getOtherPart().getName()); - System.out.println(cardName); - } else { - cardName = cardRules.getMainPart().getName(); - } - this.createDLObjects(cardRules.getPictureUrl(), cardName); + this.createDLObjects(cardRules.getPictureUrl(), cardRules.getMainPart().getName()); ICardCharacteristics secondSide = cardRules.getOtherPart(); if (secondSide != null && cardRules.getSplitType() == CardSplitType.Transform) { From 3c918be7171b10c87d86606b2e231d562be5fc4a Mon Sep 17 00:00:00 2001 From: Agetian Date: Wed, 6 Mar 2013 07:17:33 +0000 Subject: [PATCH 06/40] - The real (hopefully) fix for the split card LQ pictures not being downloaded correctly from a picture URL. --- src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java index f4ad0762fc2..46b8b344e86 100644 --- a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java +++ b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java @@ -67,7 +67,11 @@ public class GuiDownloadPicturesLQ extends GuiDownloader { for (final IPaperCard c : CardDb.instance().getUniqueCards()) { //System.out.println(c.getName()); CardRules cardRules = c.getRules(); - this.createDLObjects(cardRules.getPictureUrl(), cardRules.getMainPart().getName()); + if (cardRules != null && cardRules.getSplitType() == CardSplitType.Split && cardRules.getOtherPart() != null) { + this.createDLObjects(cardRules.getPictureUrl(), String.format("%s%s", cardRules.getMainPart().getName(), cardRules.getOtherPart().getName())); + } else { + this.createDLObjects(cardRules.getPictureUrl(), cardRules.getMainPart().getName()); + } ICardCharacteristics secondSide = cardRules.getOtherPart(); if (secondSide != null && cardRules.getSplitType() == CardSplitType.Transform) { From cab87e9de2c882315bbaef2d8891cbd75a76ba65 Mon Sep 17 00:00:00 2001 From: Agetian Date: Wed, 6 Mar 2013 07:20:24 +0000 Subject: [PATCH 07/40] - Renamed the Assault // Battery script file name to agree with all other currently submitted split card script names. --- .gitattributes | 2 +- res/cardsfolder/a/{assault__battery.txt => assault_battery.txt} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename res/cardsfolder/a/{assault__battery.txt => assault_battery.txt} (100%) diff --git a/.gitattributes b/.gitattributes index 087b00363da..765046bb63f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -553,7 +553,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_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 similarity index 100% rename from res/cardsfolder/a/assault__battery.txt rename to res/cardsfolder/a/assault_battery.txt From f344fa6726c99bd434a39c956720023e3868ef86 Mon Sep 17 00:00:00 2001 From: Agetian Date: Wed, 6 Mar 2013 07:42:41 +0000 Subject: [PATCH 08/40] - Added Night // Day. --- .gitattributes | 1 + res/cardsfolder/n/night_day.txt | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 res/cardsfolder/n/night_day.txt diff --git a/.gitattributes b/.gitattributes index 765046bb63f..2a0b33f4bd7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7154,6 +7154,7 @@ res/cardsfolder/n/niblis_of_the_mist.txt -text res/cardsfolder/n/niblis_of_the_urn.txt -text res/cardsfolder/n/nicol_bolas.txt svneol=native#text/plain res/cardsfolder/n/nicol_bolas_planeswalker.txt svneol=native#text/plain +res/cardsfolder/n/night_day.txt -text res/cardsfolder/n/night_dealings.txt -text svneol=unset#text/plain res/cardsfolder/n/night_of_souls_betrayal.txt svneol=native#text/plain res/cardsfolder/n/night_revelers.txt -text diff --git a/res/cardsfolder/n/night_day.txt b/res/cardsfolder/n/night_day.txt new file mode 100644 index 00000000000..23136665344 --- /dev/null +++ b/res/cardsfolder/n/night_day.txt @@ -0,0 +1,18 @@ +Name:Night +ManaCost:B +AlternateMode: Split +Types:Instant +A:SP$ Pump | Cost$ B | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ -1 | NumDef$ -1 | IsCurse$ True | SpellDescription$ Target creature gets -1/-1 until end of turn. +SVar:Picture:http://www.wizards.com/global/images/magic/general/night_day.jpg +Oracle:Target creature gets -1/-1 until end of turn. +SetInfo:APC Uncommon + +ALTERNATE + +Name:Day +ManaCost:2 W +Types:Instant +A:SP$ PumpAll | Cost$ 1 W | ValidTgts$ Player | TgtPrompt$ Select target player | ValidCards$ Creature | NumAtt$ +1 | NumDef$ +1 | SpellDescription$ Creatures target player controls get +1/+1 until end of turn. +Oracle:Creatures target player controls get +1/+1 until end of turn. + +End From bc354e9bd3bb30a157f9e40d47be468d78e47ebe Mon Sep 17 00:00:00 2001 From: swordshine Date: Wed, 6 Mar 2013 08:05:41 +0000 Subject: [PATCH 09/40] - Updated picture urls for split cards --- res/cardsfolder/a/assault_battery.txt | 1 + res/cardsfolder/d/dead_gone.txt | 1 + res/cardsfolder/f/fire_ice.txt | 1 + res/cardsfolder/i/illusion_reality.txt | 1 + res/cardsfolder/l/life_death.txt | 1 + res/cardsfolder/p/pure_simple.txt | 1 + res/cardsfolder/r/rough_tumble.txt | 1 + res/cardsfolder/s/supply_demand.txt | 1 + 8 files changed, 8 insertions(+) diff --git a/res/cardsfolder/a/assault_battery.txt b/res/cardsfolder/a/assault_battery.txt index fae1d1f4b26..8360b760912 100644 --- a/res/cardsfolder/a/assault_battery.txt +++ b/res/cardsfolder/a/assault_battery.txt @@ -3,6 +3,7 @@ ManaCost:R AlternateMode: Split Types:Sorcery 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. +SVar:Picture:http://www.wizards.com/global/images/magic/general/assault_battery.jpg SetInfo:INV Uncommon SetInfo:TSB Uncommon SetInfo:HOP Uncommon diff --git a/res/cardsfolder/d/dead_gone.txt b/res/cardsfolder/d/dead_gone.txt index 29fe56be504..0225bcaaf17 100644 --- a/res/cardsfolder/d/dead_gone.txt +++ b/res/cardsfolder/d/dead_gone.txt @@ -3,6 +3,7 @@ ManaCost:R AlternateMode: Split Types:Instant A:SP$ DealDamage | Cost$ R | ValidTgts$ Creature | NumDmg$ 2 | SpellDescription$ Dead deals 2 damage to target creature. +SVar:Picture:http://www.wizards.com/global/images/magic/general/dead_gone.jpg SetInfo:PLC Common Oracle:Dead deals 2 damage to target creature. diff --git a/res/cardsfolder/f/fire_ice.txt b/res/cardsfolder/f/fire_ice.txt index f3ef0303faf..93a1a4b4ce9 100644 --- a/res/cardsfolder/f/fire_ice.txt +++ b/res/cardsfolder/f/fire_ice.txt @@ -3,6 +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. +SVar:Picture:http://www.wizards.com/global/images/magic/general/fire_ice.jpg SetInfo:APC Uncommon SetInfo:COM Uncommon SetInfo:DDJ Uncommon diff --git a/res/cardsfolder/i/illusion_reality.txt b/res/cardsfolder/i/illusion_reality.txt index b471b904652..88d7e064c2a 100644 --- a/res/cardsfolder/i/illusion_reality.txt +++ b/res/cardsfolder/i/illusion_reality.txt @@ -4,6 +4,7 @@ AlternateMode: Split Types:Instant A:SP$ ChooseColor | Cost$ U | Defined$ You | SubAbility$ Animate | SpellDescription$ Target spell or permanent becomes the color of your choice until end of turn. SVar:Animate:DB$ Animate | ValidTgts$ Card | TgtPrompt$ Select target spell or permanent to change the color of | TgtZone$ Stack,Battlefield | Colors$ ChosenColor | OverwriteColors$ True +SVar:Picture:http://www.wizards.com/global/images/magic/general/illusion_reality.jpg SetInfo:APC Uncommon Oracle:Target spell or permanent becomes the color of your choice until end of turn. diff --git a/res/cardsfolder/l/life_death.txt b/res/cardsfolder/l/life_death.txt index c07ea97d638..436b35ecfac 100644 --- a/res/cardsfolder/l/life_death.txt +++ b/res/cardsfolder/l/life_death.txt @@ -3,6 +3,7 @@ ManaCost:G AlternateMode: Split Types:Sorcery A:SP$ AnimateAll | Cost$ G | Power$ 1 | Toughness$ 1 | Types$ Creature | ValidCards$ Land.YouCtrl | SpellDescription$ All lands you control become 1/1 creatures until end of turn. They're still lands. +SVar:Picture:http://www.wizards.com/global/images/magic/general/life_death.jpg SetInfo:APC Uncommon SetInfo:DDJ Uncommon Oracle:All lands you control become 1/1 creatures until end of turn. They're still lands. diff --git a/res/cardsfolder/p/pure_simple.txt b/res/cardsfolder/p/pure_simple.txt index b3b8c7ebebe..7038c536e43 100644 --- a/res/cardsfolder/p/pure_simple.txt +++ b/res/cardsfolder/p/pure_simple.txt @@ -3,6 +3,7 @@ ManaCost:1 R G AlternateMode: Split Types:Sorcery A:SP$ Destroy | Cost$ 1 R G | ValidTgts$ Permanent.MultiColor | TgtPrompt$ Select target multicolored permanent | SpellDescription$ Destroy target multicolored permanent. +SVar:Picture:http://www.wizards.com/global/images/magic/general/pure_simple.jpg SetInfo:DIS Uncommon Oracle:Destroy target multicolored permanent. diff --git a/res/cardsfolder/r/rough_tumble.txt b/res/cardsfolder/r/rough_tumble.txt index 2c32d97a5bc..99da1dc4fa8 100644 --- a/res/cardsfolder/r/rough_tumble.txt +++ b/res/cardsfolder/r/rough_tumble.txt @@ -3,6 +3,7 @@ ManaCost:1 R AlternateMode: Split Types:Sorcery A:SP$ DamageAll | Cost$ 1 R | ValidCards$ Creature.withoutFlying | NumDmg$ 2 | SpellDescription$ Rough deals 2 damage to each creature without flying. +SVar:Picture:http://www.wizards.com/global/images/magic/general/rough_tumble.jpg SetInfo:PLC Uncommon Oracle:Rough deals 2 damage to each creature without flying. diff --git a/res/cardsfolder/s/supply_demand.txt b/res/cardsfolder/s/supply_demand.txt index b282572319e..df16cc6912f 100644 --- a/res/cardsfolder/s/supply_demand.txt +++ b/res/cardsfolder/s/supply_demand.txt @@ -4,6 +4,7 @@ AlternateMode: Split Types:Sorcery A:SP$ Token | Cost$ X W G | TokenAmount$ X | References$ X | TokenName$ Saproling | TokenTypes$ Creature,Saproling | TokenOwner$ You | TokenColors$ Green | TokenPower$ 1 | TokenToughness$ 1 | SpellDescription$ Put X 1/1 green Saproling creature tokens onto the battlefield. SVar:X:Count$xPaid +SVar:Picture:http://www.wizards.com/global/images/magic/general/supply_demand.jpg SetInfo:DIS Uncommon Oracle:Put X 1/1 green Saproling creature tokens onto the battlefield. From 0836137755e921c830eff0a6d46f0ed454fcece0 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Wed, 6 Mar 2013 10:42:54 +0000 Subject: [PATCH 10/40] cardfactory - no longer instanced. some methods moved here from CardFactoryUtil --- .../forge/card/ability/AbilityApiBased.java | 4 +- .../card/ability/effects/CloneEffect.java | 5 +- .../ability/effects/CopyPermanentEffect.java | 5 +- .../effects/CopySpellAbilityEffect.java | 6 +- .../card/ability/effects/PlayEffect.java | 2 +- .../forge/card/cardfactory/CardFactory.java | 152 +++++++++++++----- .../cardfactory/CardFactoryArtifacts.java | 6 +- .../card/cardfactory/CardFactoryUtil.java | 113 +------------ .../forge/card/spellability/AbilitySub.java | 4 +- src/main/java/forge/game/GameAction.java | 5 +- src/main/java/forge/game/zone/MagicStack.java | 3 +- src/main/java/forge/gui/GuiDisplayUtil.java | 2 +- .../forge/gui/match/nonsingleton/CField.java | 3 +- src/main/java/forge/item/CardDb.java | 9 +- src/main/java/forge/item/CardPrinted.java | 3 +- src/main/java/forge/item/CardToken.java | 4 +- src/main/java/forge/model/FModel.java | 25 +-- src/main/java/forge/quest/QuestWorld.java | 1 - 18 files changed, 163 insertions(+), 189 deletions(-) diff --git a/src/main/java/forge/card/ability/AbilityApiBased.java b/src/main/java/forge/card/ability/AbilityApiBased.java index 97c2b31e056..6c616e3bf7b 100644 --- a/src/main/java/forge/card/ability/AbilityApiBased.java +++ b/src/main/java/forge/card/ability/AbilityApiBased.java @@ -7,7 +7,7 @@ import forge.card.ability.effects.ChangeZoneAllEffect; import forge.card.ability.effects.ChangeZoneEffect; import forge.card.ability.effects.ManaEffect; import forge.card.ability.effects.ManaReflectedEffect; -import forge.card.cardfactory.CardFactoryUtil; +import forge.card.cardfactory.CardFactory; import forge.card.cost.Cost; import forge.card.spellability.AbilityActivated; import forge.card.spellability.AbilityManaPart; @@ -50,7 +50,7 @@ public class AbilityApiBased extends AbilityActivated { public AbilityActivated getCopy() { Target tgt = getTarget() == null ? null : new Target(getTarget()); AbilityActivated res = new AbilityApiBased(api, getSourceCard(), getPayCosts(), tgt, params); - CardFactoryUtil.copySpellAbility(this, res); + CardFactory.copySpellAbility(this, res); return res; } diff --git a/src/main/java/forge/card/ability/effects/CloneEffect.java b/src/main/java/forge/card/ability/effects/CloneEffect.java index 6df5dac3769..a46784ff9ba 100644 --- a/src/main/java/forge/card/ability/effects/CloneEffect.java +++ b/src/main/java/forge/card/ability/effects/CloneEffect.java @@ -12,6 +12,7 @@ import forge.Command; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityEffect; +import forge.card.cardfactory.CardFactory; import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; @@ -122,7 +123,7 @@ public class CloneEffect extends SpellAbilityEffect { stateToCopy = cardToCopy.getCurState(); } - CardFactoryUtil.copyState(cardToCopy, stateToCopy, tgtCard); + CardFactory.copyState(cardToCopy, stateToCopy, tgtCard); // must call this before addAbilityFactoryAbilities so cloned added abilities are handled correctly addExtraCharacteristics(tgtCard, sa, origSVars); CardFactoryUtil.addAbilityFactoryAbilities(tgtCard); @@ -140,7 +141,7 @@ public class CloneEffect extends SpellAbilityEffect { tgtCard.addAlternateState(CardCharacteristicName.Flipped); tgtCard.setState(CardCharacteristicName.Flipped); } - CardFactoryUtil.copyState(cardToCopy, CardCharacteristicName.Flipped, tgtCard); + CardFactory.copyState(cardToCopy, CardCharacteristicName.Flipped, tgtCard); addExtraCharacteristics(tgtCard, sa, origSVars); CardFactoryUtil.addAbilityFactoryAbilities(tgtCard); for (int i = 0; i < tgtCard.getStaticAbilityStrings().size(); i++) { diff --git a/src/main/java/forge/card/ability/effects/CopyPermanentEffect.java b/src/main/java/forge/card/ability/effects/CopyPermanentEffect.java index 521ee2cb8be..1bd5ff47928 100644 --- a/src/main/java/forge/card/ability/effects/CopyPermanentEffect.java +++ b/src/main/java/forge/card/ability/effects/CopyPermanentEffect.java @@ -12,6 +12,7 @@ import forge.Command; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityEffect; +import forge.card.cardfactory.CardFactory; import forge.card.cardfactory.CardFactoryUtil; import forge.card.mana.ManaCost; import forge.card.spellability.Ability; @@ -82,7 +83,7 @@ public class CopyPermanentEffect extends SpellAbilityEffect { if (!c.isToken() || c.isCopiedToken()) { // copy creature and put it onto the battlefield - copy = Singletons.getModel().getCardFactory().getCard(CardDb.getCard(c), sa.getActivatingPlayer()); + copy = CardFactory.getCard(CardDb.getCard(c), sa.getActivatingPlayer()); // when copying something stolen: copy.addController(controller); @@ -90,7 +91,7 @@ public class CopyPermanentEffect extends SpellAbilityEffect { copy.setToken(true); copy.setCopiedToken(true); } else { // isToken() - copy = CardFactoryUtil.copyStats(c); + copy = CardFactory.copyStats(c); copy.setName(c.getName()); copy.setImageFilename(c.getImageFilename()); diff --git a/src/main/java/forge/card/ability/effects/CopySpellAbilityEffect.java b/src/main/java/forge/card/ability/effects/CopySpellAbilityEffect.java index 2197bde1aaa..398073cef00 100644 --- a/src/main/java/forge/card/ability/effects/CopySpellAbilityEffect.java +++ b/src/main/java/forge/card/ability/effects/CopySpellAbilityEffect.java @@ -5,9 +5,9 @@ import java.util.Iterator; import java.util.List; import forge.Card; -import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityEffect; +import forge.card.cardfactory.CardFactory; import forge.card.spellability.SpellAbility; import forge.game.player.Player; import forge.gui.GuiChoose; @@ -99,7 +99,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { for (final SpellAbility chosenSAcopy : chosenSAs) { chosenSAcopy.setActivatingPlayer(controller); for (int i = 0; i < amount; i++) { - Singletons.getModel().getCardFactory().copySpellontoStack(card, chosenSAcopy.getSourceCard(), chosenSAcopy, true); + CardFactory.copySpellontoStack(card, chosenSAcopy.getSourceCard(), chosenSAcopy, true); } } } @@ -115,7 +115,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { chosenSA.setActivatingPlayer(controller); for (int i = 0; i < amount; i++) { - Singletons.getModel().getCardFactory().copySpellontoStack(card, chosenSA.getSourceCard(), chosenSA, true); + CardFactory.copySpellontoStack(card, chosenSA.getSourceCard(), chosenSA, true); } } } // end resolve diff --git a/src/main/java/forge/card/ability/effects/PlayEffect.java b/src/main/java/forge/card/ability/effects/PlayEffect.java index d9c5f8b3a7d..95e2e947c9a 100644 --- a/src/main/java/forge/card/ability/effects/PlayEffect.java +++ b/src/main/java/forge/card/ability/effects/PlayEffect.java @@ -150,7 +150,7 @@ public class PlayEffect extends SpellAbilityEffect { source.clearRemembered(); } if (sa.hasParam("CopyCard")) { - tgtCard = Singletons.getModel().getCardFactory().getCard(CardDb.getCard(tgtCard), sa.getActivatingPlayer()); + tgtCard = CardDb.getCard(tgtCard).toForgeCard(sa.getActivatingPlayer()); // when copying something stolen: tgtCard.addController(sa.getActivatingPlayer()); diff --git a/src/main/java/forge/card/cardfactory/CardFactory.java b/src/main/java/forge/card/cardfactory/CardFactory.java index 16caee3b83f..c16cb4e339f 100644 --- a/src/main/java/forge/card/cardfactory/CardFactory.java +++ b/src/main/java/forge/card/cardfactory/CardFactory.java @@ -17,7 +17,6 @@ */ package forge.card.cardfactory; -import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -28,10 +27,10 @@ import forge.CardCharacteristicName; import forge.CardColor; import forge.CardUtil; import forge.Color; +import forge.card.CardCharacteristics; 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; @@ -41,13 +40,9 @@ import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellPermanent; import forge.card.spellability.Target; import forge.card.trigger.TriggerHandler; -import forge.error.BugReporter; import forge.game.player.Player; -import forge.gui.GuiUtils; import forge.item.CardDb; import forge.item.IPaperCard; -import forge.properties.ForgeProps; -import forge.properties.NewConstants; /** *

@@ -68,33 +63,6 @@ import forge.properties.NewConstants; * @version $Id$ */ public class CardFactory { - - /** - *

- * Constructor for CardFactory. - *

- * - * @param file - * a {@link java.io.File} object. - */ - private final CardStorageReader reader; - - public CardFactory(final File file) { - - GuiUtils.checkEDT("CardFactory$constructor", false); - reader = new CardStorageReader(ForgeProps.getFile(NewConstants.CARDSFOLDER), true); - try { - // this fills in our map of card names to Card instances. - final List listCardRules = reader.loadCards(); - CardDb.setup(listCardRules.iterator()); - - } catch (final Exception ex) { - BugReporter.reportException(ex); - } - - } // constructor - - /** *

* copyCard. @@ -104,15 +72,15 @@ public class CardFactory { * a {@link forge.Card} object. * @return a {@link forge.Card} object. */ - public final Card copyCard(final Card in) { + public final static Card copyCard(final Card in) { final CardCharacteristicName curState = in.getCurState(); if (in.isInAlternateState()) { in.setState(CardCharacteristicName.Original); } - final Card out = this.getCard(CardDb.getCard(in), in.getOwner()); + final Card out = getCard(CardDb.getCard(in), in.getOwner()); out.setUniqueNumber(in.getUniqueNumber()); - CardFactoryUtil.copyCharacteristics(in, out); + CardFactory.copyCharacteristics(in, out); if (in.hasAlternateState()) { for (final CardCharacteristicName state : in.getStates()) { in.setState(state); @@ -120,7 +88,7 @@ public class CardFactory { out.addAlternateState(state); } out.setState(state); - CardFactoryUtil.copyCharacteristics(in, out); + CardFactory.copyCharacteristics(in, out); } in.setState(curState); out.setState(curState); @@ -157,7 +125,7 @@ public class CardFactory { * @param bCopyDetails * a boolean. */ - public final void copySpellontoStack(final Card source, final Card original, final SpellAbility sa, + public final static void copySpellontoStack(final Card source, final Card original, final SpellAbility sa, final boolean bCopyDetails) { //Player originalController = original.getController(); Player controller = sa.getActivatingPlayer(); @@ -243,7 +211,7 @@ public class CardFactory { * @return a {@link forge.Card} instance, owned by owner; or the special * blankCard */ - public final Card getCard(final IPaperCard cp, final Player owner) { + public final static Card getCard(final IPaperCard cp, final Player owner) { //System.out.println(cardName); CardRules cardRules = cp.getRules(); @@ -438,4 +406,110 @@ public class CardFactory { } } + /** + *

+ * Copies stats like power, toughness, etc. + *

+ * + * @param sim + * a {@link java.lang.Object} object. + * @return a {@link forge.Card} object. + */ + public static Card copyStats(final Card sim) { + final Card c = new Card(); + + c.setFlipCard(sim.isFlipCard()); + c.setDoubleFaced(sim.isDoubleFaced()); + c.setCurSetCode(sim.getCurSetCode()); + + final CardCharacteristicName origState = sim.getCurState(); + for (final CardCharacteristicName state : sim.getStates()) { + c.addAlternateState(state); + c.setState(state); + sim.setState(state); + CardFactory.copyCharacteristics(sim, c); + } + + sim.setState(origState); + c.setState(origState); + c.setRules(sim.getRules()); + + return c; + } // copyStats() + + /** + * Copy characteristics. + * + * @param from + * the from + * @param to + * the to + */ + private static void copyCharacteristics(final Card from, final Card to) { + to.setBaseAttack(from.getBaseAttack()); + to.setBaseDefense(from.getBaseDefense()); + to.setBaseLoyalty(from.getBaseLoyalty()); + to.setBaseAttackString(from.getBaseAttackString()); + to.setBaseDefenseString(from.getBaseDefenseString()); + to.setIntrinsicKeyword(from.getIntrinsicKeyword()); + to.setName(from.getName()); + to.setType(from.getCharacteristics().getType()); + to.setText(from.getSpellText()); + to.setManaCost(from.getManaCost()); + to.setColor(from.getColor()); + to.setSVars(from.getSVars()); + to.setIntrinsicAbilities(from.getIntrinsicAbilities()); + + to.setImageFilename(from.getImageFilename()); + to.setTriggers(from.getTriggers()); + to.setReplacementEffects(from.getReplacementEffects()); + to.setStaticAbilityStrings(from.getStaticAbilityStrings()); + + } + + /** + * Copy characteristics. + * + * @param from + * the from + * @param stateToCopy + * the state to copy + * @param to + * the to + */ + public static void copyState(final Card from, final CardCharacteristicName stateToCopy, final Card to) { + + // copy characteristics not associated with a state + to.setBaseLoyalty(from.getBaseLoyalty()); + to.setBaseAttackString(from.getBaseAttackString()); + to.setBaseDefenseString(from.getBaseDefenseString()); + to.setText(from.getSpellText()); + + // get CardCharacteristics for desired state + CardCharacteristics characteristics = from.getState(stateToCopy); + to.getCharacteristics().copy(characteristics); + // handle triggers and replacement effect through Card class interface + to.setTriggers(characteristics.getTriggers()); + to.setReplacementEffects(characteristics.getReplacementEffects()); + } + + public static void copySpellAbility(SpellAbility from, SpellAbility to) { + to.setDescription(from.getDescription()); + to.setStackDescription(from.getDescription()); + + if (from.getSubAbility() != null) { + to.setSubAbility(from.getSubAbility().getCopy()); + } + if (from.getRestrictions() != null) { + to.setRestrictions(from.getRestrictions()); + } + if (from.getConditions() != null) { + to.setConditions(from.getConditions()); + } + + for (String sVar : from.getSVars()) { + to.setSVar(sVar, from.getSVar(sVar)); + } + } + } // end class AbstractCardFactory diff --git a/src/main/java/forge/card/cardfactory/CardFactoryArtifacts.java b/src/main/java/forge/card/cardfactory/CardFactoryArtifacts.java index 2fd9dca9477..81920f7b5c3 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryArtifacts.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryArtifacts.java @@ -49,7 +49,7 @@ class CardFactoryArtifacts { public AbilityActivated getCopy() { AbilityActivated res = new AbilityGrindstone(getSourceCard(), getPayCosts(), getTarget() == null ? null : new Target(getTarget())); - CardFactoryUtil.copySpellAbility(this, res); + CardFactory.copySpellAbility(this, res); return res; } @@ -119,7 +119,7 @@ class CardFactoryArtifacts { public AbilityActivated getCopy() { AbilityActivated res = new AbilityScrollRack(getSourceCard(), getPayCosts(), getTarget() == null ? null : new Target(getTarget())); - CardFactoryUtil.copySpellAbility(this, res); + CardFactory.copySpellAbility(this, res); return res; } @@ -262,7 +262,7 @@ class CardFactoryArtifacts { public AbilityActivated getCopy() { AbilityActivated res = new AbilityTemporalAperture(getSourceCard(), getPayCosts(), getTarget() == null ? null : new Target(getTarget())); - CardFactoryUtil.copySpellAbility(this, res); + CardFactory.copySpellAbility(this, res); return res; } diff --git a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java index a30d9dcd13d..ac1e8a4becb 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java @@ -41,7 +41,6 @@ import forge.Constant; import forge.CounterType; import forge.GameEntity; import forge.Singletons; -import forge.card.CardCharacteristics; import forge.card.ability.AbilityFactory; import forge.card.ability.AbilityUtils; import forge.card.ability.ApiType; @@ -148,7 +147,7 @@ public class CardFactoryUtil { public AbilityActivated getCopy() { AbilityActivated res = new AbilityUnearth(getSourceCard(), getPayCosts(), getTarget() == null ? null : new Target(getTarget())); - CardFactoryUtil.copySpellAbility(this, res); + CardFactory.copySpellAbility(this, res); final SpellAbilityRestriction restrict = new SpellAbilityRestriction(); restrict.setZone(ZoneType.Graveyard); restrict.setSorcerySpeed(true); @@ -361,7 +360,7 @@ public class CardFactoryUtil { public AbilityActivated getCopy() { AbilityActivated res = new AbilityTransmute(getSourceCard(), getPayCosts(), getTarget() == null ? null : new Target(getTarget())); - CardFactoryUtil.copySpellAbility(this, res); + CardFactory.copySpellAbility(this, res); res.getRestrictions().setZone(ZoneType.Hand); return res; } @@ -2490,7 +2489,7 @@ public class CardFactoryUtil { final int multiplier = controller.getTokenDoublersMagnitude(); for (int i = 0; i < multiplier; i++) { - Card temp = CardFactoryUtil.copyStats(c); + Card temp = CardFactory.copyStats(c); for (final String kw : intrinsicKeywords) { temp.addIntrinsicKeyword(kw); @@ -2671,112 +2670,6 @@ public class CardFactoryUtil { || (c == CounterType.TIME); } - /** - *

- * Copies stats like power, toughness, etc. - *

- * - * @param sim - * a {@link java.lang.Object} object. - * @return a {@link forge.Card} object. - */ - public static Card copyStats(final Card sim) { - final Card c = new Card(); - - c.setFlipCard(sim.isFlipCard()); - c.setDoubleFaced(sim.isDoubleFaced()); - c.setCurSetCode(sim.getCurSetCode()); - - final CardCharacteristicName origState = sim.getCurState(); - for (final CardCharacteristicName state : sim.getStates()) { - c.addAlternateState(state); - c.setState(state); - sim.setState(state); - CardFactoryUtil.copyCharacteristics(sim, c); - } - - sim.setState(origState); - c.setState(origState); - c.setRules(sim.getRules()); - - return c; - } // copyStats() - - /** - * Copy characteristics. - * - * @param from - * the from - * @param to - * the to - */ - public static void copyCharacteristics(final Card from, final Card to) { - to.setBaseAttack(from.getBaseAttack()); - to.setBaseDefense(from.getBaseDefense()); - to.setBaseLoyalty(from.getBaseLoyalty()); - to.setBaseAttackString(from.getBaseAttackString()); - to.setBaseDefenseString(from.getBaseDefenseString()); - to.setIntrinsicKeyword(from.getIntrinsicKeyword()); - to.setName(from.getName()); - to.setType(from.getCharacteristics().getType()); - to.setText(from.getSpellText()); - to.setManaCost(from.getManaCost()); - to.setColor(from.getColor()); - to.setSVars(from.getSVars()); - to.setIntrinsicAbilities(from.getIntrinsicAbilities()); - - to.setImageFilename(from.getImageFilename()); - to.setTriggers(from.getTriggers()); - to.setReplacementEffects(from.getReplacementEffects()); - to.setStaticAbilityStrings(from.getStaticAbilityStrings()); - - } - - /** - * Copy characteristics. - * - * @param from - * the from - * @param stateToCopy - * the state to copy - * @param to - * the to - */ - public static void copyState(final Card from, final CardCharacteristicName stateToCopy, final Card to) { - - // copy characteristics not associated with a state - to.setBaseLoyalty(from.getBaseLoyalty()); - to.setBaseAttackString(from.getBaseAttackString()); - to.setBaseDefenseString(from.getBaseDefenseString()); - to.setText(from.getSpellText()); - - // get CardCharacteristics for desired state - CardCharacteristics characteristics = from.getState(stateToCopy); - to.getCharacteristics().copy(characteristics); - // handle triggers and replacement effect through Card class interface - to.setTriggers(characteristics.getTriggers()); - to.setReplacementEffects(characteristics.getReplacementEffects()); - } - - public static void copySpellAbility(SpellAbility from, SpellAbility to) { - to.setDescription(from.getDescription()); - to.setStackDescription(from.getDescription()); - - if (from.getSubAbility() != null) { - to.setSubAbility(from.getSubAbility().getCopy()); - } - if (from.getRestrictions() != null) { - to.setRestrictions(from.getRestrictions()); - } - if (from.getConditions() != null) { - to.setConditions(from.getConditions()); - } - - for (String sVar : from.getSVars()) { - to.setSVar(sVar, from.getSVar(sVar)); - } - } - public static void correctAbilityChainSourceCard(final SpellAbility sa, final Card card) { sa.setSourceCard(card); diff --git a/src/main/java/forge/card/spellability/AbilitySub.java b/src/main/java/forge/card/spellability/AbilitySub.java index 1146b6cdc44..bf4f169432d 100644 --- a/src/main/java/forge/card/spellability/AbilitySub.java +++ b/src/main/java/forge/card/spellability/AbilitySub.java @@ -28,7 +28,7 @@ import forge.card.ability.effects.ChangeZoneAllEffect; import forge.card.ability.effects.ChangeZoneEffect; import forge.card.ability.effects.ManaEffect; import forge.card.ability.effects.ManaReflectedEffect; -import forge.card.cardfactory.CardFactoryUtil; +import forge.card.cardfactory.CardFactory; import forge.game.player.AIPlayer; /** @@ -109,7 +109,7 @@ public final class AbilitySub extends SpellAbility implements java.io.Serializab public AbilitySub getCopy() { Target t = getTarget() == null ? null : new Target(getTarget()); AbilitySub res = new AbilitySub(api, getSourceCard(), t, params); - CardFactoryUtil.copySpellAbility(this, res); + CardFactory.copySpellAbility(this, res); return res; } diff --git a/src/main/java/forge/game/GameAction.java b/src/main/java/forge/game/GameAction.java index ee587c43a60..6f1937d9ab0 100644 --- a/src/main/java/forge/game/GameAction.java +++ b/src/main/java/forge/game/GameAction.java @@ -36,6 +36,7 @@ import forge.GameEntity; import forge.card.CardSplitType; import forge.card.CardType; import forge.card.ability.effects.AttachEffect; +import forge.card.cardfactory.CardFactory; import forge.card.cost.Cost; import forge.card.mana.ManaCost; import forge.card.replacement.ReplacementEffect; @@ -157,7 +158,7 @@ public class GameAction { if (zoneFrom.is(ZoneType.Battlefield)) { c.setFlipStaus(false); } - copied = forge.Singletons.getModel().getCardFactory().copyCard(c); + copied = CardFactory.copyCard(c); copied.setUnearthed(c.isUnearthed()); copied.setTapped(false); for (final Trigger trigger : copied.getTriggers()) { @@ -669,7 +670,7 @@ public class GameAction { if (p != null && p.is(ZoneType.Battlefield)) { lastKnownInfo = CardUtil.getLKICopy(c); c.clearCounters(); // remove all counters - library.add(forge.Singletons.getModel().getCardFactory().copyCard(c), libPosition); + library.add(CardFactory.copyCard(c), libPosition); } else { c.clearCounters(); // remove all counters library.add(c, libPosition); diff --git a/src/main/java/forge/game/zone/MagicStack.java b/src/main/java/forge/game/zone/MagicStack.java index c71aa4108f8..eaa766a1ea9 100644 --- a/src/main/java/forge/game/zone/MagicStack.java +++ b/src/main/java/forge/game/zone/MagicStack.java @@ -33,6 +33,7 @@ import forge.CardPredicates.Presets; import forge.Command; import forge.Singletons; import forge.card.ability.AbilityUtils; +import forge.card.cardfactory.CardFactory; import forge.card.cardfactory.CardFactoryUtil; import forge.card.mana.ManaCostBeingPaid; import forge.card.mana.ManaCostParser; @@ -609,7 +610,7 @@ public class MagicStack extends MyObservable { @Override public void execute() { for (int i = 0; i < sp.getSourceCard().getReplicateMagnitude(); i++) { - Singletons.getModel().getCardFactory().copySpellontoStack(sp.getSourceCard(), sp.getSourceCard(), sp, false); + CardFactory.copySpellontoStack(sp.getSourceCard(), sp.getSourceCard(), sp, false); } } }; diff --git a/src/main/java/forge/gui/GuiDisplayUtil.java b/src/main/java/forge/gui/GuiDisplayUtil.java index 20418b3766d..fb99dc6afc9 100644 --- a/src/main/java/forge/gui/GuiDisplayUtil.java +++ b/src/main/java/forge/gui/GuiDisplayUtil.java @@ -507,7 +507,7 @@ public final class GuiDisplayUtil { for (final String element : data) { final String[] cardinfo = element.trim().split("\\|"); - final Card c = Singletons.getModel().getCardFactory().getCard(CardDb.instance().getCard(cardinfo[0]), player); + final Card c = CardDb.instance().getCard(cardinfo[0]).toForgeCard(player); boolean hasSetCurSet = false; for (final String info : cardinfo) { diff --git a/src/main/java/forge/gui/match/nonsingleton/CField.java b/src/main/java/forge/gui/match/nonsingleton/CField.java index 2e14f5e8dae..ce1401632cc 100644 --- a/src/main/java/forge/gui/match/nonsingleton/CField.java +++ b/src/main/java/forge/gui/match/nonsingleton/CField.java @@ -34,6 +34,7 @@ import forge.Command; import forge.Constant; import forge.Constant.Preferences; import forge.Singletons; +import forge.card.cardfactory.CardFactory; import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.control.input.Input; @@ -301,7 +302,7 @@ public class CField implements ICDoc { faceDown.setName("Face Down"); choices2.add(faceDown); } else { - final Card faceDown = Singletons.getModel().getCardFactory().copyCard(crd); + final Card faceDown = CardFactory.copyCard(crd); faceDown.setState(CardCharacteristicName.Original); choices2.add(faceDown); } diff --git a/src/main/java/forge/item/CardDb.java b/src/main/java/forge/item/CardDb.java index 825c4433dd0..c5e0b13badd 100644 --- a/src/main/java/forge/item/CardDb.java +++ b/src/main/java/forge/item/CardDb.java @@ -20,7 +20,6 @@ package forge.item; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -81,7 +80,7 @@ public final class CardDb { * @param list * the new up */ - public static void setup(final Iterator list) { + public static void setup(final Iterable list) { if (CardDb.commonCards != null) { throw new RuntimeException("CardDb has already been initialized, don't do it twice please"); } @@ -426,9 +425,9 @@ public final class CardDb { uniqueSpecialCards.put(cardName, lastAdded); } - CardSorter(final Iterator parser) { - while (parser.hasNext()) { - this.addNewCard(parser.next()); + CardSorter(final Iterable parser) { + for (CardRules cr : parser) { + this.addNewCard(cr); } } } diff --git a/src/main/java/forge/item/CardPrinted.java b/src/main/java/forge/item/CardPrinted.java index 06e2b43d810..7f8d5dcdc56 100644 --- a/src/main/java/forge/item/CardPrinted.java +++ b/src/main/java/forge/item/CardPrinted.java @@ -27,6 +27,7 @@ import forge.CardUtil; import forge.Singletons; import forge.card.CardRarity; import forge.card.CardRules; +import forge.card.cardfactory.CardFactory; import forge.game.player.Player; @@ -295,7 +296,7 @@ public final class CardPrinted implements Comparable, InventoryItemF */ @Override public Card toForgeCard(Player owner) { - final Card c = Singletons.getModel().getCardFactory().getCard(this, owner); + final Card c = CardFactory.getCard(this, owner); return c; } diff --git a/src/main/java/forge/item/CardToken.java b/src/main/java/forge/item/CardToken.java index 80aa2399c6e..0dcb5098c8d 100644 --- a/src/main/java/forge/item/CardToken.java +++ b/src/main/java/forge/item/CardToken.java @@ -1,9 +1,9 @@ package forge.item; import forge.Card; -import forge.Singletons; import forge.card.CardRarity; import forge.card.CardRules; +import forge.card.cardfactory.CardFactory; import forge.game.player.Player; public class CardToken implements InventoryItemFromSet, IPaperCard { @@ -40,7 +40,7 @@ public class CardToken implements InventoryItemFromSet, IPaperCard { @Override public Card toForgeCard(Player owner) { - final Card c = Singletons.getModel().getCardFactory().getCard(this, owner); + final Card c = CardFactory.getCard(this, owner); return c; } diff --git a/src/main/java/forge/model/FModel.java b/src/main/java/forge/model/FModel.java index 6e7df7681c8..88290e7e27e 100644 --- a/src/main/java/forge/model/FModel.java +++ b/src/main/java/forge/model/FModel.java @@ -32,8 +32,9 @@ import forge.card.CardBlock; import forge.card.EditionCollection; import forge.card.FatPackData; import forge.card.FormatCollection; -import forge.card.cardfactory.CardFactory; +import forge.card.cardfactory.CardStorageReader; import forge.deck.CardCollections; +import forge.error.BugReporter; import forge.error.ExceptionHandler; import forge.game.GameState; import forge.game.GameType; @@ -41,6 +42,8 @@ import forge.game.MatchController; import forge.game.limited.GauntletMini; import forge.game.player.LobbyPlayer; import forge.gauntlet.GauntletData; +import forge.gui.GuiUtils; +import forge.item.CardDb; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; import forge.properties.ForgeProps; @@ -81,7 +84,6 @@ public enum FModel { private GauntletData gauntletData; private GauntletMini gauntlet; - private final CardFactory cardFactory; private final QuestController quest; private final CardCollections decks; @@ -154,7 +156,16 @@ public enum FModel { this.loadDynamicGamedata(); // Loads all cards (using progress bar). - this.cardFactory = new CardFactory(ForgeProps.getFile(NewConstants.CARDSFOLDER)); + GuiUtils.checkEDT("CardFactory$constructor", false); + final CardStorageReader reader = new CardStorageReader(ForgeProps.getFile(NewConstants.CARDSFOLDER), true); + try { + // this fills in our map of card names to Card instances. + CardDb.setup(reader.loadCards()); + + } catch (final Exception ex) { + BugReporter.reportException(ex); + } + this.decks = new CardCollections(ForgeProps.getFile(NewConstants.NEW_DECKS)); this.quest = new QuestController(); } @@ -412,14 +423,6 @@ public enum FModel { return gameState; } - /** - * TODO: Write javadoc for this method. - * @return - */ - public CardFactory getCardFactory() { - return cardFactory; - } - public GauntletMini getGauntletMini() { if (gauntlet == null) { diff --git a/src/main/java/forge/quest/QuestWorld.java b/src/main/java/forge/quest/QuestWorld.java index e0dfb175035..0f7d7ce6d44 100644 --- a/src/main/java/forge/quest/QuestWorld.java +++ b/src/main/java/forge/quest/QuestWorld.java @@ -24,7 +24,6 @@ import java.util.List; import com.google.common.base.Function; import forge.quest.data.GameFormatQuest; -import forge.util.FileSection; import forge.util.storage.StorageReaderFile; /** From f47e73adbfbfa569cf2577b9d58d3a9a3e3a2bea Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Wed, 6 Mar 2013 10:49:29 +0000 Subject: [PATCH 11/40] removing view-related code from Card class. --- src/main/java/forge/Card.java | 15 --------------- src/main/java/forge/gui/CardDetailPanel.java | 6 ++++-- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index 6e6f8eb35ba..36df8896514 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -1632,21 +1632,6 @@ public class Card extends GameEntity implements Comparable { return this.getCharacteristics().getManaCost(); } - /** - *

- * Display for the field manaCost. - *

- * - * @return a {@link java.lang.String} object. - */ - public final String getManaDisplay() { - // If this is a split card, display mana as X / Y. Otherwise, Display it as normal - if (this.getRules() != null && this.getRules().getSplitType() == CardSplitType.Split) { - return String.format("%s / %s", this.getState(CardCharacteristicName.LeftSplit).getManaCost(), - this.getState(CardCharacteristicName.RightSplit).getManaCost()); - } - return this.getCharacteristics().getManaCost().toString(); - } /** *

diff --git a/src/main/java/forge/gui/CardDetailPanel.java b/src/main/java/forge/gui/CardDetailPanel.java index 123207c1b0d..0c45041759e 100644 --- a/src/main/java/forge/gui/CardDetailPanel.java +++ b/src/main/java/forge/gui/CardDetailPanel.java @@ -202,10 +202,12 @@ public class CardDetailPanel extends FPanel { final boolean canShowThis = card.canBeShownTo(Singletons.getControl().getPlayer()); if (canShowThis) { - if (card.getManaCost().toString().equals("") || card.isLand()) { + if (card.getManaCost().isNoCost()) { this.nameCostLabel.setText(card.getName()); } else { - this.nameCostLabel.setText(card.getName() + " - " + card.getManaDisplay()); + // If you want to make a special view of split cards, keep that special code in this class. + // Better if you make several labels that that draw mana symbols + this.nameCostLabel.setText(card.getName() + " - " + card.getManaCost()); } this.typeLabel.setText(GuiDisplayUtil.formatCardType(card)); From 1c9beffe56d87f160f3ddcac66286954a920a625 Mon Sep 17 00:00:00 2001 From: Sloth Date: Wed, 6 Mar 2013 11:43:16 +0000 Subject: [PATCH 12/40] - Fixed logic error in canBeSacrificedBy. - Improved SacrificeAI. --- src/main/java/forge/Card.java | 2 +- .../forge/card/ability/ai/SacrificeAi.java | 81 +++++++++---------- .../card/ability/effects/SacrificeEffect.java | 5 ++ 3 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index 36df8896514..164696aa6ba 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -9195,7 +9195,7 @@ public class Card extends GameEntity implements Comparable { System.out.println("Trying to sacrifice immutables: " + this); return false; } - if (source != null && !getController().isOpponentOf(source.getActivatingPlayer()) + if (source != null && getController().isOpponentOf(source.getActivatingPlayer()) && getController().hasKeyword("Spells and abilities your opponents control can't cause you to sacrifice permanents.")) { return false; } diff --git a/src/main/java/forge/card/ability/ai/SacrificeAi.java b/src/main/java/forge/card/ability/ai/SacrificeAi.java index 8f04e0c08c8..1b70ba49a6f 100644 --- a/src/main/java/forge/card/ability/ai/SacrificeAi.java +++ b/src/main/java/forge/card/ability/ai/SacrificeAi.java @@ -3,6 +3,7 @@ package forge.card.ability.ai; import java.util.List; import forge.Card; import forge.CardLists; +import forge.CardPredicates; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; import forge.card.spellability.SpellAbility; @@ -20,42 +21,8 @@ public class SacrificeAi extends SpellAbilityAi { @Override protected boolean canPlayAI(AIPlayer ai, SpellAbility sa) { - boolean chance = sacrificeTgtAI(ai, sa); - // Some additional checks based on what is being sacrificed, and who is - // sacrificing - final Target tgt = sa.getTarget(); - if (tgt != null) { - final String valid = sa.getParam("SacValid"); - String num = sa.getParam("Amount"); - num = (num == null) ? "1" : num; - final int amount = AbilityUtils.calculateAmount(sa.getSourceCard(), num, sa); - - List list = - CardLists.getValidCards(ai.getOpponent().getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getSourceCard()); - - if (list.size() == 0) { - return false; - } - - final Card source = sa.getSourceCard(); - if (num.equals("X") && source.getSVar(num).equals("Count$xPaid")) { - // Set PayX here to maximum value. - final int xPay = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), amount); - source.setSVar("PayX", Integer.toString(xPay)); - } - - final int half = (amount / 2) + (amount % 2); // Half of amount - // rounded up - - // If the Human has at least half rounded up of the amount to be - // sacrificed, cast the spell - if (list.size() < half) { - return false; - } - } - - return chance; + return sacrificeTgtAI(ai, sa); } @Override @@ -82,16 +49,49 @@ public class SacrificeAi extends SpellAbilityAi { private boolean sacrificeTgtAI(final Player ai, final SpellAbility sa) { - final Card card = sa.getSourceCard(); + final Card source = sa.getSourceCard(); final Target tgt = sa.getTarget(); + final boolean destroy = sa.hasParam("Destroy"); Player opp = ai.getOpponent(); if (tgt != null) { tgt.resetTargets(); - if (opp.canBeTargetedBy(sa)) { - tgt.addTarget(opp); - return true; + if (!opp.canBeTargetedBy(sa)) { + return false; + } + tgt.addTarget(opp); + final String valid = sa.getParam("SacValid"); + String num = sa.getParam("Amount"); + num = (num == null) ? "1" : num; + final int amount = AbilityUtils.calculateAmount(sa.getSourceCard(), num, sa); + + List list = + CardLists.getValidCards(ai.getOpponent().getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getSourceCard()); + if (!destroy) { + list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(sa)); } else { + if (!CardLists.getKeyword(list, "Indestructible").isEmpty()) { + // human can choose to destroy indestructibles + return false; + } + } + + if (list.size() == 0) { + return false; + } + + if (num.equals("X") && source.getSVar(num).equals("Count$xPaid")) { + // Set PayX here to maximum value. + final int xPay = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), amount); + source.setSVar("PayX", Integer.toString(xPay)); + } + + final int half = (amount / 2) + (amount % 2); // Half of amount + // rounded up + + // If the Human has at least half rounded up of the amount to be + // sacrificed, cast the spell + if (!sa.isTrigger() && list.size() < half) { return false; } } @@ -108,9 +108,8 @@ public class SacrificeAi extends SpellAbilityAi { // TODO: Cast if the type is favorable: my "worst" valid is // worse than his "worst" valid final String num = sa.hasParam("Amount") ? sa.getParam("Amount") : "1"; - int amount = AbilityUtils.calculateAmount(card, num, sa); + int amount = AbilityUtils.calculateAmount(source, num, sa); - final Card source = sa.getSourceCard(); if (num.equals("X") && source.getSVar(num).equals("Count$xPaid")) { // Set PayX here to maximum value. amount = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), amount); diff --git a/src/main/java/forge/card/ability/effects/SacrificeEffect.java b/src/main/java/forge/card/ability/effects/SacrificeEffect.java index b9cd9074dda..a875e5f701d 100644 --- a/src/main/java/forge/card/ability/effects/SacrificeEffect.java +++ b/src/main/java/forge/card/ability/effects/SacrificeEffect.java @@ -3,6 +3,8 @@ package forge.card.ability.effects; import java.util.List; import forge.Card; +import forge.CardLists; +import forge.CardPredicates; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityEffect; @@ -51,6 +53,9 @@ public class SacrificeEffect extends SpellAbilityEffect { for (final Player p : tgts) { List battlefield = p.getCardsIn(ZoneType.Battlefield); List validTargets = AbilityUtils.filterListByType(battlefield, valid, sa); + if (!destroy) { + validTargets = CardLists.filter(validTargets, CardPredicates.canBeSacrificedBy(sa)); + } if (sa.hasParam("Random")) { choosenToSacrifice = Aggregates.random(validTargets, Math.min(amount, validTargets.size())); From 3cae6cbee1a822af0265ac6b93be540dce18f4d6 Mon Sep 17 00:00:00 2001 From: Sloth Date: Wed, 6 Mar 2013 12:05:34 +0000 Subject: [PATCH 13/40] - Added the quest deck Quicksilver 3. --- .gitattributes | 1 + res/quest/duels/Quicksilver 3.dck | 42 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 res/quest/duels/Quicksilver 3.dck diff --git a/.gitattributes b/.gitattributes index 2a0b33f4bd7..696001a7a66 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13067,6 +13067,7 @@ res/quest/duels/Pointy[!!-~]Haired[!!-~]Boss[!!-~]3.dck -text res/quest/duels/Princess[!!-~]Selenia[!!-~]1.dck -text res/quest/duels/Professor[!!-~]X[!!-~]2.dck -text res/quest/duels/Professor[!!-~]X[!!-~]3.dck -text +res/quest/duels/Quicksilver[!!-~]3.dck -text res/quest/duels/R2-D2[!!-~]3.dck -text res/quest/duels/Radagast[!!-~]2.dck -text res/quest/duels/Radiant[!!-~]2.dck -text diff --git a/res/quest/duels/Quicksilver 3.dck b/res/quest/duels/Quicksilver 3.dck new file mode 100644 index 00000000000..c26b7b3b04d --- /dev/null +++ b/res/quest/duels/Quicksilver 3.dck @@ -0,0 +1,42 @@ +[duel] +[metadata] +Name=Quicksilver 3 +Title=Quicksilver +Difficulty=very hard +Description=WUG Hypergenesis/Show and Tell deck with huge creatures +Icon=Quicksilver.jpg +Deck Type=constructed +[main] +2 Tropical Island +3 Tundra +4 Misty Rainforest +3 Polluted Delta +3 Scalding Tarn +2 Flooded Strand +1 Island +1 Plains +4 Elvish Spirit Guide +4 Simian Spirit Guide +2 Hypergenesis +4 Ardent Plea +4 Shardless Agent +4 Show and Tell +1 Angel of Serenity +1 Angel of Despair +1 Avacyn, Angel of Hope +1 Blazing Archon +1 Blightsteel Colossus +1 Bogardan Hellkite +1 Elesh Norn, Grand Cenobite +1 Emrakul, the Aeons Torn +1 Gisela, Blade of Goldnight +1 Iona, Shield of Emeria +1 Jin-Gitaxias, Core Augur +1 Karrthus, Tyrant of Jund +2 Maelstrom Wanderer +1 Molten Primordial +1 Pelakka Wurm +1 Platinum Emperion +1 Progenitus +1 Thraximundar +[sideboard] From 718424f89a827feae0eb1b6f675fcc1af4d73461 Mon Sep 17 00:00:00 2001 From: swordshine Date: Wed, 6 Mar 2013 12:21:20 +0000 Subject: [PATCH 14/40] - Added Trial//Error and Wax//Wane --- .gitattributes | 2 ++ res/cardsfolder/t/trial_error.txt | 19 +++++++++++++++++++ res/cardsfolder/w/wax_wane.txt | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 res/cardsfolder/t/trial_error.txt create mode 100644 res/cardsfolder/w/wax_wane.txt diff --git a/.gitattributes b/.gitattributes index 696001a7a66..bbdefdad5a9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11182,6 +11182,7 @@ res/cardsfolder/t/treva_the_renewer.txt svneol=native#text/plain res/cardsfolder/t/trevas_attendant.txt svneol=native#text/plain res/cardsfolder/t/trevas_charm.txt svneol=native#text/plain res/cardsfolder/t/trevas_ruins.txt svneol=native#text/plain +res/cardsfolder/t/trial_error.txt -text res/cardsfolder/t/triangle_of_war.txt svneol=native#text/plain res/cardsfolder/t/triassic_egg.txt svneol=native#text/plain res/cardsfolder/t/tribal_flames.txt svneol=native#text/plain @@ -11938,6 +11939,7 @@ res/cardsfolder/w/wave_of_reckoning.txt -text res/cardsfolder/w/wave_of_terror.txt svneol=native#text/plain res/cardsfolder/w/waves_of_aggression.txt -text res/cardsfolder/w/waveskimmer_aven.txt svneol=native#text/plain +res/cardsfolder/w/wax_wane.txt -text res/cardsfolder/w/waxmane_baku.txt -text res/cardsfolder/w/way_of_the_thief.txt -text res/cardsfolder/w/wayfarers_bauble.txt svneol=native#text/plain diff --git a/res/cardsfolder/t/trial_error.txt b/res/cardsfolder/t/trial_error.txt new file mode 100644 index 00000000000..3a05d0bb11e --- /dev/null +++ b/res/cardsfolder/t/trial_error.txt @@ -0,0 +1,19 @@ +Name:Trial +ManaCost:W U +AlternateMode: Split +Types:Instant +A:SP$ ChangeZoneAll | Cost$ W U | ValidTgts$ Creature | TgtPrompt$ Select target creature | RememberTargets$ True | ChangeType$ Creature.blockingRemembered,Creature.isBlockedByRemembered | Origin$ Battlefield | Destination$ Hand | SubAbility$ DBCleanup | SpellDescription$ Return all creatures blocking or blocked by target creature to their owner's hand. +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:RemAIDeck:True +SVar:Picture:http://www.wizards.com/global/images/magic/general/trial_error.jpg +SetInfo:DIS Uncommon +Oracle:Return all creatures blocking or blocked by target creature to their owner's hand. + +ALTERNATE + +Name:Error +ManaCost:U B +Types:Instant +A:SP$ Counter | Cost$ U B | TargetType$ Spell | TgtPrompt$ Select target multicolored spell | ValidTgts$ Card.MultiColor | SpellDescription$ Counter target multicolored spell. +Oracle:Counter target multicolored spell. +End \ No newline at end of file diff --git a/res/cardsfolder/w/wax_wane.txt b/res/cardsfolder/w/wax_wane.txt new file mode 100644 index 00000000000..9e2ae123d06 --- /dev/null +++ b/res/cardsfolder/w/wax_wane.txt @@ -0,0 +1,18 @@ +Name:Wax +ManaCost:G +AlternateMode: Split +Types:Instant +A:SP$ Pump | Cost$ G | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +2 | NumDef$ +2 | SpellDescription$ Target creature gets +2/+2 until end of turn. +SVar:Picture:http://www.wizards.com/global/images/magic/general/wax_wane.jpg +SetInfo:ARC Uncommon +SetInfo:INV Uncommon +Oracle:Target creature gets +2/+2 until end of turn. + +ALTERNATE + +Name:Wane +ManaCost:W +Types:Instant +A:SP$ Destroy | Cost$ W | ValidTgts$ Enchantment | TgtPrompt$ Select target enchantment | SpellDescription$ Destroy target enchantment. +Oracle:Destroy target enchantment. +End \ No newline at end of file From 3da93a1aeeb108fc007984f45a71c134464463ae Mon Sep 17 00:00:00 2001 From: swordshine Date: Wed, 6 Mar 2013 13:02:58 +0000 Subject: [PATCH 15/40] - Fixed Murderous Spoils --- res/cardsfolder/m/murderous_spoils.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/cardsfolder/m/murderous_spoils.txt b/res/cardsfolder/m/murderous_spoils.txt index f646be0a1e9..cdf225db831 100644 --- a/res/cardsfolder/m/murderous_spoils.txt +++ b/res/cardsfolder/m/murderous_spoils.txt @@ -1,7 +1,7 @@ Name:Murderous Spoils ManaCost:5 B Types:Instant -A:SP$ Destroy | Cost$ 5 B | ValidTgts$ Creature | TgtPrompt$ Select target creature | SubAbility$ StealEquip | NoRegen$ True | SpellDescription$ Destroy target nonblack creature. It can't be regenerated. You gain control of all Equipment that was attached to it. (This effect lasts indefinitely.) +A:SP$ Destroy | Cost$ 5 B | ValidTgts$ Creature.nonBlack | TgtPrompt$ Select target non-black creature | SubAbility$ StealEquip | NoRegen$ True | SpellDescription$ Destroy target nonblack creature. It can't be regenerated. You gain control of all Equipment that was attached to it. (This effect lasts indefinitely.) SVar:StealEquip:DB$ GainControl | AllValid$ Targeted.Equipment+Attached SVar:Picture:http://www.wizards.com/global/images/magic/general/murderous_spoils.jpg Oracle:Destroy target nonblack creature. It can't be regenerated. You gain control of all Equipment that was attached to it. (This effect lasts indefinitely.) From 446bfa785edc99d98d24ed45b141423df84e9539 Mon Sep 17 00:00:00 2001 From: Sloth Date: Wed, 6 Mar 2013 13:03:47 +0000 Subject: [PATCH 16/40] - Improved AI of UntapAll. --- .../java/forge/card/ability/ai/UntapAllAi.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/forge/card/ability/ai/UntapAllAi.java b/src/main/java/forge/card/ability/ai/UntapAllAi.java index c2b53dfa1b3..8cf2becbcd9 100644 --- a/src/main/java/forge/card/ability/ai/UntapAllAi.java +++ b/src/main/java/forge/card/ability/ai/UntapAllAi.java @@ -1,18 +1,31 @@ package forge.card.ability.ai; +import java.util.List; + +import forge.Card; +import forge.CardLists; +import forge.Singletons; import forge.card.ability.SpellAbilityAi; import forge.card.spellability.AbilitySub; import forge.card.spellability.SpellAbility; import forge.game.player.AIPlayer; +import forge.game.zone.ZoneType; public class UntapAllAi extends SpellAbilityAi { @Override protected boolean canPlayAI(AIPlayer aiPlayer, SpellAbility sa) { - // check SubAbilities DoTrigger? + final Card source = sa.getSourceCard(); + final AbilitySub abSub = sa.getSubAbility(); if (abSub != null) { - return true; + String valid = ""; + List list = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield); + if (sa.hasParam("ValidCards")) { + valid = sa.getParam("ValidCards"); + } + list = CardLists.getValidCards(list, valid.split(","), source.getController(), source); + return !list.isEmpty(); } return false; } From 4153ee07ed72e65479d448bd64e669acd52a9fa4 Mon Sep 17 00:00:00 2001 From: Sloth Date: Wed, 6 Mar 2013 13:14:47 +0000 Subject: [PATCH 17/40] - Fixed multiple problems with Convoke. --- src/main/java/forge/game/GameActionPlay.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/forge/game/GameActionPlay.java b/src/main/java/forge/game/GameActionPlay.java index 49e78212e9d..0aae291fe75 100644 --- a/src/main/java/forge/game/GameActionPlay.java +++ b/src/main/java/forge/game/GameActionPlay.java @@ -180,23 +180,20 @@ public class GameActionPlay { List untappedCreats = CardLists.filter(spell.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); untappedCreats = CardLists.filter(untappedCreats, CardPredicates.Presets.UNTAPPED); - if (untappedCreats.size() != 0) { + if (!untappedCreats.isEmpty()) { final List choices = new ArrayList(); - for (final Card c : untappedCreats) { - choices.add(c); - } + choices.addAll(untappedCreats); ArrayList usableColors = new ArrayList(); ManaCostBeingPaid newCost = new ManaCostBeingPaid(originalCost.toString()); Card tapForConvoke = null; if (sa.getActivatingPlayer().isHuman()) { - tapForConvoke = GuiChoose.oneOrNone("Tap for Convoke? " + newCost.toString(), - choices); + tapForConvoke = GuiChoose.oneOrNone("Tap for Convoke? " + newCost.toString(), choices); } else { // TODO: AI to choose a creature to tap would go here // Probably along with deciding how many creatures to // tap } - while (tapForConvoke != null && untappedCreats.size() != 0) { + while (tapForConvoke != null && !untappedCreats.isEmpty()) { final Card workingCard = (Card) tapForConvoke; usableColors = GameActionPlay.getConvokableColors(workingCard, newCost); @@ -223,7 +220,7 @@ public class GameActionPlay { sa.addTappedForConvoke(workingCard); choices.remove(workingCard); untappedCreats.remove(workingCard); - if ((choices.size() < 2) || (newCost.getConvertedManaCost() == 0)) { + if (choices.isEmpty() || (newCost.getConvertedManaCost() == 0)) { break; } } else { @@ -239,7 +236,7 @@ public class GameActionPlay { } // will only be null if user cancelled. - if (tapForConvoke != null) { + if (!sa.getTappedForConvoke().isEmpty()) { // Convoked creats are tapped here with triggers // suppressed, // Then again when payment is done(In From 2f5f0f5f93f85e553232205cc19fb94acc3c8790 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 6 Mar 2013 13:56:02 +0000 Subject: [PATCH 18/40] - Added a fluff piece to the changes.txt file. - Added new card names to changes.txt. --- CHANGES.txt | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 5a7156417af..dae40938e5a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,12 +8,18 @@ Release Notes: A new quest world by Serrasmurf based on Ravinca has been added. -An effort is being made to implement the split cards (e.g. Fire/Ice) in Forge. +An effort is being made to implement the split cards (e.g. Fire/Ice) in Forge. The initial effort to add support for split cards may be considered complete and the relevant branch has reen reintegrated to trunk. Expect some rough edges and incompatibilities along the way. The "Scale Image Larger" option in the preferences should be fixed. It should no longer continue to scale images larger when it is disabled. The fat packs should now be available for purchase in the quest mode card shop. +Information for non-card items in spell shop are now shown in the card details panel. + +Multiple problems with Convoke have been fixed. + +Forge should now be the Magic rules enforcing program with the most supported cards! That means we finally beat MtGO! MtGO is missing 828 cards. Even subtracting the Power Nine, which were available in the MtGO cube for some time, that's more than we are missing (805) at the time this was written. + New Cards: @@ -28,6 +34,17 @@ Delaying Shield Fatal Lore Library of Lat-Nam Misfortune +Assault // Battery +Fire // Ice +Night // Day +Trial // Error +Wax // Wane +Dead // Gone +Illusion // Reality +Life // Death +Pure // Simple +Rough // Tumble +Supply // Demand New Phenomenons: From 0d1af64e84416b133dffb2d31bb18f0f15fa363e Mon Sep 17 00:00:00 2001 From: Agetian Date: Wed, 6 Mar 2013 14:34:47 +0000 Subject: [PATCH 19/40] - Fix a glitch that causes the "Add Card To Play" dev mode feature not to interact correctly with Split Cards as far as showing their color and name on stack goes. --- src/main/java/forge/game/GameActionPlay.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/forge/game/GameActionPlay.java b/src/main/java/forge/game/GameActionPlay.java index 0aae291fe75..6bb7c2b6687 100644 --- a/src/main/java/forge/game/GameActionPlay.java +++ b/src/main/java/forge/game/GameActionPlay.java @@ -73,6 +73,9 @@ public class GameActionPlay { * a {@link forge.card.spellability.SpellAbility} object. */ public final void playSpellAbilityForFree(final SpellAbility sa) { + final Card source = sa.getSourceCard(); + setSplitCardState(source, sa); // Split card support + if (sa.getPayCosts() != null) { if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { CharmEffect.makeChoices(sa); From c1e0346faaebd32ea1f3ef12bdaf714fb3c1245d Mon Sep 17 00:00:00 2001 From: Sloth Date: Wed, 6 Mar 2013 14:43:12 +0000 Subject: [PATCH 20/40] - Fixed Eye of the Storm. --- res/cardsfolder/e/eye_of_the_storm.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/cardsfolder/e/eye_of_the_storm.txt b/res/cardsfolder/e/eye_of_the_storm.txt index 532053ac2e4..4b8705905df 100644 --- a/res/cardsfolder/e/eye_of_the_storm.txt +++ b/res/cardsfolder/e/eye_of_the_storm.txt @@ -1,7 +1,7 @@ Name:Eye of the Storm ManaCost:5 U U Types:Enchantment -T:Mode$ SpellCast | ValidCard$ Card.Instant,Card.Sorcery | Execute$ TrigExileSpell | TriggerZones$ Battlefield | TriggerDescription$ Whenever a player casts an instant or sorcery card, exile it. Then that player copies each instant or sorcery card exiled with CARDNAME. For each copy, the player may cast the copy without paying its mana cost. +T:Mode$ SpellCast | ValidCard$ Instant.nonToken,Sorcery.nonToken | Execute$ TrigExileSpell | TriggerZones$ Battlefield | TriggerDescription$ Whenever a player casts an instant or sorcery card, exile it. Then that player copies each instant or sorcery card exiled with CARDNAME. For each copy, the player may cast the copy without paying its mana cost. SVar:TrigExileSpell:AB$ ChangeZone | Cost$ 0 | Defined$ TriggeredCard | Origin$ Stack | Destination$ Exile | Fizzle$ True | RememberChanged$ True | SubAbility$ DBPlaySpell SVar:DBPlaySpell:DB$ RepeatEach | UseImprinted$ True | RepeatCards$ Card.IsRemembered | ChooseOrder$ True | Zone$ Exile | RepeatSubAbility$ DBPlay SVar:DBPlay:DB$ Play | Defined$ Imprinted | Controller$ TriggeredCardController | WithoutManaCost$ True | CopyCard$ True | Optional$ True From 0b0f9ee09dd379e086da2f2bdae494fe5571f1b9 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Wed, 6 Mar 2013 15:06:25 +0000 Subject: [PATCH 21/40] Cosmetic changes for split card scripts --- res/cardsfolder/a/assault_battery.txt | 7 +++---- res/cardsfolder/d/dead_gone.txt | 3 +-- res/cardsfolder/f/fire_ice.txt | 7 +++---- res/cardsfolder/i/illusion_reality.txt | 3 +-- res/cardsfolder/l/life_death.txt | 5 ++--- res/cardsfolder/n/night_day.txt | 4 +--- res/cardsfolder/p/pure_simple.txt | 3 +-- res/cardsfolder/r/rough_tumble.txt | 3 +-- res/cardsfolder/s/supply_demand.txt | 3 +-- 9 files changed, 14 insertions(+), 24 deletions(-) diff --git a/res/cardsfolder/a/assault_battery.txt b/res/cardsfolder/a/assault_battery.txt index 8360b760912..b9454367de5 100644 --- a/res/cardsfolder/a/assault_battery.txt +++ b/res/cardsfolder/a/assault_battery.txt @@ -4,9 +4,6 @@ AlternateMode: Split Types:Sorcery 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. SVar:Picture:http://www.wizards.com/global/images/magic/general/assault_battery.jpg -SetInfo:INV Uncommon -SetInfo:TSB Uncommon -SetInfo:HOP Uncommon Oracle:Assault deals 2 damage to target creature or player. ALTERNATE @@ -16,4 +13,6 @@ 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. Oracle:Put a 3/3 green Elephant creature token onto the battlefield. -End +SetInfo:TSB Special +SetInfo:HOP Uncommon +SetInfo:INV Uncommon x2 \ No newline at end of file diff --git a/res/cardsfolder/d/dead_gone.txt b/res/cardsfolder/d/dead_gone.txt index 0225bcaaf17..d5ade5e10a6 100644 --- a/res/cardsfolder/d/dead_gone.txt +++ b/res/cardsfolder/d/dead_gone.txt @@ -4,7 +4,6 @@ AlternateMode: Split Types:Instant A:SP$ DealDamage | Cost$ R | ValidTgts$ Creature | NumDmg$ 2 | SpellDescription$ Dead deals 2 damage to target creature. SVar:Picture:http://www.wizards.com/global/images/magic/general/dead_gone.jpg -SetInfo:PLC Common Oracle:Dead deals 2 damage to target creature. ALTERNATE @@ -14,4 +13,4 @@ ManaCost:2 R Types:Instant A:SP$ ChangeZone | Cost$ 2 R | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Select target creature you don't control | Origin$ Battlefield | Destination$ Hand | SpellDescription$ Return target creature you don't control to its owner's hand. Oracle:Return target creature you don't control to its owner's hand. -End \ No newline at end of file +SetInfo:PLC Common \ No newline at end of file diff --git a/res/cardsfolder/f/fire_ice.txt b/res/cardsfolder/f/fire_ice.txt index 93a1a4b4ce9..a061e35adb8 100644 --- a/res/cardsfolder/f/fire_ice.txt +++ b/res/cardsfolder/f/fire_ice.txt @@ -4,9 +4,6 @@ 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. SVar:Picture:http://www.wizards.com/global/images/magic/general/fire_ice.jpg -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. ALTERNATE @@ -17,4 +14,6 @@ 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 +SetInfo:APC Uncommon +SetInfo:COM Uncommon +SetInfo:DDJ Uncommon \ No newline at end of file diff --git a/res/cardsfolder/i/illusion_reality.txt b/res/cardsfolder/i/illusion_reality.txt index 88d7e064c2a..8a805731680 100644 --- a/res/cardsfolder/i/illusion_reality.txt +++ b/res/cardsfolder/i/illusion_reality.txt @@ -5,7 +5,6 @@ Types:Instant A:SP$ ChooseColor | Cost$ U | Defined$ You | SubAbility$ Animate | SpellDescription$ Target spell or permanent becomes the color of your choice until end of turn. SVar:Animate:DB$ Animate | ValidTgts$ Card | TgtPrompt$ Select target spell or permanent to change the color of | TgtZone$ Stack,Battlefield | Colors$ ChosenColor | OverwriteColors$ True SVar:Picture:http://www.wizards.com/global/images/magic/general/illusion_reality.jpg -SetInfo:APC Uncommon Oracle:Target spell or permanent becomes the color of your choice until end of turn. ALTERNATE @@ -15,4 +14,4 @@ ManaCost:2 G Types:Instant A:SP$ Destroy | Cost$ 2 G | ValidTgts$ Artifact | TgtPrompt$ Select target artifact | SpellDescription$ Destroy target artifact. Oracle:Destroy target artifact. -End \ No newline at end of file +SetInfo:APC Uncommon \ No newline at end of file diff --git a/res/cardsfolder/l/life_death.txt b/res/cardsfolder/l/life_death.txt index 436b35ecfac..f2545760cb3 100644 --- a/res/cardsfolder/l/life_death.txt +++ b/res/cardsfolder/l/life_death.txt @@ -4,8 +4,6 @@ AlternateMode: Split Types:Sorcery A:SP$ AnimateAll | Cost$ G | Power$ 1 | Toughness$ 1 | Types$ Creature | ValidCards$ Land.YouCtrl | SpellDescription$ All lands you control become 1/1 creatures until end of turn. They're still lands. SVar:Picture:http://www.wizards.com/global/images/magic/general/life_death.jpg -SetInfo:APC Uncommon -SetInfo:DDJ Uncommon Oracle:All lands you control become 1/1 creatures until end of turn. They're still lands. ALTERNATE @@ -17,4 +15,5 @@ A:SP$ ChangeZone | Cost$ 1 B | Origin$ Graveyard | Destination$ Battlefield | Va SVar:DBLoseLifeYou:DB$ LoseLife | Defined$ You | LifeAmount$ X | References$ X SVar:X:Targeted$CardManaCost Oracle:Return target creature card from your graveyard to the battlefield. You lose life equal to its converted mana cost. -End \ No newline at end of file +SetInfo:APC Uncommon +SetInfo:DDJ Uncommon \ No newline at end of file diff --git a/res/cardsfolder/n/night_day.txt b/res/cardsfolder/n/night_day.txt index 23136665344..3493dff7369 100644 --- a/res/cardsfolder/n/night_day.txt +++ b/res/cardsfolder/n/night_day.txt @@ -5,7 +5,6 @@ Types:Instant A:SP$ Pump | Cost$ B | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ -1 | NumDef$ -1 | IsCurse$ True | SpellDescription$ Target creature gets -1/-1 until end of turn. SVar:Picture:http://www.wizards.com/global/images/magic/general/night_day.jpg Oracle:Target creature gets -1/-1 until end of turn. -SetInfo:APC Uncommon ALTERNATE @@ -14,5 +13,4 @@ ManaCost:2 W Types:Instant A:SP$ PumpAll | Cost$ 1 W | ValidTgts$ Player | TgtPrompt$ Select target player | ValidCards$ Creature | NumAtt$ +1 | NumDef$ +1 | SpellDescription$ Creatures target player controls get +1/+1 until end of turn. Oracle:Creatures target player controls get +1/+1 until end of turn. - -End +SetInfo:APC Uncommon \ No newline at end of file diff --git a/res/cardsfolder/p/pure_simple.txt b/res/cardsfolder/p/pure_simple.txt index 7038c536e43..3b566983e6a 100644 --- a/res/cardsfolder/p/pure_simple.txt +++ b/res/cardsfolder/p/pure_simple.txt @@ -4,7 +4,6 @@ AlternateMode: Split Types:Sorcery A:SP$ Destroy | Cost$ 1 R G | ValidTgts$ Permanent.MultiColor | TgtPrompt$ Select target multicolored permanent | SpellDescription$ Destroy target multicolored permanent. SVar:Picture:http://www.wizards.com/global/images/magic/general/pure_simple.jpg -SetInfo:DIS Uncommon Oracle:Destroy target multicolored permanent. ALTERNATE @@ -14,4 +13,4 @@ ManaCost:1 W G Types:Sorcery A:SP$ DestroyAll | Cost$ 1 W G | ValidCards$ Aura,Equipment | SpellDescription$ Destroy all Auras and Equipment. Oracle:Destroy all Auras and Equipment. -End \ No newline at end of file +SetInfo:DIS Uncommon \ No newline at end of file diff --git a/res/cardsfolder/r/rough_tumble.txt b/res/cardsfolder/r/rough_tumble.txt index 99da1dc4fa8..55430c479c9 100644 --- a/res/cardsfolder/r/rough_tumble.txt +++ b/res/cardsfolder/r/rough_tumble.txt @@ -4,7 +4,6 @@ AlternateMode: Split Types:Sorcery A:SP$ DamageAll | Cost$ 1 R | ValidCards$ Creature.withoutFlying | NumDmg$ 2 | SpellDescription$ Rough deals 2 damage to each creature without flying. SVar:Picture:http://www.wizards.com/global/images/magic/general/rough_tumble.jpg -SetInfo:PLC Uncommon Oracle:Rough deals 2 damage to each creature without flying. ALTERNATE @@ -14,4 +13,4 @@ ManaCost:5 R Types:Sorcery A:SP$ DamageAll | Cost$ 5 R | ValidCards$ Creature.withFlying | NumDmg$ 6 | SpellDescription$ Tumble deals 6 damage to each creature with flying. Oracle:Tumble deals 6 damage to each creature with flying. -End \ No newline at end of file +SetInfo:PLC Uncommon \ No newline at end of file diff --git a/res/cardsfolder/s/supply_demand.txt b/res/cardsfolder/s/supply_demand.txt index df16cc6912f..5ec6da11a42 100644 --- a/res/cardsfolder/s/supply_demand.txt +++ b/res/cardsfolder/s/supply_demand.txt @@ -5,7 +5,6 @@ Types:Sorcery A:SP$ Token | Cost$ X W G | TokenAmount$ X | References$ X | TokenName$ Saproling | TokenTypes$ Creature,Saproling | TokenOwner$ You | TokenColors$ Green | TokenPower$ 1 | TokenToughness$ 1 | SpellDescription$ Put X 1/1 green Saproling creature tokens onto the battlefield. SVar:X:Count$xPaid SVar:Picture:http://www.wizards.com/global/images/magic/general/supply_demand.jpg -SetInfo:DIS Uncommon Oracle:Put X 1/1 green Saproling creature tokens onto the battlefield. ALTERNATE @@ -15,4 +14,4 @@ ManaCost:1 W U Types:Sorcery A:SP$ ChangeZone | Cost$ 1 W U | Origin$ Library | Destination$ Hand | ChangeType$ Card.MultiColor | ChangeNum$ 1 | SpellDescription$ Search your library for a multicolored card, reveal it, and put it into your hand. Then shuffle your library. Oracle:Search your library for a multicolored card, reveal it, and put it into your hand. Then shuffle your library. -End \ No newline at end of file +SetInfo:DIS Uncommon \ No newline at end of file From 404552ed45b6906fcba7a36c2012f4fe82c07fb9 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Wed, 6 Mar 2013 15:07:04 +0000 Subject: [PATCH 22/40] Display of split costs in deck editor --- .../deckeditor/tables/ManaCostRenderer.java | 58 ++++++++++++++----- .../gui/deckeditor/tables/SColumnUtil.java | 12 ++-- 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/src/main/java/forge/gui/deckeditor/tables/ManaCostRenderer.java b/src/main/java/forge/gui/deckeditor/tables/ManaCostRenderer.java index f818a466aef..b1d86407488 100644 --- a/src/main/java/forge/gui/deckeditor/tables/ManaCostRenderer.java +++ b/src/main/java/forge/gui/deckeditor/tables/ManaCostRenderer.java @@ -24,6 +24,8 @@ import java.util.List; import javax.swing.JTable; import javax.swing.table.DefaultTableCellRenderer; +import forge.card.CardRules; +import forge.card.CardSplitType; import forge.card.mana.ManaCostShard; import forge.card.mana.ManaCost; import forge.gui.toolbox.CardFaceSymbols; @@ -34,7 +36,13 @@ import forge.gui.toolbox.CardFaceSymbols; public class ManaCostRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1770527102334163549L; - private ManaCost value; + static final int elemtWidth = 13; + static final int elemtGap = 0; + static final int padding0 = 1; + static final int spaceBetweenSplitCosts = 3; + + private ManaCost v1; + private ManaCost v2; /* * (non-Javadoc) @@ -46,8 +54,10 @@ public class ManaCostRenderer extends DefaultTableCellRenderer { @Override public final Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) { - this.value = (ManaCost) value; - this.setToolTipText(this.value.toString()); + CardRules v = value instanceof CardRules ? (CardRules) value : null; + this.v1 = v == null ? ManaCost.NO_COST : v.getMainPart().getManaCost(); + this.v2 = v == null || v.getSplitType() != CardSplitType.Split ? null : v.getOtherPart().getManaCost(); + this.setToolTipText(v2 == null ? v1.toString() : v1.toString() + " / " + v2.toString()); return super.getTableCellRendererComponent(table, "", isSelected, hasFocus, row, column); } @@ -60,18 +70,38 @@ public class ManaCostRenderer extends DefaultTableCellRenderer { public final void paint(final Graphics g) { super.paint(g); - final int elemtWidth = 13; - final int elemtGap = 0; - final int padding = 1; - - float xpos = padding; - - final int genericManaCost = this.value.getGenericCost(); - final int xManaCosts = this.value.countX(); - final boolean hasGeneric = (genericManaCost > 0) || this.value.isPureGeneric(); - final List shards = this.value.getShards(); - final int cellWidth = this.getWidth(); + + if ( null == v2 ) + drawCost(g, v1, padding0, cellWidth); + else + { + int shards1 = v1.isPureGeneric() || v1.getGenericCost() > 0 ? 1 : 0; + int shards2 = v2.isPureGeneric() || v2.getGenericCost() > 0 ? 1 : 0; + shards1 += v1.getShards().size(); + shards2 += v2.getShards().size(); + + int perGlyph = (cellWidth - padding0 - spaceBetweenSplitCosts) / (shards1 + shards2); + perGlyph = Math.min(perGlyph, elemtWidth + elemtGap); + drawCost(g, v1, padding0, padding0 + perGlyph * shards1); + drawCost(g, v2, cellWidth - perGlyph * shards2, cellWidth ); + } + } + + /** + * TODO: Write javadoc for this method. + * @param g + * @param padding + * @param cellWidth + */ + private void drawCost(final Graphics g, ManaCost value, final int padding, final int cellWidth) { + float xpos = padding; + final int genericManaCost = value.getGenericCost(); + final int xManaCosts = value.countX(); + final boolean hasGeneric = (genericManaCost > 0) || this.v1.isPureGeneric(); + final List shards = value.getShards(); + + final int cntGlyphs = hasGeneric ? shards.size() + 1 : shards.size(); final float offsetIfNoSpace = cntGlyphs > 1 ? (cellWidth - padding - elemtWidth) / (cntGlyphs - 1f) : elemtWidth + elemtGap; diff --git a/src/main/java/forge/gui/deckeditor/tables/SColumnUtil.java b/src/main/java/forge/gui/deckeditor/tables/SColumnUtil.java index a30c993a678..208c0f84834 100644 --- a/src/main/java/forge/gui/deckeditor/tables/SColumnUtil.java +++ b/src/main/java/forge/gui/deckeditor/tables/SColumnUtil.java @@ -31,6 +31,7 @@ import com.google.common.base.Function; import forge.Singletons; import forge.card.CardAiHints; +import forge.card.CardRules; import forge.card.ColorSet; import forge.card.CardEdition; import forge.card.CardRarity; @@ -318,11 +319,14 @@ public final class SColumnUtil { private static final Pattern AE_FINDER = Pattern.compile("AE", Pattern.LITERAL); private static ManaCost toManaCost(final InventoryItem i) { - return i instanceof CardPrinted ? ((IPaperCard) i).getRules().getManaCost() : ManaCost.NO_COST; + return i instanceof IPaperCard ? ((IPaperCard) i).getRules().getManaCost() : ManaCost.NO_COST; } - + private static CardRules toCardRules(final InventoryItem i) { + return i instanceof IPaperCard ? ((IPaperCard) i).getRules() : null; + } + private static ColorSet toColor(final InventoryItem i) { - return i instanceof CardPrinted ? ((IPaperCard) i).getRules().getColor() : ColorSet.getNullColor(); + return i instanceof IPaperCard ? ((IPaperCard) i).getRules().getColor() : ColorSet.getNullColor(); } private static int toPower(final InventoryItem i) { @@ -430,7 +434,7 @@ public final class SColumnUtil { private static final Function, Object> FN_COST_GET = new Function, Object>() { @Override public Object apply(final Entry from) { - return SColumnUtil.toManaCost(from.getKey()); + return SColumnUtil.toCardRules(from.getKey()); } }; From 5c5df4ea3b83c51fd91fd93e788069df0aeeb8f8 Mon Sep 17 00:00:00 2001 From: Sloth Date: Wed, 6 Mar 2013 15:15:55 +0000 Subject: [PATCH 23/40] - Fixed Phyrexian Soulgorger. --- src/main/java/forge/game/phase/Upkeep.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/forge/game/phase/Upkeep.java b/src/main/java/forge/game/phase/Upkeep.java index 7dc959f3192..703f226955d 100644 --- a/src/main/java/forge/game/phase/Upkeep.java +++ b/src/main/java/forge/game/phase/Upkeep.java @@ -354,13 +354,14 @@ public class Upkeep extends Phase { final Command paidCommand = Command.BLANK; final Ability blankAbility = Upkeep.BlankAbility(c, upkeepCost); + blankAbility.setActivatingPlayer(controller); final Ability upkeepAbility = new Ability(c, ManaCost.ZERO) { @Override public void resolve() { if (controller.isHuman()) { GameActionUtil.payCostDuringAbilityResolve(controller, blankAbility, blankAbility.getPayCosts(), - paidCommand, unpaidCommand, null, game); + paidCommand, unpaidCommand, this, game); } else { // computer if (ComputerUtilCost.shouldPayCost(controller, c, upkeepCost) && ComputerUtilCost.canPayCost(blankAbility, controller)) { ComputerUtil.playNoStack((AIPlayer)controller, blankAbility, game); From e6493d898c95dcd5d73b18f18e0d7d6270a0dc78 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 6 Mar 2013 15:17:37 +0000 Subject: [PATCH 24/40] - Fixed LQ pic URLs. --- res/cardsfolder/d/dead_gone.txt | 2 +- res/cardsfolder/p/pure_simple.txt | 2 +- res/cardsfolder/s/supply_demand.txt | 2 +- res/cardsfolder/t/trial_error.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/res/cardsfolder/d/dead_gone.txt b/res/cardsfolder/d/dead_gone.txt index d5ade5e10a6..31bff11b8aa 100644 --- a/res/cardsfolder/d/dead_gone.txt +++ b/res/cardsfolder/d/dead_gone.txt @@ -3,7 +3,7 @@ ManaCost:R AlternateMode: Split Types:Instant A:SP$ DealDamage | Cost$ R | ValidTgts$ Creature | NumDmg$ 2 | SpellDescription$ Dead deals 2 damage to target creature. -SVar:Picture:http://www.wizards.com/global/images/magic/general/dead_gone.jpg +SVar:Picture:http://www.wizards.com/global/images/magic/general/deadgone.jpg Oracle:Dead deals 2 damage to target creature. ALTERNATE diff --git a/res/cardsfolder/p/pure_simple.txt b/res/cardsfolder/p/pure_simple.txt index 3b566983e6a..2e308369ef0 100644 --- a/res/cardsfolder/p/pure_simple.txt +++ b/res/cardsfolder/p/pure_simple.txt @@ -3,7 +3,7 @@ ManaCost:1 R G AlternateMode: Split Types:Sorcery A:SP$ Destroy | Cost$ 1 R G | ValidTgts$ Permanent.MultiColor | TgtPrompt$ Select target multicolored permanent | SpellDescription$ Destroy target multicolored permanent. -SVar:Picture:http://www.wizards.com/global/images/magic/general/pure_simple.jpg +SVar:Picture:http://www.wizards.com/global/images/magic/general/puresimple.jpg Oracle:Destroy target multicolored permanent. ALTERNATE diff --git a/res/cardsfolder/s/supply_demand.txt b/res/cardsfolder/s/supply_demand.txt index 5ec6da11a42..b68706d9ad3 100644 --- a/res/cardsfolder/s/supply_demand.txt +++ b/res/cardsfolder/s/supply_demand.txt @@ -4,7 +4,7 @@ AlternateMode: Split Types:Sorcery A:SP$ Token | Cost$ X W G | TokenAmount$ X | References$ X | TokenName$ Saproling | TokenTypes$ Creature,Saproling | TokenOwner$ You | TokenColors$ Green | TokenPower$ 1 | TokenToughness$ 1 | SpellDescription$ Put X 1/1 green Saproling creature tokens onto the battlefield. SVar:X:Count$xPaid -SVar:Picture:http://www.wizards.com/global/images/magic/general/supply_demand.jpg +SVar:Picture:http://www.wizards.com/global/images/magic/general/supplydemand.jpg Oracle:Put X 1/1 green Saproling creature tokens onto the battlefield. ALTERNATE diff --git a/res/cardsfolder/t/trial_error.txt b/res/cardsfolder/t/trial_error.txt index 3a05d0bb11e..6efb5ea221c 100644 --- a/res/cardsfolder/t/trial_error.txt +++ b/res/cardsfolder/t/trial_error.txt @@ -5,7 +5,7 @@ Types:Instant A:SP$ ChangeZoneAll | Cost$ W U | ValidTgts$ Creature | TgtPrompt$ Select target creature | RememberTargets$ True | ChangeType$ Creature.blockingRemembered,Creature.isBlockedByRemembered | Origin$ Battlefield | Destination$ Hand | SubAbility$ DBCleanup | SpellDescription$ Return all creatures blocking or blocked by target creature to their owner's hand. SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:RemAIDeck:True -SVar:Picture:http://www.wizards.com/global/images/magic/general/trial_error.jpg +SVar:Picture:http://www.wizards.com/global/images/magic/general/trialerror.jpg SetInfo:DIS Uncommon Oracle:Return all creatures blocking or blocked by target creature to their owner's hand. From 48dcd5bed4b0997f6a75f6ebd3276b5e6c4f1b9d Mon Sep 17 00:00:00 2001 From: myk Date: Wed, 6 Mar 2013 15:51:55 +0000 Subject: [PATCH 25/40] change base cost for unlocking sets to 4000 --- src/main/java/forge/quest/QuestUtilUnlockSets.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/forge/quest/QuestUtilUnlockSets.java b/src/main/java/forge/quest/QuestUtilUnlockSets.java index 2de5e3e16c1..14f907b0667 100644 --- a/src/main/java/forge/quest/QuestUtilUnlockSets.java +++ b/src/main/java/forge/quest/QuestUtilUnlockSets.java @@ -44,6 +44,7 @@ import forge.util.storage.IStorageView; * */ public class QuestUtilUnlockSets { + private static int UNLOCK_COST = 4000; /** * Consider unlocking a new expansion in limited quest format. @@ -64,10 +65,10 @@ public class QuestUtilUnlockSets { final List> setPrices = new ArrayList>(); for (CardEdition ed : getUnlockableEditions(qData)) { - int price = 7500; + int price = UNLOCK_COST; if (mapPrices.containsKey(ed.getName() + " Booster Pack")) { price = Math.max(new Double(60 * Math.pow(Math.sqrt(mapPrices.get(ed.getName() - + " Booster Pack")), 1.65)).intValue(), 7500); + + " Booster Pack")), 1.65)).intValue(), UNLOCK_COST); } setPrices.add(ImmutablePair.of(ed, price)); } From 3a7c0787d63db528704bf18d03ef79baacbe2b6d Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Wed, 6 Mar 2013 16:00:36 +0000 Subject: [PATCH 26/40] simple manacost display shows split card costs aside --- src/main/java/forge/gui/CardDetailPanel.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/forge/gui/CardDetailPanel.java b/src/main/java/forge/gui/CardDetailPanel.java index 0c45041759e..fa6898ff26c 100644 --- a/src/main/java/forge/gui/CardDetailPanel.java +++ b/src/main/java/forge/gui/CardDetailPanel.java @@ -36,10 +36,12 @@ import javax.swing.border.EtchedBorder; import org.apache.commons.lang3.StringUtils; import forge.Card; +import forge.CardCharacteristicName; import forge.CounterType; import forge.GameEntity; import forge.Singletons; import forge.card.CardEdition; +import forge.card.CardSplitType; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.toolbox.FLabel; @@ -205,9 +207,11 @@ public class CardDetailPanel extends FPanel { if (card.getManaCost().isNoCost()) { this.nameCostLabel.setText(card.getName()); } else { - // If you want to make a special view of split cards, keep that special code in this class. - // Better if you make several labels that that draw mana symbols - this.nameCostLabel.setText(card.getName() + " - " + card.getManaCost()); + String manaCost = card.getManaCost().toString(); + if ( card.getRules() != null && card.getRules().getSplitType() == CardSplitType.Split && card.getCurState() == CardCharacteristicName.Original) { + manaCost = card.getRules().getMainPart().getManaCost().toString() + " // " + card.getRules().getOtherPart().getManaCost().toString(); + } + this.nameCostLabel.setText(card.getName() + " - " + manaCost); } this.typeLabel.setText(GuiDisplayUtil.formatCardType(card)); From 066cad5aec4aa336d70bfa6c5fa0b0c283f04c67 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Wed, 6 Mar 2013 16:27:24 +0000 Subject: [PATCH 27/40] Drawing two costs in CardPanel for split cards --- .../forge/gui/toolbox/CardFaceSymbols.java | 5 ++++ .../java/forge/view/arcane/CardPanel.java | 26 ++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/main/java/forge/gui/toolbox/CardFaceSymbols.java b/src/main/java/forge/gui/toolbox/CardFaceSymbols.java index a2e05e06e9f..4bc8c37cc2e 100644 --- a/src/main/java/forge/gui/toolbox/CardFaceSymbols.java +++ b/src/main/java/forge/gui/toolbox/CardFaceSymbols.java @@ -222,6 +222,7 @@ public class CardFaceSymbols { g.drawImage(image, x, y, null); } + /** *

* getWidth. @@ -240,4 +241,8 @@ public class CardFaceSymbols { //System.out.println(String.format("%d for %s", width, manaCost.toString())); return width * 14; } + + public static int getHeight() { + return 14; + } } diff --git a/src/main/java/forge/view/arcane/CardPanel.java b/src/main/java/forge/view/arcane/CardPanel.java index cbbbe3dcb32..06d5d0c23ec 100644 --- a/src/main/java/forge/view/arcane/CardPanel.java +++ b/src/main/java/forge/view/arcane/CardPanel.java @@ -36,10 +36,13 @@ import javax.swing.JRootPane; import javax.swing.SwingUtilities; import forge.Card; +import forge.CardCharacteristicName; import forge.CounterType; import forge.ImageCache; import forge.Singletons; import forge.card.CardEdition; +import forge.card.CardSplitType; +import forge.card.mana.ManaCost; import forge.gui.CardContainer; import forge.gui.toolbox.CardFaceSymbols; import forge.properties.ForgePreferences.FPref; @@ -351,6 +354,17 @@ public class CardPanel extends JPanel implements CardContainer { } } + /** + * TODO: Write javadoc for this method. + * @param g + * @param manaCost + */ + private void drawManaCost(final Graphics g, ManaCost cost, int deltaY ) { + int width = CardFaceSymbols.getWidth(cost); + int height = CardFaceSymbols.getHeight(); + CardFaceSymbols.draw(g, cost, (this.cardXOffset + (this.cardWidth / 2)) - (width / 2), deltaY + this.cardYOffset + (this.cardHeight / 2) - height/2); + } + /** {@inheritDoc} */ @Override protected final void paintChildren(final Graphics g) { @@ -361,10 +375,16 @@ public class CardPanel extends JPanel implements CardContainer { } if (this.showCastingCost) { - int width = CardFaceSymbols.getWidth(this.getGameCard().getManaCost()); if (this.cardWidth < 200) { - CardFaceSymbols.draw(g, this.getGameCard().getManaCost(), (this.cardXOffset + (this.cardWidth / 2)) - - (width / 2), this.cardYOffset + (this.cardHeight / 2)); + Card gameCard = this.getGameCard(); + boolean showSplitMana = gameCard.getRules() != null && gameCard.getRules().getSplitType() == CardSplitType.Split && gameCard.getCurState() == CardCharacteristicName.Original; + if ( !showSplitMana ) { + drawManaCost(g, gameCard.getManaCost(), 0); + } else { + drawManaCost(g, gameCard.getRules().getMainPart().getManaCost(), +12); + drawManaCost(g, gameCard.getRules().getOtherPart().getManaCost(), -12); + } + } } From 1e0afc90853657c8e7d8b51ebc8c03fdeaae1d39 Mon Sep 17 00:00:00 2001 From: Agetian Date: Wed, 6 Mar 2013 17:21:05 +0000 Subject: [PATCH 28/40] - Corrected Assault // Battery SetInfo. --- res/cardsfolder/a/assault_battery.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/cardsfolder/a/assault_battery.txt b/res/cardsfolder/a/assault_battery.txt index b9454367de5..23e0732f152 100644 --- a/res/cardsfolder/a/assault_battery.txt +++ b/res/cardsfolder/a/assault_battery.txt @@ -15,4 +15,4 @@ A:SP$ Token | Cost$ 3 G | TokenAmount$ 1 | TokenName$ Elephant| TokenTypes$ Crea Oracle:Put a 3/3 green Elephant creature token onto the battlefield. SetInfo:TSB Special SetInfo:HOP Uncommon -SetInfo:INV Uncommon x2 \ No newline at end of file +SetInfo:INV Uncommon From 850d246193122e9f38d041bb6771804894798f46 Mon Sep 17 00:00:00 2001 From: myk Date: Wed, 6 Mar 2013 19:09:45 +0000 Subject: [PATCH 29/40] ensure the start button can only be clicked once at a time --- src/main/java/forge/gui/home/StartButton.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/forge/gui/home/StartButton.java b/src/main/java/forge/gui/home/StartButton.java index 67e4ed4b23e..20302f888ee 100644 --- a/src/main/java/forge/gui/home/StartButton.java +++ b/src/main/java/forge/gui/home/StartButton.java @@ -1,9 +1,12 @@ package forge.gui.home; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import javax.swing.JButton; +import javax.swing.SwingUtilities; import forge.gui.toolbox.FSkin; @@ -30,5 +33,17 @@ public class StartButton extends JButton { setIcon(FSkin.getIcon(FSkin.ButtonImages.IMG_BTN_START_OVER)); } }); + + addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setEnabled(false); + + // ensure the click action can resolve before we allow the button to be clicked again + SwingUtilities.invokeLater(new Runnable() { + @Override public void run() { setEnabled(true); } + }); + } + }); } } From b78f21fa21c17d4b38ab92e39935ee247a7e44ef Mon Sep 17 00:00:00 2001 From: swordshine Date: Thu, 7 Mar 2013 01:18:01 +0000 Subject: [PATCH 30/40] - Added a few split cards --- .gitattributes | 5 +++++ res/cardsfolder/h/hide_seek.txt | 20 ++++++++++++++++++++ res/cardsfolder/o/order_chaos.txt | 20 ++++++++++++++++++++ res/cardsfolder/p/pain_suffering.txt | 17 +++++++++++++++++ res/cardsfolder/s/spite_malice.txt | 17 +++++++++++++++++ res/cardsfolder/s/stand_deliver.txt | 17 +++++++++++++++++ res/cardsfolder/t/trial_error.txt | 3 +-- res/cardsfolder/w/wax_wane.txt | 5 ++--- 8 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 res/cardsfolder/h/hide_seek.txt create mode 100644 res/cardsfolder/o/order_chaos.txt create mode 100644 res/cardsfolder/p/pain_suffering.txt create mode 100644 res/cardsfolder/s/spite_malice.txt create mode 100644 res/cardsfolder/s/stand_deliver.txt diff --git a/.gitattributes b/.gitattributes index bbdefdad5a9..65ad7f1f2ab 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4871,6 +4871,7 @@ res/cardsfolder/h/hidden_path.txt svneol=native#text/plain res/cardsfolder/h/hidden_predators.txt -text res/cardsfolder/h/hidden_spider.txt svneol=native#text/plain res/cardsfolder/h/hidden_stag.txt -text svneol=unset#text/plain +res/cardsfolder/h/hide_seek.txt -text res/cardsfolder/h/hideous_end.txt svneol=native#text/plain res/cardsfolder/h/hideous_laughter.txt -text res/cardsfolder/h/hideous_visage.txt svneol=native#text/plain @@ -7425,6 +7426,7 @@ res/cardsfolder/o/orcish_spy.txt svneol=native#text/plain res/cardsfolder/o/orcish_squatters.txt -text svneol=unset#text/plain res/cardsfolder/o/orcish_squatters_avatar.txt -text res/cardsfolder/o/orcish_veteran.txt svneol=native#text/plain +res/cardsfolder/o/order_chaos.txt -text res/cardsfolder/o/order_of_leitbur.txt svneol=native#text/plain res/cardsfolder/o/order_of_the_ebon_hand.txt svneol=native#text/plain res/cardsfolder/o/order_of_the_golden_cricket.txt svneol=native#text/plain @@ -7519,6 +7521,7 @@ res/cardsfolder/p/pact_of_negation.txt svneol=native#text/plain res/cardsfolder/p/pact_of_the_titan.txt svneol=native#text/plain res/cardsfolder/p/pain_kami.txt svneol=native#text/plain res/cardsfolder/p/pain_magnification.txt svneol=native#text/plain +res/cardsfolder/p/pain_suffering.txt -text res/cardsfolder/p/painbringer.txt -text svneol=unset#text/plain res/cardsfolder/p/painful_memories.txt svneol=native#text/plain res/cardsfolder/p/painful_quandary.txt -text @@ -10071,6 +10074,7 @@ res/cardsfolder/s/spiritual_guardian.txt svneol=native#text/plain res/cardsfolder/s/spiritual_sanctuary.txt svneol=native#text/plain res/cardsfolder/s/spiritual_visit.txt -text res/cardsfolder/s/spiritualize.txt -text svneol=unset#text/plain +res/cardsfolder/s/spite_malice.txt -text res/cardsfolder/s/spitebellows.txt svneol=native#text/plain res/cardsfolder/s/spiteflame_witch.txt svneol=native#text/plain res/cardsfolder/s/spiteful_bully.txt svneol=native#text/plain @@ -10173,6 +10177,7 @@ res/cardsfolder/s/stampede_driver.txt svneol=native#text/plain res/cardsfolder/s/stampeding_rhino.txt svneol=native#text/plain res/cardsfolder/s/stampeding_serow.txt svneol=native#text/plain res/cardsfolder/s/stampeding_wildebeests.txt svneol=native#text/plain +res/cardsfolder/s/stand_deliver.txt -text res/cardsfolder/s/stand_firm.txt svneol=native#text/plain res/cardsfolder/s/stand_together.txt -text res/cardsfolder/s/standardize.txt -text svneol=unset#text/plain diff --git a/res/cardsfolder/h/hide_seek.txt b/res/cardsfolder/h/hide_seek.txt new file mode 100644 index 00000000000..c5a0d04cdb1 --- /dev/null +++ b/res/cardsfolder/h/hide_seek.txt @@ -0,0 +1,20 @@ +Name:Hide +ManaCost:W R +AlternateMode: Split +Types:Instant +A:SP$ ChangeZone | Cost$ W R | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | Origin$ Battlefield | Destination$ Library | LibraryPosition$ -1 | SpellDescription$ Put target artifact or enchantment on the bottom of its owner's library. +SVar:Picture:http://www.wizards.com/global/images/magic/general/hideseek.jpg + +Oracle:Put target artifact or enchantment on the bottom of its owner's library. + +ALTERNATE + +Name:Seek +ManaCost:W B +Types:Instant +A:SP$ ChangeZone | Cost$ W B | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | Origin$ Library | DefinedPlayer$ Targeted | Chooser$ You | Destination$ Exile | Changetype$ Card | ChangeNum$ 1 | RememberChanged$ True | SubAbility$ DBGainLife | SpellDescription$ Search target opponent's library for a card and exile it. You gain life equal to its converted mana cost. Then that player shuffles his or her library. +SVar:DBGainLife:DB$ GainLife | LifeAmount$ X | References$ X | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:X:Remembered$CardManaCost +Oracle:Search target opponent's library for a card and exile it. You gain life equal to its converted mana cost. Then that player shuffles his or her library. +SetInfo:DIS Rare \ No newline at end of file diff --git a/res/cardsfolder/o/order_chaos.txt b/res/cardsfolder/o/order_chaos.txt new file mode 100644 index 00000000000..26a27592eaa --- /dev/null +++ b/res/cardsfolder/o/order_chaos.txt @@ -0,0 +1,20 @@ +Name:Order +ManaCost:3 W +AlternateMode: Split +Types:Instant +A:SP$ ChangeZone | Cost$ 3 W | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature | Origin$ Battlefield | Destination$ Exile | SpellDescription$ Exile target attacking creature. +SVar:Picture:http://www.wizards.com/global/images/magic/general/order_chaos.jpg + +Oracle:Exile target attacking creature. + +ALTERNATE + +Name:Chaos +ManaCost:2 R +Types:Instant +A:SP$ Effect | Cost$ 2 R | Name$ Chaos Effect | StaticAbilities$ KWPump | AILogic$ Evasion | SpellDescription$ Creatures can't block this turn. +SVar:KWPump:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature | AddHiddenKeyword$ CARDNAME can't block. | Description$ Creatures can't block this turn. +SVar:RemAIDeck:True +Oracle:Creatures can't block this turn. +SetInfo:APC Uncommon +SetInfo:HOP Uncommon \ No newline at end of file diff --git a/res/cardsfolder/p/pain_suffering.txt b/res/cardsfolder/p/pain_suffering.txt new file mode 100644 index 00000000000..d254639f83b --- /dev/null +++ b/res/cardsfolder/p/pain_suffering.txt @@ -0,0 +1,17 @@ +Name:Pain +ManaCost:B +AlternateMode: Split +Types:Sorcery +A:SP$ Discard | Cost$ B | ValidTgts$ Player | NumCards$ 1 | Mode$ TgtChoose | SpellDescription$ Target player discards a card. +SVar:Picture:http://www.wizards.com/global/images/magic/general/pain_suffering.jpg +Oracle:Target player discards a card. + +ALTERNATE + +Name:Suffering +ManaCost:3 R +Types:Sorcery +A:SP$ Destroy | Cost$ 3 R | ValidTgts$ Land | TgtPrompt$ Select target land | SpellDescription$ Destroy target land. +Oracle:Destroy target land. +SetInfo:DDH Uncommon +SetInfo:INV Uncommon \ No newline at end of file diff --git a/res/cardsfolder/s/spite_malice.txt b/res/cardsfolder/s/spite_malice.txt new file mode 100644 index 00000000000..7a465049dc2 --- /dev/null +++ b/res/cardsfolder/s/spite_malice.txt @@ -0,0 +1,17 @@ +Name:Spite +ManaCost:3 U +AlternateMode: Split +Types:Instant +A:SP$ Counter | Cost$ 3 U | TargetType$ Spell | TgtPrompt$ Select target nonCreature spell | ValidTgts$ Card.nonCreature | SpellDescription$ Counter target noncreature spell. +SVar:Picture:http://www.wizards.com/global/images/magic/general/spite_malice.jpg +Oracle:Counter target noncreature spell. + +ALTERNATE + +Name:Malice +ManaCost:3 B +Types:Instant +A:SP$ Destroy | Cost$ 3 B | ValidTgts$ Creature.nonBlack | TgtPrompt$ Select target nonblack creature | NoRegen$ True | SpellDescription$ Destroy target nonblack creature. It can't be regenerated. +Oracle:Destroy target nonblack creature. It can't be regenerated. +SetInfo:DDH Uncommon +SetInfo:INV Uncommon \ No newline at end of file diff --git a/res/cardsfolder/s/stand_deliver.txt b/res/cardsfolder/s/stand_deliver.txt new file mode 100644 index 00000000000..81e01e2c497 --- /dev/null +++ b/res/cardsfolder/s/stand_deliver.txt @@ -0,0 +1,17 @@ +Name:Stand +ManaCost:W +AlternateMode: Split +Types:Instant +A:SP$ PreventDamage | Cost$ W | ValidTgts$ Creature | Amount$ 2 | TgtPrompt$ Select target creature | SpellDescription$ Prevent the next 2 damage that would be dealt to target creature this turn. +SVar:Picture:http://www.wizards.com/global/images/magic/general/stand_deliver.jpg + +Oracle:Prevent the next 2 damage that would be dealt to target creature this turn. + +ALTERNATE + +Name:Deliver +ManaCost:2 U +Types:Instant +A:SP$ ChangeZone | Cost$ 2 U | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | Origin$ Battlefield | Destination$ Hand | SpellDescription$ Return target permanent to its owner's hand. +Oracle:Return target permanent to its owner's hand. +SetInfo:INV Uncommon \ No newline at end of file diff --git a/res/cardsfolder/t/trial_error.txt b/res/cardsfolder/t/trial_error.txt index 6efb5ea221c..8f09b21280d 100644 --- a/res/cardsfolder/t/trial_error.txt +++ b/res/cardsfolder/t/trial_error.txt @@ -6,7 +6,6 @@ A:SP$ ChangeZoneAll | Cost$ W U | ValidTgts$ Creature | TgtPrompt$ Select target SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/trialerror.jpg -SetInfo:DIS Uncommon Oracle:Return all creatures blocking or blocked by target creature to their owner's hand. ALTERNATE @@ -16,4 +15,4 @@ ManaCost:U B Types:Instant A:SP$ Counter | Cost$ U B | TargetType$ Spell | TgtPrompt$ Select target multicolored spell | ValidTgts$ Card.MultiColor | SpellDescription$ Counter target multicolored spell. Oracle:Counter target multicolored spell. -End \ No newline at end of file +SetInfo:DIS Uncommon \ No newline at end of file diff --git a/res/cardsfolder/w/wax_wane.txt b/res/cardsfolder/w/wax_wane.txt index 9e2ae123d06..146a4ae4695 100644 --- a/res/cardsfolder/w/wax_wane.txt +++ b/res/cardsfolder/w/wax_wane.txt @@ -4,8 +4,6 @@ AlternateMode: Split Types:Instant A:SP$ Pump | Cost$ G | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +2 | NumDef$ +2 | SpellDescription$ Target creature gets +2/+2 until end of turn. SVar:Picture:http://www.wizards.com/global/images/magic/general/wax_wane.jpg -SetInfo:ARC Uncommon -SetInfo:INV Uncommon Oracle:Target creature gets +2/+2 until end of turn. ALTERNATE @@ -15,4 +13,5 @@ ManaCost:W Types:Instant A:SP$ Destroy | Cost$ W | ValidTgts$ Enchantment | TgtPrompt$ Select target enchantment | SpellDescription$ Destroy target enchantment. Oracle:Destroy target enchantment. -End \ No newline at end of file +SetInfo:ARC Uncommon +SetInfo:INV Uncommon \ No newline at end of file From 6004bbb91be20b6e811d959001f6d96e8b3e8cfd Mon Sep 17 00:00:00 2001 From: myk Date: Thu, 7 Mar 2013 06:47:44 +0000 Subject: [PATCH 31/40] add in Carnage quest opponent icon --- res/quest/quest-opponent-icons.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/res/quest/quest-opponent-icons.txt b/res/quest/quest-opponent-icons.txt index 9932bb93404..c807e841861 100644 --- a/res/quest/quest-opponent-icons.txt +++ b/res/quest/quest-opponent-icons.txt @@ -27,6 +27,7 @@ http://www.cardforge.org/fpics/questAvatars/Buffy.jpg http://www.cardforge.org/fpics/questAvatars/Bushwhacked.jpg http://www.cardforge.org/fpics/questAvatars/C3PO.jpg http://www.cardforge.org/fpics/questAvatars/Cable.jpg +http://www.cardforge.org/fpics/questAvatars/Carnage.jpg http://www.cardforge.org/fpics/questAvatars/Captain%20America.jpg http://www.cardforge.org/fpics/questAvatars/Catwoman.jpg http://www.cardforge.org/fpics/questAvatars/Chief_Wiggum.jpg From 8b08ac5e786478886c58a29366fbaab36ba3944b Mon Sep 17 00:00:00 2001 From: myk Date: Thu, 7 Mar 2013 08:15:24 +0000 Subject: [PATCH 32/40] added Quicksilver opponent avatar --- res/quest/quest-opponent-icons.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/res/quest/quest-opponent-icons.txt b/res/quest/quest-opponent-icons.txt index c807e841861..a75ec8758ec 100644 --- a/res/quest/quest-opponent-icons.txt +++ b/res/quest/quest-opponent-icons.txt @@ -146,6 +146,7 @@ http://www.cardforge.org/fpics/questAvatars/Princess%20Selenia.jpg http://www.cardforge.org/fpics/questAvatars/Private%20Domain.jpg http://www.cardforge.org/fpics/questAvatars/Professor%20X.jpg http://www.cardforge.org/fpics/questAvatars/Quest%20for%20Ulas%20Temple.jpg +http://www.cardforge.org/fpics/questAvatars/Quicksilver.jpg http://www.cardforge.org/fpics/questAvatars/R2-D2.jpg http://www.cardforge.org/fpics/questAvatars/Radagast.jpg http://www.cardforge.org/fpics/questAvatars/Radiant.jpg From 3c017f36d88754fbee35bf906218caadd021713c Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Thu, 7 Mar 2013 09:00:43 +0000 Subject: [PATCH 33/40] order attackes and blockers moved to PlayerController --- .../java/forge/game/phase/CombatUtil.java | 33 ++----------------- .../forge/game/player/PlayerController.java | 3 ++ .../forge/game/player/PlayerControllerAi.java | 11 +++++++ .../game/player/PlayerControllerHuman.java | 13 ++++++++ 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/main/java/forge/game/phase/CombatUtil.java b/src/main/java/forge/game/phase/CombatUtil.java index 9525c72a756..0ada189912e 100644 --- a/src/main/java/forge/game/phase/CombatUtil.java +++ b/src/main/java/forge/game/phase/CombatUtil.java @@ -49,7 +49,6 @@ import forge.game.GameActionUtil; import forge.game.GameState; import forge.game.GlobalRuleChange; import forge.game.ai.ComputerUtil; -import forge.game.ai.ComputerUtilBlock; import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.player.AIPlayer; @@ -58,7 +57,6 @@ import forge.game.zone.PlayerZone; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; import forge.gui.GuiDialog; -import forge.gui.GuiUtils; import forge.gui.framework.EDocID; import forge.gui.framework.SDisplayUtil; import forge.gui.match.views.VCombat; @@ -432,21 +430,8 @@ public class CombatUtil { if (blockers.size() <= 1) { continue; } - - List orderedBlockers = null; - if (player.isHuman()) { - GuiUtils.setPanelSelection(attacker); - List ordered = GuiChoose.order("Choose Blocking Order", "Damaged First", 0, blockers, null, attacker); - - orderedBlockers = new ArrayList(); - for (Object o : ordered) { - orderedBlockers.add((Card) o); - } - } - else { - orderedBlockers = ComputerUtilBlock.orderBlockers(attacker, blockers); - } - combat.setBlockerList(attacker, orderedBlockers); + List orderedBlockers = player.getController().orderBlockers(attacker, blockers); + combat.setBlockerList(attacker, orderedBlockers); } CombatUtil.showCombat(); // Refresh Combat Panel @@ -460,19 +445,7 @@ public class CombatUtil { continue; } - List orderedAttacker = null; - if (blocker.getController().isHuman()) { - GuiUtils.setPanelSelection(blocker); - List ordered = GuiChoose.order("Choose Blocking Order", "Damaged First", 0, attackers, null, blocker); - - orderedAttacker = new ArrayList(); - for (Object o : ordered) { - orderedAttacker.add((Card) o); - } - } - else { - orderedAttacker = ComputerUtilBlock.orderAttackers(blocker, attackers); - } + List orderedAttacker = blocker.getController().getController().orderAttackers(blocker, attackers); combat.setAttackersBlockedByList(blocker, orderedAttacker); } CombatUtil.showCombat(); diff --git a/src/main/java/forge/game/player/PlayerController.java b/src/main/java/forge/game/player/PlayerController.java index 60fc5ab4808..91092f71e57 100644 --- a/src/main/java/forge/game/player/PlayerController.java +++ b/src/main/java/forge/game/player/PlayerController.java @@ -97,4 +97,7 @@ public abstract class PlayerController { public abstract boolean confirmAction(SpellAbility sa, String mode, String message); public abstract boolean getWillPlayOnFirstTurn(String message); public abstract boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message); + + public abstract List orderBlockers(Card attacker, List blockers); + public abstract List orderAttackers(Card blocker, List attackers); } diff --git a/src/main/java/forge/game/player/PlayerControllerAi.java b/src/main/java/forge/game/player/PlayerControllerAi.java index 89b9daaf663..de9e1477167 100644 --- a/src/main/java/forge/game/player/PlayerControllerAi.java +++ b/src/main/java/forge/game/player/PlayerControllerAi.java @@ -15,6 +15,7 @@ import forge.game.ai.AiController; import forge.game.ai.AiInputBlock; import forge.game.ai.AiInputCommon; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilBlock; import forge.game.ai.ComputerUtilCombat; import forge.gui.GuiChoose; @@ -208,4 +209,14 @@ public class PlayerControllerAi extends PlayerController { return brains.confirmStaticApplication(hostCard, affected, logic, message); } + @Override + public List orderBlockers(Card attacker, List blockers) { + return ComputerUtilBlock.orderBlockers(attacker, blockers); + } + + @Override + public List orderAttackers(Card blocker, List attackers) { + return ComputerUtilBlock.orderAttackers(blocker, attackers); + } + } diff --git a/src/main/java/forge/game/player/PlayerControllerHuman.java b/src/main/java/forge/game/player/PlayerControllerHuman.java index e749b87b238..0ed479af529 100644 --- a/src/main/java/forge/game/player/PlayerControllerHuman.java +++ b/src/main/java/forge/game/player/PlayerControllerHuman.java @@ -22,6 +22,7 @@ import forge.game.GameType; import forge.game.phase.PhaseType; import forge.gui.GuiChoose; import forge.gui.GuiDialog; +import forge.gui.GuiUtils; import forge.gui.match.CMatchUI; import forge.item.CardPrinted; @@ -260,4 +261,16 @@ public class PlayerControllerHuman extends PlayerController { return !playDraw.equals(1); } + + @Override + public List orderBlockers(Card attacker, List blockers) { + GuiUtils.setPanelSelection(attacker); + return GuiChoose.order("Choose Blocking Order", "Damaged First", 0, blockers, null, attacker); + } + + @Override + public List orderAttackers(Card blocker, List attackers) { + GuiUtils.setPanelSelection(blocker); + return GuiChoose.order("Choose Blocking Order", "Damaged First", 0, attackers, null, blocker); + } } From 0db2f0aeb49dbf3d4b57eaa393e0af59e8ee7528 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Thu, 7 Mar 2013 10:43:43 +0000 Subject: [PATCH 34/40] 'Mulligan' phase removed --- .../java/forge/control/input/InputControl.java | 3 +++ .../java/forge/control/input/InputMulligan.java | 5 +++-- src/main/java/forge/game/GameNew.java | 15 --------------- src/main/java/forge/game/GameState.java | 4 ++++ src/main/java/forge/game/phase/PhaseHandler.java | 2 +- src/main/java/forge/game/phase/PhaseType.java | 2 -- src/main/java/forge/gui/InputProxy.java | 2 +- 7 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/main/java/forge/control/input/InputControl.java b/src/main/java/forge/control/input/InputControl.java index 01cccb60cbf..2d45e142391 100644 --- a/src/main/java/forge/control/input/InputControl.java +++ b/src/main/java/forge/control/input/InputControl.java @@ -148,6 +148,9 @@ public class InputControl extends MyObservable implements java.io.Serializable { * @return a {@link forge.control.input.Input} object. */ public final Input getActualInput() { + if ( !game.hasMulliganned() ) + return new InputMulligan(); + final PhaseHandler handler = game.getPhaseHandler(); final PhaseType phase = handler.getPhase(); final Player playerTurn = handler.getPlayerTurn(); diff --git a/src/main/java/forge/control/input/InputMulligan.java b/src/main/java/forge/control/input/InputMulligan.java index 6939ff93c8c..65989ff448f 100644 --- a/src/main/java/forge/control/input/InputMulligan.java +++ b/src/main/java/forge/control/input/InputMulligan.java @@ -174,7 +174,6 @@ public class InputMulligan extends Input { } ga.checkStateEffects(); - Singletons.getModel().getMatch().getInput().clearInput(); Player next = game.getPhaseHandler().getPlayerTurn(); @@ -187,7 +186,9 @@ public class InputMulligan extends Input { VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(next); SDisplayUtil.showTab(nextField); - game.getPhaseHandler().nextPhase(); + game.setMulliganComplete(); + Singletons.getModel().getMatch().getInput().clearInput(); + Singletons.getModel().getMatch().getInput().resetInput(); } @Override diff --git a/src/main/java/forge/game/GameNew.java b/src/main/java/forge/game/GameNew.java index e80a1fa73c2..45ed843e9b5 100644 --- a/src/main/java/forge/game/GameNew.java +++ b/src/main/java/forge/game/GameNew.java @@ -23,16 +23,12 @@ import forge.CardUtil; import forge.Singletons; import forge.card.trigger.TriggerHandler; import forge.card.trigger.TriggerType; -import forge.control.input.Input; -import forge.control.input.InputControl; -import forge.control.input.InputMulligan; import forge.deck.Deck; import forge.deck.CardPool; import forge.deck.DeckSection; import forge.error.BugReporter; import forge.game.event.FlipCoinEvent; import forge.game.phase.PhaseHandler; -import forge.game.phase.PhaseType; import forge.game.player.AIPlayer; import forge.game.player.LobbyPlayer; import forge.game.player.Player; @@ -389,18 +385,7 @@ public class GameNew { p.drawCards(p.getMaxHandSize()); } - - - game.getPhaseHandler().setPhaseState(PhaseType.MULLIGAN); - - InputControl control = match.getInput(); - Input tmp = new InputMulligan(); - control.setInput(tmp); - - Thread thGame = new GameInputUpdatesThread(match, game); - - match.getInput().getInput().showMessage(); thGame.setName("Game input updater"); thGame.start(); } // newGame() diff --git a/src/main/java/forge/game/GameState.java b/src/main/java/forge/game/GameState.java index ebe30d10398..5f84a1640c2 100644 --- a/src/main/java/forge/game/GameState.java +++ b/src/main/java/forge/game/GameState.java @@ -666,4 +666,8 @@ public class GameState { // TODO Auto-generated method stub return actionPlay; } + + public boolean mulliganned = false; + public boolean hasMulliganned(){ return mulliganned; } + public void setMulliganComplete() { mulliganned = true; } } diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index 97281b57b7a..17422cbf546 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -52,7 +52,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { /** Constant serialVersionUID=5207222278370963197L. */ private static final long serialVersionUID = 5207222278370963197L; - private PhaseType phase = PhaseType.MULLIGAN; + private PhaseType phase = PhaseType.UNTAP; private int turn = 0; // Start turn at 0, so first untap step will turn it to 1 diff --git a/src/main/java/forge/game/phase/PhaseType.java b/src/main/java/forge/game/phase/PhaseType.java index 75616ee2b62..a75cc138b06 100644 --- a/src/main/java/forge/game/phase/PhaseType.java +++ b/src/main/java/forge/game/phase/PhaseType.java @@ -9,8 +9,6 @@ import org.apache.commons.lang3.StringUtils; public enum PhaseType { - MULLIGAN("Mulligan"), - // Note: Mulligan is not part of "All Phases" which are strictly ingame phases UNTAP("Untap"), UPKEEP("Upkeep"), DRAW("Draw"), diff --git a/src/main/java/forge/gui/InputProxy.java b/src/main/java/forge/gui/InputProxy.java index d767040375b..8219cd50199 100644 --- a/src/main/java/forge/gui/InputProxy.java +++ b/src/main/java/forge/gui/InputProxy.java @@ -52,7 +52,7 @@ public class InputProxy extends MyObservable implements Observer { * @param in * a {@link forge.control.input.Input} object. */ - public void setInput(final Input in) { + public final void setInput(final Input in) { valid = true; this.input = in; this.input.showMessage(); // this call may invalidate the input by the time it returns From 186fd50a7c2754303a7ddd7a3aabeb37b85cac62 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 7 Mar 2013 13:09:30 +0000 Subject: [PATCH 35/40] - Added new card names to changes.txt. --- CHANGES.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index dae40938e5a..97248ead715 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -45,6 +45,11 @@ Life // Death Pure // Simple Rough // Tumble Supply // Demand +Hide // Seek +Order // Chaos +Pain // Suffering +Spite // Malice +Stand // Deliver New Phenomenons: From ff3652c766fcad68db55e1c5616f5f77ffeb7349 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Thu, 7 Mar 2013 14:58:51 +0000 Subject: [PATCH 36/40] restart game effect (from Karn Liberated) will set mulliganned flag to false --- .../forge/control/input/InputMulligan.java | 2 +- src/main/java/forge/game/GameNew.java | 224 +++++++++--------- src/main/java/forge/game/GameState.java | 2 +- 3 files changed, 112 insertions(+), 116 deletions(-) diff --git a/src/main/java/forge/control/input/InputMulligan.java b/src/main/java/forge/control/input/InputMulligan.java index 65989ff448f..6524268240d 100644 --- a/src/main/java/forge/control/input/InputMulligan.java +++ b/src/main/java/forge/control/input/InputMulligan.java @@ -186,7 +186,7 @@ public class InputMulligan extends Input { VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(next); SDisplayUtil.showTab(nextField); - game.setMulliganComplete(); + game.setMulliganned(true); Singletons.getModel().getMatch().getInput().clearInput(); Singletons.getModel().getMatch().getInput().resetInput(); } diff --git a/src/main/java/forge/game/GameNew.java b/src/main/java/forge/game/GameNew.java index 45ed843e9b5..165d5c34013 100644 --- a/src/main/java/forge/game/GameNew.java +++ b/src/main/java/forge/game/GameNew.java @@ -191,8 +191,6 @@ public class GameNew { removedAnteCards.put(player, myRemovedAnteCards); } - - if (rAICards.size() > 0) { String message = buildFourColumnList("AI deck contains the following cards that it can't play or may be buggy:", rAICards); if (GameType.Quest == game.getType()) { @@ -211,7 +209,116 @@ public class GameNew { JOptionPane.showMessageDialog(null, ante.toString(), "", JOptionPane.INFORMATION_MESSAGE); } - GameNew.actuateGame(match, game, false); + // Deciding which cards go to ante + if (preferences.getPrefBoolean(FPref.UI_ANTE)) { + final String nl = System.getProperty("line.separator"); + final StringBuilder msg = new StringBuilder(); + for (final Player p : game.getPlayers()) { + + final List lib = p.getCardsIn(ZoneType.Library); + Predicate goodForAnte = Predicates.not(CardPredicates.Presets.BASIC_LANDS); + Card ante = Aggregates.random(Iterables.filter(lib, goodForAnte)); + if (ante == null) { + throw new RuntimeException(p + " library is empty."); + } + game.getGameLog().add("Ante", p + " anted " + ante, 0); + VAntes.SINGLETON_INSTANCE.addAnteCard(p, ante); + game.getAction().moveTo(ZoneType.Ante, ante); + msg.append(p.getName()).append(" ante: ").append(ante).append(nl); + } + JOptionPane.showMessageDialog(null, msg, "Ante", JOptionPane.INFORMATION_MESSAGE); + } + + determineFirstTurnPlayer(match.getLastGameOutcome(), game); + + // Draw cards + for (final Player p1 : game.getPlayers()) { + p1.drawCards(p1.getMaxHandSize()); + } + + Thread thGame = new GameInputUpdatesThread(match, game); + thGame.setName("Game input updater"); + thGame.start(); + } + + // ultimate of Karn the Liberated + public static void restartGame(final MatchController match, final GameState game, final Player startingTurn, Map> playerLibraries) { + + Map players = match.getPlayers(); + Map playersConditions = new HashMap(); + + for (Player p : game.getPlayers()) { + playersConditions.put(p, players.get(p.getLobbyPlayer())); + } + + game.setMulliganned(false); + match.getInput().clearInput(); + + //Card.resetUniqueNumber(); + // need this code here, otherwise observables fail + forge.card.trigger.Trigger.resetIDs(); + TriggerHandler trigHandler = game.getTriggerHandler(); + trigHandler.clearTriggerSettings(); + trigHandler.clearDelayedTrigger(); + trigHandler.cleanUpTemporaryTriggers(); + trigHandler.suppressMode(TriggerType.ChangesZone); + + game.getStack().reset(); + GameAction action = game.getAction(); + + + for (Entry p : playersConditions.entrySet()) { + final Player player = p.getKey(); + player.setStartingLife(p.getValue().getStartingLife()); + player.setNumLandsPlayed(0); + putCardsOnBattlefield(player, p.getValue().getCardsOnBattlefield(player)); + + PlayerZone library = player.getZone(ZoneType.Library); + List newLibrary = playerLibraries.get(player); + for (Card c : newLibrary) { + action.moveTo(library, c); + } + + player.shuffle(); + player.getZone(ZoneType.Battlefield).updateObservers(); + player.updateObservers(); + player.getZone(ZoneType.Hand).updateObservers(); + } + + trigHandler.clearSuppression(TriggerType.ChangesZone); + + PhaseHandler phaseHandler = game.getPhaseHandler(); + phaseHandler.setPlayerTurn(startingTurn); + + // Draw cards + for (final Player p : game.getPlayers()) { + p.drawCards(p.getMaxHandSize()); + } + } + + /** + * TODO: Write javadoc for this method. + * @param match + * @param game + */ + private static void determineFirstTurnPlayer(final GameOutcome lastGameOutcome, final GameState game) { + // Only cut/coin toss if it's the first game of the match + Player goesFirst; + Player humanPlayer = Singletons.getControl().getPlayer(); + boolean isFirstGame = lastGameOutcome == null; + if (isFirstGame) { + goesFirst = GameNew.seeWhoPlaysFirstDice(game); + } else { + + goesFirst = lastGameOutcome.isWinner(humanPlayer.getLobbyPlayer()) ? humanPlayer.getOpponent() : humanPlayer; + } + String message = goesFirst + ( isFirstGame ? " has won the coin toss." : " lost the last game."); + boolean willPlay = goesFirst.getController().getWillPlayOnFirstTurn(message); + if ( goesFirst != humanPlayer ) { + JOptionPane.showMessageDialog(null, message + "\nComputer Going First", "You are drawing", JOptionPane.INFORMATION_MESSAGE); + } + goesFirst = willPlay ? goesFirst : goesFirst.getOpponent(); + game.getPhaseHandler().setPlayerTurn(goesFirst); } private static void initVariantsZones(final Player player, final PlayerStartConditions psc) { @@ -279,117 +386,6 @@ public class GameNew { } - // ultimate of Karn the Liberated - public static void restartGame(final MatchController match, final GameState game, final Player startingTurn, Map> playerLibraries) { - - Map players = match.getPlayers(); - Map playersConditions = new HashMap(); - - for (Player p : game.getPlayers()) { - playersConditions.put(p, players.get(p.getLobbyPlayer())); - } - - match.getInput().clearInput(); - - //Card.resetUniqueNumber(); - // need this code here, otherwise observables fail - forge.card.trigger.Trigger.resetIDs(); - TriggerHandler trigHandler = game.getTriggerHandler(); - trigHandler.clearTriggerSettings(); - trigHandler.clearDelayedTrigger(); - trigHandler.cleanUpTemporaryTriggers(); - trigHandler.suppressMode(TriggerType.ChangesZone); - - game.getStack().reset(); - GameAction action = game.getAction(); - - - for (Entry p : playersConditions.entrySet()) { - final Player player = p.getKey(); - player.setStartingLife(p.getValue().getStartingLife()); - player.setNumLandsPlayed(0); - putCardsOnBattlefield(player, p.getValue().getCardsOnBattlefield(player)); - - PlayerZone library = player.getZone(ZoneType.Library); - List newLibrary = playerLibraries.get(player); - for (Card c : newLibrary) { - action.moveTo(library, c); - } - - player.shuffle(); - player.getZone(ZoneType.Battlefield).updateObservers(); - player.updateObservers(); - player.getZone(ZoneType.Hand).updateObservers(); - } - - trigHandler.clearSuppression(TriggerType.ChangesZone); - - PhaseHandler phaseHandler = game.getPhaseHandler(); - phaseHandler.setPlayerTurn(startingTurn); - - GameNew.actuateGame(match, game, true); - } - - /** - * This must be separated from the newGame method since life totals and - * player details could be adjusted before the game is started. - * - * That process (also cleanup and observer updates) should be done in - * newGame, then when all is ready, call this function. - * @param isRestartedGame Whether the actuated game is the first start or a restart - */ - private static void actuateGame(final MatchController match, final GameState game, boolean isRestartedGame) { - if (!isRestartedGame) { - // Deciding which cards go to ante - if (preferences.getPrefBoolean(FPref.UI_ANTE)) { - final String nl = System.getProperty("line.separator"); - final StringBuilder msg = new StringBuilder(); - for (final Player p : game.getPlayers()) { - - final List lib = p.getCardsIn(ZoneType.Library); - Predicate goodForAnte = Predicates.not(CardPredicates.Presets.BASIC_LANDS); - Card ante = Aggregates.random(Iterables.filter(lib, goodForAnte)); - if (ante == null) { - throw new RuntimeException(p + " library is empty."); - } - game.getGameLog().add("Ante", p + " anted " + ante, 0); - VAntes.SINGLETON_INSTANCE.addAnteCard(p, ante); - game.getAction().moveTo(ZoneType.Ante, ante); - msg.append(p.getName()).append(" ante: ").append(ante).append(nl); - } - JOptionPane.showMessageDialog(null, msg, "Ante", JOptionPane.INFORMATION_MESSAGE); - } - - GameOutcome lastGameOutcome = match.getLastGameOutcome(); - // Only cut/coin toss if it's the first game of the match - Player goesFirst; - Player humanPlayer = Singletons.getControl().getPlayer(); - boolean isFirstGame = lastGameOutcome == null; - if (isFirstGame) { - goesFirst = GameNew.seeWhoPlaysFirstDice(game); - } else { - - goesFirst = lastGameOutcome.isWinner(humanPlayer.getLobbyPlayer()) ? humanPlayer.getOpponent() : humanPlayer; - } - String message = goesFirst + ( isFirstGame ? " has won the coin toss." : " lost the last game."); - boolean willPlay = goesFirst.getController().getWillPlayOnFirstTurn(message); - if ( goesFirst != humanPlayer ) { - JOptionPane.showMessageDialog(null, message + "\nComputer Going First", "You are drawing", JOptionPane.INFORMATION_MESSAGE); - } - goesFirst = willPlay ? goesFirst : goesFirst.getOpponent(); - game.getPhaseHandler().setPlayerTurn(goesFirst); - } - - // Draw cards - for (final Player p : game.getPlayers()) { - p.drawCards(p.getMaxHandSize()); - } - - Thread thGame = new GameInputUpdatesThread(match, game); - thGame.setName("Game input updater"); - thGame.start(); - } // newGame() - private static String buildFourColumnList(String firstLine, Iterable cAnteRemoved) { StringBuilder sb = new StringBuilder(firstLine); int i = 0; diff --git a/src/main/java/forge/game/GameState.java b/src/main/java/forge/game/GameState.java index 5f84a1640c2..88a1c9903f5 100644 --- a/src/main/java/forge/game/GameState.java +++ b/src/main/java/forge/game/GameState.java @@ -669,5 +669,5 @@ public class GameState { public boolean mulliganned = false; public boolean hasMulliganned(){ return mulliganned; } - public void setMulliganComplete() { mulliganned = true; } + public void setMulliganned(boolean value) { mulliganned = value; } } From 0496dca7059210770b07fe39067b85411df375ad Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Thu, 7 Mar 2013 19:09:57 +0000 Subject: [PATCH 37/40] fixed initial turn number (that affects draw on 1st turn) --- .../java/forge/game/phase/PhaseHandler.java | 6 ++--- src/main/java/forge/game/phase/PhaseUtil.java | 23 +------------------ src/main/java/forge/game/player/Player.java | 14 +++++++++++ 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index 17422cbf546..966777b33be 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -53,8 +53,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { private static final long serialVersionUID = 5207222278370963197L; private PhaseType phase = PhaseType.UNTAP; - private int turn = 0; - // Start turn at 0, so first untap step will turn it to 1 + private int turn = 1; + // Start turn at 1, since first untap is where we start private final transient Stack extraTurns = new Stack(); private final transient Map> extraPhases = new HashMap>(); @@ -262,7 +262,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { break; case DRAW: - if (getTurn() == 1 || PhaseUtil.skipDraw(this.getPlayerTurn())) { + if (getTurn() == 1 || this.getPlayerTurn().isSkippingDraw()) { this.setPlayersPriorityPermission(false); } else { this.getPlayerTurn().drawCards(1, true); diff --git a/src/main/java/forge/game/phase/PhaseUtil.java b/src/main/java/forge/game/phase/PhaseUtil.java index ee1e14b0668..ea4cdaa8e65 100644 --- a/src/main/java/forge/game/phase/PhaseUtil.java +++ b/src/main/java/forge/game/phase/PhaseUtil.java @@ -114,28 +114,7 @@ public class PhaseUtil { game.getPhaseHandler().setPlayersPriorityPermission(false); } - /** - *

- * skipDraw. - *

- * - * @param player - * a {@link forge.game.player.Player} object. - * @return a boolean. - */ - public static boolean skipDraw(final Player player) { - - if (player.hasKeyword("Skip your next draw step.")) { - player.removeKeyword("Skip your next draw step."); - return true; - } - - if (player.hasKeyword("Skip your draw step.")) { - return true; - } - - return false; - } + // ********* Declare Attackers *********** diff --git a/src/main/java/forge/game/player/Player.java b/src/main/java/forge/game/player/Player.java index a8d5cde84fd..8e7e8e7745a 100644 --- a/src/main/java/forge/game/player/Player.java +++ b/src/main/java/forge/game/player/Player.java @@ -3242,6 +3242,20 @@ public abstract class Player extends GameEntity implements Comparable { game.getStack().add(miracleTrigger); } + public boolean isSkippingDraw() { + + if (hasKeyword("Skip your next draw step.")) { + removeKeyword("Skip your next draw step."); + return true; + } + + if (hasKeyword("Skip your draw step.")) { + return true; + } + + return false; + } + /** * TODO: Write javadoc for this type. * From ec98a428d38ade6b25e1fbf824bb96b26050b87a Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Thu, 7 Mar 2013 21:08:11 +0000 Subject: [PATCH 38/40] Monocolored decks generation --- .gitattributes | 1 + src/main/java/forge/deck/DeckgenUtil.java | 45 ++++----- .../deck/generate/Generate2ColorDeck.java | 2 +- .../deck/generate/Generate3ColorDeck.java | 2 +- .../deck/generate/Generate5ColorDeck.java | 2 +- .../generate/GenerateColoredDeckBase.java | 4 + .../deck/generate/GenerateMonoColorDeck.java | 99 +++++++++++++++++++ .../gui/deckeditor/controllers/CDeckgen.java | 6 +- .../deck/generate/Generate2ColorDeckTest.java | 2 +- .../deck/generate/Generate3ColorDeckTest.java | 2 +- .../deck/generate/Generate5ColorDeckTest.java | 2 +- 11 files changed, 132 insertions(+), 35 deletions(-) create mode 100644 src/main/java/forge/deck/generate/GenerateMonoColorDeck.java diff --git a/.gitattributes b/.gitattributes index 65ad7f1f2ab..fd5078245cd 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14125,6 +14125,7 @@ src/main/java/forge/deck/generate/Generate3ColorDeck.java svneol=native#text/pla src/main/java/forge/deck/generate/Generate5ColorDeck.java svneol=native#text/plain src/main/java/forge/deck/generate/GenerateColoredDeckBase.java -text src/main/java/forge/deck/generate/GenerateDeckUtil.java -text +src/main/java/forge/deck/generate/GenerateMonoColorDeck.java -text src/main/java/forge/deck/generate/GenerateThemeDeck.java svneol=native#text/plain src/main/java/forge/deck/generate/package-info.java svneol=native#text/plain src/main/java/forge/deck/io/DeckFileHeader.java -text diff --git a/src/main/java/forge/deck/DeckgenUtil.java b/src/main/java/forge/deck/DeckgenUtil.java index 95a5adfe313..e370b055412 100644 --- a/src/main/java/forge/deck/DeckgenUtil.java +++ b/src/main/java/forge/deck/DeckgenUtil.java @@ -18,6 +18,8 @@ import forge.Singletons; import forge.deck.generate.Generate2ColorDeck; import forge.deck.generate.Generate3ColorDeck; import forge.deck.generate.Generate5ColorDeck; +import forge.deck.generate.GenerateColoredDeckBase; +import forge.deck.generate.GenerateMonoColorDeck; import forge.deck.generate.GenerateThemeDeck; import forge.game.player.PlayerType; import forge.item.CardDb; @@ -66,7 +68,7 @@ public class DeckgenUtil { * @return {@link forge.deck.Deck} */ public static Deck buildColorDeck(final String[] selection, PlayerType pt) { - ItemPoolView cards = null; + final Deck deck; // Replace "random" with "AI" for deck generation code @@ -74,22 +76,20 @@ public class DeckgenUtil { selection[i] = COLOR_VALS.get(selection[i]); } - // 2, 3, and 5 colors. - if (selection.length == 2) { - final Generate2ColorDeck gen = new Generate2ColorDeck( - selection[0], selection[1]); - cards = gen.get2ColorDeck(60, pt); + GenerateColoredDeckBase gen = null; + + if (selection.length == 1) { + gen = new GenerateMonoColorDeck(selection[0]); + } else if (selection.length == 2) { + gen = new Generate2ColorDeck(selection[0], selection[1]); + } else if (selection.length == 3) { + gen = new Generate3ColorDeck(selection[0], selection[1], selection[2]); + } else { + gen = new Generate5ColorDeck(); } - else if (selection.length == 3) { - final Generate3ColorDeck gen = new Generate3ColorDeck( - selection[0], selection[1], selection[2]); - cards = gen.get3ColorDeck(60, pt); - } - else { - final Generate5ColorDeck gen = new Generate5ColorDeck(); - cards = gen.get5ColorDeck(60, pt); - } - + + ItemPoolView cards = gen == null ? null : gen.getDeck(60, pt); + // After generating card lists, build deck. deck = new Deck(); deck.getMain().addAll(cards); @@ -131,8 +131,8 @@ public class DeckgenUtil { /** @return {@link forge.deck.Deck} */ public static Deck getRandomColorDeck(PlayerType pt) { - final int[] colorCount = new int[] {2, 3, 5}; - final int count = colorCount[(int) (Math.round(Math.random() * 2))]; + final int[] colorCount = new int[] {1, 2, 3, 5}; + final int count = colorCount[MyRandom.getRandom().nextInt(colorCount.length)]; final String[] selection = new String[count]; // A simulated selection of "random 1" will trigger the AI selection process. @@ -287,14 +287,7 @@ public class DeckgenUtil { public static boolean colorCheck(final String[] colors0) { boolean result = true; - if (colors0.length == 1) { - JOptionPane.showMessageDialog(null, - "Sorry, single color generated decks aren't supported yet." - + "\n\rPlease choose at least one more color for this deck.", - "Generate deck: 1 color", JOptionPane.ERROR_MESSAGE); - result = false; - } - else if (colors0.length == 4) { + if (colors0.length == 4) { JOptionPane.showMessageDialog(null, "Sorry, four color generated decks aren't supported yet." + "\n\rPlease use 2, 3, or 5 colors for this deck.", diff --git a/src/main/java/forge/deck/generate/Generate2ColorDeck.java b/src/main/java/forge/deck/generate/Generate2ColorDeck.java index 448c563f2e2..046b6f2f7b9 100644 --- a/src/main/java/forge/deck/generate/Generate2ColorDeck.java +++ b/src/main/java/forge/deck/generate/Generate2ColorDeck.java @@ -78,7 +78,7 @@ public class Generate2ColorDeck extends GenerateColoredDeckBase { } - public final ItemPoolView get2ColorDeck(final int size, final PlayerType pt) { + public final ItemPoolView getDeck(final int size, final PlayerType pt) { addCreaturesAndSpells(size, cmcLevels, cmcAmounts, pt); // Add lands diff --git a/src/main/java/forge/deck/generate/Generate3ColorDeck.java b/src/main/java/forge/deck/generate/Generate3ColorDeck.java index 0e944c6a02c..d0d6c68b548 100644 --- a/src/main/java/forge/deck/generate/Generate3ColorDeck.java +++ b/src/main/java/forge/deck/generate/Generate3ColorDeck.java @@ -77,7 +77,7 @@ public class Generate3ColorDeck extends GenerateColoredDeckBase { * the pt * @return a {@link forge.CardList} object. */ - public final ItemPoolView get3ColorDeck(final int size, final PlayerType pt) { + public final ItemPoolView getDeck(final int size, final PlayerType pt) { addCreaturesAndSpells(size, cmcLevels, cmcAmounts, pt); // Add lands diff --git a/src/main/java/forge/deck/generate/Generate5ColorDeck.java b/src/main/java/forge/deck/generate/Generate5ColorDeck.java index 4e3865ab9a9..35ac5e6b08d 100644 --- a/src/main/java/forge/deck/generate/Generate5ColorDeck.java +++ b/src/main/java/forge/deck/generate/Generate5ColorDeck.java @@ -66,7 +66,7 @@ public class Generate5ColorDeck extends GenerateColoredDeckBase { * a PlayerType * @return a {@link forge.CardList} object. */ - public final ItemPoolView get5ColorDeck(final int size, final PlayerType pt) { + public final ItemPoolView getDeck(final int size, final PlayerType pt) { addCreaturesAndSpells(size, cmcLevels, cmcAmounts, pt); // Add lands diff --git a/src/main/java/forge/deck/generate/GenerateColoredDeckBase.java b/src/main/java/forge/deck/generate/GenerateColoredDeckBase.java index 1743021a11c..0807dcb8b83 100644 --- a/src/main/java/forge/deck/generate/GenerateColoredDeckBase.java +++ b/src/main/java/forge/deck/generate/GenerateColoredDeckBase.java @@ -39,6 +39,7 @@ import forge.game.player.PlayerType; import forge.item.CardDb; import forge.item.CardPrinted; import forge.item.ItemPool; +import forge.item.ItemPoolView; import forge.properties.ForgePreferences.FPref; import forge.util.Aggregates; import forge.util.MyRandom; @@ -100,6 +101,9 @@ public abstract class GenerateColoredDeckBase { addCmcAdjusted(spells, spellCnt, cmcLevels, cmcAmounts); } + public ItemPoolView getDeck(final int size, final PlayerType pt) { + return null; // all but theme deck do override this method + } protected void addSome(int cnt, List source) { for (int i = 0; i < cnt; i++) { diff --git a/src/main/java/forge/deck/generate/GenerateMonoColorDeck.java b/src/main/java/forge/deck/generate/GenerateMonoColorDeck.java new file mode 100644 index 00000000000..29244405ef5 --- /dev/null +++ b/src/main/java/forge/deck/generate/GenerateMonoColorDeck.java @@ -0,0 +1,99 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package forge.deck.generate; + +import java.util.Arrays; +import java.util.List; + +import forge.card.MagicColor; +import forge.card.ColorSet; +import forge.deck.generate.GenerateDeckUtil.FilterCMC; +import forge.error.BugReporter; +import forge.game.player.PlayerType; +import forge.item.CardPrinted; +import forge.item.ItemPoolView; +import forge.properties.ForgeProps; + +/** + *

+ * Generate2ColorDeck class. + *

+ * + * @author Forge + * @version $Id: Generate2ColorDeck.java 19765 2013-02-20 03:01:37Z myk $ + */ +public class GenerateMonoColorDeck extends GenerateColoredDeckBase { + @Override protected final float getLandsPercentage() { return 0.39f; } + @Override protected final float getCreatPercentage() { return 0.36f; } + @Override protected final float getSpellPercentage() { return 0.25f; } + + final List cmcLevels = Arrays.asList( + new GenerateDeckUtil.FilterCMC(0, 2), + new GenerateDeckUtil.FilterCMC(3, 4), + new GenerateDeckUtil.FilterCMC(5, 6), + new GenerateDeckUtil.FilterCMC(7, 20)); + final int[] cmcAmounts = {10, 8, 5, 3}; + + // mana curve of the card pool + // 20x 0 - 2 + // 16x 3 - 4 + // 12x 5 - 6 + // 4x 7 - 20 + // = 52x - card pool (before further random filtering) + + /** + *

+ * Constructor for Generate2ColorDeck. + *

+ * + * @param clr1 + * a {@link java.lang.String} object. + * @param clr2 + * a {@link java.lang.String} object. + */ + public GenerateMonoColorDeck(final String clr1) { + + if (clr1.equals("AI")) { + int color1 = r.nextInt(5); + colors = ColorSet.fromMask(MagicColor.WHITE << color1); + } else { + colors = ColorSet.fromNames(clr1); + } + } + + + public final ItemPoolView getDeck(final int size, final PlayerType pt) { + addCreaturesAndSpells(size, cmcLevels, cmcAmounts, pt); + + // Add lands + int numLands = (int) (getLandsPercentage() * size); + + tmpDeck.append("numLands:").append(numLands).append("\n"); + + addBasicLand(numLands); + tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n"); + + adjustDeckSize(size); + tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n"); + if (ForgeProps.getProperty("showdeck/1color", "false").equals("true")) { + BugReporter.reportBug(tmpDeck.toString()); + } + + return tDeck; + } +} diff --git a/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java b/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java index 9ee2a0026de..aa7d0d5228c 100644 --- a/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java +++ b/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java @@ -106,15 +106,15 @@ public enum CDeckgen implements ICDoc { switch (colorCount0) { case 2: genConstructed.getMain().addAll( - (new Generate2ColorDeck("AI", "AI")).get2ColorDeck(60, PlayerType.HUMAN)); + (new Generate2ColorDeck("AI", "AI")).getDeck(60, PlayerType.HUMAN)); break; case 3: genConstructed.getMain().addAll( - (new Generate3ColorDeck("AI", "AI", "AI")).get3ColorDeck(60, PlayerType.HUMAN)); + (new Generate3ColorDeck("AI", "AI", "AI")).getDeck(60, PlayerType.HUMAN)); break; case 5: genConstructed.getMain().addAll( - (new Generate5ColorDeck()).get5ColorDeck(60, PlayerType.HUMAN)); + (new Generate5ColorDeck()).getDeck(60, PlayerType.HUMAN)); break; default: } diff --git a/src/test/java/forge/deck/generate/Generate2ColorDeckTest.java b/src/test/java/forge/deck/generate/Generate2ColorDeckTest.java index 713faff083c..47e5a873bf6 100644 --- a/src/test/java/forge/deck/generate/Generate2ColorDeckTest.java +++ b/src/test/java/forge/deck/generate/Generate2ColorDeckTest.java @@ -18,7 +18,7 @@ public class Generate2ColorDeckTest { @Test(enabled = false) public void generate2ColorDeckTest1() { final Generate2ColorDeck gen = new Generate2ColorDeck("white", "blue"); - final ItemPoolView cardList = gen.get2ColorDeck(60, null); + final ItemPoolView cardList = gen.getDeck(60, null); Assert.assertNotNull(cardList); } } diff --git a/src/test/java/forge/deck/generate/Generate3ColorDeckTest.java b/src/test/java/forge/deck/generate/Generate3ColorDeckTest.java index 7d33f05b731..77c70046b1e 100644 --- a/src/test/java/forge/deck/generate/Generate3ColorDeckTest.java +++ b/src/test/java/forge/deck/generate/Generate3ColorDeckTest.java @@ -18,7 +18,7 @@ public class Generate3ColorDeckTest { @Test(timeOut = 1000, enabled = false) public void generate3ColorDeckTest1() { final Generate3ColorDeck gen = new Generate3ColorDeck("white", "blue", "black"); - final ItemPoolView cardList = gen.get3ColorDeck(60, null); + final ItemPoolView cardList = gen.getDeck(60, null); Assert.assertNotNull(cardList); } } diff --git a/src/test/java/forge/deck/generate/Generate5ColorDeckTest.java b/src/test/java/forge/deck/generate/Generate5ColorDeckTest.java index 1e2a0708225..65179d3cd36 100644 --- a/src/test/java/forge/deck/generate/Generate5ColorDeckTest.java +++ b/src/test/java/forge/deck/generate/Generate5ColorDeckTest.java @@ -18,7 +18,7 @@ public class Generate5ColorDeckTest { @Test(timeOut = 1000, enabled = false) public void generate5ColorDeckTest1() { final Generate5ColorDeck gen = new Generate5ColorDeck(); - final ItemPoolView cardList = gen.get5ColorDeck(60, null); + final ItemPoolView cardList = gen.getDeck(60, null); Assert.assertNotNull(cardList); } } From a7a2f08d6c078b886b186a9fc1a1130143e3e6d3 Mon Sep 17 00:00:00 2001 From: swordshine Date: Fri, 8 Mar 2013 00:55:53 +0000 Subject: [PATCH 39/40] - Added Boom//Bust Crime//Punishment --- .gitattributes | 2 ++ res/cardsfolder/b/boom_bust.txt | 17 +++++++++++++++++ res/cardsfolder/c/crime_punishment.txt | 17 +++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 res/cardsfolder/b/boom_bust.txt create mode 100644 res/cardsfolder/c/crime_punishment.txt diff --git a/.gitattributes b/.gitattributes index fd5078245cd..33256e799c6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1181,6 +1181,7 @@ res/cardsfolder/b/bonfire_of_the_damned.txt -text res/cardsfolder/b/booby_trap.txt -text res/cardsfolder/b/book_burning.txt -text res/cardsfolder/b/book_of_rass.txt svneol=native#text/plain +res/cardsfolder/b/boom_bust.txt -text res/cardsfolder/b/boomerang.txt svneol=native#text/plain res/cardsfolder/b/boon_reflection.txt svneol=native#text/plain res/cardsfolder/b/borborygmos.txt svneol=native#text/plain @@ -2098,6 +2099,7 @@ res/cardsfolder/c/crescendo_of_war.txt -text res/cardsfolder/c/crested_craghorn.txt -text res/cardsfolder/c/crevasse.txt svneol=native#text/plain res/cardsfolder/c/crib_swap.txt svneol=native#text/plain +res/cardsfolder/c/crime_punishment.txt -text res/cardsfolder/c/crimson_acolyte.txt svneol=native#text/plain res/cardsfolder/c/crimson_hellkite.txt -text res/cardsfolder/c/crimson_kobolds.txt svneol=native#text/plain diff --git a/res/cardsfolder/b/boom_bust.txt b/res/cardsfolder/b/boom_bust.txt new file mode 100644 index 00000000000..1f32915f3bd --- /dev/null +++ b/res/cardsfolder/b/boom_bust.txt @@ -0,0 +1,17 @@ +Name:Boom +ManaCost:1 R +AlternateMode: Split +Types:Sorcery +A:SP$ Destroy | Cost$ 1 R | TgtPrompt$ Choose target land you control to destroy | ValidTgts$ Land.YouCtrl | SubAbility$ DestroyOpp | SpellDescription$ Destroy target land you control and target land you don't control. +SVar:DestroyOpp:DB$ Destroy | TgtPrompt$ Choose target land you don't control to destroy | ValidTgts$ Land.YouDontCtrl +SVar:Picture:http://www.wizards.com/global/images/magic/general/boombust.jpg +Oracle:Destroy target land you control and target land you don't control. + +ALTERNATE + +Name:Bust +ManaCost:5 R +Types:Sorcery +A:SP$ DestroyAll | Cost$ 5 R | ValidCards$ Land | SpellDescription$ Destroy all lands. +Oracle:Destroy all lands. +SetInfo:PLC Rare \ No newline at end of file diff --git a/res/cardsfolder/c/crime_punishment.txt b/res/cardsfolder/c/crime_punishment.txt new file mode 100644 index 00000000000..f2f3aab1ca3 --- /dev/null +++ b/res/cardsfolder/c/crime_punishment.txt @@ -0,0 +1,17 @@ +Name:Crime +ManaCost:3 W B +AlternateMode: Split +Types:Sorcery +A:SP$ ChangeZone | Cost$ 3 W B | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | TgtPrompt$ Choose target creature or enchantment in an opponent's graveyard | ValidTgts$ Creature.OppCtrl,Enchantment.OppCtrl | SpellDescription$ Put target creature or enchantment card from an opponent's graveyard onto the battlefield under your control. +SVar:Picture:http://www.wizards.com/global/images/magic/general/crimepunishment.jpg +Oracle:Put target creature or enchantment card from an opponent's graveyard onto the battlefield under your control. + +ALTERNATE + +Name:Punishment +ManaCost:X B G +Types:Sorcery +A:SP$ DestroyAll | Cost$ X B G | ValidCards$ Artifact.cmcEQX,Creature.cmcEQX,Enchantment.cmcEQX | References$ X | SpellDescription$ Destroy each artifact, creature, and enchantment with converted mana cost X. +SVar:X:Count$xPaid +Oracle:Destroy each artifact, creature, and enchantment with converted mana cost X. +SetInfo:DIS Rare \ No newline at end of file From 712f2a74746f5af2731984b61920dcdb28cc90cc Mon Sep 17 00:00:00 2001 From: Sol Date: Fri, 8 Mar 2013 01:36:50 +0000 Subject: [PATCH 40/40] - Fixing Display of Sakashima's clone ability --- res/cardsfolder/s/sakashima_the_impostor.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/cardsfolder/s/sakashima_the_impostor.txt b/res/cardsfolder/s/sakashima_the_impostor.txt index 0aa1dc5153c..4d7fbf49f37 100644 --- a/res/cardsfolder/s/sakashima_the_impostor.txt +++ b/res/cardsfolder/s/sakashima_the_impostor.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Human Rogue PT:3/1 # Make Svars for granting abilities and triggers on clones distinct to avoid SVars getting overwritten when cloning a clone K:ETBReplacement:Copy:ChooseCreature:Optional -SVar:ChooseCreature:AB$ ChooseCard | Cost$ 0 | Defined$ You | Amount$ 1 | Choices$ Creature.Other | SubAbility$ DBCopy | RememberChosen$ True | SpellDescription$ You may have CARDNAME enter the battlefield as a copy of any creature on the battlefield, except its name is still CARDNAME, it's legendary in addition to its other types, and it gains "2 U U: Return CARDNAME to its owner's hand at the beginning of the next end step." +SVar:ChooseCreature:DB$ ChooseCard | Defined$ You | Amount$ 1 | Choices$ Creature.Other | SubAbility$ DBCopy | RememberChosen$ True | SpellDescription$ You may have CARDNAME enter the battlefield as a copy of any creature on the battlefield, except its name is still CARDNAME, it's legendary in addition to its other types, and it gains "2 U U: Return CARDNAME to its owner's hand at the beginning of the next end step." SVar:DBCopy:DB$ Clone | Defined$ Remembered | KeepName$ True | AddTypes$ Legendary | AddAbilities$ ReturnSakashima | AddSVars$ TrigReturnSak SVar:ReturnSakashima:AB$ DelayedTrigger | Cost$ 2 U U | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturnSak | SpellDescription$ Return CARDNAME to it's owners hand at the beginning of the next end step. SVar:TrigReturnSak:AB$ChangeZone | Cost$ 0 | Defined$ Self | Origin$ Battlefield | Destination$ Hand