mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
- 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:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -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
|
||||
|
||||
9
res/cardsfolder/pyromancy.txt
Normal file
9
res/cardsfolder/pyromancy.txt
Normal 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
|
||||
10
res/cardsfolder/stormscale_anarch.txt
Normal file
10
res/cardsfolder/stormscale_anarch.txt
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,7 @@ 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;
|
||||
|
||||
@@ -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<String,String> 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<Object> 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<String,String> 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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
if(sq[0].contains("MaxCMC")) {
|
||||
int mmc = 0;
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user