mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
- Added PayLife as a new kind of Ability_Cost
- Pulled targeting from Ability_Cost into it's own class. - Added Player info to PlayerLife - Added Reckless Assault as a sample of PayLife<> cost.
This commit is contained in:
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -557,12 +557,15 @@ src/forge/Spell.java svneol=native#text/plain
|
|||||||
src/forge/SpellAbility.java -text svneol=native#text/plain
|
src/forge/SpellAbility.java -text svneol=native#text/plain
|
||||||
src/forge/SpellAbilityList.java svneol=native#text/plain
|
src/forge/SpellAbilityList.java svneol=native#text/plain
|
||||||
src/forge/SpellAbilityUtil.java svneol=native#text/plain
|
src/forge/SpellAbilityUtil.java svneol=native#text/plain
|
||||||
|
src/forge/SpellAbility_Requirements.java -text svneol=native#text/plain
|
||||||
src/forge/Spell_Evoke.java svneol=native#text/plain
|
src/forge/Spell_Evoke.java svneol=native#text/plain
|
||||||
src/forge/Spell_Permanent.java svneol=native#text/plain
|
src/forge/Spell_Permanent.java svneol=native#text/plain
|
||||||
src/forge/StackObserver.java svneol=native#text/plain
|
src/forge/StackObserver.java svneol=native#text/plain
|
||||||
src/forge/StaticEffects.java -text svneol=native#text/plain
|
src/forge/StaticEffects.java -text svneol=native#text/plain
|
||||||
src/forge/TableModel.java -text svneol=native#text/plain
|
src/forge/TableModel.java -text svneol=native#text/plain
|
||||||
src/forge/TableSorter.java svneol=native#text/plain
|
src/forge/TableSorter.java svneol=native#text/plain
|
||||||
|
src/forge/Target.java -text svneol=native#text/plain
|
||||||
|
src/forge/Target_Selection.java -text svneol=native#text/plain
|
||||||
src/forge/TempRun.java svneol=native#text/plain
|
src/forge/TempRun.java svneol=native#text/plain
|
||||||
src/forge/Test.java svneol=native#text/plain
|
src/forge/Test.java svneol=native#text/plain
|
||||||
src/forge/TestMove.java svneol=native#text/plain
|
src/forge/TestMove.java svneol=native#text/plain
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
|
Reckless Assault
|
||||||
|
2 B R
|
||||||
|
Enchantment
|
||||||
|
no text
|
||||||
|
abDamageTgtCP 1 PayLife<2>:1
|
||||||
|
SVar:RemAIDeck:True
|
||||||
|
|
||||||
Disfigure
|
Disfigure
|
||||||
B
|
B
|
||||||
Instant
|
Instant
|
||||||
|
|||||||
@@ -1,25 +1,6 @@
|
|||||||
package forge;
|
package forge;
|
||||||
|
|
||||||
public class Ability_Cost {
|
public class Ability_Cost {
|
||||||
private boolean tgtPlayer = false;
|
|
||||||
public boolean canTgtPlayer() { return tgtPlayer; }
|
|
||||||
private boolean tgtCreature = false;
|
|
||||||
public boolean canTgtCreature() { return tgtCreature; }
|
|
||||||
|
|
||||||
public boolean canTgtCreaturePlayer() { return tgtCreature && tgtPlayer; }
|
|
||||||
public boolean doesTarget() { return tgtCreature || tgtPlayer; }
|
|
||||||
|
|
||||||
private int minTargets = 0;
|
|
||||||
public int getMinTargets() { return minTargets; }
|
|
||||||
private int maxTargets = 0;
|
|
||||||
public int getMaxTargets() { return maxTargets; }
|
|
||||||
// add array of targets here?
|
|
||||||
|
|
||||||
private int numTargeted = 0;
|
|
||||||
public int getNumTargeted() { return numTargeted; }
|
|
||||||
public void incrementTargets() { numTargeted++; }
|
|
||||||
public void resetTargets() { numTargeted = 0; }
|
|
||||||
|
|
||||||
private boolean sacCost = false;
|
private boolean sacCost = false;
|
||||||
public boolean getSacCost() { return sacCost; }
|
public boolean getSacCost() { return sacCost; }
|
||||||
private String sacType = ""; // <type> or CARDNAME
|
private String sacType = ""; // <type> or CARDNAME
|
||||||
@@ -30,7 +11,7 @@ public class Ability_Cost {
|
|||||||
private boolean tapCost = false;
|
private boolean tapCost = false;
|
||||||
public boolean getTap() { return tapCost; }
|
public boolean getTap() { return tapCost; }
|
||||||
|
|
||||||
// future expansion of Ability_Cost class: untap, and lifeCost
|
// future expansion of Ability_Cost class: untap
|
||||||
// private boolean untapCost = false;
|
// private boolean untapCost = false;
|
||||||
|
|
||||||
private boolean subtractCounterCost = false;
|
private boolean subtractCounterCost = false;
|
||||||
@@ -44,7 +25,9 @@ public class Ability_Cost {
|
|||||||
public Counters getCounterType() { return counterType; }
|
public Counters getCounterType() { return counterType; }
|
||||||
|
|
||||||
private boolean lifeCost = false;
|
private boolean lifeCost = false;
|
||||||
|
public boolean getLifeCost() { return lifeCost; }
|
||||||
private int lifeAmount = 0;
|
private int lifeAmount = 0;
|
||||||
|
public int getLifeAmount() { return lifeAmount; }
|
||||||
|
|
||||||
public boolean hasNoManaCost() { return manaCost.equals("") || manaCost.equals("0"); };
|
public boolean hasNoManaCost() { return manaCost.equals("") || manaCost.equals("0"); };
|
||||||
private String manaCost = "";
|
private String manaCost = "";
|
||||||
@@ -57,34 +40,8 @@ public class Ability_Cost {
|
|||||||
// when adding new costs for cost string, place them here
|
// when adding new costs for cost string, place them here
|
||||||
name = cardName;
|
name = cardName;
|
||||||
|
|
||||||
if (parse.contains("Tgt")){
|
|
||||||
// Tgt{C}{P}{/<MinTargets>/<MaxTargets>}
|
|
||||||
int tgtPos = parse.indexOf("Tgt");
|
|
||||||
int endTgt = parse.indexOf(" ");
|
|
||||||
//System.out.println(cardName);
|
|
||||||
String tgtStr = parse.substring(tgtPos, endTgt);
|
|
||||||
parse = parse.substring(endTgt+1);
|
|
||||||
tgtStr = tgtStr.replace("Tgt", "");
|
|
||||||
String[] tgtSplit = tgtStr.split("/");
|
|
||||||
|
|
||||||
if (tgtSplit[0].contains("C"))
|
|
||||||
tgtCreature = true;
|
|
||||||
if (tgtSplit[0].contains("P"))
|
|
||||||
tgtPlayer = true;
|
|
||||||
//todo(sol) add Opp
|
|
||||||
|
|
||||||
if (tgtSplit.length != 3){
|
|
||||||
minTargets = 1;
|
|
||||||
maxTargets = 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
minTargets = Integer.parseInt(tgtSplit[1]);
|
|
||||||
maxTargets = Integer.parseInt(tgtSplit[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(parse.contains("SubCounter<")) {
|
if(parse.contains("SubCounter<")) {
|
||||||
// SubCounter/<Counter Type>/counters removed
|
// SubCounter<CounterType/NumCounters>
|
||||||
subtractCounterCost = true;
|
subtractCounterCost = true;
|
||||||
int counterPos = parse.indexOf("SubCounter<");
|
int counterPos = parse.indexOf("SubCounter<");
|
||||||
int endPos = parse.indexOf(">", counterPos);
|
int endPos = parse.indexOf(">", counterPos);
|
||||||
@@ -99,11 +56,26 @@ public class Ability_Cost {
|
|||||||
counterAmount = Integer.parseInt(strSplit[1]);
|
counterAmount = Integer.parseInt(strSplit[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(parse.contains("PayLife<")) {
|
||||||
|
// PayLife<LifeCost>
|
||||||
|
lifeCost = true;
|
||||||
|
int lifePos = parse.indexOf("PayLife<");
|
||||||
|
int endPos = parse.indexOf(">", lifePos);
|
||||||
|
String str = parse.substring(lifePos, endPos+1);
|
||||||
|
parse = parse.replace(str, "").trim();
|
||||||
|
|
||||||
|
str = str.replace("PayLife<", "");
|
||||||
|
str = str.replace(">", "");
|
||||||
|
|
||||||
|
lifeAmount = Integer.parseInt(str);
|
||||||
|
}
|
||||||
|
|
||||||
if(parse.contains("Sac-")) {
|
if(parse.contains("Sac-")) {
|
||||||
sacCost = true;
|
sacCost = true;
|
||||||
int sacPos = parse.indexOf("Sac-");
|
int sacPos = parse.indexOf("Sac-");
|
||||||
sacType = parse.substring(sacPos).replace("Sac-", "").trim();
|
sacType = parse.substring(sacPos).replace("Sac-", "").trim();
|
||||||
sacThis = (sacType.equals("CARDNAME"));
|
sacThis = (sacType.equals("CARDNAME"));
|
||||||
|
if (sacPos > 0)
|
||||||
parse = parse.substring(0,sacPos-1).trim();
|
parse = parse.substring(0,sacPos-1).trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,8 +128,9 @@ public class Ability_Cost {
|
|||||||
if (caps)
|
if (caps)
|
||||||
cost.append("Pay ");
|
cost.append("Pay ");
|
||||||
else
|
else
|
||||||
cost.append(", Pay");
|
cost.append(", Pay ");
|
||||||
cost.append(lifeAmount);
|
cost.append(lifeAmount);
|
||||||
|
cost.append(" Life");
|
||||||
|
|
||||||
caps = false;
|
caps = false;
|
||||||
}
|
}
|
||||||
@@ -192,19 +165,4 @@ public class Ability_Cost {
|
|||||||
}
|
}
|
||||||
return cost.toString();
|
return cost.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String targetString()
|
|
||||||
{
|
|
||||||
String tgt = "";
|
|
||||||
if (tgtCreature)
|
|
||||||
tgt += "creature";
|
|
||||||
if (tgtPlayer && !tgt.equals(""))
|
|
||||||
tgt += " or ";
|
|
||||||
if (tgtPlayer)
|
|
||||||
tgt += "player";
|
|
||||||
|
|
||||||
tgt += ".";
|
|
||||||
|
|
||||||
return "target " + tgt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ public class AllZone implements NewConstants {
|
|||||||
public static Combat Combat = new Combat();
|
public static Combat Combat = new Combat();
|
||||||
public static Combat pwCombat = new Combat();//for Planeswalker combat
|
public static Combat pwCombat = new Combat();//for Planeswalker combat
|
||||||
|
|
||||||
public static PlayerLife Human_Life = new PlayerLife();
|
public static PlayerLife Human_Life = new PlayerLife(Constant.Player.Human);
|
||||||
public static PlayerLife Computer_Life = new PlayerLife();
|
public static PlayerLife Computer_Life = new PlayerLife(Constant.Player.Computer);
|
||||||
|
|
||||||
public static PlayerPoisonCounter Human_PoisonCounter = new PlayerPoisonCounter();
|
public static PlayerPoisonCounter Human_PoisonCounter = new PlayerPoisonCounter();
|
||||||
public static PlayerPoisonCounter Computer_PoisonCounter = new PlayerPoisonCounter();
|
public static PlayerPoisonCounter Computer_PoisonCounter = new PlayerPoisonCounter();
|
||||||
|
|||||||
@@ -1267,10 +1267,10 @@ public class CardFactory implements NewConstants {
|
|||||||
card.removeIntrinsicKeyword(parse);
|
card.removeIntrinsicKeyword(parse);
|
||||||
|
|
||||||
String k[] = parse.split(":");
|
String k[] = parse.split(":");
|
||||||
|
String tmpCost[] = k[0].replace("abAllPump", "").split(" ", 2);
|
||||||
|
|
||||||
String tmpCost = k[0].substring(9);
|
final Target abTgt = new Target(tmpCost[0]);
|
||||||
|
final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName());
|
||||||
final Ability_Cost abCost = new Ability_Cost(tmpCost, card.getName());
|
|
||||||
|
|
||||||
final String Scope[] = k[1].split("/");
|
final String Scope[] = k[1].split("/");
|
||||||
|
|
||||||
@@ -1423,6 +1423,8 @@ public class CardFactory implements NewConstants {
|
|||||||
|
|
||||||
// temporarily disabled until AI is improved
|
// temporarily disabled until AI is improved
|
||||||
if (abCost.getSacCost()) return false;
|
if (abCost.getSacCost()) return false;
|
||||||
|
if (abCost.getSubCounter()) return false;
|
||||||
|
if (abCost.getLifeCost()) return false;
|
||||||
|
|
||||||
if (abCost.getTap() && (card.isTapped() || card.isSick()))
|
if (abCost.getTap() && (card.isTapped() || card.isSick()))
|
||||||
return false;
|
return false;
|
||||||
@@ -1516,6 +1518,7 @@ public class CardFactory implements NewConstants {
|
|||||||
abAllPump.setDescription(abCost.toString() + spDesc[0]);
|
abAllPump.setDescription(abCost.toString() + spDesc[0]);
|
||||||
abAllPump.setStackDescription(stDesc[0]);
|
abAllPump.setStackDescription(stDesc[0]);
|
||||||
abAllPump.setPayCosts(abCost);
|
abAllPump.setPayCosts(abCost);
|
||||||
|
abAllPump.setTarget(abTgt);
|
||||||
|
|
||||||
card.addSpellAbility(abAllPump);
|
card.addSpellAbility(abAllPump);
|
||||||
}
|
}
|
||||||
@@ -1528,10 +1531,12 @@ public class CardFactory implements NewConstants {
|
|||||||
card.removeIntrinsicKeyword(parse);
|
card.removeIntrinsicKeyword(parse);
|
||||||
|
|
||||||
String k[] = parse.split(":");
|
String k[] = parse.split(":");
|
||||||
|
String tmp = k[0].replace("abPump", "");
|
||||||
|
|
||||||
String tmpCost = k[0].substring(6);
|
String[] tmpCost = tmp.split(" ", 2);
|
||||||
|
|
||||||
final Ability_Cost abCost = new Ability_Cost(tmpCost, card.getName());
|
final Target abTgt = new Target(tmpCost[0]);
|
||||||
|
final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName());
|
||||||
|
|
||||||
final int NumAttack[] = {-1138};
|
final int NumAttack[] = {-1138};
|
||||||
final String AttackX[] = {"none"};
|
final String AttackX[] = {"none"};
|
||||||
@@ -1597,7 +1602,7 @@ public class CardFactory implements NewConstants {
|
|||||||
if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
|
if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
|
||||||
&& (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && Keyword[0].equals("none")) {
|
&& (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && Keyword[0].equals("none")) {
|
||||||
// pt boost
|
// pt boost
|
||||||
if(abCost.doesTarget()) sbD.append("Target creature gets ");
|
if(abTgt.doesTarget()) sbD.append("Target creature gets ");
|
||||||
else {
|
else {
|
||||||
sbD.append(cardName);
|
sbD.append(cardName);
|
||||||
sbD.append(" gets ");
|
sbD.append(" gets ");
|
||||||
@@ -1621,7 +1626,7 @@ public class CardFactory implements NewConstants {
|
|||||||
if((AttackX[0].equals("none") && NumAttack[0] == -1138)
|
if((AttackX[0].equals("none") && NumAttack[0] == -1138)
|
||||||
&& (DefenseX[0].equals("none") && NumDefense[0] == -1138) && !Keyword[0].equals("none")) {
|
&& (DefenseX[0].equals("none") && NumDefense[0] == -1138) && !Keyword[0].equals("none")) {
|
||||||
// k boost
|
// k boost
|
||||||
if(abCost.doesTarget()) sbD.append("Target creature gains ");
|
if(abTgt.doesTarget()) sbD.append("Target creature gains ");
|
||||||
else {
|
else {
|
||||||
sbD.append(cardName);
|
sbD.append(cardName);
|
||||||
sbD.append(" gains ");
|
sbD.append(" gains ");
|
||||||
@@ -1633,7 +1638,7 @@ public class CardFactory implements NewConstants {
|
|||||||
if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
|
if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
|
||||||
&& (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && !Keyword[0].equals("none")) {
|
&& (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && !Keyword[0].equals("none")) {
|
||||||
// ptk boost
|
// ptk boost
|
||||||
if(abCost.doesTarget()) sbD.append("Target creature gets ");
|
if(abTgt.doesTarget()) sbD.append("Target creature gets ");
|
||||||
else {
|
else {
|
||||||
sbD.append(cardName);
|
sbD.append(cardName);
|
||||||
sbD.append(" gets ");
|
sbD.append(" gets ");
|
||||||
@@ -1700,6 +1705,7 @@ public class CardFactory implements NewConstants {
|
|||||||
// temporarily disabled until AI is improved
|
// temporarily disabled until AI is improved
|
||||||
if (abCost.getSacCost()) return false;
|
if (abCost.getSacCost()) return false;
|
||||||
if (abCost.getSubCounter()) return false;
|
if (abCost.getSubCounter()) return false;
|
||||||
|
if (abCost.getLifeCost()) return false;
|
||||||
|
|
||||||
if (!ComputerUtil.canPayCost(this))
|
if (!ComputerUtil.canPayCost(this))
|
||||||
return false;
|
return false;
|
||||||
@@ -1709,7 +1715,7 @@ public class CardFactory implements NewConstants {
|
|||||||
|
|
||||||
if(AllZone.Phase.getPhase().equals(Constant.Phase.Main2)) return false;
|
if(AllZone.Phase.getPhase().equals(Constant.Phase.Main2)) return false;
|
||||||
|
|
||||||
if(!abCost.doesTarget()) {
|
if(!abTgt.doesTarget()) {
|
||||||
setTargetCard(card);
|
setTargetCard(card);
|
||||||
|
|
||||||
if((card.getNetDefense() + defense > 0) && (!card.getKeyword().contains(keyword))) {
|
if((card.getNetDefense() + defense > 0) && (!card.getKeyword().contains(keyword))) {
|
||||||
@@ -1778,9 +1784,9 @@ public class CardFactory implements NewConstants {
|
|||||||
@Override
|
@Override
|
||||||
public void resolve() {
|
public void resolve() {
|
||||||
if(AllZone.GameAction.isCardInPlay(getTargetCard())
|
if(AllZone.GameAction.isCardInPlay(getTargetCard())
|
||||||
&& (CardFactoryUtil.canTarget(card, getTargetCard()) || !abCost.doesTarget() )) {
|
&& (CardFactoryUtil.canTarget(card, getTargetCard()) || !abTgt.doesTarget() )) {
|
||||||
final Card[] creature = new Card[1];
|
final Card[] creature = new Card[1];
|
||||||
if(abCost.doesTarget()) creature[0] = getTargetCard();
|
if(abTgt.doesTarget()) creature[0] = getTargetCard();
|
||||||
else creature[0] = card;
|
else creature[0] = card;
|
||||||
|
|
||||||
final int a = getNumAttack();
|
final int a = getNumAttack();
|
||||||
@@ -1829,8 +1835,10 @@ public class CardFactory implements NewConstants {
|
|||||||
ability.setDescription(spDesc[0]);
|
ability.setDescription(spDesc[0]);
|
||||||
ability.setStackDescription(stDesc[0]);
|
ability.setStackDescription(stDesc[0]);
|
||||||
|
|
||||||
if(!abCost.doesTarget())
|
if(!abTgt.doesTarget())
|
||||||
ability.setTargetCard(card);
|
ability.setTargetCard(card);
|
||||||
|
else
|
||||||
|
ability.setTarget(abTgt);
|
||||||
|
|
||||||
card.addSpellAbility(ability);
|
card.addSpellAbility(ability);
|
||||||
}
|
}
|
||||||
@@ -2265,9 +2273,10 @@ public class CardFactory implements NewConstants {
|
|||||||
card.removeIntrinsicKeyword(parse);
|
card.removeIntrinsicKeyword(parse);
|
||||||
|
|
||||||
String k[] = parse.split(":");
|
String k[] = parse.split(":");
|
||||||
String tmpCost = k[0].substring(8);
|
String tmpCost[] = k[0].replace("abDamage", "").split(" ", 2);
|
||||||
|
|
||||||
final Ability_Cost abCost = new Ability_Cost(tmpCost, card.getName());
|
final Target abTgt = new Target(tmpCost[0]);
|
||||||
|
final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName());
|
||||||
|
|
||||||
final int NumDmg[] = {-1};
|
final int NumDmg[] = {-1};
|
||||||
final String NumDmgX[] = {"none"};
|
final String NumDmgX[] = {"none"};
|
||||||
@@ -2301,7 +2310,7 @@ public class CardFactory implements NewConstants {
|
|||||||
sb.append(card.getName());
|
sb.append(card.getName());
|
||||||
sb.append(" deals " + NumDmg[0] + " damage to ");
|
sb.append(" deals " + NumDmg[0] + " damage to ");
|
||||||
|
|
||||||
sb.append(abCost.targetString());
|
sb.append(abTgt.targetString());
|
||||||
spDesc[0] = sb.toString();
|
spDesc[0] = sb.toString();
|
||||||
stDesc[0] = card.getName() + " -" + sb.toString();
|
stDesc[0] = card.getName() + " -" + sb.toString();
|
||||||
}
|
}
|
||||||
@@ -2380,6 +2389,7 @@ public class CardFactory implements NewConstants {
|
|||||||
// temporarily disabled until better AI
|
// temporarily disabled until better AI
|
||||||
if (abCost.getSacCost()) return false;
|
if (abCost.getSacCost()) return false;
|
||||||
if (abCost.getSubCounter()) return false;
|
if (abCost.getSubCounter()) return false;
|
||||||
|
if (abCost.getLifeCost()) return false;
|
||||||
|
|
||||||
if (!ComputerUtil.canPayCost(this))
|
if (!ComputerUtil.canPayCost(this))
|
||||||
return false;
|
return false;
|
||||||
@@ -2391,7 +2401,7 @@ public class CardFactory implements NewConstants {
|
|||||||
if(r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
|
if(r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
|
||||||
rr = true;
|
rr = true;
|
||||||
|
|
||||||
if(abCost.canTgtCreaturePlayer()) {
|
if(abTgt.canTgtCreaturePlayer()) {
|
||||||
if(shouldTgtP()) {
|
if(shouldTgtP()) {
|
||||||
setTargetPlayer(Constant.Player.Human);
|
setTargetPlayer(Constant.Player.Human);
|
||||||
return rr;
|
return rr;
|
||||||
@@ -2404,12 +2414,12 @@ public class CardFactory implements NewConstants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(abCost.canTgtPlayer()/* || TgtOpp[0] == true */) {
|
if(abTgt.canTgtPlayer()/* || TgtOpp[0] == true */) {
|
||||||
setTargetPlayer(Constant.Player.Human);
|
setTargetPlayer(Constant.Player.Human);
|
||||||
return rr;
|
return rr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(abCost.canTgtCreature()) {
|
if(abTgt.canTgtCreature()) {
|
||||||
Card c = chooseTgtC();
|
Card c = chooseTgtC();
|
||||||
if(c != null) {
|
if(c != null) {
|
||||||
setTargetCard(c);
|
setTargetCard(c);
|
||||||
@@ -2453,6 +2463,7 @@ public class CardFactory implements NewConstants {
|
|||||||
};//Ability_Activated
|
};//Ability_Activated
|
||||||
|
|
||||||
abDamage.setPayCosts(abCost);
|
abDamage.setPayCosts(abCost);
|
||||||
|
abDamage.setTarget(abTgt);
|
||||||
abDamage.setDescription(spDesc[0]);
|
abDamage.setDescription(spDesc[0]);
|
||||||
abDamage.setStackDescription(stDesc[0]);
|
abDamage.setStackDescription(stDesc[0]);
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public class ComputerUtil
|
|||||||
AllZone.Computer_Hand.remove(all[i].getSourceCard());
|
AllZone.Computer_Hand.remove(all[i].getSourceCard());
|
||||||
|
|
||||||
Ability_Cost cost = all[i].getPayCosts();
|
Ability_Cost cost = all[i].getPayCosts();
|
||||||
|
Target tgt = all[i].getTarget();
|
||||||
|
|
||||||
if (cost == null){
|
if (cost == null){
|
||||||
if(all[i] instanceof Ability_Tap)
|
if(all[i] instanceof Ability_Tap)
|
||||||
@@ -43,6 +44,9 @@ public class ComputerUtil
|
|||||||
AllZone.Stack.add(all[i]);
|
AllZone.Stack.add(all[i]);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
if (tgt != null && tgt.doesTarget())
|
||||||
|
all[i].chooseTargetAI();
|
||||||
|
|
||||||
Cost_Payment pay = new Cost_Payment(cost, all[i]);
|
Cost_Payment pay = new Cost_Payment(cost, all[i]);
|
||||||
pay.payComputerCosts();
|
pay.payComputerCosts();
|
||||||
}
|
}
|
||||||
@@ -232,6 +236,11 @@ public class ComputerUtil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cost.getLifeCost()){
|
||||||
|
if (AllZone.GameAction.getPlayerLife(Constant.Player.Computer).getLife() <= cost.getLifeAmount())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// check additional costs.
|
// check additional costs.
|
||||||
if (cost.getSacCost()){
|
if (cost.getSacCost()){
|
||||||
// if there's a sacrifice in the cost, just because we can Pay it doesn't mean we want to.
|
// if there's a sacrifice in the cost, just because we can Pay it doesn't mean we want to.
|
||||||
|
|||||||
@@ -1,23 +1,28 @@
|
|||||||
package forge;
|
package forge;
|
||||||
|
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
public class Cost_Payment {
|
public class Cost_Payment {
|
||||||
Ability_Cost cost = null;
|
private Ability_Cost cost = null;
|
||||||
SpellAbility ability = null;
|
private SpellAbility ability = null;
|
||||||
Card card = null;
|
private Card card = null;
|
||||||
|
private SpellAbility_Requirements req = null;
|
||||||
|
|
||||||
public Ability_Cost getCost() { return cost; }
|
public Ability_Cost getCost() { return cost; }
|
||||||
public SpellAbility getAbility() { return ability; }
|
public SpellAbility getAbility() { return ability; }
|
||||||
|
public Card getCard() { return card; }
|
||||||
|
|
||||||
|
public void setRequirements(SpellAbility_Requirements reqs) { req = reqs; }
|
||||||
public void setCancel(boolean cancel) { bCancel = cancel; }
|
public void setCancel(boolean cancel) { bCancel = cancel; }
|
||||||
public void setDoneTarget(boolean done) { bCancel = done; }
|
public boolean isCanceled() { return bCancel; }
|
||||||
|
|
||||||
private boolean payTap = false;
|
private boolean payTap = false;
|
||||||
private boolean payMana = false;
|
private boolean payMana = false;
|
||||||
private boolean paySubCounter = false;
|
private boolean paySubCounter = false;
|
||||||
private boolean paySac = false;
|
private boolean paySac = false;
|
||||||
|
private boolean payLife = false;
|
||||||
|
|
||||||
private boolean bCancel = false;
|
private boolean bCancel = false;
|
||||||
private boolean bCasting = false;
|
|
||||||
private boolean bDoneTarget = false;
|
|
||||||
private PlayerZone fromZone = null;
|
|
||||||
|
|
||||||
public void setPayMana(boolean bPay){ payMana = bPay; }
|
public void setPayMana(boolean bPay){ payMana = bPay; }
|
||||||
public void setPaySac(boolean bSac){ paySac = bSac; }
|
public void setPaySac(boolean bSac){ paySac = bSac; }
|
||||||
@@ -33,6 +38,7 @@ public class Cost_Payment {
|
|||||||
payMana = cost.hasNoManaCost();
|
payMana = cost.hasNoManaCost();
|
||||||
paySubCounter = !cost.getSubCounter();
|
paySubCounter = !cost.getSubCounter();
|
||||||
paySac = !cost.getSacCost();
|
paySac = !cost.getSacCost();
|
||||||
|
payLife = !cost.getLifeCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canPayAdditionalCosts(){
|
public boolean canPayAdditionalCosts(){
|
||||||
@@ -48,6 +54,12 @@ public class Cost_Payment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cost.getLifeCost()){
|
||||||
|
int curLife = AllZone.GameAction.getPlayerLife(card.getController()).getLife();
|
||||||
|
if (curLife < cost.getLifeAmount())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cost.getSacCost()){
|
if (cost.getSacCost()){
|
||||||
if (!cost.getSacThis()){
|
if (!cost.getSacThis()){
|
||||||
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
|
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
|
||||||
@@ -64,27 +76,8 @@ public class Cost_Payment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean payCost(){
|
public boolean payCost(){
|
||||||
if (bCancel || bDoneTarget && cost.getNumTargeted() < cost.getMinTargets()){
|
if (bCancel){
|
||||||
cancelPayment();
|
req.finishPaying();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ability instanceof Spell && !bCasting){
|
|
||||||
// remove from hand, todo(sol) be careful of spell copies when spells start using this
|
|
||||||
bCasting = true;
|
|
||||||
Card c = ability.getSourceCard();
|
|
||||||
fromZone = AllZone.getZone(c);
|
|
||||||
fromZone.remove(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
// targetting, with forward code for multiple target abilities
|
|
||||||
if (!bDoneTarget && cost.getMinTargets() > 0 && cost.getNumTargeted() < cost.getMaxTargets()){
|
|
||||||
if (cost.canTgtCreature() && cost.canTgtPlayer())
|
|
||||||
changeInput.stopSetNext(targetCreaturePlayer(ability, Command.Blank, true, this));
|
|
||||||
else if(cost.canTgtCreature())
|
|
||||||
changeInput.stopSetNext(targetCreature(ability, this));
|
|
||||||
else if(cost.canTgtPlayer())
|
|
||||||
changeInput.stopSetNext(targetPlayer(ability, this));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,13 +91,12 @@ public class Cost_Payment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert untap here
|
// insert untap here
|
||||||
if (!payMana && !cost.hasNoManaCost()){
|
|
||||||
// pay mana here
|
if (!payMana && !cost.hasNoManaCost()){ // pay mana here
|
||||||
changeInput.stopSetNext(new Input_PayCostMana(this));
|
changeInput.stopSetNext(new Input_PayCostMana(this));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!paySubCounter && cost.getSubCounter()){
|
if (!paySubCounter && cost.getSubCounter()){ // pay counters here.
|
||||||
// subtract counters here.
|
|
||||||
Counters c = cost.getCounterType();
|
Counters c = cost.getCounterType();
|
||||||
int countersLeft = card.getCounters(c) - cost.getCounterNum();
|
int countersLeft = card.getCounters(c) - cost.getCounterNum();
|
||||||
if (countersLeft >= 0){
|
if (countersLeft >= 0){
|
||||||
@@ -112,12 +104,35 @@ public class Cost_Payment {
|
|||||||
paySubCounter = true;
|
paySubCounter = true;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
cancelPayment();
|
bCancel = true;
|
||||||
|
req.finishPaying();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!paySac && cost.getSacCost())
|
|
||||||
{
|
if (!payLife && cost.getLifeCost()){ // pay life here
|
||||||
|
// todo: should ask with a yes/no popup box to pay life?
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(getCard().getName());
|
||||||
|
sb.append(" - Pay ");
|
||||||
|
sb.append(cost.getLifeAmount());
|
||||||
|
sb.append(" Life?");
|
||||||
|
Object[] possibleValues = {"Yes", "No"};
|
||||||
|
Object choice = JOptionPane.showOptionDialog(null, sb.toString(), getCard().getName() + " - Cost",
|
||||||
|
JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
|
||||||
|
null, possibleValues, possibleValues[0]);
|
||||||
|
if(choice.equals(0)) {
|
||||||
|
AllZone.GameAction.getPlayerLife(card.getController()).payLife(cost.getLifeAmount());
|
||||||
|
payLife = true;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
bCancel = true;
|
||||||
|
req.finishPaying();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!paySac && cost.getSacCost()){
|
||||||
// sacrifice stuff here
|
// sacrifice stuff here
|
||||||
if (cost.getSacThis())
|
if (cost.getSacThis())
|
||||||
changeInput.stopSetNext(sacrificeThis(ability, this));
|
changeInput.stopSetNext(sacrificeThis(ability, this));
|
||||||
@@ -126,28 +141,16 @@ public class Cost_Payment {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAllPaid())
|
req.finishPaying();
|
||||||
allPaid();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAllPaid(){
|
public boolean isAllPaid(){
|
||||||
return (payTap && payMana && paySubCounter && paySac);
|
return (payTap && payMana && paySubCounter && paySac && payLife);
|
||||||
}
|
|
||||||
|
|
||||||
public void allPaid(){
|
|
||||||
AllZone.ManaPool.clearPay(false);
|
|
||||||
AllZone.Stack.add(ability);
|
|
||||||
cost.resetTargets();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancelPayment(){
|
public void cancelPayment(){
|
||||||
// unpay anything we can.
|
// unpay anything we can.
|
||||||
cost.resetTargets();
|
|
||||||
if (bCasting){
|
|
||||||
// add back to hand
|
|
||||||
fromZone.add(ability.getSourceCard());
|
|
||||||
}
|
|
||||||
if (cost.getTap() && payTap){
|
if (cost.getTap() && payTap){
|
||||||
// untap if tapped
|
// untap if tapped
|
||||||
card.untap();
|
card.untap();
|
||||||
@@ -162,9 +165,61 @@ public class Cost_Payment {
|
|||||||
card.setCounter(c, countersLeft);
|
card.setCounter(c, countersLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// refund life
|
||||||
|
if (cost.getLifeCost() && payLife){
|
||||||
|
PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController());
|
||||||
|
life.payLife(cost.getLifeAmount()*-1);
|
||||||
|
}
|
||||||
|
|
||||||
// can't really unsacrifice things
|
// can't really unsacrifice things
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void payComputerCosts(){
|
||||||
|
Card sacCard = null;
|
||||||
|
ability.setActivatingPlayer(Constant.Player.Computer);
|
||||||
|
|
||||||
|
// double check if something can be sacrificed here. Real check is in ComputerUtil.canPayAdditionalCosts()
|
||||||
|
if (cost.getSacCost()){
|
||||||
|
if (cost.getSacThis())
|
||||||
|
sacCard = card;
|
||||||
|
else
|
||||||
|
sacCard = ComputerUtil.chooseSacrificeType(cost.getSacType(), card, ability.getTargetCard());
|
||||||
|
|
||||||
|
if (sacCard == null){
|
||||||
|
System.out.println("Couldn't find a valid card to sacrifice for: "+card.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// double check if counters available? Real check is in ComputerUtil.canPayAdditionalCosts()
|
||||||
|
int countersLeft = 0;
|
||||||
|
if (cost.getSubCounter()){
|
||||||
|
Counters c = cost.getCounterType();
|
||||||
|
countersLeft = card.getCounters(c) - cost.getCounterNum();
|
||||||
|
if (countersLeft < 0){
|
||||||
|
System.out.println("Not enough " + c.getName() + " on "+card.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cost.getTap())
|
||||||
|
card.tap();
|
||||||
|
|
||||||
|
if (!cost.hasNoManaCost())
|
||||||
|
ComputerUtil.payManaCost(ability);
|
||||||
|
|
||||||
|
if (cost.getSubCounter())
|
||||||
|
card.setCounter(cost.getCounterType(), countersLeft);
|
||||||
|
|
||||||
|
if (cost.getLifeCost())
|
||||||
|
AllZone.GameAction.getPlayerLife(card.getController()).payLife(cost.getLifeAmount());
|
||||||
|
|
||||||
|
if (cost.getSacCost())
|
||||||
|
AllZone.GameAction.sacrifice(sacCard);
|
||||||
|
|
||||||
|
AllZone.Stack.add(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Input sacrificeThis(final SpellAbility spell, final Cost_Payment payment) {
|
public static Input sacrificeThis(final SpellAbility spell, final Cost_Payment payment) {
|
||||||
Input target = new Input() {
|
Input target = new Input() {
|
||||||
private static final long serialVersionUID = 2685832214519141903L;
|
private static final long serialVersionUID = 2685832214519141903L;
|
||||||
@@ -172,10 +227,15 @@ public class Cost_Payment {
|
|||||||
@Override
|
@Override
|
||||||
public void showMessage() {
|
public void showMessage() {
|
||||||
Card card = spell.getSourceCard();
|
Card card = spell.getSourceCard();
|
||||||
String[] choices = {"Yes", "No"};
|
|
||||||
if(card.getController().equals(Constant.Player.Human)) {
|
if(card.getController().equals(Constant.Player.Human)) {
|
||||||
Object o = AllZone.Display.getChoice("Sacrifice " + card.getName() + " ?", choices);
|
StringBuilder sb = new StringBuilder();
|
||||||
if(o.equals("Yes")) {
|
sb.append(card.getName());
|
||||||
|
sb.append(" - Sacrifice?");
|
||||||
|
Object[] possibleValues = {"Yes", "No"};
|
||||||
|
Object choice = JOptionPane.showOptionDialog(null, sb.toString(), card.getName() + " - Cost",
|
||||||
|
JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
|
||||||
|
null, possibleValues, possibleValues[0]);
|
||||||
|
if(choice.equals(0)) {
|
||||||
AllZone.GameAction.sacrifice(card);
|
AllZone.GameAction.sacrifice(card);
|
||||||
payment.setPaySac(true);
|
payment.setPaySac(true);
|
||||||
stop();
|
stop();
|
||||||
@@ -226,171 +286,4 @@ public class Cost_Payment {
|
|||||||
};
|
};
|
||||||
return target;
|
return target;
|
||||||
}//sacrificeType()
|
}//sacrificeType()
|
||||||
|
|
||||||
public static Input targetCreaturePlayer(final SpellAbility ability, final Command paid, final boolean targeted, final Cost_Payment payment) {
|
|
||||||
Input target = new Input() {
|
|
||||||
private static final long serialVersionUID = 2781418414287281005L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showMessage() {
|
|
||||||
AllZone.Display.showMessage("Select target Creature, Player, or Planeswalker");
|
|
||||||
// when multi targets (Arc Mage) are added, need this:
|
|
||||||
// if payment.targeted < mintarget only enable cancel
|
|
||||||
// else if payment.targeted < maxtarget enable cancel and ok
|
|
||||||
ButtonUtil.enableOnlyCancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectButtonCancel() {
|
|
||||||
payment.setCancel(true);
|
|
||||||
stop();
|
|
||||||
payment.payCost();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectButtonOK() {
|
|
||||||
payment.setDoneTarget(true);
|
|
||||||
stop();
|
|
||||||
payment.payCost();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectCard(Card card, PlayerZone zone) {
|
|
||||||
if((card.isCreature() || card.isPlaneswalker()) && zone.is(Constant.Zone.Play)
|
|
||||||
&& (!targeted || CardFactoryUtil.canTarget(ability, card))) {
|
|
||||||
ability.setTargetCard(card);
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
}//selectCard()
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectPlayer(String player) {
|
|
||||||
ability.setTargetPlayer(player);
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
|
|
||||||
void done() {
|
|
||||||
payment.getCost().incrementTargets();
|
|
||||||
paid.execute();
|
|
||||||
stop();
|
|
||||||
payment.payCost();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return target;
|
|
||||||
}//input_targetCreaturePlayer()
|
|
||||||
|
|
||||||
public static Input targetCreature(final SpellAbility ability, final Cost_Payment payment) {
|
|
||||||
Input target = new Input() {
|
|
||||||
private static final long serialVersionUID = 2781418414287281005L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showMessage() {
|
|
||||||
AllZone.Display.showMessage("Select target Creature");
|
|
||||||
ButtonUtil.enableOnlyCancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectButtonCancel() {
|
|
||||||
payment.setCancel(true);
|
|
||||||
stop();
|
|
||||||
payment.payCost();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectCard(Card card, PlayerZone zone) {
|
|
||||||
if(card.isCreature() && zone.is(Constant.Zone.Play) && (CardFactoryUtil.canTarget(ability, card))) {
|
|
||||||
ability.setTargetCard(card);
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
}//selectCard()
|
|
||||||
|
|
||||||
void done() {
|
|
||||||
payment.getCost().incrementTargets();
|
|
||||||
stop();
|
|
||||||
payment.payCost();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return target;
|
|
||||||
}//targetCreature()
|
|
||||||
|
|
||||||
public static Input targetPlayer(final SpellAbility ability, final Cost_Payment payment) {
|
|
||||||
Input target = new Input() {
|
|
||||||
private static final long serialVersionUID = 2781418414287281005L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showMessage() {
|
|
||||||
AllZone.Display.showMessage("Select target Player or Planeswalker");
|
|
||||||
ButtonUtil.enableOnlyCancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectButtonCancel() {
|
|
||||||
payment.setCancel(true);
|
|
||||||
stop();
|
|
||||||
payment.payCost();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectCard(Card card, PlayerZone zone) {
|
|
||||||
if(card.isPlaneswalker() && zone.is(Constant.Zone.Play) && (!CardFactoryUtil.canTarget(ability, card))) {
|
|
||||||
ability.setTargetCard(card);
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
}//selectCard()
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectPlayer(String player) {
|
|
||||||
ability.setTargetPlayer(player);
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
|
|
||||||
void done() {
|
|
||||||
payment.getCost().incrementTargets();
|
|
||||||
stop();
|
|
||||||
payment.payCost();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return target;
|
|
||||||
}//targetPlayer()
|
|
||||||
|
|
||||||
public void payComputerCosts(){
|
|
||||||
Card sacCard = null;
|
|
||||||
ability.setActivatingPlayer(Constant.Player.Computer);
|
|
||||||
if (cost.doesTarget())
|
|
||||||
ability.chooseTargetAI();
|
|
||||||
|
|
||||||
// double check if something can be sacrificed here. Real check is in ComputerUtil.canPayAdditionalCosts()
|
|
||||||
if (cost.getSacCost()){
|
|
||||||
if (cost.getSacThis())
|
|
||||||
sacCard = card;
|
|
||||||
else
|
|
||||||
sacCard = ComputerUtil.chooseSacrificeType(cost.getSacType(), card, ability.getTargetCard());
|
|
||||||
|
|
||||||
if (sacCard == null){
|
|
||||||
System.out.println("Couldn't find a valid card to sacrifice for: "+card.getName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// double check if counters available? Real check is in ComputerUtil.canPayAdditionalCosts()
|
|
||||||
int countersLeft = 0;
|
|
||||||
if (cost.getSubCounter()){
|
|
||||||
Counters c = cost.getCounterType();
|
|
||||||
countersLeft = card.getCounters(c) - cost.getCounterNum();
|
|
||||||
if (countersLeft < 0){
|
|
||||||
System.out.println("Not enough " + c.getName() + " on "+card.getName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cost.getTap())
|
|
||||||
card.tap();
|
|
||||||
if (!cost.hasNoManaCost())
|
|
||||||
ComputerUtil.payManaCost(ability);
|
|
||||||
if (cost.getSubCounter())
|
|
||||||
card.setCounter(cost.getCounterType(), countersLeft);
|
|
||||||
if (cost.getSacCost())
|
|
||||||
AllZone.GameAction.sacrifice(sacCard);
|
|
||||||
|
|
||||||
AllZone.Stack.add(ability);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3456,8 +3456,11 @@ public class GameAction {
|
|||||||
public void playSpellAbility(SpellAbility sa) {
|
public void playSpellAbility(SpellAbility sa) {
|
||||||
sa.setActivatingPlayer(Constant.Player.Human);
|
sa.setActivatingPlayer(Constant.Player.Human);
|
||||||
if (sa.getPayCosts() != null){
|
if (sa.getPayCosts() != null){
|
||||||
|
Target_Selection ts = new Target_Selection(sa.getTarget(), sa);
|
||||||
Cost_Payment payment = new Cost_Payment(sa.getPayCosts(), sa);
|
Cost_Payment payment = new Cost_Payment(sa.getPayCosts(), sa);
|
||||||
payment.payCost();
|
|
||||||
|
SpellAbility_Requirements req = new SpellAbility_Requirements(sa, ts, payment);
|
||||||
|
req.fillRequirements();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
ManaCost manaCost = new ManaCost(sa.getManaCost());
|
ManaCost manaCost = new ManaCost(sa.getManaCost());
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class Input_PayCostMana extends Input {
|
|||||||
|
|
||||||
public Input_PayCostMana(Cost_Payment payment) {
|
public Input_PayCostMana(Cost_Payment payment) {
|
||||||
costPayment = payment;
|
costPayment = payment;
|
||||||
originalManaCost = costPayment.cost.getMana();
|
originalManaCost = costPayment.getCost().getMana();
|
||||||
sa = payment.getAbility();
|
sa = payment.getAbility();
|
||||||
|
|
||||||
if(Phase.GameBegins == 1) {
|
if(Phase.GameBegins == 1) {
|
||||||
|
|||||||
@@ -3,12 +3,23 @@ public class PlayerLife extends MyObservable implements java.io.Serializable
|
|||||||
{
|
{
|
||||||
private static final long serialVersionUID = -1614695903669967202L;
|
private static final long serialVersionUID = -1614695903669967202L;
|
||||||
|
|
||||||
|
private String player;
|
||||||
|
private Card playerCard;
|
||||||
private int life;
|
private int life;
|
||||||
private int assignedDamage;//from combat
|
private int assignedDamage;//from combat
|
||||||
|
|
||||||
public void setAssignedDamage(int n) {assignedDamage = n;}
|
public void setAssignedDamage(int n) {assignedDamage = n;}
|
||||||
public int getAssignedDamage() {return assignedDamage;}
|
public int getAssignedDamage() {return assignedDamage;}
|
||||||
|
|
||||||
|
public PlayerLife(String pl)
|
||||||
|
{
|
||||||
|
player = pl;
|
||||||
|
if (player.equals(Constant.Player.Human))
|
||||||
|
playerCard = AllZone.CardFactory.HumanNullCard;
|
||||||
|
else
|
||||||
|
playerCard = AllZone.CardFactory.ComputerNullCard;
|
||||||
|
}
|
||||||
|
|
||||||
public int getLife()
|
public int getLife()
|
||||||
{
|
{
|
||||||
return life;
|
return life;
|
||||||
@@ -18,39 +29,28 @@ public class PlayerLife extends MyObservable implements java.io.Serializable
|
|||||||
life = life2;
|
life = life2;
|
||||||
this.updateObservers();
|
this.updateObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLife(int life2)
|
public void addLife(int life2)
|
||||||
{
|
{
|
||||||
Card WhoGainedLife = new Card();
|
|
||||||
if(AllZone.Human_Life.getLife() != AllZone.Computer_Life.getLife()) {
|
|
||||||
if(AllZone.Human_Life.getLife() == life) WhoGainedLife = AllZone.CardFactory.HumanNullCard;
|
|
||||||
else WhoGainedLife = AllZone.CardFactory.ComputerNullCard;
|
|
||||||
}
|
|
||||||
life += life2;
|
life += life2;
|
||||||
if(WhoGainedLife != AllZone.CardFactory.HumanNullCard && WhoGainedLife != AllZone.CardFactory.ComputerNullCard) {
|
|
||||||
if(AllZone.Human_Life.getLife() == life) WhoGainedLife = AllZone.CardFactory.HumanNullCard;
|
|
||||||
else WhoGainedLife = AllZone.CardFactory.ComputerNullCard;
|
|
||||||
}
|
|
||||||
Object[] Life_Whenever_Parameters = new Object[1];
|
Object[] Life_Whenever_Parameters = new Object[1];
|
||||||
Life_Whenever_Parameters[0] = life2;
|
Life_Whenever_Parameters[0] = life2;
|
||||||
AllZone.GameAction.CheckWheneverKeyword(WhoGainedLife, "GainLife", Life_Whenever_Parameters);
|
AllZone.GameAction.CheckWheneverKeyword(playerCard, "GainLife", Life_Whenever_Parameters);
|
||||||
this.updateObservers();
|
this.updateObservers();
|
||||||
}
|
}
|
||||||
public void subtractLife(int life2, Card SourceCard)
|
public void subtractLife(int life2, Card SourceCard)
|
||||||
{
|
{
|
||||||
Card WhoGainedLife = new Card();
|
|
||||||
if(AllZone.Human_Life.getLife() != AllZone.Computer_Life.getLife()) {
|
|
||||||
if(AllZone.Human_Life.getLife() == life) WhoGainedLife = AllZone.CardFactory.HumanNullCard;
|
|
||||||
else WhoGainedLife = AllZone.CardFactory.ComputerNullCard;
|
|
||||||
}
|
|
||||||
life -= life2;
|
life -= life2;
|
||||||
if(WhoGainedLife != AllZone.CardFactory.HumanNullCard && WhoGainedLife != AllZone.CardFactory.ComputerNullCard) {
|
|
||||||
if(AllZone.Human_Life.getLife() == life) WhoGainedLife = AllZone.CardFactory.HumanNullCard;
|
|
||||||
else WhoGainedLife = AllZone.CardFactory.ComputerNullCard;
|
|
||||||
}
|
|
||||||
Object[] DealsDamage_Whenever_Parameters = new Object[3];
|
Object[] DealsDamage_Whenever_Parameters = new Object[3];
|
||||||
DealsDamage_Whenever_Parameters[0] = WhoGainedLife.getController();
|
DealsDamage_Whenever_Parameters[0] = player;
|
||||||
DealsDamage_Whenever_Parameters[2] = SourceCard;
|
DealsDamage_Whenever_Parameters[2] = SourceCard;
|
||||||
AllZone.GameAction.CheckWheneverKeyword(WhoGainedLife, "DealsDamage", DealsDamage_Whenever_Parameters);
|
AllZone.GameAction.CheckWheneverKeyword(playerCard, "DealsDamage", DealsDamage_Whenever_Parameters);
|
||||||
|
this.updateObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void payLife(int life2)
|
||||||
|
{
|
||||||
|
life -= life2;
|
||||||
this.updateObservers();
|
this.updateObservers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,6 +40,7 @@ public abstract class SpellAbility {
|
|||||||
private Input afterPayMana;
|
private Input afterPayMana;
|
||||||
|
|
||||||
protected Ability_Cost payCosts = null;
|
protected Ability_Cost payCosts = null;
|
||||||
|
protected Target chosenTarget = null;
|
||||||
|
|
||||||
private Command cancelCommand = Command.Blank;
|
private Command cancelCommand = Command.Blank;
|
||||||
private Command beforePayManaAI = Command.Blank;
|
private Command beforePayManaAI = Command.Blank;
|
||||||
@@ -238,6 +239,14 @@ public abstract class SpellAbility {
|
|||||||
payCosts = abCost;
|
payCosts = abCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Target getTarget() {
|
||||||
|
return chosenTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTarget(Target tgt) {
|
||||||
|
chosenTarget = tgt;
|
||||||
|
}
|
||||||
|
|
||||||
public Input getAfterResolve() {
|
public Input getAfterResolve() {
|
||||||
return afterResolve;
|
return afterResolve;
|
||||||
}
|
}
|
||||||
|
|||||||
74
src/forge/SpellAbility_Requirements.java
Normal file
74
src/forge/SpellAbility_Requirements.java
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package forge;
|
||||||
|
|
||||||
|
public class SpellAbility_Requirements {
|
||||||
|
private SpellAbility ability = null;
|
||||||
|
private Target_Selection select = null;
|
||||||
|
private Cost_Payment payment = null;
|
||||||
|
|
||||||
|
private PlayerZone fromZone = null;
|
||||||
|
private boolean bCasting = false;
|
||||||
|
|
||||||
|
public SpellAbility_Requirements(SpellAbility sa, Target_Selection ts, Cost_Payment cp){
|
||||||
|
ability = sa;
|
||||||
|
select = ts;
|
||||||
|
payment = cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fillRequirements(){
|
||||||
|
if (ability instanceof Spell && !bCasting){
|
||||||
|
// remove from hand, todo(sol) be careful of spell copies if spells start using this
|
||||||
|
bCasting = true;
|
||||||
|
Card c = ability.getSourceCard();
|
||||||
|
fromZone = AllZone.getZone(c);
|
||||||
|
fromZone.remove(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (select.getTgt().doesTarget()){
|
||||||
|
select.setRequirements(this);
|
||||||
|
select.chooseTargets();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
startPaying();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finishedTargeting(){
|
||||||
|
if (select.isCanceled()){
|
||||||
|
// cancel ability during target choosing
|
||||||
|
if (bCasting){ // and not a copy
|
||||||
|
// add back to hand
|
||||||
|
fromZone.add(ability.getSourceCard());
|
||||||
|
}
|
||||||
|
|
||||||
|
select.getTgt().resetTargets();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
startPaying();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startPaying(){
|
||||||
|
payment.setRequirements(this);
|
||||||
|
payment.payCost();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finishPaying(){
|
||||||
|
if (payment.isAllPaid())
|
||||||
|
addAbilityToStack();
|
||||||
|
else if (payment.isCanceled()){
|
||||||
|
if (bCasting){ // and not a copy
|
||||||
|
// add back to hand
|
||||||
|
fromZone.add(ability.getSourceCard());
|
||||||
|
}
|
||||||
|
if (select.getTgt().doesTarget())
|
||||||
|
select.getTgt().resetTargets();
|
||||||
|
|
||||||
|
payment.cancelPayment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAbilityToStack(){
|
||||||
|
AllZone.ManaPool.clearPay(false);
|
||||||
|
AllZone.Stack.add(ability);
|
||||||
|
if (select != null)
|
||||||
|
select.getTgt().resetTargets();
|
||||||
|
}
|
||||||
|
}
|
||||||
60
src/forge/Target.java
Normal file
60
src/forge/Target.java
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package forge;
|
||||||
|
|
||||||
|
public class Target {
|
||||||
|
private boolean tgtPlayer = false;
|
||||||
|
public boolean canTgtPlayer() { return tgtPlayer; }
|
||||||
|
private boolean tgtCreature = false;
|
||||||
|
public boolean canTgtCreature() { return tgtCreature; }
|
||||||
|
|
||||||
|
public boolean canTgtCreaturePlayer() { return tgtCreature && tgtPlayer; }
|
||||||
|
public boolean doesTarget() { return tgtCreature || tgtPlayer; }
|
||||||
|
|
||||||
|
private int minTargets = 0;
|
||||||
|
public int getMinTargets() { return minTargets; }
|
||||||
|
private int maxTargets = 0;
|
||||||
|
public int getMaxTargets() { return maxTargets; }
|
||||||
|
// add array of targets here?
|
||||||
|
|
||||||
|
private int numTargeted = 0;
|
||||||
|
public int getNumTargeted() { return numTargeted; }
|
||||||
|
public void incrementTargets() { numTargeted++; }
|
||||||
|
public void resetTargets() { numTargeted = 0; }
|
||||||
|
|
||||||
|
public Target(String parse){
|
||||||
|
if (parse.contains("Tgt")){
|
||||||
|
// Tgt{C}{P}[/<MinTargets>/<MaxTargets>] min-max is optional
|
||||||
|
String tgtStr = parse.replace("Tgt", "");
|
||||||
|
String[] tgtSplit = tgtStr.split("/");
|
||||||
|
|
||||||
|
if (tgtSplit[0].contains("C")) // creature
|
||||||
|
tgtCreature = true;
|
||||||
|
if (tgtSplit[0].contains("P")) // player
|
||||||
|
tgtPlayer = true;
|
||||||
|
//todo add Opponent and other permanent types
|
||||||
|
|
||||||
|
if (tgtSplit.length != 3){
|
||||||
|
minTargets = 1;
|
||||||
|
maxTargets = 1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
minTargets = Integer.parseInt(tgtSplit[1]);
|
||||||
|
maxTargets = Integer.parseInt(tgtSplit[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String targetString()
|
||||||
|
{
|
||||||
|
String tgt = "";
|
||||||
|
if (tgtCreature)
|
||||||
|
tgt += "creature";
|
||||||
|
if (tgtPlayer && !tgt.equals(""))
|
||||||
|
tgt += " or ";
|
||||||
|
if (tgtPlayer)
|
||||||
|
tgt += "player";
|
||||||
|
|
||||||
|
tgt += ".";
|
||||||
|
|
||||||
|
return "target " + tgt;
|
||||||
|
}
|
||||||
|
}
|
||||||
182
src/forge/Target_Selection.java
Normal file
182
src/forge/Target_Selection.java
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
package forge;
|
||||||
|
|
||||||
|
public class Target_Selection {
|
||||||
|
private Target target = null;
|
||||||
|
private SpellAbility ability = null;
|
||||||
|
private Card card = null;
|
||||||
|
|
||||||
|
public Target getTgt() { return target; }
|
||||||
|
public SpellAbility getAbility() { return ability; }
|
||||||
|
public Card getCard() { return card; }
|
||||||
|
|
||||||
|
private SpellAbility_Requirements req = null;
|
||||||
|
public void setRequirements(SpellAbility_Requirements reqs) { req = reqs; }
|
||||||
|
|
||||||
|
private boolean bCancel = false;
|
||||||
|
public void setCancel(boolean done) { bCancel = done; }
|
||||||
|
public boolean isCanceled() { return bCancel; }
|
||||||
|
private boolean bDoneTarget = false;
|
||||||
|
public void setDoneTarget(boolean done) { bDoneTarget = done; }
|
||||||
|
|
||||||
|
final private Input changeInput = new Input() {
|
||||||
|
private static final long serialVersionUID = -5750122411788688459L; };
|
||||||
|
|
||||||
|
public Target_Selection(Target tgt, SpellAbility sa){
|
||||||
|
target = tgt;
|
||||||
|
ability = sa;
|
||||||
|
card = sa.getSourceCard();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean chooseTargets(){
|
||||||
|
// if not enough targets chosen, reset and cancel Ability
|
||||||
|
if (bCancel || bDoneTarget && target.getNumTargeted() < target.getMinTargets()){
|
||||||
|
bCancel = true;
|
||||||
|
target.resetTargets();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we haven't reached minimum targets, or we're stil less than Max targets keep choosing
|
||||||
|
// targetting, with forward code for multiple target abilities
|
||||||
|
if (!bDoneTarget && target.getMinTargets() > 0 && target.getNumTargeted() < target.getMaxTargets()){
|
||||||
|
if (target.canTgtCreature() && target.canTgtPlayer())
|
||||||
|
changeInput.stopSetNext(targetCreaturePlayer(ability, Command.Blank, true, this, req));
|
||||||
|
else if(target.canTgtCreature())
|
||||||
|
changeInput.stopSetNext(targetCreature(ability, this, req));
|
||||||
|
else if(target.canTgtPlayer())
|
||||||
|
changeInput.stopSetNext(targetPlayer(ability, this, req));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Input targetCreaturePlayer(final SpellAbility ability, final Command paid, final boolean targeted,
|
||||||
|
final Target_Selection select, final SpellAbility_Requirements req) {
|
||||||
|
Input target = new Input() {
|
||||||
|
private static final long serialVersionUID = 2781418414287281005L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showMessage() {
|
||||||
|
AllZone.Display.showMessage("Select target Creature, Player, or Planeswalker");
|
||||||
|
// when multi targets (Arc Mage) are added, need this:
|
||||||
|
// if payment.targeted < mintarget only enable cancel
|
||||||
|
// else if payment.targeted < maxtarget enable cancel and ok
|
||||||
|
ButtonUtil.enableOnlyCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectButtonCancel() {
|
||||||
|
select.setCancel(true);
|
||||||
|
stop();
|
||||||
|
req.finishedTargeting();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectButtonOK() {
|
||||||
|
select.setDoneTarget(true);
|
||||||
|
stop();
|
||||||
|
req.finishedTargeting();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectCard(Card card, PlayerZone zone) {
|
||||||
|
if((card.isCreature() || card.isPlaneswalker()) && zone.is(Constant.Zone.Play)
|
||||||
|
&& (!targeted || CardFactoryUtil.canTarget(ability, card))) {
|
||||||
|
ability.setTargetCard(card);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
}//selectCard()
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectPlayer(String player) {
|
||||||
|
ability.setTargetPlayer(player);
|
||||||
|
// if multitarget increment then select again
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void done() {
|
||||||
|
select.getTgt().incrementTargets();
|
||||||
|
paid.execute();
|
||||||
|
stop();
|
||||||
|
req.finishedTargeting();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return target;
|
||||||
|
}//input_targetCreaturePlayer()
|
||||||
|
|
||||||
|
public static Input targetCreature(final SpellAbility ability, final Target_Selection select, final SpellAbility_Requirements req) {
|
||||||
|
Input target = new Input() {
|
||||||
|
private static final long serialVersionUID = 2781418414287281005L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showMessage() {
|
||||||
|
AllZone.Display.showMessage("Select target Creature");
|
||||||
|
ButtonUtil.enableOnlyCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectButtonCancel() {
|
||||||
|
select.setCancel(true);
|
||||||
|
stop();
|
||||||
|
req.finishedTargeting();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectCard(Card card, PlayerZone zone) {
|
||||||
|
if(card.isCreature() && zone.is(Constant.Zone.Play) && (CardFactoryUtil.canTarget(ability, card))) {
|
||||||
|
ability.setTargetCard(card);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
}//selectCard()
|
||||||
|
|
||||||
|
void done() {
|
||||||
|
select.getTgt().incrementTargets();
|
||||||
|
stop();
|
||||||
|
req.finishedTargeting();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return target;
|
||||||
|
}//targetCreature()
|
||||||
|
|
||||||
|
public static Input targetPlayer(final SpellAbility ability, final Target_Selection select, final SpellAbility_Requirements req) {
|
||||||
|
Input target = new Input() {
|
||||||
|
private static final long serialVersionUID = 2781418414287281005L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showMessage() {
|
||||||
|
AllZone.Display.showMessage("Select target Player or Planeswalker");
|
||||||
|
ButtonUtil.enableOnlyCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectButtonCancel() {
|
||||||
|
select.setCancel(true);
|
||||||
|
stop();
|
||||||
|
req.finishedTargeting();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectCard(Card card, PlayerZone zone) {
|
||||||
|
if(card.isPlaneswalker() && zone.is(Constant.Zone.Play) && (!CardFactoryUtil.canTarget(ability, card))) {
|
||||||
|
ability.setTargetCard(card);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
}//selectCard()
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectPlayer(String player) {
|
||||||
|
ability.setTargetPlayer(player);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void done() {
|
||||||
|
select.getTgt().incrementTargets();
|
||||||
|
stop();
|
||||||
|
req.finishedTargeting();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return target;
|
||||||
|
}//targetPlayer()
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user