mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
OptionalCosts (Buyback, Kicker, AltCost) moved to EnumSet (there was a string list)
intrinsic abilities renamed to unparsed ones, getMultiKickerMagnitude is getKickerMagnitude, it returns 1 for simple Kickers now Kicker syntax changed, AltCost avaiable to check on triggers
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -13839,6 +13839,7 @@ src/main/java/forge/card/spellability/AbilitySub.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/AbilityTriggered.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/HumanPlaySpellAbility.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/ISpellAbility.java -text
|
||||
src/main/java/forge/card/spellability/OptionalCost.java -text
|
||||
src/main/java/forge/card/spellability/Spell.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/SpellAbility.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/SpellAbilityCondition.java svneol=native#text/plain
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -51,6 +52,7 @@ import forge.card.replacement.ReplaceMoved;
|
||||
import forge.card.replacement.ReplacementEffect;
|
||||
import forge.card.replacement.ReplacementResult;
|
||||
import forge.card.spellability.AbilityTriggered;
|
||||
import forge.card.spellability.OptionalCost;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellPermanent;
|
||||
import forge.card.spellability.Target;
|
||||
@@ -110,7 +112,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
|
||||
// if this card is an Aura, what Entity is it enchanting?
|
||||
private GameEntity enchanting = null;
|
||||
private ArrayList<String> optionalAdditionalCostsPaid = null;
|
||||
|
||||
// changes by AF animate and continuous static effects - timestamp is the key of maps
|
||||
private Map<Long, CardType> changedCardTypes = new ConcurrentSkipListMap<Long, CardType>();
|
||||
@@ -182,7 +183,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
|
||||
private int xManaCostPaid = 0;
|
||||
|
||||
private int multiKickerMagnitude = 0;
|
||||
private int replicateMagnitude = 0;
|
||||
|
||||
private int sunburstValue = 0;
|
||||
@@ -3892,23 +3892,14 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
return this.getNetAttack();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* addMultiKickerMagnitude.
|
||||
* </p>
|
||||
*
|
||||
* @param n
|
||||
* a int.
|
||||
*/
|
||||
public final void addMultiKickerMagnitude(final int n) {
|
||||
this.multiKickerMagnitude += n;
|
||||
}
|
||||
public final void setMultiKickerMagnitude(final int n) {
|
||||
this.multiKickerMagnitude = n;
|
||||
}
|
||||
|
||||
public final int getMultiKickerMagnitude() {
|
||||
return this.multiKickerMagnitude;
|
||||
private int multiKickerMagnitude = 0;
|
||||
public final void addMultiKickerMagnitude(final int n) { this.multiKickerMagnitude += n; }
|
||||
public final void setKickerMagnitude(final int n) { this.multiKickerMagnitude = n; }
|
||||
public final int getKickerMagnitude() {
|
||||
if ( this.multiKickerMagnitude > 0 )
|
||||
return multiKickerMagnitude;
|
||||
boolean hasK1 = costsPaid.contains(OptionalCost.Kicker1);
|
||||
return hasK1 == costsPaid.contains(OptionalCost.Kicker2) ? (hasK1 ? 2 : 0) : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4290,8 +4281,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
*
|
||||
* @return a {@link java.util.ArrayList} object.
|
||||
*/
|
||||
public final ArrayList<String> getIntrinsicAbilities() {
|
||||
return this.getCharacteristics().getIntrinsicAbility();
|
||||
public final List<String> getUnparsedAbilities() {
|
||||
return this.getCharacteristics().getUnparsedAbilities();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4328,8 +4319,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
* @param a
|
||||
* a {@link java.util.ArrayList} object.
|
||||
*/
|
||||
public final void setIntrinsicAbilities(final ArrayList<String> a) {
|
||||
this.getCharacteristics().setIntrinsicAbility(new ArrayList<String>(a));
|
||||
public final void setIntrinsicAbilities(final List<String> a) {
|
||||
this.getCharacteristics().setUnparsedAbilities(new ArrayList<String>(a));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4358,7 +4349,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
*/
|
||||
public final void addIntrinsicAbility(final String s) {
|
||||
if (s.trim().length() != 0) {
|
||||
this.getCharacteristics().getIntrinsicAbility().add(s);
|
||||
this.getCharacteristics().getUnparsedAbilities().add(s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4796,64 +4787,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
this.suspendCast = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* optionalAdditionalCostsPaid.
|
||||
* </p>
|
||||
*
|
||||
* @param cost
|
||||
* a String.
|
||||
*/
|
||||
public final void addOptionalAdditionalCostsPaid(final String cost) {
|
||||
if (optionalAdditionalCostsPaid == null) {
|
||||
optionalAdditionalCostsPaid = new ArrayList<String>();
|
||||
}
|
||||
this.optionalAdditionalCostsPaid.add(cost);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* optionalAdditionalCostsPaid.
|
||||
* </p>
|
||||
*/
|
||||
public final void clearAdditionalCostsPaid() {
|
||||
if (optionalAdditionalCostsPaid != null) {
|
||||
optionalAdditionalCostsPaid.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* isOptionalAdditionalCostsPaid.
|
||||
* </p>
|
||||
*
|
||||
* @param cost
|
||||
* a String.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public final boolean isOptionalAdditionalCostsPaid(final String cost) {
|
||||
if (optionalAdditionalCostsPaid == null) {
|
||||
return false;
|
||||
}
|
||||
for (String s : optionalAdditionalCostsPaid) {
|
||||
if (s.startsWith(cost)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* isOptionalAdditionalCostsPaid.
|
||||
* </p>
|
||||
* @return an ArrayList<String>.
|
||||
*
|
||||
*/
|
||||
public final ArrayList<String> getOptionalAdditionalCostsPaid() {
|
||||
return this.optionalAdditionalCostsPaid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is phased out.
|
||||
*
|
||||
@@ -6369,17 +6302,16 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
} else if (property.startsWith("kicked")) {
|
||||
if (property.equals("kicked")) {
|
||||
if (!this.isOptionalAdditionalCostsPaid("Kicker")) {
|
||||
if (this.getKickerMagnitude() == 0) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
String s = "Kicker " + property.split("kicked ")[1];
|
||||
if (!this.isOptionalAdditionalCostsPaid(s)) {
|
||||
return false;
|
||||
}
|
||||
if ("1".equals(s) && !this.isOptionalCostPaid(OptionalCost.Kicker1)) return false;
|
||||
if ("2".equals(s) && !this.isOptionalCostPaid(OptionalCost.Kicker2)) return false;
|
||||
}
|
||||
} else if (property.startsWith("notkicked")) {
|
||||
if (this.isOptionalAdditionalCostsPaid("Kicker")) {
|
||||
if (this.getKickerMagnitude() > 0) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("evoked")) {
|
||||
@@ -8317,15 +8249,13 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
public void setSplitStateToPlayAbility(SpellAbility sa) {
|
||||
if( !isSplitCard() ) return; // just in case
|
||||
// Split card support
|
||||
List<SpellAbility> leftSplitAbilities = getState(CardCharacteristicName.LeftSplit).getSpellAbility();
|
||||
List<SpellAbility> rightSplitAbilities = getState(CardCharacteristicName.RightSplit).getSpellAbility();
|
||||
for (SpellAbility a : leftSplitAbilities) {
|
||||
for (SpellAbility a : getState(CardCharacteristicName.LeftSplit).getSpellAbility()) {
|
||||
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
||||
setState(CardCharacteristicName.LeftSplit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (SpellAbility a : rightSplitAbilities) {
|
||||
for (SpellAbility a : getState(CardCharacteristicName.RightSplit).getSpellAbility()) {
|
||||
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
||||
setState(CardCharacteristicName.RightSplit);
|
||||
return;
|
||||
@@ -8336,5 +8266,12 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
|
||||
throw new RuntimeException("Not found which part to choose for ability " + sa + " from card " + this);
|
||||
}
|
||||
|
||||
|
||||
// Optional costs paid
|
||||
private final EnumSet<OptionalCost> costsPaid = EnumSet.noneOf(OptionalCost.class);
|
||||
public void clearOptionalCostsPaid() { costsPaid.clear(); }
|
||||
public void addOptionalCostPaid(OptionalCost cost) { costsPaid.add(cost); }
|
||||
public Iterable<OptionalCost> getOptionalCostsPaid() { return costsPaid; }
|
||||
public boolean isOptionalCostPaid(OptionalCost cost) { return costsPaid.contains(cost); }
|
||||
|
||||
} // end Card class
|
||||
|
||||
@@ -46,7 +46,7 @@ public class CardCharacteristics {
|
||||
private ArrayList<String> intrinsicKeyword = new ArrayList<String>();
|
||||
private final List<SpellAbility> spellAbility = new ArrayList<SpellAbility>();
|
||||
private final List<SpellAbility> manaAbility = new ArrayList<SpellAbility>();
|
||||
private ArrayList<String> intrinsicAbility = new ArrayList<String>();
|
||||
private List<String> unparsedAbilities = new ArrayList<String>();
|
||||
private ArrayList<Trigger> triggers = new ArrayList<Trigger>();
|
||||
private ArrayList<ReplacementEffect> replacementEffects = new ArrayList<ReplacementEffect>();
|
||||
private ArrayList<StaticAbility> staticAbilities = new ArrayList<StaticAbility>();
|
||||
@@ -215,18 +215,18 @@ public class CardCharacteristics {
|
||||
*
|
||||
* @return the intrinsicAbility
|
||||
*/
|
||||
public final ArrayList<String> getIntrinsicAbility() {
|
||||
return this.intrinsicAbility;
|
||||
public final List<String> getUnparsedAbilities() {
|
||||
return this.unparsedAbilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the intrinsic ability.
|
||||
*
|
||||
* @param intrinsicAbility0
|
||||
* @param list
|
||||
* the intrinsicAbility to set
|
||||
*/
|
||||
public final void setIntrinsicAbility(final ArrayList<String> intrinsicAbility0) {
|
||||
this.intrinsicAbility = intrinsicAbility0;
|
||||
public final void setUnparsedAbilities(final List<String> list) {
|
||||
this.unparsedAbilities = list;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -408,7 +408,7 @@ public class CardCharacteristics {
|
||||
// ArrayList<String> intrinsicKeyword : list of String objects so use copy constructor
|
||||
this.intrinsicKeyword = new ArrayList<String>(source.getIntrinsicKeyword());
|
||||
// ArrayList<String> intrinsicAbility : list of String objects so use copy constructor
|
||||
this.intrinsicAbility = new ArrayList<String>(source.getIntrinsicAbility());
|
||||
this.unparsedAbilities = new ArrayList<String>(source.getUnparsedAbilities());
|
||||
// ArrayList<String> staticAbilityStrings : list of String objects so use copy constructor
|
||||
this.staticAbilityStrings = new ArrayList<String>(source.getStaticAbilityStrings());
|
||||
// String imageFilename = copy reference
|
||||
|
||||
@@ -121,7 +121,7 @@ public final class AbilityFactory {
|
||||
return abCost;
|
||||
}
|
||||
|
||||
private static final SpellAbility getAbility(AbilityRecordType type, ApiType api, Map<String, String> mapParams, Cost abCost, Card hostCard) {
|
||||
public static final SpellAbility getAbility(AbilityRecordType type, ApiType api, Map<String, String> mapParams, Cost abCost, Card hostCard) {
|
||||
|
||||
|
||||
Target abTgt = mapParams.containsKey("ValidTgts") ? readTarget(hostCard, mapParams) : null;
|
||||
@@ -350,7 +350,7 @@ public final class AbilityFactory {
|
||||
if(!card.isSplitCard())
|
||||
throw new IllegalStateException("Fuse ability may be built only on split cards");
|
||||
|
||||
final String strLeftAbility = card.getState(CardCharacteristicName.LeftSplit).getIntrinsicAbility().get(0);
|
||||
final String strLeftAbility = card.getState(CardCharacteristicName.LeftSplit).getUnparsedAbilities().get(0);
|
||||
Map<String, String> leftMap = getMapParams(strLeftAbility);
|
||||
AbilityRecordType leftType = AbilityRecordType.getRecordType(leftMap);
|
||||
ApiType leftApi = leftType.getApiTypeOf(leftMap);
|
||||
@@ -358,7 +358,7 @@ public final class AbilityFactory {
|
||||
leftMap.put("SpellDescription", "Fuse (you may cast both halves of this card from your hand).");
|
||||
leftMap.put("ActivationZone", "Hand");
|
||||
|
||||
final String strRightAbility = card.getState(CardCharacteristicName.RightSplit).getIntrinsicAbility().get(0);
|
||||
final String strRightAbility = card.getState(CardCharacteristicName.RightSplit).getUnparsedAbilities().get(0);
|
||||
Map<String, String> rightMap = getMapParams(strRightAbility);
|
||||
AbilityRecordType rightType = AbilityRecordType.getRecordType(leftMap);
|
||||
ApiType rightApi = leftType.getApiTypeOf(rightMap);
|
||||
|
||||
@@ -248,7 +248,7 @@ public class CloneEffect extends SpellAbilityEffect {
|
||||
final String actualAbility = origSVars.get(s);
|
||||
// final SpellAbility grantedAbility = newAF.getAbility(actualAbility, tgtCard);
|
||||
// tgtCard.addSpellAbility(grantedAbility);
|
||||
tgtCard.getIntrinsicAbilities().add(actualAbility);
|
||||
tgtCard.getUnparsedAbilities().add(actualAbility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ public class TokenEffect extends SpellAbilityEffect {
|
||||
final SpellAbility grantedAbility = AbilityFactory.getAbility(actualAbility, c);
|
||||
c.addSpellAbility(grantedAbility);
|
||||
// added ability to intrinsic list so copies and clones work
|
||||
c.getIntrinsicAbilities().add(actualAbility);
|
||||
c.getUnparsedAbilities().add(actualAbility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import forge.card.mana.ManaCost;
|
||||
import forge.card.replacement.ReplacementHandler;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.OptionalCost;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellPermanent;
|
||||
import forge.card.spellability.Target;
|
||||
@@ -191,11 +192,10 @@ public class CardFactory {
|
||||
|
||||
if (bCopyDetails) {
|
||||
c.addXManaCostPaid(original.getXManaCostPaid());
|
||||
c.addMultiKickerMagnitude(original.getMultiKickerMagnitude());
|
||||
if (original.getOptionalAdditionalCostsPaid() != null) {
|
||||
for (String cost : original.getOptionalAdditionalCostsPaid()) {
|
||||
c.addOptionalAdditionalCostsPaid(cost);
|
||||
}
|
||||
c.setKickerMagnitude(original.getKickerMagnitude());
|
||||
|
||||
for (OptionalCost cost : original.getOptionalCostsPaid()) {
|
||||
c.addOptionalCostPaid(cost);
|
||||
}
|
||||
c.addReplicateMagnitude(original.getReplicateMagnitude());
|
||||
if (sa.isReplicate()) {
|
||||
@@ -488,7 +488,7 @@ public class CardFactory {
|
||||
to.setManaCost(from.getManaCost());
|
||||
to.setColor(from.getColor());
|
||||
to.setSVars(from.getSVars());
|
||||
to.setIntrinsicAbilities(from.getIntrinsicAbilities());
|
||||
to.setIntrinsicAbilities(from.getUnparsedAbilities());
|
||||
|
||||
to.setImageKey(from.getImageKey());
|
||||
to.setTriggers(from.getTriggers());
|
||||
|
||||
@@ -55,6 +55,7 @@ import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilityStatic;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.OptionalCost;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellAbilityRestriction;
|
||||
@@ -1556,11 +1557,8 @@ public class CardFactoryUtil {
|
||||
}
|
||||
}
|
||||
if (sq[0].startsWith("Kicked")) {
|
||||
if (c.isOptionalAdditionalCostsPaid("Kicker")) {
|
||||
return CardFactoryUtil.doXMath(Integer.parseInt(sq[1]), m, c);
|
||||
} else {
|
||||
return CardFactoryUtil.doXMath(Integer.parseInt(sq[2]), m, c);
|
||||
}
|
||||
int ix = c.getKickerMagnitude() > 0 ? 1 : 2;
|
||||
return CardFactoryUtil.doXMath(Integer.parseInt(sq[ix]), m, c);
|
||||
}
|
||||
|
||||
if (sq[0].contains("GraveyardWithGE20Cards")) {
|
||||
@@ -1660,7 +1658,7 @@ public class CardFactoryUtil {
|
||||
|
||||
// Count$TimesKicked
|
||||
if (sq[0].contains("TimesKicked")) {
|
||||
return CardFactoryUtil.doXMath(c.getMultiKickerMagnitude(), m, c);
|
||||
return CardFactoryUtil.doXMath(c.getKickerMagnitude(), m, c);
|
||||
}
|
||||
if (sq[0].contains("NumCounters")) {
|
||||
final int num = c.getCounters(CounterType.getType(sq[1]));
|
||||
@@ -2370,14 +2368,8 @@ public class CardFactoryUtil {
|
||||
public static final void addAbilityFactoryAbilities(final Card card) {
|
||||
// **************************************************
|
||||
// AbilityFactory cards
|
||||
final ArrayList<String> ia = card.getIntrinsicAbilities();
|
||||
for (int i = 0; i < ia.size(); i++) {
|
||||
// System.out.println(cardName);
|
||||
final SpellAbility sa = AbilityFactory.getAbility(ia.get(i), card);
|
||||
if (sa.hasParam("SetAsKicked")) {
|
||||
sa.addOptionalAdditionalCosts("Kicker");
|
||||
}
|
||||
card.addSpellAbility(sa);
|
||||
for (String rawAbility : card.getUnparsedAbilities()) {
|
||||
card.addSpellAbility(AbilityFactory.getAbility(rawAbility, card));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2601,10 +2593,11 @@ public class CardFactoryUtil {
|
||||
}
|
||||
|
||||
// AltCost
|
||||
if (!card.getSVar("AltCost").equals("")) {
|
||||
String altCost = card.getSVar("AltCost");
|
||||
if (StringUtils.isNotBlank(altCost)) {
|
||||
final SpellAbility sa1 = card.getFirstSpellAbility();
|
||||
if (sa1 != null && sa1.isSpell()) {
|
||||
card.addSpellAbility(makeAltCost(card, sa1));
|
||||
card.addSpellAbility(makeAltCostAbility(card, altCost, sa1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2779,7 +2772,7 @@ public class CardFactoryUtil {
|
||||
final SpellAbility sa = AbilityFactory.getAbility(abilityStr.toString(), card);
|
||||
card.addSpellAbility(sa);
|
||||
// add ability to instrinic strings so copies/clones create the ability also
|
||||
card.getIntrinsicAbilities().add(abilityStr.toString());
|
||||
card.getUnparsedAbilities().add(abilityStr.toString());
|
||||
}
|
||||
|
||||
setupEtbKeywords(card);
|
||||
@@ -3066,63 +3059,26 @@ public class CardFactoryUtil {
|
||||
* @param abilities
|
||||
* @return
|
||||
*/
|
||||
private static SpellAbility makeAltCost(final Card card, final SpellAbility sa) {
|
||||
String altCost = card.getSVar("AltCost");
|
||||
final HashMap<String, String> mapParams = new HashMap<String, String>();
|
||||
String altCostDescription = "";
|
||||
final String[] altCosts = altCost.split("\\|");
|
||||
|
||||
for (int aCnt = 0; aCnt < altCosts.length; aCnt++) {
|
||||
altCosts[aCnt] = altCosts[aCnt].trim();
|
||||
}
|
||||
|
||||
for (final String altCost2 : altCosts) {
|
||||
final String[] aa = altCost2.split("\\$");
|
||||
|
||||
for (int aaCnt = 0; aaCnt < aa.length; aaCnt++) {
|
||||
aa[aaCnt] = aa[aaCnt].trim();
|
||||
}
|
||||
|
||||
if (aa.length != 2) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("StaticEffectFactory Parsing Error: Split length of ");
|
||||
sb.append(altCost2).append(" in ").append(card.getName()).append(" is not 2.");
|
||||
throw new RuntimeException(sb.toString());
|
||||
}
|
||||
|
||||
mapParams.put(aa[0], aa[1]);
|
||||
}
|
||||
|
||||
altCost = mapParams.get("Cost");
|
||||
|
||||
if (mapParams.containsKey("Description")) {
|
||||
altCostDescription = mapParams.get("Description");
|
||||
}
|
||||
private static SpellAbility makeAltCostAbility(final Card card, final String altCost, final SpellAbility sa) {
|
||||
final Map<String, String> params = AbilityFactory.getMapParams(altCost);
|
||||
|
||||
final SpellAbility altCostSA = sa.copy();
|
||||
|
||||
final Cost abCost = new Cost(altCost, altCostSA.isAbility());
|
||||
final Cost abCost = new Cost(params.get("Cost"), altCostSA.isAbility());
|
||||
altCostSA.setPayCosts(abCost);
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (!altCostDescription.equals("")) {
|
||||
sb.append(altCostDescription);
|
||||
} else {
|
||||
sb.append("You may ").append(abCost.toStringAlt());
|
||||
sb.append(" rather than pay ").append(card.getName()).append("'s mana cost.");
|
||||
}
|
||||
altCostSA.setBasicSpell(false);
|
||||
altCostSA.addOptionalCost(OptionalCost.AltCost);
|
||||
|
||||
final SpellAbilityRestriction restriction = new SpellAbilityRestriction();
|
||||
restriction.setRestrictions(mapParams);
|
||||
if (!mapParams.containsKey("ActivationZone")) {
|
||||
restriction.setRestrictions(params);
|
||||
if (!params.containsKey("ActivationZone")) {
|
||||
restriction.setZone(ZoneType.Hand);
|
||||
}
|
||||
altCostSA.setRestrictions(restriction);
|
||||
altCostSA.setDescription(sb.toString());
|
||||
altCostSA.setBasicSpell(false);
|
||||
altCostSA.setAltCost(true);
|
||||
|
||||
final String costDescription = params.containsKey("Description") ? params.get("Description")
|
||||
: String.format("You may %s rather than pay %s's mana cost.", abCost.toStringAlt(), card.getName());
|
||||
|
||||
altCostSA.setDescription(costDescription);
|
||||
return altCostSA;
|
||||
}
|
||||
|
||||
@@ -3186,14 +3142,7 @@ public class CardFactoryUtil {
|
||||
* @return a int.
|
||||
*/
|
||||
public static final int hasKeyword(final Card c, final String k) {
|
||||
final List<String> a = c.getKeyword();
|
||||
for (int i = 0; i < a.size(); i++) {
|
||||
if (a.get(i).startsWith(k)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return hasKeyword(c, k, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3209,7 +3158,7 @@ public class CardFactoryUtil {
|
||||
* a int.
|
||||
* @return a int.
|
||||
*/
|
||||
static final int hasKeyword(final Card c, final String k, final int startPos) {
|
||||
private static final int hasKeyword(final Card c, final String k, final int startPos) {
|
||||
final List<String> a = c.getKeyword();
|
||||
for (int i = startPos; i < a.size(); i++) {
|
||||
if (a.get(i).startsWith(k)) {
|
||||
|
||||
@@ -128,7 +128,7 @@ public class CostPartMana extends CostPart {
|
||||
toPay.increaseShard(ManaCostShard.valueOf(xColor), xCost);
|
||||
xWasBilled = true;
|
||||
}
|
||||
int timesMultikicked = ability.getSourceCard().getMultiKickerMagnitude();
|
||||
int timesMultikicked = ability.getSourceCard().getKickerMagnitude();
|
||||
if ( timesMultikicked > 0 && ability.isAnnouncing("Multikicker")) {
|
||||
ManaCost mkCost = ability.getMultiKickerManaCost();
|
||||
for(int i = 0; i < timesMultikicked; i++)
|
||||
|
||||
@@ -168,7 +168,7 @@ public class HumanPlaySpellAbility {
|
||||
|
||||
ability.setSVar(varName, value.toString());
|
||||
if( "Multikicker".equals(varName) ) {
|
||||
ability.getSourceCard().setMultiKickerMagnitude(value);
|
||||
ability.getSourceCard().setKickerMagnitude(value);
|
||||
} else {
|
||||
ability.getSourceCard().setSVar(varName, value.toString());
|
||||
}
|
||||
|
||||
13
src/main/java/forge/card/spellability/OptionalCost.java
Normal file
13
src/main/java/forge/card/spellability/OptionalCost.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package forge.card.spellability;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public enum OptionalCost {
|
||||
Conspire,
|
||||
Buyback,
|
||||
Kicker1,
|
||||
Kicker2,
|
||||
AltCost, // used by prowl
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
package forge.card.spellability;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -92,7 +93,6 @@ public abstract class SpellAbility implements ISpellAbility {
|
||||
|
||||
private final ArrayList<Mana> payingMana = new ArrayList<Mana>();
|
||||
private final List<SpellAbility> paidAbilities = new ArrayList<SpellAbility>();
|
||||
private List<String> optionalAdditionalCosts = new ArrayList<String>();
|
||||
|
||||
private HashMap<String, List<Card>> paidLists = new HashMap<String, List<Card>>();
|
||||
|
||||
@@ -109,7 +109,6 @@ public abstract class SpellAbility implements ISpellAbility {
|
||||
private boolean undoable;
|
||||
|
||||
private boolean isCopied = false;
|
||||
private boolean isAltCost = false;
|
||||
|
||||
public final AbilityManaPart getManaPart() {
|
||||
return manaPart;
|
||||
@@ -302,43 +301,6 @@ public abstract class SpellAbility implements ISpellAbility {
|
||||
public boolean isSpell() { return false; }
|
||||
public boolean isAbility() { return true; }
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* isBuyBackAbility.
|
||||
* </p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isBuyBackAbility() {
|
||||
return this.optionalAdditionalCosts.contains("Buyback");
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* isKicked.
|
||||
* </p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isKicked() {
|
||||
return isOptionalAdditionalCostPaid("Kicker");
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* isOptionalAdditionalCostPaid.
|
||||
* </p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isOptionalAdditionalCostPaid(String cost) {
|
||||
for (String s : this.optionalAdditionalCosts) {
|
||||
if (s.startsWith(cost)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -668,27 +630,37 @@ public abstract class SpellAbility implements ISpellAbility {
|
||||
this.paidLists = new HashMap<String, List<Card>>();
|
||||
}
|
||||
|
||||
private EnumSet<OptionalCost> optionalCosts = EnumSet.noneOf(OptionalCost.class);
|
||||
/**
|
||||
* @return the optionalAdditionalCosts
|
||||
*/
|
||||
public List<String> getOptionalAdditionalCosts() {
|
||||
return optionalAdditionalCosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param costs the optionalAdditionalCosts to set
|
||||
*/
|
||||
public final void setOptionalAdditionalCosts(List<String> costs) {
|
||||
this.optionalAdditionalCosts = costs;
|
||||
public Iterable<OptionalCost> getOptionalCosts() {
|
||||
return optionalCosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cost the optionalAdditionalCost to add
|
||||
*/
|
||||
public final void addOptionalAdditionalCosts(String cost) {
|
||||
this.optionalAdditionalCosts.add(cost);
|
||||
public final void addOptionalCost(OptionalCost cost) {
|
||||
// Optional costs are added to swallow copies of original SAs,
|
||||
// Thus, to protect the original's set from changes, we make a copy right here.
|
||||
this.optionalCosts = EnumSet.copyOf(optionalCosts);
|
||||
this.optionalCosts.add(cost);
|
||||
}
|
||||
|
||||
public boolean isBuyBackAbility() {
|
||||
return isOptionalCostPaid(OptionalCost.Buyback);
|
||||
}
|
||||
|
||||
public boolean isKicked() {
|
||||
return isOptionalCostPaid(OptionalCost.Kicker1) || isOptionalCostPaid(OptionalCost.Kicker2);
|
||||
}
|
||||
|
||||
public boolean isOptionalCostPaid(OptionalCost cost) {
|
||||
SpellAbility saRoot = this.getRootAbility();
|
||||
return saRoot.optionalCosts.contains(cost);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>triggeringObjects</code>.
|
||||
@@ -1724,22 +1696,4 @@ public abstract class SpellAbility implements ISpellAbility {
|
||||
CostPartMana cm = payCosts != null ? getPayCosts().getCostMana() : null;
|
||||
return cm != null && cm.getAmountOfX() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isAltCost the isAltCost to set
|
||||
*/
|
||||
public void setAltCost(boolean isAltCost) {
|
||||
this.isAltCost = isAltCost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the isAltCost
|
||||
*/
|
||||
public boolean isAltCost() {
|
||||
// only used in prowl, cannot distinguish the alt cost type currently
|
||||
// TODO : support the altcost type
|
||||
return isAltCost;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -78,11 +78,19 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
this.setHellbent(true);
|
||||
}
|
||||
if (value.equals("Kicked")) {
|
||||
this.setKicked(true);
|
||||
this.kicked = true;
|
||||
}
|
||||
if (value.equals("Kicked 1")) {
|
||||
this.kicked1 = true;
|
||||
}
|
||||
if (value.equals("Kicked 2")) {
|
||||
this.kicked2 = true;
|
||||
}
|
||||
if (value.equals("AllTargetsLegal")) {
|
||||
this.setAllTargetsLegal(true);
|
||||
}
|
||||
if (value.equals("AltCost"))
|
||||
this.altCostPaid = true;
|
||||
}
|
||||
|
||||
if (params.containsKey("ConditionZone")) {
|
||||
@@ -177,27 +185,15 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
+ " Did not have activator set in SpellAbility_Condition.checkConditions()");
|
||||
}
|
||||
|
||||
if (this.isHellbent()) {
|
||||
if (!activator.hasHellbent()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.isThreshold()) {
|
||||
if (!activator.hasThreshold()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.isMetalcraft()) {
|
||||
if (!activator.hasMetalcraft()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.isKicked()) {
|
||||
SpellAbility root = sa.getRootAbility();
|
||||
if (!root.isKicked()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.isHellbent() && !activator.hasHellbent()) return false;
|
||||
if (this.isThreshold() && !activator.hasThreshold()) return false;
|
||||
if (this.isMetalcraft() && !activator.hasMetalcraft()) return false;
|
||||
|
||||
if (this.kicked && !sa.isKicked()) return false;
|
||||
if (this.kicked1 && !sa.isOptionalCostPaid(OptionalCost.Kicker1)) return false;
|
||||
if (this.kicked2 && !sa.isOptionalCostPaid(OptionalCost.Kicker2)) return false;
|
||||
if( this.altCostPaid && !sa.isOptionalCostPaid(OptionalCost.AltCost)) return false;
|
||||
|
||||
if (this.isAllTargetsLegal()) {
|
||||
for (Card c : sa.getTarget().getTargetCards()) {
|
||||
if (!CardFactoryUtil.isTargetStillValid(sa, c)) {
|
||||
@@ -210,11 +206,11 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isPlayerTurn() && !Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(activator)) {
|
||||
if (this.isPlayerTurn() && !activator.getGame().getPhaseHandler().isPlayerTurn(activator)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isOpponentTurn() && !Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn().isOpponentOf(activator)) {
|
||||
if (this.isOpponentTurn() && !activator.getGame().getPhaseHandler().getPlayerTurn().isOpponentOf(activator)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
|
||||
if (value.split("Prowl").length > 1) {
|
||||
prowlTypes.add(value.split("Prowl")[1]);
|
||||
}
|
||||
this.setProwl(prowlTypes);
|
||||
this.setProwlTypes(prowlTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,11 +352,11 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.getProwl() != null && !this.getProwl().isEmpty()) {
|
||||
if (this.getProwlTypes() != null && !this.getProwlTypes().isEmpty()) {
|
||||
// only true if the activating player has damaged the opponent with
|
||||
// one of the specified types
|
||||
boolean prowlFlag = false;
|
||||
for (final String type : this.getProwl()) {
|
||||
for (final String type : this.getProwlTypes()) {
|
||||
if (activator.hasProwl(type)) {
|
||||
prowlFlag = true;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class SpellAbilityVariables {
|
||||
this.metalcraft = sav.isThreshold();
|
||||
this.hellbent = sav.isHellbent();
|
||||
this.allTargetsLegal = sav.isAllTargetsLegal();
|
||||
this.prowl = new ArrayList<String>(sav.getProwl());
|
||||
this.prowlTypes = new ArrayList<String>(sav.getProwlTypes());
|
||||
this.isPresent = sav.getIsPresent();
|
||||
this.presentCompare = sav.getPresentCompare();
|
||||
this.presentDefined = sav.getPresentDefined();
|
||||
@@ -135,13 +135,10 @@ public class SpellAbilityVariables {
|
||||
/** The hellbent. */
|
||||
private boolean hellbent = false;
|
||||
|
||||
/** The Kicked. */
|
||||
private boolean kicked = false;
|
||||
|
||||
private boolean allTargetsLegal = false;
|
||||
|
||||
/** The prowl. */
|
||||
private ArrayList<String> prowl = new ArrayList<String>();
|
||||
private ArrayList<String> prowlTypes = new ArrayList<String>();
|
||||
|
||||
/** The s is present. */
|
||||
private String isPresent = null;
|
||||
@@ -186,6 +183,8 @@ public class SpellAbilityVariables {
|
||||
/** The chosen colors string. */
|
||||
private String chosenColors = null;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Setter for the field <code>notAllM12Empires</code>.
|
||||
@@ -507,20 +506,11 @@ public class SpellAbilityVariables {
|
||||
this.metalcraft = bMetalcraft;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the kicked
|
||||
*/
|
||||
public boolean isKicked() {
|
||||
return kicked;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param kicked the kicked to set
|
||||
*/
|
||||
public void setKicked(boolean kicked) {
|
||||
this.kicked = kicked;
|
||||
}
|
||||
|
||||
/** The Kicked. */
|
||||
protected boolean kicked = false;
|
||||
protected boolean kicked1 = false; // http://magiccards.info/query?q=o%3A%22kicker%22+not+o%3A%22multikicker%22+o%3A%22and%2For+{%22
|
||||
protected boolean kicked2 = false; // Some spells have 2 kickers with different effects
|
||||
protected boolean altCostPaid = false;
|
||||
|
||||
/**
|
||||
* @return the allTargetsLegal
|
||||
@@ -535,7 +525,7 @@ public class SpellAbilityVariables {
|
||||
public void setAllTargetsLegal(boolean allTargets) {
|
||||
this.allTargetsLegal = allTargets;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -545,8 +535,8 @@ public class SpellAbilityVariables {
|
||||
* @param types
|
||||
* the new prowl
|
||||
*/
|
||||
public final void setProwl(final ArrayList<String> types) {
|
||||
this.prowl = types;
|
||||
public final void setProwlTypes(final ArrayList<String> types) {
|
||||
this.prowlTypes = types;
|
||||
}
|
||||
|
||||
// IsPresent for Valid battlefield stuff
|
||||
@@ -760,8 +750,8 @@ public class SpellAbilityVariables {
|
||||
*
|
||||
* @return the prowl
|
||||
*/
|
||||
public final ArrayList<String> getProwl() {
|
||||
return this.prowl;
|
||||
public final ArrayList<String> getProwlTypes() {
|
||||
return this.prowlTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -238,25 +238,13 @@ public class SpellPermanent extends Spell {
|
||||
continue;
|
||||
}
|
||||
} else if (params.get("ValidCard").contains("kicked")) {
|
||||
if (!params.get("ValidCard").contains("kicked ")) {
|
||||
if (!sa.isKicked()) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
String s = "Kicker " + params.get("ValidCard").split("kicked ")[1];
|
||||
boolean rightKicker = false;
|
||||
if (sa.getOptionalAdditionalCosts() != null) {
|
||||
for (String string : sa.getOptionalAdditionalCosts()) {
|
||||
if (string.startsWith(s)) {
|
||||
rightKicker = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!rightKicker) {
|
||||
continue;
|
||||
}
|
||||
if (params.get("ValidCard").contains("kicked ")) { // want a specific kicker
|
||||
String s = params.get("ValidCard").split("kicked ")[1];
|
||||
if ( "1".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker1)) continue;
|
||||
if ( "2".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker2)) continue;
|
||||
} else if (!sa.isKicked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,23 +323,12 @@ public class SpellPermanent extends Spell {
|
||||
continue;
|
||||
}
|
||||
} else if (params.get("ValidCard").contains("kicked")) {
|
||||
if (!params.get("ValidCard").contains("kicked ")) {
|
||||
if (!sa.isKicked()) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
String s = "Kicker " + params.get("ValidCard").split("kicked ")[1];
|
||||
boolean rightKicker = false;
|
||||
if (sa.getOptionalAdditionalCosts() != null) {
|
||||
for (String string : sa.getOptionalAdditionalCosts()) {
|
||||
if (string.startsWith(s)) {
|
||||
rightKicker = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!rightKicker) {
|
||||
continue;
|
||||
}
|
||||
if (params.get("ValidCard").contains("kicked ")) { // want a specific kicker
|
||||
String s = params.get("ValidCard").split("kicked ")[1];
|
||||
if ( "1".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker1)) continue;
|
||||
if ( "2".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker2)) continue;
|
||||
} else if (!sa.isKicked()) { // otherwise just any must be present
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,28 +497,21 @@ public class StaticAbility {
|
||||
}
|
||||
}
|
||||
|
||||
if (params.containsKey("Condition")) {
|
||||
if (params.get("Condition").equals("Threshold")) {
|
||||
if (!controller.hasThreshold()) {
|
||||
String condition = params.get("Condition");
|
||||
if (null != condition) {
|
||||
if (condition.equals("Threshold") && !controller.hasThreshold()) return false;
|
||||
if (condition.equals("Hellbent") && !controller.hasHellbent()) return false;
|
||||
if (condition.equals("Metalcraft") && !controller.hasMetalcraft()) return false;
|
||||
|
||||
if (condition.equals("PlayerTurn")) {
|
||||
if (!controller.getGame().getPhaseHandler().isPlayerTurn(controller)) {
|
||||
return false;
|
||||
}
|
||||
} else if (params.get("Condition").equals("Hellbent")) {
|
||||
if (!controller.hasHellbent()) {
|
||||
} else if (condition.equals("NotPlayerTurn")) {
|
||||
if (controller.getGame().getPhaseHandler().isPlayerTurn(controller)) {
|
||||
return false;
|
||||
}
|
||||
} else if (params.get("Condition").equals("Metalcraft")) {
|
||||
if (!controller.hasMetalcraft()) {
|
||||
return false;
|
||||
}
|
||||
} else if (params.get("Condition").equals("PlayerTurn")) {
|
||||
if (!Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(controller)) {
|
||||
return false;
|
||||
}
|
||||
} else if (params.get("Condition").equals("NotPlayerTurn")) {
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(controller)) {
|
||||
return false;
|
||||
}
|
||||
} else if (params.get("Condition").equals("PermanentOfEachColor")) {
|
||||
} else if (condition.equals("PermanentOfEachColor")) {
|
||||
if ((controller.getColoredCardsInPlay(Constant.Color.BLACK).isEmpty()
|
||||
|| controller.getColoredCardsInPlay(Constant.Color.BLUE).isEmpty()
|
||||
|| controller.getColoredCardsInPlay(Constant.Color.GREEN).isEmpty()
|
||||
@@ -526,7 +519,7 @@ public class StaticAbility {
|
||||
|| controller.getColoredCardsInPlay(Constant.Color.WHITE).isEmpty())) {
|
||||
return false;
|
||||
}
|
||||
} else if (params.get("Condition").equals("FatefulHour")) {
|
||||
} else if (condition.equals("FatefulHour")) {
|
||||
if (controller.getLife() > 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.TriggerReplacementBase;
|
||||
import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.OptionalCost;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -315,22 +316,28 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
if ( !meetsCommonRequirements(getMapParams()))
|
||||
return false;
|
||||
|
||||
if (this.getMapParams().containsKey("EvolveCondition")) {
|
||||
if (this.getMapParams().get("EvolveCondition").equals("True")) {
|
||||
final Card moved = (Card) runParams2.get("Card");
|
||||
if (moved == null) {
|
||||
return false;
|
||||
// final StringBuilder sb = new StringBuilder();
|
||||
// sb.append("Trigger::requirementsCheck() - EvolveCondition condition being checked without a moved card. ");
|
||||
// sb.append(this.getHostCard().getName());
|
||||
// throw new RuntimeException(sb.toString());
|
||||
}
|
||||
if (moved.getNetAttack() <= this.getHostCard().getNetAttack()
|
||||
&& moved.getNetDefense() <= this.getHostCard().getNetDefense()) {
|
||||
return false;
|
||||
}
|
||||
if ("True".equals(getMapParams().get("EvolveCondition"))) {
|
||||
final Card moved = (Card) runParams2.get("Card");
|
||||
if (moved == null) {
|
||||
return false;
|
||||
// final StringBuilder sb = new StringBuilder();
|
||||
// sb.append("Trigger::requirementsCheck() - EvolveCondition condition being checked without a moved card. ");
|
||||
// sb.append(this.getHostCard().getName());
|
||||
// throw new RuntimeException(sb.toString());
|
||||
}
|
||||
if (moved.getNetAttack() <= this.getHostCard().getNetAttack()
|
||||
&& moved.getNetDefense() <= this.getHostCard().getNetDefense()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String condition = getMapParams().get("Condition");
|
||||
if( "AltCost".equals(condition) ) {
|
||||
final Card moved = (Card) runParams2.get("Card");
|
||||
if( null != moved && !moved.isOptionalCostPaid(OptionalCost.AltCost))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package forge.card.trigger;
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.OptionalCost;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.player.Player;
|
||||
@@ -76,7 +77,7 @@ public class TriggerSpellAbilityCast extends Trigger {
|
||||
}
|
||||
|
||||
if (this.getMapParams().containsKey("AltCostSpellAbility")) {
|
||||
if (!spellAbility.isAltCost()) {
|
||||
if (!spellAbility.isOptionalCostPaid(OptionalCost.AltCost)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -157,7 +158,7 @@ public class TriggerSpellAbilityCast extends Trigger {
|
||||
}
|
||||
|
||||
if (this.getMapParams().containsKey("Conspire")) {
|
||||
if (!spellAbility.isOptionalAdditionalCostPaid("Conspire")) {
|
||||
if (!spellAbility.isOptionalCostPaid(OptionalCost.Conspire)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +291,7 @@ public class GameAction {
|
||||
}
|
||||
} else if (zoneFrom.is(ZoneType.Exile) && !zoneTo.is(ZoneType.Battlefield)) {
|
||||
// Pull from Eternity used on a suspended card
|
||||
copied.clearAdditionalCostsPaid();
|
||||
copied.clearOptionalCostsPaid();
|
||||
if (copied.isFaceDown()) {
|
||||
copied.turnFaceUp();
|
||||
}
|
||||
@@ -315,7 +315,7 @@ public class GameAction {
|
||||
copied.removeHiddenExtrinsicKeyword(s);
|
||||
}
|
||||
}
|
||||
copied.clearAdditionalCostsPaid();
|
||||
copied.clearOptionalCostsPaid();
|
||||
if (copied.isFaceDown()) {
|
||||
copied.turnFaceUp();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ package forge.game;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
@@ -36,6 +38,7 @@ import forge.CounterType;
|
||||
import forge.FThreads;
|
||||
import forge.Singletons;
|
||||
import forge.card.ability.AbilityFactory;
|
||||
import forge.card.ability.AbilityFactory.AbilityRecordType;
|
||||
import forge.card.ability.AbilityUtils;
|
||||
import forge.card.ability.ApiType;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
@@ -57,6 +60,7 @@ import forge.card.mana.ManaCost;
|
||||
import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.AbilityManaPart;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.OptionalCost;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellAbilityRestriction;
|
||||
import forge.control.input.InputPayManaExecuteCommands;
|
||||
@@ -72,6 +76,7 @@ import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiChoose;
|
||||
import forge.gui.GuiDialog;
|
||||
import forge.sound.SoundEffectType;
|
||||
import forge.util.TextUtil;
|
||||
|
||||
|
||||
/**
|
||||
@@ -1209,6 +1214,115 @@ public final class GameActionUtil {
|
||||
return alternatives;
|
||||
}
|
||||
|
||||
/**
|
||||
* get optional additional costs.
|
||||
*
|
||||
* @param original
|
||||
* the original sa
|
||||
* @return an ArrayList<SpellAbility>.
|
||||
*/
|
||||
public static List<SpellAbility> getOptionalCosts(final SpellAbility original) {
|
||||
final List<SpellAbility> abilities = new ArrayList<SpellAbility>();
|
||||
|
||||
final Card source = original.getSourceCard();
|
||||
abilities.add(original);
|
||||
if (!original.isSpell()) {
|
||||
return abilities;
|
||||
}
|
||||
|
||||
// Buyback, Kicker
|
||||
for (String keyword : source.getKeyword()) {
|
||||
if (keyword.startsWith("AlternateAdditionalCost")) {
|
||||
final List<SpellAbility> newAbilities = new ArrayList<SpellAbility>();
|
||||
String[] costs = TextUtil.split(keyword, ':');
|
||||
for (SpellAbility sa : abilities) {
|
||||
final SpellAbility newSA = sa.copy();
|
||||
newSA.setBasicSpell(false);
|
||||
|
||||
final Cost cost1 = new Cost(costs[1], false);
|
||||
newSA.setDescription(sa.getDescription() + " (Additional cost " + cost1.toSimpleString() + ")");
|
||||
newSA.setPayCosts(cost1.add(sa.getPayCosts()));
|
||||
if (newSA.canPlay()) {
|
||||
newAbilities.add(newSA);
|
||||
}
|
||||
|
||||
//second option
|
||||
final SpellAbility newSA2 = sa.copy();
|
||||
newSA2.setBasicSpell(false);
|
||||
|
||||
final Cost cost2 = new Cost(costs[2], false);
|
||||
newSA2.setDescription(sa.getDescription() + " (Additional cost " + cost2.toSimpleString() + ")");
|
||||
newSA2.setPayCosts(cost2.add(sa.getPayCosts()));
|
||||
if (newSA2.canPlay()) {
|
||||
newAbilities.add(newAbilities.size(), newSA2);
|
||||
}
|
||||
}
|
||||
abilities.clear();
|
||||
abilities.addAll(newAbilities);
|
||||
} else if (keyword.startsWith("Buyback")) {
|
||||
for (int i = 0; i < abilities.size(); i++) {
|
||||
final SpellAbility newSA = abilities.get(i).copy();
|
||||
newSA.setBasicSpell(false);
|
||||
newSA.setPayCosts(new Cost(keyword.substring(8), false).add(newSA.getPayCosts()));
|
||||
newSA.setDescription(newSA.getDescription() + " (with Buyback)");
|
||||
newSA.addOptionalCost(OptionalCost.Buyback);
|
||||
if ( newSA.canPlay() )
|
||||
abilities.add(++i, newSA);
|
||||
}
|
||||
} else if (keyword.startsWith("Kicker")) {
|
||||
for (int i = 0; i < abilities.size(); i++) {
|
||||
String[] sCosts = TextUtil.split(keyword.substring(7), ':');
|
||||
int iUnKicked = i;
|
||||
for(int j = 0; j < sCosts.length; j++) {
|
||||
final SpellAbility newSA = abilities.get(iUnKicked).copy();
|
||||
newSA.setBasicSpell(false);
|
||||
final Cost cost = new Cost(sCosts[j], false);
|
||||
newSA.setDescription(newSA.getDescription() + " (Kicker " + cost.toSimpleString() + ")");
|
||||
newSA.setPayCosts(cost.add(newSA.getPayCosts()));
|
||||
newSA.addOptionalCost(j == 0 ? OptionalCost.Kicker1 : OptionalCost.Kicker2);
|
||||
if ( newSA.canPlay() )
|
||||
abilities.add(++i, newSA);
|
||||
}
|
||||
if(sCosts.length == 2) { // case for both kickers - it's hardcoded since they never have more that 2 kickers
|
||||
final SpellAbility newSA = abilities.get(iUnKicked).copy();
|
||||
newSA.setBasicSpell(false);
|
||||
final Cost cost1 = new Cost(sCosts[0], false);
|
||||
final Cost cost2 = new Cost(sCosts[1], false);
|
||||
newSA.setDescription(newSA.getDescription() + String.format(" (Both kickers: %s and %s)", cost1.toSimpleString(), cost2.toSimpleString()));
|
||||
newSA.setPayCosts(cost2.add(cost1.add(newSA.getPayCosts())));
|
||||
newSA.addOptionalCost(OptionalCost.Kicker1);
|
||||
newSA.addOptionalCost(OptionalCost.Kicker2);
|
||||
if ( newSA.canPlay() )
|
||||
abilities.add(++i, newSA);
|
||||
}
|
||||
}
|
||||
} else if (keyword.startsWith("Conspire")) {
|
||||
for (int i = 0; i < abilities.size(); i++) {
|
||||
final SpellAbility newSA = abilities.get(i).copy();
|
||||
newSA.setBasicSpell(false);
|
||||
final String conspireCost = "tapXType<2/Creature.SharesColorWith/untapped creature you control that shares a color with " + source.getName() + ">";
|
||||
newSA.setPayCosts(new Cost(conspireCost, false).add(newSA.getPayCosts()));
|
||||
newSA.setDescription(newSA.getDescription() + " (Conspire)");
|
||||
newSA.addOptionalCost(OptionalCost.Conspire);
|
||||
if ( newSA.canPlay() )
|
||||
abilities.add(++i, newSA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Splice
|
||||
final List<SpellAbility> newAbilities = new ArrayList<SpellAbility>();
|
||||
for (SpellAbility sa : abilities) {
|
||||
if( sa.isSpell() && sa.getSourceCard().isType("Arcane") && sa.getApi() != null ) {
|
||||
newAbilities.addAll(GameActionUtil.getSpliceAbilities(sa));
|
||||
}
|
||||
}
|
||||
abilities.addAll(newAbilities);
|
||||
|
||||
|
||||
return abilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getSpliceAbilities.
|
||||
@@ -1219,179 +1333,70 @@ public final class GameActionUtil {
|
||||
* @return an ArrayList<SpellAbility>.
|
||||
* get abilities with all Splice options
|
||||
*/
|
||||
public static final ArrayList<SpellAbility> getSpliceAbilities(SpellAbility sa) {
|
||||
private static final ArrayList<SpellAbility> getSpliceAbilities(SpellAbility sa) {
|
||||
ArrayList<SpellAbility> newSAs = new ArrayList<SpellAbility>();
|
||||
ArrayList<SpellAbility> allSAs = new ArrayList<SpellAbility>();
|
||||
allSAs.add(sa);
|
||||
ArrayList<SpellAbility> allSaCombinations = new ArrayList<SpellAbility>();
|
||||
allSaCombinations.add(sa);
|
||||
Card source = sa.getSourceCard();
|
||||
|
||||
if (!sa.isSpell() || !source.isType("Arcane") || sa.getApi() == null) {
|
||||
return newSAs;
|
||||
}
|
||||
|
||||
|
||||
for (Card c : sa.getActivatingPlayer().getCardsIn(ZoneType.Hand)) {
|
||||
if (c.equals(source)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String spliceKwCost = null;
|
||||
for (String keyword : c.getKeyword()) {
|
||||
if (!keyword.startsWith("Splice")) {
|
||||
continue;
|
||||
if (keyword.startsWith("Splice")) {
|
||||
spliceKwCost = keyword.substring(19);
|
||||
break;
|
||||
}
|
||||
String newSubSAString = c.getCharacteristics().getIntrinsicAbility().get(0);
|
||||
newSubSAString = newSubSAString.replace("SP", "DB");
|
||||
final AbilitySub newSubSA = (AbilitySub) AbilityFactory.getAbility(newSubSAString, c);
|
||||
ArrayList<SpellAbility> addSAs = new ArrayList<SpellAbility>();
|
||||
// Add the subability to all existing variants
|
||||
for (SpellAbility s : allSAs) {
|
||||
//create a new spell copy
|
||||
final SpellAbility newSA = s.copy();
|
||||
newSA.setBasicSpell(false);
|
||||
newSA.setPayCosts(new Cost(keyword.substring(19), false).add(newSA.getPayCosts()));
|
||||
newSA.setDescription(s.getDescription() + " (Splicing " + c + " onto it)");
|
||||
newSA.addSplicedCards(c);
|
||||
}
|
||||
|
||||
// copy all subAbilities
|
||||
SpellAbility child = newSA;
|
||||
while (child.getSubAbility() != null) {
|
||||
AbilitySub newChild = child.getSubAbility().getCopy();
|
||||
child.setSubAbility(newChild);
|
||||
child.setActivatingPlayer(s.getActivatingPlayer());
|
||||
child = newChild;
|
||||
}
|
||||
if( spliceKwCost == null )
|
||||
continue;
|
||||
|
||||
//add the spliced ability to the end of the chain
|
||||
child.setSubAbility(newSubSA);
|
||||
Map<String, String> params = AbilityFactory.getMapParams(c.getCharacteristics().getUnparsedAbilities().get(0));
|
||||
AbilityRecordType rc = AbilityRecordType.getRecordType(params);
|
||||
ApiType api = rc.getApiTypeOf(params);
|
||||
AbilitySub subAbility = (AbilitySub) AbilityFactory.getAbility(AbilityRecordType.SubAbility, api, params, null, c);
|
||||
|
||||
//set correct source and activating player to all the spliced abilities
|
||||
child = newSubSA;
|
||||
while (child != null) {
|
||||
child.setSourceCard(source);
|
||||
child.setActivatingPlayer(s.getActivatingPlayer());
|
||||
child = child.getSubAbility();
|
||||
}
|
||||
newSAs.add(0, newSA);
|
||||
addSAs.add(newSA);
|
||||
// Add the subability to all existing variants
|
||||
for (int i = 0; i < allSaCombinations.size(); ++i) {
|
||||
//create a new spell copy
|
||||
final SpellAbility newSA = allSaCombinations.get(i).copy();
|
||||
newSA.setBasicSpell(false);
|
||||
newSA.setPayCosts(new Cost(spliceKwCost, false).add(newSA.getPayCosts()));
|
||||
newSA.setDescription(newSA.getDescription() + " (Splicing " + c + " onto it)");
|
||||
newSA.addSplicedCards(c);
|
||||
|
||||
// copy all subAbilities
|
||||
SpellAbility child = newSA;
|
||||
while (child.getSubAbility() != null) {
|
||||
AbilitySub newChild = child.getSubAbility().getCopy();
|
||||
child.setSubAbility(newChild);
|
||||
child.setActivatingPlayer(newSA.getActivatingPlayer());
|
||||
child = newChild;
|
||||
}
|
||||
allSAs.addAll(addSAs);
|
||||
break;
|
||||
|
||||
//add the spliced ability to the end of the chain
|
||||
child.setSubAbility(subAbility);
|
||||
|
||||
//set correct source and activating player to all the spliced abilities
|
||||
child = subAbility;
|
||||
while (child != null) {
|
||||
child.setSourceCard(source);
|
||||
child.setActivatingPlayer(newSA.getActivatingPlayer());
|
||||
child = child.getSubAbility();
|
||||
}
|
||||
newSAs.add(newSA);
|
||||
allSaCombinations.add(++i, newSA);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return newSAs;
|
||||
}
|
||||
|
||||
/**
|
||||
* get optional additional costs.
|
||||
*
|
||||
* @param original
|
||||
* the original sa
|
||||
* @return an ArrayList<SpellAbility>.
|
||||
*/
|
||||
public static List<SpellAbility> getOptionalAdditionalCosts(final SpellAbility original) {
|
||||
final List<SpellAbility> abilities = new ArrayList<SpellAbility>();
|
||||
final List<SpellAbility> newAbilities = new ArrayList<SpellAbility>();
|
||||
final Card source = original.getSourceCard();
|
||||
abilities.add(original);
|
||||
if (!original.isSpell()) {
|
||||
return abilities;
|
||||
}
|
||||
|
||||
// Buyback, Kicker
|
||||
for (String keyword : source.getKeyword()) {
|
||||
if (keyword.startsWith("Buyback")) {
|
||||
for (SpellAbility sa : abilities) {
|
||||
final SpellAbility newSA = sa.copy();
|
||||
newSA.setBasicSpell(false);
|
||||
newSA.setPayCosts(new Cost(keyword.substring(8), false).add(newSA.getPayCosts()));
|
||||
newSA.setDescription(sa.getDescription() + " (with Buyback)");
|
||||
|
||||
ArrayList<String> newoacs = new ArrayList<String>(sa.getOptionalAdditionalCosts());
|
||||
newoacs.add(keyword);
|
||||
newSA.setOptionalAdditionalCosts(newoacs);
|
||||
if (newSA.canPlay()) {
|
||||
newAbilities.add(newSA);
|
||||
}
|
||||
}
|
||||
abilities.addAll(0, newAbilities);
|
||||
newAbilities.clear();
|
||||
} else if (keyword.startsWith("Kicker")) {
|
||||
for (SpellAbility sa : abilities) {
|
||||
final SpellAbility newSA = sa.copy();
|
||||
newSA.setBasicSpell(false);
|
||||
final Cost cost = new Cost(keyword.substring(7), false);
|
||||
newSA.setDescription(sa.getDescription() + " (Kicker " + cost.toSimpleString() + ")");
|
||||
newSA.setPayCosts(cost.add(newSA.getPayCosts()));
|
||||
|
||||
ArrayList<String> newoacs = new ArrayList<String>(sa.getOptionalAdditionalCosts());
|
||||
newoacs.add(keyword);
|
||||
newSA.setOptionalAdditionalCosts(newoacs);
|
||||
if (newSA.canPlay()) {
|
||||
newAbilities.add(newSA);
|
||||
}
|
||||
}
|
||||
abilities.addAll(0, newAbilities);
|
||||
newAbilities.clear();
|
||||
} else if (keyword.startsWith("AlternateAdditionalCost")) {
|
||||
String costString1 = keyword.split(":")[1];
|
||||
String costString2 = keyword.split(":")[2];
|
||||
for (SpellAbility sa : abilities) {
|
||||
final SpellAbility newSA = sa.copy();
|
||||
newSA.setBasicSpell(false);
|
||||
|
||||
final Cost cost1 = new Cost(costString1, false);
|
||||
newSA.setDescription(sa.getDescription() + " (Additional cost " + cost1.toSimpleString() + ")");
|
||||
newSA.setPayCosts(cost1.add(sa.getPayCosts()));
|
||||
newSA.setOptionalAdditionalCosts(new ArrayList<String>(sa.getOptionalAdditionalCosts()));
|
||||
if (newSA.canPlay()) {
|
||||
newAbilities.add(newSA);
|
||||
}
|
||||
|
||||
//second option
|
||||
final SpellAbility newSA2 = sa.copy();
|
||||
newSA2.setBasicSpell(false);
|
||||
|
||||
final Cost cost2 = new Cost(costString2, false);
|
||||
newSA2.setDescription(sa.getDescription() + " (Additional cost " + cost2.toSimpleString() + ")");
|
||||
newSA2.setPayCosts(cost2.add(sa.getPayCosts()));
|
||||
newSA2.setOptionalAdditionalCosts(new ArrayList<String>(sa.getOptionalAdditionalCosts()));
|
||||
if (newSA2.canPlay()) {
|
||||
newAbilities.add(newAbilities.size(), newSA2);
|
||||
}
|
||||
}
|
||||
abilities.clear();
|
||||
abilities.addAll(0, newAbilities);
|
||||
newAbilities.clear();
|
||||
} else if (keyword.startsWith("Conspire")) {
|
||||
for (SpellAbility sa : abilities) {
|
||||
final SpellAbility newSA = sa.copy();
|
||||
newSA.setBasicSpell(false);
|
||||
final String conspireCost = "tapXType<2/Creature.SharesColorWith/untapped creature you control"
|
||||
+ " that shares a color with " + source.getName() + ">";
|
||||
newSA.setPayCosts(new Cost(conspireCost, false).add(newSA.getPayCosts()));
|
||||
newSA.setDescription(sa.getDescription() + " (Conspire)");
|
||||
|
||||
ArrayList<String> newoacs = new ArrayList<String>(sa.getOptionalAdditionalCosts());
|
||||
newoacs.add(keyword);
|
||||
newSA.setOptionalAdditionalCosts(newoacs);
|
||||
if (newSA.canPlay()) {
|
||||
newAbilities.add(newAbilities.size(), newSA);
|
||||
}
|
||||
}
|
||||
abilities.addAll(0, newAbilities);
|
||||
newAbilities.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Splice
|
||||
for (SpellAbility sa : abilities) {
|
||||
newAbilities.addAll(GameActionUtil.getSpliceAbilities(sa));
|
||||
}
|
||||
abilities.addAll(newAbilities);
|
||||
newAbilities.clear();
|
||||
|
||||
return abilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* hasUrzaLands.
|
||||
|
||||
@@ -173,7 +173,7 @@ public class AiController {
|
||||
final List<SpellAbility> result = new ArrayList<SpellAbility>();
|
||||
for (SpellAbility sa : newAbilities) {
|
||||
sa.setActivatingPlayer(player);
|
||||
result.addAll(GameActionUtil.getOptionalAdditionalCosts(sa));
|
||||
result.addAll(GameActionUtil.getOptionalCosts(sa));
|
||||
}
|
||||
result.addAll(newAbilities);
|
||||
return result;
|
||||
|
||||
@@ -217,7 +217,7 @@ public class HumanPlayer extends Player {
|
||||
*/
|
||||
public SpellAbility chooseOptionalAdditionalCosts(final SpellAbility original) {
|
||||
//final HashMap<String, SpellAbility> map = new HashMap<String, SpellAbility>();
|
||||
final List<SpellAbility> abilities = GameActionUtil.getOptionalAdditionalCosts(original);
|
||||
final List<SpellAbility> abilities = GameActionUtil.getOptionalCosts(original);
|
||||
|
||||
if (!original.isSpell()) {
|
||||
return original;
|
||||
|
||||
@@ -74,7 +74,7 @@ public class PlayerControllerHuman extends PlayerController {
|
||||
* Uses GUI to learn which spell the player (human in our case) would like to play
|
||||
*/
|
||||
public SpellAbility getAbilityToPlay(List<SpellAbility> abilities) {
|
||||
if (abilities.size() == 0) {
|
||||
if (abilities.isEmpty()) {
|
||||
return null;
|
||||
} else if (abilities.size() == 1) {
|
||||
return abilities.get(0);
|
||||
|
||||
@@ -36,6 +36,7 @@ import forge.card.mana.ManaCost;
|
||||
import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.AbilityStatic;
|
||||
import forge.card.spellability.AbilityTriggered;
|
||||
import forge.card.spellability.OptionalCost;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellAbilityStackInstance;
|
||||
@@ -369,10 +370,9 @@ public class MagicStack extends MyObservable {
|
||||
game.getAction().checkStateEffects();
|
||||
//GuiDisplayUtil.updateGUI();
|
||||
} else {
|
||||
if (sp.getOptionalAdditionalCosts() != null) {
|
||||
for (String s : sp.getOptionalAdditionalCosts()) {
|
||||
sp.getSourceCard().addOptionalAdditionalCostsPaid(s);
|
||||
}
|
||||
for (OptionalCost s : sp.getOptionalCosts()) {
|
||||
|
||||
sp.getSourceCard().addOptionalCostPaid(s);
|
||||
}
|
||||
if (sp.getSourceCard().isCopiedSpell()) {
|
||||
this.push(sp);
|
||||
@@ -384,7 +384,7 @@ public class MagicStack extends MyObservable {
|
||||
|
||||
if (activating.isHuman()) {
|
||||
while(true) {
|
||||
int mkMagnitude = sa.getSourceCard().getMultiKickerMagnitude();
|
||||
int mkMagnitude = sa.getSourceCard().getKickerMagnitude();
|
||||
String prompt = String.format("Multikicker for %s\r\nTimes Kicked: %d\r\n", sa.getSourceCard(), mkMagnitude );
|
||||
InputPayManaExecuteCommands toSet = new InputPayManaExecuteCommands(activating, prompt, sp.getMultiKickerManaCost());
|
||||
FThreads.setInputAndWait(toSet);
|
||||
|
||||
Reference in New Issue
Block a user