- 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
This commit is contained in:
jendave
2011-08-06 11:16:28 +00:00
parent 6ec3546483
commit a43b5a619c
10 changed files with 82 additions and 54 deletions

2
.gitattributes vendored
View File

@@ -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/pyroclasm.txt -text svneol=native#text/plain
res/cardsfolder/pyroclast_consul.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/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/pyromania.txt -text svneol=native#text/plain
res/cardsfolder/python.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 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/stormcallers_boon.txt -text svneol=native#text/plain
res/cardsfolder/stormcloud_djinn.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/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_apprentice.txt -text svneol=native#text/plain
res/cardsfolder/stormscape_familiar.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 res/cardsfolder/stormscape_master.txt -text svneol=native#text/plain

View File

@@ -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

View File

@@ -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

View File

@@ -446,6 +446,10 @@ public class AbilityFactory {
{ {
return CardFactoryUtil.handlePaid(ability.getSacrificedCost(), calcX[1]); return CardFactoryUtil.handlePaid(ability.getSacrificedCost(), calcX[1]);
} }
else if (ability != null && calcX[0].startsWith("Discarded"))
{
return CardFactoryUtil.handlePaid(ability.getDiscardedCost(), calcX[1]);
}
else else
return 0; return 0;
} }

View File

@@ -8,9 +8,7 @@ import java.util.Random;
public class AbilityFactory_DealDamage { public class AbilityFactory_DealDamage {
private AbilityFactory AF = null; private AbilityFactory AF = null;
private int nDamage = -1; private String damage;
private String XDamage = "none";
private boolean TgtOpp = false; private boolean TgtOpp = false;
@@ -25,15 +23,7 @@ import java.util.Random;
{ {
AF = newAF; AF = newAF;
String tmpND = AF.getMapParams().get("NumDmg"); damage = 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);
}
if(AF.getMapParams().containsKey("Tgt")) if(AF.getMapParams().containsKey("Tgt"))
if (AF.getMapParams().get("Tgt").equals("TgtOpp")) if (AF.getMapParams().get("Tgt").equals("TgtOpp"))
@@ -155,23 +145,7 @@ import java.util.Random;
private int getNumDamage(SpellAbility saMe) { private int getNumDamage(SpellAbility saMe) {
if(nDamage != -1) return nDamage; return AbilityFactory.calculateAmount(saMe.getSourceCard(), damage, saMe);
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;
} }
private boolean shouldTgtP(int d, final boolean noPrevention) { private boolean shouldTgtP(int d, final boolean noPrevention) {
@@ -227,21 +201,21 @@ import java.util.Random;
private boolean doCanPlayAI(SpellAbility saMe) private boolean doCanPlayAI(SpellAbility saMe)
{ {
int damage = getNumDamage(saMe); int dmg = getNumDamage(saMe);
boolean rr = AF.isSpell(); boolean rr = AF.isSpell();
// temporarily disabled until better AI // temporarily disabled until better AI
if (AF.getAbCost().getSacCost()) { 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; return false;
} }
if (AF.getAbCost().getSubCounter()) { if (AF.getAbCost().getSubCounter()) {
// +1/+1 counters only if damage from this ability would kill the human, otherwise ok // +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; return false;
} }
if (AF.getAbCost().getLifeCost()) { 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; return false;
} }
@@ -269,7 +243,7 @@ import java.util.Random;
} }
private boolean damageTargetAI(SpellAbility saMe) { private boolean damageTargetAI(SpellAbility saMe) {
int damage = getNumDamage(saMe); int dmg = getNumDamage(saMe);
Target tgt = AF.getAbTgt(); Target tgt = AF.getAbTgt();
HashMap<String,String> params = AF.getMapParams(); HashMap<String,String> params = AF.getMapParams();
@@ -297,12 +271,12 @@ import java.util.Random;
// TODO: Consider targeting the planeswalker // TODO: Consider targeting the planeswalker
if (tgt.canTgtCreatureAndPlayer()) { if (tgt.canTgtCreatureAndPlayer()) {
if (shouldTgtP(damage,noPrevention)) { if (shouldTgtP(dmg,noPrevention)) {
tgt.addTarget(AllZone.HumanPlayer); tgt.addTarget(AllZone.HumanPlayer);
continue; continue;
} }
Card c = chooseTgtC(damage,noPrevention); Card c = chooseTgtC(dmg,noPrevention);
if (c != null) { if (c != null) {
tgt.addTarget(c); tgt.addTarget(c);
continue; continue;
@@ -315,7 +289,7 @@ import java.util.Random;
} }
if (tgt.canTgtCreature()) { if (tgt.canTgtCreature()) {
Card c = chooseTgtC(damage,noPrevention); Card c = chooseTgtC(dmg,noPrevention);
if (c != null) { if (c != null) {
tgt.addTarget(c); tgt.addTarget(c);
continue; continue;
@@ -338,14 +312,14 @@ import java.util.Random;
// when damageStackDescription is called, just build exactly what is happening // when damageStackDescription is called, just build exactly what is happening
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String name = af.getHostCard().getName(); String name = af.getHostCard().getName();
int damage = getNumDamage(sa); int dmg = getNumDamage(sa);
ArrayList<Object> tgts = findTargets(sa); ArrayList<Object> tgts = findTargets(sa);
if (!(sa instanceof Ability_Sub)) if (!(sa instanceof Ability_Sub))
sb.append(name).append(" - "); 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++){ for(int i = 0; i < tgts.size(); i++){
if (i != 0) if (i != 0)
sb.append(" "); sb.append(" ");
@@ -392,7 +366,7 @@ import java.util.Random;
private void doResolve(SpellAbility saMe) private void doResolve(SpellAbility saMe)
{ {
int damage = getNumDamage(saMe); int dmg = getNumDamage(saMe);
HashMap<String,String> params = AF.getMapParams(); HashMap<String,String> params = AF.getMapParams();
boolean noPrevention = params.containsKey("NoPrevention"); boolean noPrevention = params.containsKey("NoPrevention");
@@ -410,9 +384,9 @@ import java.util.Random;
Card c = (Card)o; Card c = (Card)o;
if(AllZone.GameAction.isCardInPlay(c) && (!targeted || CardFactoryUtil.canTarget(AF.getHostCard(), c))) { if(AllZone.GameAction.isCardInPlay(c) && (!targeted || CardFactoryUtil.canTarget(AF.getHostCard(), c))) {
if (noPrevention) if (noPrevention)
c.addDamageWithoutPrevention(damage, AF.getHostCard()); c.addDamageWithoutPrevention(dmg, AF.getHostCard());
else else
c.addDamage(damage, AF.getHostCard()); c.addDamage(dmg, AF.getHostCard());
} }
} }
@@ -420,9 +394,9 @@ import java.util.Random;
Player p = (Player) o; Player p = (Player) o;
if (!targeted || p.canTarget(AF.getHostCard())) { if (!targeted || p.canTarget(AF.getHostCard())) {
if (noPrevention) if (noPrevention)
p.addDamageWithoutPrevention(damage, AF.getHostCard()); p.addDamageWithoutPrevention(dmg, AF.getHostCard());
else else
p.addDamage(damage, AF.getHostCard()); p.addDamage(dmg, AF.getHostCard());
} }
} }
} }
@@ -446,7 +420,7 @@ import java.util.Random;
else{ else{
pl = (Player)obj; 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); AF.getHostCard().getController().getOpponent(), pl, AF.getHostCard(), c, saMe);
} }

View File

@@ -3967,6 +3967,15 @@ public class CardFactoryUtil {
} }
}); });
//Count$IsMulticolor.<numMC>.<numNotMC>
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 // 1/10 - Count$MaxCMCYouCtrl
if(sq[0].contains("MaxCMC")) { if(sq[0].contains("MaxCMC")) {
int mmc = 0; int mmc = 0;

View File

@@ -275,7 +275,6 @@ public class Cost_Payment {
} }
else if( discType.equals("LastDrawn") ) { else if( discType.equals("LastDrawn") ) {
if(handList.contains(card.getController().getLastDrawnCard())) { if(handList.contains(card.getController().getLastDrawnCard())) {
//AllZone.GameAction.discard(card.getController().getLastDrawnCard(), ability);
card.getController().discard(card.getController().getLastDrawnCard(), ability); card.getController().discard(card.getController().getLastDrawnCard(), ability);
payDiscard = true; payDiscard = true;
} }
@@ -616,7 +615,6 @@ public class Cost_Payment {
public void selectCard(Card card, PlayerZone zone) { public void selectCard(Card card, PlayerZone zone) {
if(zone.is(Constant.Zone.Hand) && handList.contains(card) ) { if(zone.is(Constant.Zone.Hand) && handList.contains(card) ) {
// send in CardList for Typing // send in CardList for Typing
//AllZone.GameAction.discard(card, sp);
card.getController().discard(card, sp); card.getController().discard(card, sp);
handList.remove(card); handList.remove(card);
nDiscard++; nDiscard++;

View File

@@ -199,11 +199,16 @@ public class MagicStack extends MyObservable {
if (sp.getSourceCard().isCopiedSpell()) if (sp.getSourceCard().isCopiedSpell())
push(sp); push(sp);
if (!sp.isMultiKicker() && !sp.isXCost() && !sp.getSourceCard().isCopiedSpell()) { else if (!sp.isMultiKicker() && !sp.isXCost()) {
push(sp); 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 SpellAbility sa = sp;
final Ability ability = new Ability(sp.getSourceCard(), sa.getXManaCost()) { final Ability ability = new Ability(sp.getSourceCard(), sa.getXManaCost()) {
public void resolve() { 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 // both X and multi is not supported yet
final SpellAbility sa = sp; final SpellAbility sa = sp;
@@ -510,8 +516,9 @@ public class MagicStack extends MyObservable {
AllZone.InputControl.setResolving(false); AllZone.InputControl.setResolving(false);
this.unfreezeStack(); // unfreeze the stack once we're done resolving this.unfreezeStack(); // unfreeze the stack once we're done resolving
AllZone.GameAction.checkStateEffects();
sa.resetSacrificedCost(); sa.resetSacrificedCost();
sa.resetDiscardedCost();
AllZone.GameAction.checkStateEffects();
AllZone.Phase.setNeedToNextPhase(false); AllZone.Phase.setNeedToNextPhase(false);

View File

@@ -473,7 +473,7 @@ public abstract class Player extends MyObservable{
public void doDiscard(final Card c, final SpellAbility sa) { public void doDiscard(final Card c, final SpellAbility sa) {
if (sa!= null){ if (sa!= null){
; sa.addDiscardedCost(c);
} }
AllZone.GameAction.checkWheneverKeyword(c,"DiscardsCard",null); AllZone.GameAction.checkWheneverKeyword(c,"DiscardsCard",null);

View File

@@ -51,6 +51,7 @@ public abstract class SpellAbility {
private Ability_Sub subAbility = null; private Ability_Sub subAbility = null;
private CardList sacrificedCards = null; private CardList sacrificedCards = null;
private CardList discardedCards = null;
private Command cancelCommand = Command.Blank; private Command cancelCommand = Command.Blank;
private Command beforePayManaAI = Command.Blank; private Command beforePayManaAI = Command.Blank;
@@ -278,6 +279,20 @@ public abstract class SpellAbility {
sacrificedCards = null; 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() { public Input getAfterResolve() {
return afterResolve; return afterResolve;
} }