From a43b5a619c9300386472cef7f2016b18fc8b580a Mon Sep 17 00:00:00 2001 From: jendave Date: Sat, 6 Aug 2011 11:16:28 +0000 Subject: [PATCH] - Cards discarded as a cost will now be recorded in the SA and cleared at resolution. - Altered DealDamage to use AF.calculateAmount() - Added Pyromancy and Stormscale Anarch --- .gitattributes | 2 + res/cardsfolder/pyromancy.txt | 9 ++++ res/cardsfolder/stormscale_anarch.txt | 10 ++++ src/forge/AbilityFactory.java | 4 ++ src/forge/AbilityFactory_DealDamage.java | 66 +++++++----------------- src/forge/CardFactoryUtil.java | 9 ++++ src/forge/Cost_Payment.java | 2 - src/forge/MagicStack.java | 17 ++++-- src/forge/Player.java | 2 +- src/forge/SpellAbility.java | 15 ++++++ 10 files changed, 82 insertions(+), 54 deletions(-) create mode 100644 res/cardsfolder/pyromancy.txt create mode 100644 res/cardsfolder/stormscale_anarch.txt diff --git a/.gitattributes b/.gitattributes index e3d555c4b01..8dbeb55f779 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3533,6 +3533,7 @@ res/cardsfolder/pyrite_spellbomb.txt -text svneol=native#text/plain res/cardsfolder/pyroclasm.txt -text svneol=native#text/plain res/cardsfolder/pyroclast_consul.txt -text svneol=native#text/plain res/cardsfolder/pyrohemia.txt -text svneol=native#text/plain +res/cardsfolder/pyromancy.txt -text svneol=native#text/plain res/cardsfolder/pyromania.txt -text svneol=native#text/plain res/cardsfolder/python.txt -text svneol=native#text/plain res/cardsfolder/qasali_pridemage.txt -text svneol=native#text/plain @@ -4449,6 +4450,7 @@ res/cardsfolder/stormbind.txt -text svneol=native#text/plain res/cardsfolder/stormcallers_boon.txt -text svneol=native#text/plain res/cardsfolder/stormcloud_djinn.txt -text svneol=native#text/plain res/cardsfolder/stormfront_pegasus.txt -text svneol=native#text/plain +res/cardsfolder/stormscale_anarch.txt -text svneol=native#text/plain res/cardsfolder/stormscape_apprentice.txt -text svneol=native#text/plain res/cardsfolder/stormscape_familiar.txt -text svneol=native#text/plain res/cardsfolder/stormscape_master.txt -text svneol=native#text/plain diff --git a/res/cardsfolder/pyromancy.txt b/res/cardsfolder/pyromancy.txt new file mode 100644 index 00000000000..e0734dc9058 --- /dev/null +++ b/res/cardsfolder/pyromancy.txt @@ -0,0 +1,9 @@ +Name:Pyromancy +ManaCost:2 R R +Types:Enchantment +Text:no text +A:AB$DealDamage | Cost$ 3 Discard<1/Random> | Tgt$ TgtCP | NumDmg$ X | SpellDescription$ CARDNAME deals damage to target creature or player equal to the converted mana cost of the discarded card. +SVar:X:Discarded$CardManaCost +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/pyromancy.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/stormscale_anarch.txt b/res/cardsfolder/stormscale_anarch.txt new file mode 100644 index 00000000000..172562dd72c --- /dev/null +++ b/res/cardsfolder/stormscale_anarch.txt @@ -0,0 +1,10 @@ +Name:Stormscale Anarch +ManaCost:2 R R +Types:Creature Viashino Shaman +Text:no text +PT:2/2 +A:AB$DealDamage | Cost$ 2 R Discard<1/Random> | Tgt$ TgtCP | NumDmg$ X | SpellDescription$ CARDNAME deals 2 damage to target creature or player. If the discarded card was multicolored, CARDNAME deals 4 damage to that creature or player instead. +SVar:X:Discarded$CardMulticolor.4.2 +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/stormscale_anarch.jpg +End \ No newline at end of file diff --git a/src/forge/AbilityFactory.java b/src/forge/AbilityFactory.java index 85c45ae643f..da021ec9a79 100644 --- a/src/forge/AbilityFactory.java +++ b/src/forge/AbilityFactory.java @@ -446,6 +446,10 @@ public class AbilityFactory { { return CardFactoryUtil.handlePaid(ability.getSacrificedCost(), calcX[1]); } + else if (ability != null && calcX[0].startsWith("Discarded")) + { + return CardFactoryUtil.handlePaid(ability.getDiscardedCost(), calcX[1]); + } else return 0; } diff --git a/src/forge/AbilityFactory_DealDamage.java b/src/forge/AbilityFactory_DealDamage.java index e7950facb1f..a6f636fce10 100644 --- a/src/forge/AbilityFactory_DealDamage.java +++ b/src/forge/AbilityFactory_DealDamage.java @@ -8,10 +8,8 @@ import java.util.Random; public class AbilityFactory_DealDamage { private AbilityFactory AF = null; - private int nDamage = -1; - - private String XDamage = "none"; - + private String damage; + private boolean TgtOpp = false; private Ability_Sub subAbAF = null; @@ -25,15 +23,7 @@ import java.util.Random; { AF = newAF; - String tmpND = AF.getMapParams().get("NumDmg"); - if (tmpND.length() > 0) - { - if (tmpND.matches("[xX]")) - XDamage = AF.getHostCard().getSVar(tmpND.substring(1)); - - else if (tmpND.matches("[0-9][0-9]?")) - nDamage = Integer.parseInt(tmpND); - } + damage = AF.getMapParams().get("NumDmg"); if(AF.getMapParams().containsKey("Tgt")) if (AF.getMapParams().get("Tgt").equals("TgtOpp")) @@ -155,23 +145,7 @@ import java.util.Random; private int getNumDamage(SpellAbility saMe) { - if(nDamage != -1) return nDamage; - - String calcX[] = XDamage.split("\\$"); - - if (calcX.length == 1 || calcX[1].equals("none")) - return 0; - - if (calcX[0].startsWith("Count")) - { - return CardFactoryUtil.xCount(AF.getHostCard(), calcX[1]); - } - else if (calcX[0].startsWith("Sacrificed")) - { - return CardFactoryUtil.handlePaid(saMe.getSacrificedCost(), calcX[1]); - } - - return 0; + return AbilityFactory.calculateAmount(saMe.getSourceCard(), damage, saMe); } private boolean shouldTgtP(int d, final boolean noPrevention) { @@ -227,21 +201,21 @@ import java.util.Random; private boolean doCanPlayAI(SpellAbility saMe) { - int damage = getNumDamage(saMe); + int dmg = getNumDamage(saMe); boolean rr = AF.isSpell(); // temporarily disabled until better AI if (AF.getAbCost().getSacCost()) { - if(AllZone.HumanPlayer.getLife() - damage > 0) // only if damage from this ability would kill the human + if(AllZone.HumanPlayer.getLife() - dmg > 0) // only if damage from this ability would kill the human return false; } if (AF.getAbCost().getSubCounter()) { // +1/+1 counters only if damage from this ability would kill the human, otherwise ok - if(AllZone.HumanPlayer.getLife() - damage > 0 && AF.getAbCost().getCounterType().equals(Counters.P1P1)) + if(AllZone.HumanPlayer.getLife() - dmg > 0 && AF.getAbCost().getCounterType().equals(Counters.P1P1)) return false; } if (AF.getAbCost().getLifeCost()) { - if(AllZone.HumanPlayer.getLife() - damage > 0) // only if damage from this ability would kill the human + if(AllZone.HumanPlayer.getLife() - dmg > 0) // only if damage from this ability would kill the human return false; } @@ -269,7 +243,7 @@ import java.util.Random; } private boolean damageTargetAI(SpellAbility saMe) { - int damage = getNumDamage(saMe); + int dmg = getNumDamage(saMe); Target tgt = AF.getAbTgt(); HashMap params = AF.getMapParams(); @@ -297,12 +271,12 @@ import java.util.Random; // TODO: Consider targeting the planeswalker if (tgt.canTgtCreatureAndPlayer()) { - if (shouldTgtP(damage,noPrevention)) { + if (shouldTgtP(dmg,noPrevention)) { tgt.addTarget(AllZone.HumanPlayer); continue; } - Card c = chooseTgtC(damage,noPrevention); + Card c = chooseTgtC(dmg,noPrevention); if (c != null) { tgt.addTarget(c); continue; @@ -315,7 +289,7 @@ import java.util.Random; } if (tgt.canTgtCreature()) { - Card c = chooseTgtC(damage,noPrevention); + Card c = chooseTgtC(dmg,noPrevention); if (c != null) { tgt.addTarget(c); continue; @@ -338,14 +312,14 @@ import java.util.Random; // when damageStackDescription is called, just build exactly what is happening StringBuilder sb = new StringBuilder(); String name = af.getHostCard().getName(); - int damage = getNumDamage(sa); + int dmg = getNumDamage(sa); ArrayList tgts = findTargets(sa); if (!(sa instanceof Ability_Sub)) sb.append(name).append(" - "); - sb.append("Deals ").append(damage).append(" damage to "); + sb.append("Deals ").append(dmg).append(" damage to "); for(int i = 0; i < tgts.size(); i++){ if (i != 0) sb.append(" "); @@ -392,7 +366,7 @@ import java.util.Random; private void doResolve(SpellAbility saMe) { - int damage = getNumDamage(saMe); + int dmg = getNumDamage(saMe); HashMap params = AF.getMapParams(); boolean noPrevention = params.containsKey("NoPrevention"); @@ -410,9 +384,9 @@ import java.util.Random; Card c = (Card)o; if(AllZone.GameAction.isCardInPlay(c) && (!targeted || CardFactoryUtil.canTarget(AF.getHostCard(), c))) { if (noPrevention) - c.addDamageWithoutPrevention(damage, AF.getHostCard()); + c.addDamageWithoutPrevention(dmg, AF.getHostCard()); else - c.addDamage(damage, AF.getHostCard()); + c.addDamage(dmg, AF.getHostCard()); } } @@ -420,9 +394,9 @@ import java.util.Random; Player p = (Player) o; if (!targeted || p.canTarget(AF.getHostCard())) { if (noPrevention) - p.addDamageWithoutPrevention(damage, AF.getHostCard()); + p.addDamageWithoutPrevention(dmg, AF.getHostCard()); else - p.addDamage(damage, AF.getHostCard()); + p.addDamage(dmg, AF.getHostCard()); } } } @@ -446,7 +420,7 @@ import java.util.Random; else{ pl = (Player)obj; } - CardFactoryUtil.doDrawBack(subAbStr, damage, AF.getHostCard().getController(), + CardFactoryUtil.doDrawBack(subAbStr, dmg, AF.getHostCard().getController(), AF.getHostCard().getController().getOpponent(), pl, AF.getHostCard(), c, saMe); } diff --git a/src/forge/CardFactoryUtil.java b/src/forge/CardFactoryUtil.java index 00dcd5e749d..55232c336e3 100644 --- a/src/forge/CardFactoryUtil.java +++ b/src/forge/CardFactoryUtil.java @@ -3967,6 +3967,15 @@ public class CardFactoryUtil { } }); + //Count$IsMulticolor.. + if(sq[0].contains("IsMulticolor")) + { + if(CardUtil.getColors(c).size() > 1) + return doXMath(Integer.parseInt(sq[1]),m); + else + return doXMath(Integer.parseInt(sq[2]),m); + } + // 1/10 - Count$MaxCMCYouCtrl if(sq[0].contains("MaxCMC")) { int mmc = 0; diff --git a/src/forge/Cost_Payment.java b/src/forge/Cost_Payment.java index d849cc8c02f..a07d6e8d8df 100644 --- a/src/forge/Cost_Payment.java +++ b/src/forge/Cost_Payment.java @@ -275,7 +275,6 @@ public class Cost_Payment { } else if( discType.equals("LastDrawn") ) { if(handList.contains(card.getController().getLastDrawnCard())) { - //AllZone.GameAction.discard(card.getController().getLastDrawnCard(), ability); card.getController().discard(card.getController().getLastDrawnCard(), ability); payDiscard = true; } @@ -616,7 +615,6 @@ public class Cost_Payment { public void selectCard(Card card, PlayerZone zone) { if(zone.is(Constant.Zone.Hand) && handList.contains(card) ) { // send in CardList for Typing - //AllZone.GameAction.discard(card, sp); card.getController().discard(card, sp); handList.remove(card); nDiscard++; diff --git a/src/forge/MagicStack.java b/src/forge/MagicStack.java index 1373c278821..41e9b78b34d 100644 --- a/src/forge/MagicStack.java +++ b/src/forge/MagicStack.java @@ -199,11 +199,16 @@ public class MagicStack extends MyObservable { if (sp.getSourceCard().isCopiedSpell()) push(sp); - if (!sp.isMultiKicker() && !sp.isXCost() && !sp.getSourceCard().isCopiedSpell()) { + else if (!sp.isMultiKicker() && !sp.isXCost()) { push(sp); - } + } - else if (sp.isXCost() && !sp.getSourceCard().isCopiedSpell()) { + else if (sp.payCosts != null){ + push(sp); + } + + else if (sp.isXCost()) { + // todo: convert any X costs to use abCost so it happens earlier final SpellAbility sa = sp; final Ability ability = new Ability(sp.getSourceCard(), sa.getXManaCost()) { public void resolve() { @@ -250,7 +255,8 @@ public class MagicStack extends MyObservable { } } - else if (sp.isMultiKicker() && !sp.getSourceCard().isCopiedSpell()){ + else if (sp.isMultiKicker()){ + // todo: convert multikicker support in abCost so this doesn't happen here // both X and multi is not supported yet final SpellAbility sa = sp; @@ -510,8 +516,9 @@ public class MagicStack extends MyObservable { AllZone.InputControl.setResolving(false); this.unfreezeStack(); // unfreeze the stack once we're done resolving - AllZone.GameAction.checkStateEffects(); sa.resetSacrificedCost(); + sa.resetDiscardedCost(); + AllZone.GameAction.checkStateEffects(); AllZone.Phase.setNeedToNextPhase(false); diff --git a/src/forge/Player.java b/src/forge/Player.java index 4ac25d13353..c716da8e764 100644 --- a/src/forge/Player.java +++ b/src/forge/Player.java @@ -473,7 +473,7 @@ public abstract class Player extends MyObservable{ public void doDiscard(final Card c, final SpellAbility sa) { if (sa!= null){ - ; + sa.addDiscardedCost(c); } AllZone.GameAction.checkWheneverKeyword(c,"DiscardsCard",null); diff --git a/src/forge/SpellAbility.java b/src/forge/SpellAbility.java index 572216ba054..0bfdda1a765 100644 --- a/src/forge/SpellAbility.java +++ b/src/forge/SpellAbility.java @@ -51,6 +51,7 @@ public abstract class SpellAbility { private Ability_Sub subAbility = null; private CardList sacrificedCards = null; + private CardList discardedCards = null; private Command cancelCommand = Command.Blank; private Command beforePayManaAI = Command.Blank; @@ -278,6 +279,20 @@ public abstract class SpellAbility { sacrificedCards = null; } + public void addDiscardedCost(Card c){ + if (discardedCards == null) + discardedCards = new CardList(); + discardedCards.add(c); + } + + public CardList getDiscardedCost(){ + return discardedCards; + } + + public void resetDiscardedCost(){ + discardedCards = null; + } + public Input getAfterResolve() { return afterResolve; }