mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
- Added SubCounter<counterType/counterAmount> to Ability_Cost and appropriately pay for it in correct locations.
- Minor checks for Cost_Payment requirements Note: SubCounter is not in any cards.txt yet, but has been tested with cards locally. Ex. Triskelion's ability would be: abDamageTgtCP SubCounter<P1P1/1>:1
This commit is contained in:
@@ -33,6 +33,16 @@ public class Ability_Cost {
|
||||
// future expansion of Ability_Cost class: untap, and lifeCost
|
||||
// private boolean untapCost = false;
|
||||
|
||||
private boolean subtractCounterCost = false;
|
||||
public boolean getSubCounter() { return subtractCounterCost; }
|
||||
private boolean addCounterCost = false;
|
||||
public boolean getAddCounter() { return addCounterCost; }
|
||||
|
||||
private int counterAmount = 0;
|
||||
public int getCounterNum() { return counterAmount; }
|
||||
private Counters counterType;
|
||||
public Counters getCounterType() { return counterType; }
|
||||
|
||||
private boolean lifeCost = false;
|
||||
private int lifeAmount = 0;
|
||||
|
||||
@@ -73,6 +83,22 @@ public class Ability_Cost {
|
||||
}
|
||||
}
|
||||
|
||||
if(parse.contains("SubCounter<")) {
|
||||
// SubCounter/<Counter Type>/counters removed
|
||||
subtractCounterCost = true;
|
||||
int counterPos = parse.indexOf("SubCounter<");
|
||||
int endPos = parse.indexOf(">", counterPos);
|
||||
String str = parse.substring(counterPos, endPos+1);
|
||||
parse = parse.replace(str, "").trim();
|
||||
|
||||
str = str.replace("SubCounter<", "");
|
||||
str = str.replace(">", "");
|
||||
String[] strSplit = str.split("/");
|
||||
// convert strSplit[0] to Counter.something
|
||||
counterType = Counters.valueOf(strSplit[0]);
|
||||
counterAmount = Integer.parseInt(strSplit[1]);
|
||||
}
|
||||
|
||||
if(parse.contains("Sac-")) {
|
||||
sacCost = true;
|
||||
int sacPos = parse.indexOf("Sac-");
|
||||
@@ -105,6 +131,25 @@ public class Ability_Cost {
|
||||
cost.append("Tap");
|
||||
else
|
||||
cost.append(", tap");
|
||||
caps = false;
|
||||
}
|
||||
|
||||
if (subtractCounterCost){
|
||||
if (caps)
|
||||
cost.append("Remove ");
|
||||
else
|
||||
cost.append(", remove ");
|
||||
if (counterAmount != 1)
|
||||
cost.append(counterAmount);
|
||||
else
|
||||
cost.append("a");
|
||||
cost.append(" " + counterType.getName());
|
||||
cost.append(" counter");
|
||||
if (counterAmount != 1)
|
||||
cost.append("s");
|
||||
cost.append(" from CARDNAME");
|
||||
|
||||
caps = false;
|
||||
}
|
||||
|
||||
if (lifeCost){
|
||||
@@ -113,6 +158,8 @@ public class Ability_Cost {
|
||||
else
|
||||
cost.append(", Pay");
|
||||
cost.append(lifeAmount);
|
||||
|
||||
caps = false;
|
||||
}
|
||||
|
||||
cost.append(sacString(caps));
|
||||
|
||||
@@ -1692,9 +1692,7 @@ public class CardFactory implements NewConstants {
|
||||
public boolean canPlayAI() {
|
||||
// temporarily disabled until AI is improved
|
||||
if (abCost.getSacCost()) return false;
|
||||
|
||||
if (abCost.getTap() && (card.isTapped() || card.isSick()))
|
||||
return false;
|
||||
if (abCost.getSubCounter()) return false;
|
||||
|
||||
if (!ComputerUtil.canPayCost(this))
|
||||
return false;
|
||||
@@ -1745,10 +1743,8 @@ public class CardFactory implements NewConstants {
|
||||
|
||||
@Override
|
||||
public boolean canPlay() {
|
||||
if (abCost.getTap() && (card.isTapped() || card.isSick()))
|
||||
return false;
|
||||
|
||||
return (CardFactoryUtil.canUseAbility(card) && super.canPlay());
|
||||
Cost_Payment pay = new Cost_Payment(abCost, this);
|
||||
return (pay.canPayAdditionalCosts() && CardFactoryUtil.canUseAbility(card) && super.canPlay());
|
||||
}
|
||||
|
||||
private CardList getCreatures() {
|
||||
@@ -2212,21 +2208,19 @@ public class CardFactory implements NewConstants {
|
||||
|
||||
@Override
|
||||
public boolean canPlay(){
|
||||
if (abCost.getTap() && (card.isTapped() || card.isSick()))
|
||||
return false;
|
||||
|
||||
return (CardFactoryUtil.canUseAbility(card) && super.canPlay());
|
||||
Cost_Payment pay = new Cost_Payment(abCost, this);
|
||||
return (pay.canPayAdditionalCosts() && CardFactoryUtil.canUseAbility(card) && super.canPlay());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
// temporarily disable sac canPlay until better AI
|
||||
//if (abCost.getSacCost()) return false;
|
||||
if (abCost.getTap() && (card.isTapped() || card.isSick()))
|
||||
return false;
|
||||
// temporarily disabled until better AI
|
||||
if (abCost.getSacCost()) return false;
|
||||
if (abCost.getSubCounter()) return false;
|
||||
|
||||
if (!ComputerUtil.canPayCost(this))
|
||||
return false;
|
||||
|
||||
damage = getNumDamage();
|
||||
|
||||
Random r = new Random(); // prevent run-away activations
|
||||
|
||||
@@ -216,28 +216,39 @@ public class ComputerUtil
|
||||
|
||||
static public boolean canPayAdditionalCosts(SpellAbility sa)
|
||||
{
|
||||
Ability_Cost cost = sa.getPayCosts();
|
||||
if (cost == null)
|
||||
return true;
|
||||
// Add additional cost checks here before attempting to activate abilities
|
||||
Ability_Cost cost = sa.getPayCosts();
|
||||
if (cost == null)
|
||||
return true;
|
||||
Card card = sa.getSourceCard();
|
||||
|
||||
if (cost.getTap() && (card.isTapped() || card.isSick()))
|
||||
return false;
|
||||
|
||||
if (cost.getSubCounter()){
|
||||
Counters c = cost.getCounterType();
|
||||
if (card.getCounters(c) - cost.getCounterNum() < 0 || !AllZone.GameAction.isCardInPlay(card)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// check additional costs.
|
||||
if (cost.getSacCost()){
|
||||
// if there's a sacrifice in the cost, just because we can Pay it doesn't mean we want to.
|
||||
if (!cost.getSacThis()){
|
||||
String type = cost.getSacType();
|
||||
PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
|
||||
CardList typeList = new CardList(play.getCards());
|
||||
typeList = typeList.getType(type);
|
||||
Card target = sa.getTargetCard();
|
||||
if (target != null && target.getController().equals(Constant.Player.Computer)) // don't sacrifice the card we're pumping
|
||||
typeList.remove(target);
|
||||
return typeList.size() > 0;
|
||||
}
|
||||
else if (cost.getSacThis() && AllZone.GameAction.isCardInPlay(sa.getSourceCard()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// check additional costs.
|
||||
if (cost.getSacCost()){
|
||||
// if there's a sacrifice in the cost, just because we can Pay it doesn't mean we want to.
|
||||
if (!cost.getSacThis()){
|
||||
String type = cost.getSacType();
|
||||
PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
|
||||
CardList typeList = new CardList(play.getCards());
|
||||
typeList = typeList.getType(type);
|
||||
Card target = sa.getTargetCard();
|
||||
if (target != null && target.getController().equals(Constant.Player.Computer)) // don't sacrifice the card we're pumping
|
||||
typeList.remove(target);
|
||||
return typeList.size() > 0;
|
||||
}
|
||||
else if (cost.getSacThis() && !AllZone.GameAction.isCardInPlay(card))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static public boolean canPayCost(String cost)
|
||||
|
||||
@@ -12,6 +12,7 @@ public class Cost_Payment {
|
||||
|
||||
private boolean payTap = false;
|
||||
private boolean payMana = false;
|
||||
private boolean paySubCounter = false;
|
||||
private boolean paySac = false;
|
||||
private boolean bCancel = false;
|
||||
private boolean bCasting = false;
|
||||
@@ -30,9 +31,38 @@ public class Cost_Payment {
|
||||
card = this.ability.getSourceCard();
|
||||
payTap = !cost.getTap();
|
||||
payMana = cost.hasNoManaCost();
|
||||
paySubCounter = !cost.getSubCounter();
|
||||
paySac = !cost.getSacCost();
|
||||
}
|
||||
|
||||
public boolean canPayAdditionalCosts(){
|
||||
if (cost.getTap() && (card.isTapped() || card.isSick()))
|
||||
return false;
|
||||
|
||||
int countersLeft = 0;
|
||||
if (cost.getSubCounter()){
|
||||
Counters c = cost.getCounterType();
|
||||
countersLeft = card.getCounters(c) - cost.getCounterNum();
|
||||
if (countersLeft < 0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cost.getSacCost()){
|
||||
if (!cost.getSacThis()){
|
||||
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
|
||||
CardList typeList = new CardList(play.getCards());
|
||||
typeList = typeList.getType(cost.getSacType());
|
||||
if (typeList.size() == 0)
|
||||
return false;
|
||||
}
|
||||
else if (cost.getSacThis() && !AllZone.GameAction.isCardInPlay(card))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean payCost(){
|
||||
if (bCancel || bDoneTarget && cost.getNumTargeted() < cost.getMinTargets()){
|
||||
cancelPayment();
|
||||
@@ -71,8 +101,22 @@ public class Cost_Payment {
|
||||
if (!payMana && !cost.hasNoManaCost()){
|
||||
// pay mana here
|
||||
changeInput.stopSetNext(new Input_PayCostMana(this));
|
||||
return false;
|
||||
}
|
||||
else if (!paySac && cost.getSacCost())
|
||||
if (!paySubCounter && cost.getSubCounter()){
|
||||
// subtract counters here.
|
||||
Counters c = cost.getCounterType();
|
||||
int countersLeft = card.getCounters(c) - cost.getCounterNum();
|
||||
if (countersLeft >= 0){
|
||||
card.setCounter(c, countersLeft);
|
||||
paySubCounter = true;
|
||||
}
|
||||
else{
|
||||
cancelPayment();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!paySac && cost.getSacCost())
|
||||
{
|
||||
// sacrifice stuff here
|
||||
if (cost.getSacThis())
|
||||
@@ -82,10 +126,14 @@ public class Cost_Payment {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (payTap && payMana && paySac)
|
||||
if (isAllPaid())
|
||||
allPaid();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isAllPaid(){
|
||||
return (payTap && payMana && paySubCounter && paySac);
|
||||
}
|
||||
|
||||
public void allPaid(){
|
||||
AllZone.ManaPool.clearPay(false);
|
||||
@@ -106,6 +154,14 @@ public class Cost_Payment {
|
||||
}
|
||||
// refund mana
|
||||
AllZone.ManaPool.unpaid();
|
||||
|
||||
// refund counters
|
||||
if (cost.getSubCounter() && paySubCounter){
|
||||
Counters c = cost.getCounterType();
|
||||
int countersLeft = card.getCounters(c) + cost.getCounterNum();
|
||||
card.setCounter(c, countersLeft);
|
||||
}
|
||||
|
||||
// can't really unsacrifice things
|
||||
}
|
||||
|
||||
@@ -303,7 +359,7 @@ public class Cost_Payment {
|
||||
if (cost.doesTarget())
|
||||
ability.chooseTargetAI();
|
||||
|
||||
// make sure something is there to be sacrificed before going through payments
|
||||
// double check if something can be sacrificed here. Real check is in ComputerUtil.canPayAdditionalCosts()
|
||||
if (cost.getSacCost()){
|
||||
if (cost.getSacThis())
|
||||
sacCard = card;
|
||||
@@ -315,18 +371,26 @@ public class Cost_Payment {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user