mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
Merged changes from trunk to GuiRefactoring: 27239-27260
This commit is contained in:
@@ -74,14 +74,12 @@ public class ComputerUtilMana {
|
|||||||
manaSpent.clear();
|
manaSpent.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static boolean payManaCost(final SpellAbility sa, final Player ai, final boolean test, final int extraMana, boolean checkPlayable) {
|
private static boolean payManaCost(final SpellAbility sa, final Player ai, final boolean test, final int extraMana, boolean checkPlayable) {
|
||||||
ManaCostBeingPaid cost = ComputerUtilMana.calculateManaCost(sa, test, extraMana);
|
ManaCostBeingPaid cost = ComputerUtilMana.calculateManaCost(sa, test, extraMana);
|
||||||
return payManaCost(cost, sa, ai, test, checkPlayable);
|
return payManaCost(cost, sa, ai, test, checkPlayable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ManaProducingCard {
|
private static class ManaProducingCard {
|
||||||
|
|
||||||
private CoreType cardType;
|
private CoreType cardType;
|
||||||
private int manaCount;
|
private int manaCount;
|
||||||
|
|
||||||
@@ -1169,10 +1167,11 @@ public class ComputerUtilMana {
|
|||||||
* @since 1.0.15
|
* @since 1.0.15
|
||||||
*/
|
*/
|
||||||
public static int determineLeftoverMana(final SpellAbility sa, final Player player) {
|
public static int determineLeftoverMana(final SpellAbility sa, final Player player) {
|
||||||
for (int i = 1; i < 100; i++)
|
for (int i = 1; i < 100; i++) {
|
||||||
if (!canPayManaCost(sa, player, i))
|
if (!canPayManaCost(sa, player, i)) {
|
||||||
return i - 1;
|
return i - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
return 99;
|
return 99;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1134,6 +1134,14 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
if( fetchList.isEmpty() )
|
if( fetchList.isEmpty() )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
if (sa.hasParam("AILogic") && sa.getParam("AILogic").equals("NeverBounceItself")) {
|
||||||
|
Card source = sa.getHostCard();
|
||||||
|
if (fetchList.contains(source)) {
|
||||||
|
// For cards that should never be bounced back to hand with their own [e.g. triggered] abilities, such as guild lands.
|
||||||
|
fetchList.remove(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String type = sa.getParam("ChangeType");
|
String type = sa.getParam("ChangeType");
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
type = "Card";
|
type = "Card";
|
||||||
|
|||||||
@@ -13,19 +13,19 @@ import forge.game.player.RegisteredPlayer;
|
|||||||
public enum GameType {
|
public enum GameType {
|
||||||
|
|
||||||
// deck composition rules, isPoolRestricted, can sideboard between matches
|
// deck composition rules, isPoolRestricted, can sideboard between matches
|
||||||
Sealed (DeckFormat.Limited, true, true, true, "Sealed", null),
|
Sealed (DeckFormat.Limited, true, true, true, "Sealed", "", null),
|
||||||
Draft (DeckFormat.Limited, true, true, true, "Draft", null),
|
Draft (DeckFormat.Limited, true, true, true, "Draft", "", null),
|
||||||
Winston (DeckFormat.Limited, true, true, true, "Winston", null),
|
Winston (DeckFormat.Limited, true, true, true, "Winston", "", null),
|
||||||
Gauntlet (DeckFormat.Limited, true, true, true, "Gauntlet", null),
|
Gauntlet (DeckFormat.Limited, true, true, true, "Gauntlet", "", null),
|
||||||
Quest (DeckFormat.QuestDeck, true, true, false, "Quest", null),
|
Quest (DeckFormat.QuestDeck, true, true, false, "Quest", "", null),
|
||||||
QuestDraft (DeckFormat.Limited, true, true, true, "Quest Draft", null),
|
QuestDraft (DeckFormat.Limited, true, true, true, "Quest Draft", "", null),
|
||||||
Constructed (DeckFormat.Constructed, false, true, true, "Constructed", null),
|
Constructed (DeckFormat.Constructed, false, true, true, "Constructed", "", null),
|
||||||
Vanguard (DeckFormat.Vanguard, true, true, true, "Vanguard", null),
|
Vanguard (DeckFormat.Vanguard, true, true, true, "Vanguard", "Each player has a special \"Avatar\" card that affects the game.", null),
|
||||||
Commander (DeckFormat.Commander, false, false, false, "Commander", null),
|
Commander (DeckFormat.Commander, false, false, false, "Commander", "Each player has a legendary \"General\" card which can be cast at any time and determines deck colors.", null),
|
||||||
Planechase (DeckFormat.Planechase, false, false, true, "Planechase", null),
|
Planechase (DeckFormat.Planechase, false, false, true, "Planechase", "Plane cards apply global effects. Plane card changed when a player rolls \"Chaos\" on the planar die.", null),
|
||||||
Archenemy (DeckFormat.Archenemy, false, false, true, "Archenemy", null),
|
Archenemy (DeckFormat.Archenemy, false, false, true, "Archenemy", "One player is the Archenemy and can play scheme cards.", null),
|
||||||
ArchenemyRumble (DeckFormat.Archenemy, false, false, true, "Archenemy Rumble", null),
|
ArchenemyRumble (DeckFormat.Archenemy, false, false, true, "Archenemy Rumble", "All players are Archenemies and can play scheme cards.", null),
|
||||||
MomirBasic (DeckFormat.Constructed, false, false, false, "Momir Basic", new Function<RegisteredPlayer, Deck>() {
|
MomirBasic (DeckFormat.Constructed, false, false, false, "Momir Basic", "Each player has a deck containing 60 basic lands and the Momir Vig avatar.", new Function<RegisteredPlayer, Deck>() {
|
||||||
@Override
|
@Override
|
||||||
public Deck apply(RegisteredPlayer player) {
|
public Deck apply(RegisteredPlayer player) {
|
||||||
Deck deck = new Deck();
|
Deck deck = new Deck();
|
||||||
@@ -43,15 +43,16 @@ public enum GameType {
|
|||||||
|
|
||||||
private final DeckFormat deckFormat;
|
private final DeckFormat deckFormat;
|
||||||
private final boolean isCardPoolLimited, canSideboard, addWonCardsMidGame;
|
private final boolean isCardPoolLimited, canSideboard, addWonCardsMidGame;
|
||||||
private final String name;
|
private final String name, description;
|
||||||
private final Function<RegisteredPlayer, Deck> deckAutoGenerator;
|
private final Function<RegisteredPlayer, Deck> deckAutoGenerator;
|
||||||
|
|
||||||
GameType(DeckFormat deckFormat0, boolean isCardPoolLimited0, boolean canSideboard0, boolean addWonCardsMidgame0, String name0, Function<RegisteredPlayer, Deck> deckAutoGenerator0) {
|
GameType(DeckFormat deckFormat0, boolean isCardPoolLimited0, boolean canSideboard0, boolean addWonCardsMidgame0, String name0, String description0, Function<RegisteredPlayer, Deck> deckAutoGenerator0) {
|
||||||
deckFormat = deckFormat0;
|
deckFormat = deckFormat0;
|
||||||
isCardPoolLimited = isCardPoolLimited0;
|
isCardPoolLimited = isCardPoolLimited0;
|
||||||
canSideboard = canSideboard0;
|
canSideboard = canSideboard0;
|
||||||
addWonCardsMidGame = addWonCardsMidgame0;
|
addWonCardsMidGame = addWonCardsMidgame0;
|
||||||
name = name0;
|
name = name0;
|
||||||
|
description = description0;
|
||||||
deckAutoGenerator = deckAutoGenerator0;
|
deckAutoGenerator = deckAutoGenerator0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,4 +105,8 @@ public enum GameType {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2535,7 +2535,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
sb.indexOf("Storm (When you cast this spell, copy it for each spell cast before it this turn.") + 81,
|
sb.indexOf("Storm (When you cast this spell, copy it for each spell cast before it this turn.") + 81,
|
||||||
" You may choose new targets for the copies.");
|
" You may choose new targets for the copies.");
|
||||||
}
|
}
|
||||||
} else if (keyword.contains("Replicate") && !sb.toString().contains("you paid its replicate cost.")) {
|
} else if (keyword.startsWith("Replicate") && !sb.toString().contains("you paid its replicate cost.")) {
|
||||||
if (sb.toString().endsWith("\r\n\r\n")) {
|
if (sb.toString().endsWith("\r\n\r\n")) {
|
||||||
sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n") + 3);
|
sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n") + 3);
|
||||||
}
|
}
|
||||||
@@ -4181,8 +4181,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final void addMultiKickerMagnitude(final int n) { this.multiKickerMagnitude += n; }
|
public final void addMultiKickerMagnitude(final int n) { this.multiKickerMagnitude += n; }
|
||||||
public final void setKickerMagnitude(final int n) { this.multiKickerMagnitude = n; }
|
public final void setKickerMagnitude(final int n) { this.multiKickerMagnitude = n; }
|
||||||
public final int getKickerMagnitude() {
|
public final int getKickerMagnitude() {
|
||||||
if (this.multiKickerMagnitude > 0)
|
if (this.multiKickerMagnitude > 0) {
|
||||||
return multiKickerMagnitude;
|
return multiKickerMagnitude;
|
||||||
|
}
|
||||||
boolean hasK1 = costsPaid.contains(OptionalCost.Kicker1);
|
boolean hasK1 = costsPaid.contains(OptionalCost.Kicker1);
|
||||||
return hasK1 == costsPaid.contains(OptionalCost.Kicker2) ? (hasK1 ? 2 : 0) : 1;
|
return hasK1 == costsPaid.contains(OptionalCost.Kicker2) ? (hasK1 ? 2 : 0) : 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -363,7 +363,6 @@ public class CardFactoryUtil {
|
|||||||
card.setSVar(playSvar.toString(),playWithoutCost.toString());
|
card.setSVar(playSvar.toString(),playWithoutCost.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* multiplyCost.
|
* multiplyCost.
|
||||||
@@ -392,7 +391,8 @@ public class CardFactoryUtil {
|
|||||||
cost = multiplier * cost;
|
cost = multiplier * cost;
|
||||||
tokenized[0] = "" + cost;
|
tokenized[0] = "" + cost;
|
||||||
sb.append(tokenized[0]);
|
sb.append(tokenized[0]);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (tokenized[0].contains("<")) {
|
if (tokenized[0].contains("<")) {
|
||||||
final String[] advCostPart = tokenized[0].split("<");
|
final String[] advCostPart = tokenized[0].split("<");
|
||||||
final String costVariable = advCostPart[1].split(">")[0];
|
final String costVariable = advCostPart[1].split(">")[0];
|
||||||
@@ -406,7 +406,8 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
tokenized[0] = tokenized[0] + ">";
|
tokenized[0] = tokenized[0] + ">";
|
||||||
sb.append(tokenized[0]);
|
sb.append(tokenized[0]);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
for (int i = 0; i < multiplier; i++) {
|
for (int i = 0; i < multiplier; i++) {
|
||||||
// tokenized[0] = tokenized[0] + " " + tokenized[0];
|
// tokenized[0] = tokenized[0] + " " + tokenized[0];
|
||||||
sb.append((" "));
|
sb.append((" "));
|
||||||
@@ -430,7 +431,8 @@ public class CardFactoryUtil {
|
|||||||
tokenized[i] = tokenized[i] + ">";
|
tokenized[i] = tokenized[i] + ">";
|
||||||
sb.append((" "));
|
sb.append((" "));
|
||||||
sb.append(tokenized[i]);
|
sb.append(tokenized[i]);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
for (int j = 0; j < multiplier; j++) {
|
for (int j = 0; j < multiplier; j++) {
|
||||||
// tokenized[i] = tokenized[i] + " " + tokenized[i];
|
// tokenized[i] = tokenized[i] + " " + tokenized[i];
|
||||||
sb.append((" "));
|
sb.append((" "));
|
||||||
@@ -457,7 +459,6 @@ public class CardFactoryUtil {
|
|||||||
* @return a boolean.
|
* @return a boolean.
|
||||||
*/
|
*/
|
||||||
public static boolean isTargetStillValid(final SpellAbility ability, final Card target) {
|
public static boolean isTargetStillValid(final SpellAbility ability, final Card target) {
|
||||||
|
|
||||||
Zone zone = target.getGame().getZoneOf(target);
|
Zone zone = target.getGame().getZoneOf(target);
|
||||||
if (zone == null) {
|
if (zone == null) {
|
||||||
return false; // for tokens that disappeared
|
return false; // for tokens that disappeared
|
||||||
@@ -477,7 +478,8 @@ public class CardFactoryUtil {
|
|||||||
if (!tgt.getZone().contains(zone.getZoneType())) {
|
if (!tgt.getZone().contains(zone.getZoneType())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// If an Aura's target is removed before it resolves, the Aura
|
// If an Aura's target is removed before it resolves, the Aura
|
||||||
// fizzles
|
// fizzles
|
||||||
if (source.isAura() && !target.isInZone(ZoneType.Battlefield)) {
|
if (source.isAura() && !target.isInZone(ZoneType.Battlefield)) {
|
||||||
@@ -561,7 +563,6 @@ public class CardFactoryUtil {
|
|||||||
* @return a int.
|
* @return a int.
|
||||||
*/
|
*/
|
||||||
public static int countOccurrences(final String arg1, final String arg2) {
|
public static int countOccurrences(final String arg1, final String arg2) {
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while ((index = arg1.indexOf(arg2, index)) != -1) {
|
while ((index = arg1.indexOf(arg2, index)) != -1) {
|
||||||
@@ -650,7 +651,9 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return doXMath(n, m, source);
|
return doXMath(n, m, source);
|
||||||
} else if (l[0].startsWith("Lowest")) {
|
}
|
||||||
|
|
||||||
|
if (l[0].startsWith("Lowest")) {
|
||||||
n = 99999; // if no players have fewer than 99999 valids, the game is frozen anyway
|
n = 99999; // if no players have fewer than 99999 valids, the game is frozen anyway
|
||||||
for (final Player player : players) {
|
for (final Player player : players) {
|
||||||
final int current = playerXProperty(player, s.replace("Lowest", ""), source);
|
final int current = playerXProperty(player, s.replace("Lowest", ""), source);
|
||||||
@@ -669,6 +672,7 @@ public class CardFactoryUtil {
|
|||||||
if (sq[0].equals("Amount")) {
|
if (sq[0].equals("Amount")) {
|
||||||
return doXMath(players.size(), m, source);
|
return doXMath(players.size(), m, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("DamageThisTurn")) {
|
if (sq[0].contains("DamageThisTurn")) {
|
||||||
int totDmg = 0;
|
int totDmg = 0;
|
||||||
for (Player p : players) {
|
for (Player p : players) {
|
||||||
@@ -677,8 +681,9 @@ public class CardFactoryUtil {
|
|||||||
return doXMath(totDmg, m, source);
|
return doXMath(totDmg, m, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(players.size() > 0)
|
if (players.size() > 0) {
|
||||||
return playerXProperty(players.get(0), s, source);
|
return playerXProperty(players.get(0), s, source);
|
||||||
|
}
|
||||||
|
|
||||||
return doXMath(n, m, source);
|
return doXMath(n, m, source);
|
||||||
}
|
}
|
||||||
@@ -699,6 +704,7 @@ public class CardFactoryUtil {
|
|||||||
cards = CardLists.getValidCards(cards, rest, player, source);
|
cards = CardLists.getValidCards(cards, rest, player, source);
|
||||||
return doXMath(cards.size(), m, source);
|
return doXMath(cards.size(), m, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// count valid cards on the battlefield
|
// count valid cards on the battlefield
|
||||||
if (l[0].startsWith("Valid ")) {
|
if (l[0].startsWith("Valid ")) {
|
||||||
final String restrictions = l[0].substring(6);
|
final String restrictions = l[0].substring(6);
|
||||||
@@ -819,8 +825,12 @@ public class CardFactoryUtil {
|
|||||||
* @return a int.
|
* @return a int.
|
||||||
*/
|
*/
|
||||||
public static int xCount(final Card c, final String expression) {
|
public static int xCount(final Card c, final String expression) {
|
||||||
if (StringUtils.isBlank(expression)) return 0;
|
if (StringUtils.isBlank(expression)) {
|
||||||
if (StringUtils.isNumeric(expression)) return Integer.parseInt(expression);
|
return 0;
|
||||||
|
}
|
||||||
|
if (StringUtils.isNumeric(expression)) {
|
||||||
|
return Integer.parseInt(expression);
|
||||||
|
}
|
||||||
|
|
||||||
final Player cc = c.getController();
|
final Player cc = c.getController();
|
||||||
final Game game = c.getGame();
|
final Game game = c.getGame();
|
||||||
@@ -834,9 +844,8 @@ public class CardFactoryUtil {
|
|||||||
final String number = l[0].substring(7);
|
final String number = l[0].substring(7);
|
||||||
if (number.equals("ChosenNumber")) {
|
if (number.equals("ChosenNumber")) {
|
||||||
return doXMath(c.getChosenNumber(), m, c);
|
return doXMath(c.getChosenNumber(), m, c);
|
||||||
} else {
|
|
||||||
return doXMath(Integer.parseInt(number), m, c);
|
|
||||||
}
|
}
|
||||||
|
return doXMath(Integer.parseInt(number), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l[0].startsWith("Count$")) {
|
if (l[0].startsWith("Count$")) {
|
||||||
@@ -847,18 +856,17 @@ public class CardFactoryUtil {
|
|||||||
return doXMath(xCount(c, c.getSVar(l[0].substring(5))), m, c);
|
return doXMath(xCount(c, c.getSVar(l[0].substring(5))), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l[0].startsWith("Controller$"))
|
if (l[0].startsWith("Controller$")) {
|
||||||
return playerXProperty(cc, l[0].substring(11), c);
|
return playerXProperty(cc, l[0].substring(11), c);
|
||||||
|
}
|
||||||
|
|
||||||
// Manapool
|
// Manapool
|
||||||
if (l[0].startsWith("ManaPool")) {
|
if (l[0].startsWith("ManaPool")) {
|
||||||
final String color = l[0].split(":")[1];
|
final String color = l[0].split(":")[1];
|
||||||
if (color.equals("All")) {
|
if (color.equals("All")) {
|
||||||
return cc.getManaPool().totalMana();
|
return cc.getManaPool().totalMana();
|
||||||
} else {
|
|
||||||
return cc.getManaPool().getAmountOfColor(MagicColor.fromName(color));
|
|
||||||
}
|
}
|
||||||
|
return cc.getManaPool().getAmountOfColor(MagicColor.fromName(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
// count valid cards in any specified zone/s
|
// count valid cards in any specified zone/s
|
||||||
@@ -874,7 +882,9 @@ public class CardFactoryUtil {
|
|||||||
return doXMath(cards.size(), m, c);
|
return doXMath(cards.size(), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l[0].startsWith("ImprintedCardManaCost") && !c.getImprinted().isEmpty()) return c.getImprinted().get(0).getCMC();
|
if (l[0].startsWith("ImprintedCardManaCost") && !c.getImprinted().isEmpty()) {
|
||||||
|
return c.getImprinted().get(0).getCMC();
|
||||||
|
}
|
||||||
|
|
||||||
if (l[0].startsWith("GreatestPower_")) {
|
if (l[0].startsWith("GreatestPower_")) {
|
||||||
final String restriction = l[0].substring(14);
|
final String restriction = l[0].substring(14);
|
||||||
@@ -903,7 +913,8 @@ public class CardFactoryUtil {
|
|||||||
if (crd.getCMC(Card.SplitCMCMode.RightSplitCMC) > highest) {
|
if (crd.getCMC(Card.SplitCMCMode.RightSplitCMC) > highest) {
|
||||||
highest = crd.getCMC(Card.SplitCMCMode.RightSplitCMC);
|
highest = crd.getCMC(Card.SplitCMCMode.RightSplitCMC);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (crd.getCMC() > highest) {
|
if (crd.getCMC() > highest) {
|
||||||
highest = crd.getCMC();
|
highest = crd.getCMC();
|
||||||
}
|
}
|
||||||
@@ -983,7 +994,10 @@ public class CardFactoryUtil {
|
|||||||
final String[] sq;
|
final String[] sq;
|
||||||
sq = l[0].split("\\.");
|
sq = l[0].split("\\.");
|
||||||
|
|
||||||
if (sq[0].contains("xPaid")) return doXMath(c.getXManaCostPaid(), m, c);
|
if (sq[0].contains("xPaid")) {
|
||||||
|
return doXMath(c.getXManaCostPaid(), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
if (sq[0].contains("xColorPaid")) {
|
if (sq[0].contains("xColorPaid")) {
|
||||||
String[] attrs = sq[0].split(" ");
|
String[] attrs = sq[0].split(" ");
|
||||||
String colors = "";
|
String colors = "";
|
||||||
@@ -994,21 +1008,41 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (sq[0].equals("YouDrewThisTurn")) return doXMath(c.getController().getNumDrawnThisTurn(), m, c);
|
if (sq[0].equals("YouDrewThisTurn")) {
|
||||||
|
return doXMath(c.getController().getNumDrawnThisTurn(), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
if (sq[0].equals("FirstSpellTotalManaSpent")) return doXMath(c.getFirstSpellAbility().getTotalManaSpent(), m, c);
|
if (sq[0].equals("FirstSpellTotalManaSpent")) {
|
||||||
if (sq[0].equals("StormCount")) return doXMath(game.getStack().getCardsCastThisTurn().size() - 1, m, c);
|
return doXMath(c.getFirstSpellAbility().getTotalManaSpent(), m, c);
|
||||||
if (sq[0].equals("DamageDoneThisTurn")) return doXMath(c.getDamageDoneThisTurn(), m, c);
|
}
|
||||||
if (sq[0].equals("BloodthirstAmount")) return doXMath(c.getController().getBloodthirstAmount(), m, c);
|
if (sq[0].equals("StormCount")) {
|
||||||
if (sq[0].equals("RegeneratedThisTurn")) return doXMath(c.getRegeneratedThisTurn(), m, c);
|
return doXMath(game.getStack().getCardsCastThisTurn().size() - 1, m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].equals("DamageDoneThisTurn")) {
|
||||||
|
return doXMath(c.getDamageDoneThisTurn(), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].equals("BloodthirstAmount")) {
|
||||||
|
return doXMath(c.getController().getBloodthirstAmount(), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].equals("RegeneratedThisTurn")) {
|
||||||
|
return doXMath(c.getRegeneratedThisTurn(), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
// TriggeringObjects
|
// TriggeringObjects
|
||||||
if (sq[0].startsWith("Triggered")) return doXMath(xCount((Card) c.getTriggeringObject("Card"), sq[0].substring(9)), m, c);
|
if (sq[0].startsWith("Triggered")) {
|
||||||
|
return doXMath(xCount((Card) c.getTriggeringObject("Card"), sq[0].substring(9)), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
if (sq[0].contains("YourStartingLife")) return doXMath(cc.getStartingLife(), m, c);
|
if (sq[0].contains("YourStartingLife")) {
|
||||||
|
return doXMath(cc.getStartingLife(), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
if (sq[0].contains("YourLifeTotal")) return doXMath(cc.getLife(), m, c);
|
if (sq[0].contains("YourLifeTotal")) {
|
||||||
if (sq[0].contains("OppGreatestLifeTotal")) return doXMath(cc.getOpponentsGreatestLifeTotal(), m, c);
|
return doXMath(cc.getLife(), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].contains("OppGreatestLifeTotal")) {
|
||||||
|
return doXMath(cc.getOpponentsGreatestLifeTotal(), m, c);
|
||||||
|
}
|
||||||
if (sq[0].contains("OppsAtLifeTotal")) {
|
if (sq[0].contains("OppsAtLifeTotal")) {
|
||||||
final int lifeTotal = xCount(c, sq[1]);
|
final int lifeTotal = xCount(c, sq[1]);
|
||||||
int number = 0;
|
int number = 0;
|
||||||
@@ -1032,8 +1066,12 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("LifeYouLostThisTurn")) return doXMath(cc.getLifeLostThisTurn(), m, c);
|
if (sq[0].contains("LifeYouLostThisTurn")) {
|
||||||
if (sq[0].contains("LifeYouGainedThisTurn")) return doXMath(cc.getLifeGainedThisTurn(), m, c);
|
return doXMath(cc.getLifeLostThisTurn(), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].contains("LifeYouGainedThisTurn")) {
|
||||||
|
return doXMath(cc.getLifeGainedThisTurn(), m, c);
|
||||||
|
}
|
||||||
if (sq[0].contains("LifeOppsLostThisTurn")) {
|
if (sq[0].contains("LifeOppsLostThisTurn")) {
|
||||||
int lost = 0;
|
int lost = 0;
|
||||||
for (Player opp : cc.getOpponents()) {
|
for (Player opp : cc.getOpponents()) {
|
||||||
@@ -1042,18 +1080,34 @@ public class CardFactoryUtil {
|
|||||||
return doXMath(lost, m, c);
|
return doXMath(lost, m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].equals("TotalDamageDoneByThisTurn")) return doXMath(c.getTotalDamageDoneBy(), m, c);
|
if (sq[0].equals("TotalDamageDoneByThisTurn")) {
|
||||||
if (sq[0].equals("TotalDamageReceivedThisTurn")) return doXMath(c.getTotalDamageRecievedThisTurn(), m, c);
|
return doXMath(c.getTotalDamageDoneBy(), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].equals("TotalDamageReceivedThisTurn")) {
|
||||||
|
return doXMath(c.getTotalDamageRecievedThisTurn(), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
if (sq[0].contains("YourPoisonCounters")) return doXMath(cc.getPoisonCounters(), m, c);
|
if (sq[0].contains("YourPoisonCounters")) {
|
||||||
if (sq[0].contains("TotalOppPoisonCounters")) return doXMath(cc.getOpponentsTotalPoisonCounters(), m, c);
|
return doXMath(cc.getPoisonCounters(), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].contains("TotalOppPoisonCounters")) {
|
||||||
|
return doXMath(cc.getOpponentsTotalPoisonCounters(), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
if (sq[0].contains("YourDamageThisTurn")) return doXMath(cc.getAssignedDamage(), m, c);
|
if (sq[0].contains("YourDamageThisTurn")) {
|
||||||
if (sq[0].contains("TotalOppDamageThisTurn")) return doXMath(cc.getOpponentsAssignedDamage(), m, c);
|
return doXMath(cc.getAssignedDamage(), m, c);
|
||||||
if (sq[0].contains("MaxOppDamageThisTurn")) return doXMath(cc.getMaxOpponentAssignedDamage(), m, c);
|
}
|
||||||
|
if (sq[0].contains("TotalOppDamageThisTurn")) {
|
||||||
|
return doXMath(cc.getOpponentsAssignedDamage(), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].contains("MaxOppDamageThisTurn")) {
|
||||||
|
return doXMath(cc.getMaxOpponentAssignedDamage(), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
// Count$YourTypeDamageThisTurn Type
|
// Count$YourTypeDamageThisTurn Type
|
||||||
if (sq[0].contains("YourTypeDamageThisTurn")) return doXMath(cc.getAssignedDamage(sq[0].split(" ")[1]), m, c);
|
if (sq[0].contains("YourTypeDamageThisTurn")) {
|
||||||
|
return doXMath(cc.getAssignedDamage(sq[0].split(" ")[1]), m, c);
|
||||||
|
}
|
||||||
if (sq[0].contains("YourDamageSourcesThisTurn")) {
|
if (sq[0].contains("YourDamageSourcesThisTurn")) {
|
||||||
Iterable<Card> allSrc = cc.getAssignedDamageSources();
|
Iterable<Card> allSrc = cc.getAssignedDamageSources();
|
||||||
String restriction = sq[0].split(" ")[1];
|
String restriction = sq[0].split(" ")[1];
|
||||||
@@ -1061,7 +1115,9 @@ public class CardFactoryUtil {
|
|||||||
return doXMath(filtered.size(), m, c);
|
return doXMath(filtered.size(), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("YourLandsPlayed")) return doXMath(cc.getNumLandsPlayed(), m, c);
|
if (sq[0].contains("YourLandsPlayed")) {
|
||||||
|
return doXMath(cc.getNumLandsPlayed(), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
// Count$TopOfLibraryCMC
|
// Count$TopOfLibraryCMC
|
||||||
if (sq[0].contains("TopOfLibraryCMC")) {
|
if (sq[0].contains("TopOfLibraryCMC")) {
|
||||||
@@ -1095,7 +1151,8 @@ public class CardFactoryUtil {
|
|||||||
final List<Card> cards;
|
final List<Card> cards;
|
||||||
if (sq[0].contains("ChromaSource")) { // Runs Chroma for passed in Source card
|
if (sq[0].contains("ChromaSource")) { // Runs Chroma for passed in Source card
|
||||||
cards = Lists.newArrayList(c);
|
cards = Lists.newArrayList(c);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
cards = cc.getCardsIn(sourceZone);
|
cards = cc.getCardsIn(sourceZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1124,14 +1181,28 @@ public class CardFactoryUtil {
|
|||||||
return doXMath(colorOcurrencices, m, c);
|
return doXMath(colorOcurrencices, m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("Hellbent")) return doXMath(Integer.parseInt(sq[cc.hasHellbent() ? 1 : 2]), m, c);
|
if (sq[0].contains("Hellbent")) {
|
||||||
if (sq[0].contains("Metalcraft")) return doXMath(Integer.parseInt(sq[cc.hasMetalcraft() ? 1 : 2]), m, c);
|
return doXMath(Integer.parseInt(sq[cc.hasHellbent() ? 1 : 2]), m, c);
|
||||||
if (sq[0].contains("FatefulHour")) return doXMath(Integer.parseInt(sq[cc.getLife() <= 5 ? 1 : 2]), m, c);
|
}
|
||||||
|
if (sq[0].contains("Metalcraft")) {
|
||||||
|
return doXMath(Integer.parseInt(sq[cc.hasMetalcraft() ? 1 : 2]), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].contains("FatefulHour")) {
|
||||||
|
return doXMath(Integer.parseInt(sq[cc.getLife() <= 5 ? 1 : 2]), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
if (sq[0].contains("Landfall")) return doXMath(Integer.parseInt(sq[cc.hasLandfall() ? 1 : 2]), m, c);
|
if (sq[0].contains("Landfall")) {
|
||||||
if (sq[0].contains("Threshold")) return doXMath(Integer.parseInt(sq[cc.hasThreshold() ? 1 : 2]), m, c);
|
return doXMath(Integer.parseInt(sq[cc.hasLandfall() ? 1 : 2]), m, c);
|
||||||
if (sq[0].startsWith("Kicked")) return doXMath(Integer.parseInt(sq[c.getKickerMagnitude() > 0 ? 1 : 2]), m, c);
|
}
|
||||||
if (sq[0].startsWith("AltCost")) return doXMath(Integer.parseInt(sq[c.isOptionalCostPaid(OptionalCost.AltCost) ? 1 : 2]), m, c);
|
if (sq[0].contains("Threshold")) {
|
||||||
|
return doXMath(Integer.parseInt(sq[cc.hasThreshold() ? 1 : 2]), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].startsWith("Kicked")) {
|
||||||
|
return doXMath(Integer.parseInt(sq[c.getKickerMagnitude() > 0 ? 1 : 2]), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].startsWith("AltCost")) {
|
||||||
|
return doXMath(Integer.parseInt(sq[c.isOptionalCostPaid(OptionalCost.AltCost) ? 1 : 2]), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
// Count$wasCastFrom<Zone>.<true>.<false>
|
// Count$wasCastFrom<Zone>.<true>.<false>
|
||||||
if (sq[0].startsWith("wasCastFrom")) {
|
if (sq[0].startsWith("wasCastFrom")) {
|
||||||
@@ -1145,9 +1216,15 @@ public class CardFactoryUtil {
|
|||||||
return doXMath(cl.size(), m, c);
|
return doXMath(cl.size(), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("CardPower")) return doXMath(c.getNetAttack(), m, c);
|
if (sq[0].contains("CardPower")) {
|
||||||
if (sq[0].contains("CardToughness")) return doXMath(c.getNetDefense(), m, c);
|
return doXMath(c.getNetAttack(), m, c);
|
||||||
if (sq[0].contains("CardSumPT")) return doXMath((c.getNetAttack() + c.getNetDefense()), m, c);
|
}
|
||||||
|
if (sq[0].contains("CardToughness")) {
|
||||||
|
return doXMath(c.getNetDefense(), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].contains("CardSumPT")) {
|
||||||
|
return doXMath((c.getNetAttack() + c.getNetDefense()), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
// Count$SumPower_valid
|
// Count$SumPower_valid
|
||||||
if (sq[0].contains("SumPower")) {
|
if (sq[0].contains("SumPower")) {
|
||||||
@@ -1161,9 +1238,11 @@ public class CardFactoryUtil {
|
|||||||
Card ce;
|
Card ce;
|
||||||
if (sq[0].contains("Equipped") && c.isEquipping()) {
|
if (sq[0].contains("Equipped") && c.isEquipping()) {
|
||||||
ce = c.getEquipping().get(0);
|
ce = c.getEquipping().get(0);
|
||||||
} else if (sq[0].contains("Remembered")) {
|
}
|
||||||
|
else if (sq[0].contains("Remembered")) {
|
||||||
ce = (Card) c.getRemembered().get(0);
|
ce = (Card) c.getRemembered().get(0);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
ce = c;
|
ce = c;
|
||||||
}
|
}
|
||||||
return doXMath(ce.getCMC(), m, c);
|
return doXMath(ce.getCMC(), m, c);
|
||||||
@@ -1177,8 +1256,12 @@ public class CardFactoryUtil {
|
|||||||
return Aggregates.sum(filteredCards, CardPredicates.Accessors.fnGetCmc);
|
return Aggregates.sum(filteredCards, CardPredicates.Accessors.fnGetCmc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("CardNumColors")) return doXMath(CardUtil.getColors(c).countColors(), m, c);
|
if (sq[0].contains("CardNumColors")) {
|
||||||
if (sq[0].contains("ChosenNumber")) return doXMath(c.getChosenNumber(), m, c);
|
return doXMath(CardUtil.getColors(c).countColors(), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].contains("ChosenNumber")) {
|
||||||
|
return doXMath(c.getChosenNumber(), m, c);
|
||||||
|
}
|
||||||
if (sq[0].contains("CardCounters")) {
|
if (sq[0].contains("CardCounters")) {
|
||||||
// CardCounters.ALL to be used for Kinsbaile Borderguard and anything that cares about all counters
|
// CardCounters.ALL to be used for Kinsbaile Borderguard and anything that cares about all counters
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -1188,7 +1271,8 @@ public class CardFactoryUtil {
|
|||||||
count += i;
|
count += i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
count = c.getCounters(CounterType.getType(sq[1]));
|
count = c.getCounters(CounterType.getType(sq[1]));
|
||||||
}
|
}
|
||||||
return doXMath(count, m, c);
|
return doXMath(count, m, c);
|
||||||
@@ -1208,12 +1292,19 @@ public class CardFactoryUtil {
|
|||||||
return doXMath(cCount, m, c);
|
return doXMath(cCount, m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("CardTypes")) return doXMath(getCardTypesFromList(game.getCardsIn(ZoneType.smartValueOf(sq[1]))), m, c);
|
if (sq[0].contains("CardTypes")) {
|
||||||
|
return doXMath(getCardTypesFromList(game.getCardsIn(ZoneType.smartValueOf(sq[1]))), m, c);
|
||||||
if (sq[0].contains("BushidoPoint")) return doXMath(c.getKeywordMagnitude("Bushido"), m, c);
|
}
|
||||||
if (sq[0].contains("TimesKicked")) return doXMath(c.getKickerMagnitude(), m, c);
|
|
||||||
if (sq[0].contains("NumCounters")) return doXMath(c.getCounters(CounterType.getType(sq[1])), m, c);
|
|
||||||
|
|
||||||
|
if (sq[0].contains("BushidoPoint")) {
|
||||||
|
return doXMath(c.getKeywordMagnitude("Bushido"), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].contains("TimesKicked")) {
|
||||||
|
return doXMath(c.getKickerMagnitude(), m, c);
|
||||||
|
}
|
||||||
|
if (sq[0].contains("NumCounters")) {
|
||||||
|
return doXMath(c.getCounters(CounterType.getType(sq[1])), m, c);
|
||||||
|
}
|
||||||
|
|
||||||
// Count$IfMainPhase.<numMain>.<numNotMain> // 7/10
|
// Count$IfMainPhase.<numMain>.<numNotMain> // 7/10
|
||||||
if (sq[0].contains("IfMainPhase")) {
|
if (sq[0].contains("IfMainPhase")) {
|
||||||
@@ -1272,7 +1363,8 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
if (workingCopy[0].contains("This")) {
|
if (workingCopy[0].contains("This")) {
|
||||||
res = CardUtil.getThisTurnCast(validFilter, c);
|
res = CardUtil.getThisTurnCast(validFilter, c);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
res = CardUtil.getLastTurnCast(validFilter, c);
|
res = CardUtil.getLastTurnCast(validFilter, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1285,9 +1377,8 @@ public class CardFactoryUtil {
|
|||||||
final List<Card> res = CardUtil.getThisTurnEntered(ZoneType.Graveyard, ZoneType.Battlefield, "Creature", c);
|
final List<Card> res = CardUtil.getThisTurnEntered(ZoneType.Graveyard, ZoneType.Battlefield, "Creature", c);
|
||||||
if (res.size() > 0) {
|
if (res.size() > 0) {
|
||||||
return doXMath(Integer.parseInt(sq[1]), m, c);
|
return doXMath(Integer.parseInt(sq[1]), m, c);
|
||||||
} else {
|
|
||||||
return doXMath(Integer.parseInt(sq[2]), m, c);
|
|
||||||
}
|
}
|
||||||
|
return doXMath(Integer.parseInt(sq[2]), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].equals("YourTurns")) {
|
if (sq[0].equals("YourTurns")) {
|
||||||
@@ -2009,7 +2100,8 @@ public class CardFactoryUtil {
|
|||||||
final String text;
|
final String text;
|
||||||
if (p.equals(originPlayer)) {
|
if (p.equals(originPlayer)) {
|
||||||
text = "Commander Damage from own Commander: ";
|
text = "Commander Damage from own Commander: ";
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
text = "Commander Damage to " + p.getName() + ": ";
|
text = "Commander Damage to " + p.getName() + ": ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2036,32 +2128,28 @@ public class CardFactoryUtil {
|
|||||||
// Cards with Cycling abilities
|
// Cards with Cycling abilities
|
||||||
// -1 means keyword "Cycling" not found
|
// -1 means keyword "Cycling" not found
|
||||||
|
|
||||||
if (hasKeyword(card, "Multikicker") != -1) {
|
for (String keyword : card.getKeyword()) {
|
||||||
final int n = hasKeyword(card, "Multikicker");
|
if (keyword.startsWith("Multikicker")) {
|
||||||
if (n != -1) {
|
final String[] k = keyword.split("kicker ");
|
||||||
final String parse = card.getKeyword().get(n).toString();
|
|
||||||
final String[] k = parse.split("kicker ");
|
|
||||||
|
|
||||||
final SpellAbility sa = card.getFirstSpellAbility();
|
final SpellAbility sa = card.getFirstSpellAbility();
|
||||||
sa.setMultiKickerManaCost(new ManaCost(new ManaCostParser(k[1])));
|
sa.setMultiKickerManaCost(new ManaCost(new ManaCostParser(k[1])));
|
||||||
|
sa.addAnnounceVar("Multikicker");
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Replicate")) {
|
||||||
|
card.getFirstSpellAbility().addAnnounceVar("Replicate");
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Fuse")) {
|
||||||
if(hasKeyword(card, "Fuse") != -1) {
|
|
||||||
card.getState(CardCharacteristicName.Original).getSpellAbility().add(AbilityFactory.buildFusedAbility(card));
|
card.getState(CardCharacteristicName.Original).getSpellAbility().add(AbilityFactory.buildFusedAbility(card));
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Evoke")) {
|
||||||
final int evokePos = hasKeyword(card, "Evoke");
|
card.addSpellAbility(makeEvokeSpell(card, keyword));
|
||||||
if (evokePos != -1) {
|
|
||||||
card.addSpellAbility(makeEvokeSpell(card, card.getKeyword().get(evokePos)));
|
|
||||||
}
|
}
|
||||||
final int monstrousPos = hasKeyword(card, "Monstrosity");
|
else if (keyword.startsWith("Monstrosity")) {
|
||||||
if (monstrousPos != -1) {
|
final String[] k = keyword.split(":");
|
||||||
final String parse = card.getKeyword().get(monstrousPos).toString();
|
|
||||||
final String[] k = parse.split(":");
|
|
||||||
final String magnitude = k[0].substring(12);
|
final String magnitude = k[0].substring(12);
|
||||||
final String manacost = k[1];
|
final String manacost = k[1];
|
||||||
card.removeIntrinsicKeyword(parse);
|
card.removeIntrinsicKeyword(keyword);
|
||||||
|
|
||||||
String ref = "X".equals(magnitude) ? " | References$ X" : "";
|
String ref = "X".equals(magnitude) ? " | References$ X" : "";
|
||||||
String counters = StringUtils.isNumeric(magnitude)
|
String counters = StringUtils.isNumeric(magnitude)
|
||||||
@@ -2076,15 +2164,10 @@ public class CardFactoryUtil {
|
|||||||
// add ability to instrinic strings so copies/clones create the ability also
|
// add ability to instrinic strings so copies/clones create the ability also
|
||||||
card.getUnparsedAbilities().add(effect);
|
card.getUnparsedAbilities().add(effect);
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Unearth")) {
|
||||||
|
card.removeIntrinsicKeyword(keyword);
|
||||||
|
|
||||||
if (hasKeyword(card, "Unearth") != -1) {
|
final String[] k = keyword.split(":");
|
||||||
final int n = hasKeyword(card, "Unearth");
|
|
||||||
if (n != -1) {
|
|
||||||
final String parse = card.getKeyword().get(n).toString();
|
|
||||||
card.removeIntrinsicKeyword(parse);
|
|
||||||
|
|
||||||
final String[] k = parse.split(":");
|
|
||||||
|
|
||||||
final String manacost = k[1];
|
final String manacost = k[1];
|
||||||
|
|
||||||
String effect = "AB$ ChangeZone | Cost$ " + manacost + " | Defined$ Self" +
|
String effect = "AB$ ChangeZone | Cost$ " + manacost + " | Defined$ Self" +
|
||||||
@@ -2110,16 +2193,11 @@ public class CardFactoryUtil {
|
|||||||
// add ability to instrinic strings so copies/clones create the ability also
|
// add ability to instrinic strings so copies/clones create the ability also
|
||||||
card.getUnparsedAbilities().add(effect);
|
card.getUnparsedAbilities().add(effect);
|
||||||
}
|
}
|
||||||
} // unearth
|
else if (keyword.startsWith("Level up")) {
|
||||||
|
|
||||||
final int iLvlUp = hasKeyword(card, "Level up");
|
|
||||||
|
|
||||||
if (iLvlUp != -1) {
|
|
||||||
final String strLevelCost = card.getKeyword().get(iLvlUp);
|
|
||||||
final String strMaxLevel = card.getSVar("maxLevel");
|
final String strMaxLevel = card.getSVar("maxLevel");
|
||||||
card.removeIntrinsicKeyword(strLevelCost);
|
card.removeIntrinsicKeyword(keyword);
|
||||||
|
|
||||||
final String[] k = strLevelCost.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final String manacost = k[1];
|
final String manacost = k[1];
|
||||||
|
|
||||||
String effect = "AB$ PutCounter | Cost$ " + manacost + " | " +
|
String effect = "AB$ PutCounter | Cost$ " + manacost + " | " +
|
||||||
@@ -2132,41 +2210,27 @@ public class CardFactoryUtil {
|
|||||||
card.addSpellAbility(AbilityFactory.getAbility(effect, card));
|
card.addSpellAbility(AbilityFactory.getAbility(effect, card));
|
||||||
// add ability to instrinic strings so copies/clones create the ability also
|
// add ability to instrinic strings so copies/clones create the ability also
|
||||||
card.getUnparsedAbilities().add(effect);
|
card.getUnparsedAbilities().add(effect);
|
||||||
} // level up
|
}
|
||||||
|
else if (keyword.startsWith("Cycling")) {
|
||||||
|
card.removeIntrinsicKeyword(keyword);
|
||||||
|
|
||||||
if (hasKeyword(card, "Cycling") != -1) {
|
final String[] k = keyword.split(":");
|
||||||
final int n = hasKeyword(card, "Cycling");
|
|
||||||
if (n != -1) {
|
|
||||||
final String parse = card.getKeyword().get(n).toString();
|
|
||||||
card.removeIntrinsicKeyword(parse);
|
|
||||||
|
|
||||||
final String[] k = parse.split(":");
|
|
||||||
final String manacost = k[1];
|
final String manacost = k[1];
|
||||||
|
|
||||||
card.addSpellAbility(abilityCycle(card, manacost));
|
card.addSpellAbility(abilityCycle(card, manacost));
|
||||||
}
|
}
|
||||||
} // Cycling
|
else if (keyword.startsWith("TypeCycling")) {
|
||||||
|
card.removeIntrinsicKeyword(keyword);
|
||||||
|
|
||||||
while (hasKeyword(card, "TypeCycling") != -1) {
|
final String[] k = keyword.split(":");
|
||||||
final int n = hasKeyword(card, "TypeCycling");
|
|
||||||
if (n != -1) {
|
|
||||||
final String parse = card.getKeyword().get(n).toString();
|
|
||||||
card.removeIntrinsicKeyword(parse);
|
|
||||||
|
|
||||||
final String[] k = parse.split(":");
|
|
||||||
final String type = k[1];
|
final String type = k[1];
|
||||||
final String manacost = k[2];
|
final String manacost = k[2];
|
||||||
|
|
||||||
card.addSpellAbility(abilityTypecycle(card, manacost, type));
|
card.addSpellAbility(abilityTypecycle(card, manacost, type));
|
||||||
}
|
}
|
||||||
} // TypeCycling
|
else if (keyword.startsWith("Transmute")) {
|
||||||
|
card.removeIntrinsicKeyword(keyword);
|
||||||
if (hasKeyword(card, "Transmute") != -1) {
|
final String manacost = keyword.split(":")[1];
|
||||||
final int n = hasKeyword(card, "Transmute");
|
|
||||||
if (n != -1) {
|
|
||||||
final String parse = card.getKeyword().get(n);
|
|
||||||
card.removeIntrinsicKeyword(parse);
|
|
||||||
final String manacost = parse.split(":")[1];
|
|
||||||
final String sbTransmute = "AB$ ChangeZone | Cost$ " + manacost + " Discard<1/CARDNAME>"
|
final String sbTransmute = "AB$ ChangeZone | Cost$ " + manacost + " Discard<1/CARDNAME>"
|
||||||
+ " | CostDesc$ Transmute " + ManaCostParser.parse(manacost)+ " | ActivationZone$ Hand"
|
+ " | CostDesc$ Transmute " + ManaCostParser.parse(manacost)+ " | ActivationZone$ Hand"
|
||||||
+ " | Origin$ Library | Destination$ Hand | ChangeType$ Card.cmcEQ" + card.getManaCost().getCMC()
|
+ " | Origin$ Library | Destination$ Hand | ChangeType$ Card.cmcEQ" + card.getManaCost().getCMC()
|
||||||
@@ -2179,18 +2243,13 @@ public class CardFactoryUtil {
|
|||||||
card.addSpellAbility(abTransmute);
|
card.addSpellAbility(abTransmute);
|
||||||
card.getUnparsedAbilities().add(sbTransmute);
|
card.getUnparsedAbilities().add(sbTransmute);
|
||||||
}
|
}
|
||||||
} // transmute
|
else if (keyword.startsWith("Soulshift")) {
|
||||||
|
final String[] k = keyword.split(" ");
|
||||||
int shiftPos = hasKeyword(card, "Soulshift");
|
|
||||||
while (shiftPos != -1) {
|
|
||||||
final int n = shiftPos;
|
|
||||||
final String parse = card.getKeyword().get(n);
|
|
||||||
final String[] k = parse.split(" ");
|
|
||||||
final int manacost = Integer.parseInt(k[1]);
|
final int manacost = Integer.parseInt(k[1]);
|
||||||
|
|
||||||
final String actualTrigger = "Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard"
|
final String actualTrigger = "Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard"
|
||||||
+ "| OptionalDecider$ You | ValidCard$ Card.Self | Execute$ SoulshiftAbility"
|
+ "| OptionalDecider$ You | ValidCard$ Card.Self | Execute$ SoulshiftAbility"
|
||||||
+ "| TriggerController$ TriggeredCardController | TriggerDescription$ " + parse
|
+ "| TriggerController$ TriggeredCardController | TriggerDescription$ " + keyword
|
||||||
+ " (When this creature dies, you may return target Spirit card with converted mana cost "
|
+ " (When this creature dies, you may return target Spirit card with converted mana cost "
|
||||||
+ manacost + " or less from your graveyard to your hand.)";
|
+ manacost + " or less from your graveyard to your hand.)";
|
||||||
final String abString = "DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand"
|
final String abString = "DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand"
|
||||||
@@ -2198,15 +2257,11 @@ public class CardFactoryUtil {
|
|||||||
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, card, true);
|
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, card, true);
|
||||||
card.addTrigger(parsedTrigger);
|
card.addTrigger(parsedTrigger);
|
||||||
card.setSVar("SoulshiftAbility", abString);
|
card.setSVar("SoulshiftAbility", abString);
|
||||||
shiftPos = hasKeyword(card, "Soulshift", n + 1);
|
}
|
||||||
} // Soulshift
|
else if (keyword.startsWith("Champion")) {
|
||||||
|
card.removeIntrinsicKeyword(keyword);
|
||||||
|
|
||||||
final int championPos = hasKeyword(card, "Champion");
|
final String[] k = keyword.split(":");
|
||||||
if (championPos != -1) {
|
|
||||||
String parse = card.getKeyword().get(championPos);
|
|
||||||
card.removeIntrinsicKeyword(parse);
|
|
||||||
|
|
||||||
final String[] k = parse.split(":");
|
|
||||||
final String[] valid = k[1].split(",");
|
final String[] valid = k[1].split(",");
|
||||||
String desc = k.length > 2 ? k[2] : k[1];
|
String desc = k.length > 2 ? k[2] : k[1];
|
||||||
String article = Lang.startsWithVowel(desc) ? "an" : "a";
|
String article = Lang.startsWithVowel(desc) ? "an" : "a";
|
||||||
@@ -2248,21 +2303,16 @@ public class CardFactoryUtil {
|
|||||||
card.setSVar("ChampionReturn", returnChampion);
|
card.setSVar("ChampionReturn", returnChampion);
|
||||||
card.setSVar("ChampionSacrifice", subAb.toString());
|
card.setSVar("ChampionSacrifice", subAb.toString());
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("If CARDNAME would be put into a graveyard "
|
||||||
if (card.hasKeyword("If CARDNAME would be put into a graveyard "
|
|
||||||
+ "from anywhere, reveal CARDNAME and shuffle it into its owner's library instead.")) {
|
+ "from anywhere, reveal CARDNAME and shuffle it into its owner's library instead.")) {
|
||||||
|
|
||||||
String replacement = "Event$ Moved | Destination$ Graveyard | ValidCard$ Card.Self | ReplaceWith$ GraveyardToLibrary";
|
String replacement = "Event$ Moved | Destination$ Graveyard | ValidCard$ Card.Self | ReplaceWith$ GraveyardToLibrary";
|
||||||
String ab = "DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Library | Defined$ ReplacedCard | Reveal$ True | Shuffle$ True";
|
String ab = "DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Library | Defined$ ReplacedCard | Reveal$ True | Shuffle$ True";
|
||||||
|
|
||||||
card.addReplacementEffect(ReplacementHandler.parseReplacement(replacement, card, true));
|
card.addReplacementEffect(ReplacementHandler.parseReplacement(replacement, card, true));
|
||||||
card.setSVar("GraveyardToLibrary", ab);
|
card.setSVar("GraveyardToLibrary", ab);
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Echo")) {
|
||||||
final int echoPos = hasKeyword(card, "Echo");
|
final String[] k = keyword.split(":");
|
||||||
if (echoPos != -1) {
|
|
||||||
// card.removeIntrinsicKeyword(parse);
|
|
||||||
final String[] k = card.getKeyword().get(echoPos).split(":");
|
|
||||||
final String manacost = k[1];
|
final String manacost = k[1];
|
||||||
|
|
||||||
card.setEchoCost(manacost);
|
card.setEchoCost(manacost);
|
||||||
@@ -2277,16 +2327,11 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
card.addComesIntoPlayCommand(intoPlay);
|
card.addComesIntoPlayCommand(intoPlay);
|
||||||
} // echo
|
}
|
||||||
|
else if (keyword.startsWith("Suspend")) {
|
||||||
if (hasKeyword(card, "Suspend") != -1) {
|
card.removeIntrinsicKeyword(keyword);
|
||||||
// Suspend:<TimeCounters>:<Cost>
|
|
||||||
final int n = hasKeyword(card, "Suspend");
|
|
||||||
if (n != -1) {
|
|
||||||
final String parse = card.getKeyword().get(n);
|
|
||||||
card.removeIntrinsicKeyword(parse);
|
|
||||||
card.setSuspend(true);
|
card.setSuspend(true);
|
||||||
final String[] k = parse.split(":");
|
final String[] k = keyword.split(":");
|
||||||
|
|
||||||
final String timeCounters = k[1];
|
final String timeCounters = k[1];
|
||||||
final String cost = k[2];
|
final String cost = k[2];
|
||||||
@@ -2294,12 +2339,8 @@ public class CardFactoryUtil {
|
|||||||
addSuspendUpkeepTrigger(card);
|
addSuspendUpkeepTrigger(card);
|
||||||
addSuspendPlayTrigger(card);
|
addSuspendPlayTrigger(card);
|
||||||
}
|
}
|
||||||
} // Suspend
|
else if (keyword.startsWith("Fading")) {
|
||||||
|
final String[] k = keyword.split(":");
|
||||||
if (hasKeyword(card, "Fading") != -1) {
|
|
||||||
final int n = hasKeyword(card, "Fading");
|
|
||||||
if (n != -1) {
|
|
||||||
final String[] k = card.getKeyword().get(n).split(":");
|
|
||||||
|
|
||||||
card.addIntrinsicKeyword("etbCounter:FADE:" + k[1] + ":no Condition:no desc");
|
card.addIntrinsicKeyword("etbCounter:FADE:" + k[1] + ":no Condition:no desc");
|
||||||
|
|
||||||
@@ -2316,12 +2357,8 @@ public class CardFactoryUtil {
|
|||||||
final Trigger parsedUpkeepTrig = TriggerHandler.parseTrigger(upkeepTrig, card, true);
|
final Trigger parsedUpkeepTrig = TriggerHandler.parseTrigger(upkeepTrig, card, true);
|
||||||
card.addTrigger(parsedUpkeepTrig);
|
card.addTrigger(parsedUpkeepTrig);
|
||||||
}
|
}
|
||||||
} // Fading
|
else if (keyword.startsWith("Vanishing")) {
|
||||||
|
final String[] k = keyword.split(":");
|
||||||
if (hasKeyword(card, "Vanishing") != -1) {
|
|
||||||
final int n = hasKeyword(card, "Vanishing");
|
|
||||||
if (n != -1) {
|
|
||||||
final String[] k = card.getKeyword().get(n).split(":");
|
|
||||||
// etbcounter
|
// etbcounter
|
||||||
card.addIntrinsicKeyword("etbCounter:TIME:" + k[1] + ":no Condition:no desc");
|
card.addIntrinsicKeyword("etbCounter:TIME:" + k[1] + ":no Condition:no desc");
|
||||||
// Remove Time counter trigger
|
// Remove Time counter trigger
|
||||||
@@ -2344,33 +2381,13 @@ public class CardFactoryUtil {
|
|||||||
final Trigger parsedSacTrigger = TriggerHandler.parseTrigger(sacTrig, card, true);
|
final Trigger parsedSacTrigger = TriggerHandler.parseTrigger(sacTrig, card, true);
|
||||||
card.addTrigger(parsedSacTrigger);
|
card.addTrigger(parsedSacTrigger);
|
||||||
}
|
}
|
||||||
} // Vanishing
|
else if (keyword.equals("Delve")) {
|
||||||
|
|
||||||
// AddCost
|
|
||||||
if (card.hasSVar("FullCost")) {
|
|
||||||
final SpellAbility sa1 = card.getFirstSpellAbility();
|
|
||||||
if (sa1 != null && sa1.isSpell()) {
|
|
||||||
sa1.setPayCosts(new Cost(card.getSVar("FullCost"), sa1.isAbility()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AltCost
|
|
||||||
String altCost = card.getSVar("AltCost");
|
|
||||||
if (StringUtils.isNotBlank(altCost)) {
|
|
||||||
final SpellAbility sa1 = card.getFirstSpellAbility();
|
|
||||||
if (sa1 != null && sa1.isSpell()) {
|
|
||||||
card.addSpellAbility(makeAltCostAbility(card, altCost, sa1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (card.hasKeyword("Delve")) {
|
|
||||||
card.getSpellAbilities().get(0).setDelve(true);
|
card.getSpellAbilities().get(0).setDelve(true);
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Haunt")) {
|
||||||
if (card.hasStartOfKeyword("Haunt")) {
|
|
||||||
setupHauntSpell(card);
|
setupHauntSpell(card);
|
||||||
}
|
}
|
||||||
|
else if (keyword.equals("Provoke")) {
|
||||||
if (card.hasKeyword("Provoke")) {
|
|
||||||
final String actualTrigger = "Mode$ Attacks | ValidCard$ Card.Self | "
|
final String actualTrigger = "Mode$ Attacks | ValidCard$ Card.Self | "
|
||||||
+ "OptionalDecider$ You | Execute$ ProvokeAbility | Secondary$ True | TriggerDescription$ "
|
+ "OptionalDecider$ You | Execute$ ProvokeAbility | Secondary$ True | TriggerDescription$ "
|
||||||
+ "When this attacks, you may have target creature defending player "
|
+ "When this attacks, you may have target creature defending player "
|
||||||
@@ -2383,9 +2400,8 @@ public class CardFactoryUtil {
|
|||||||
card.setSVar("ProvokeAbility", abString);
|
card.setSVar("ProvokeAbility", abString);
|
||||||
card.setSVar("ProvokeUntap", dbString);
|
card.setSVar("ProvokeUntap", dbString);
|
||||||
}
|
}
|
||||||
|
else if (keyword.equals("Living Weapon")) {
|
||||||
if (card.hasKeyword("Living Weapon")) {
|
card.removeIntrinsicKeyword(keyword);
|
||||||
card.removeIntrinsicKeyword("Living Weapon");
|
|
||||||
|
|
||||||
final StringBuilder sbTrig = new StringBuilder();
|
final StringBuilder sbTrig = new StringBuilder();
|
||||||
sbTrig.append("Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ");
|
sbTrig.append("Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ");
|
||||||
@@ -2410,12 +2426,10 @@ public class CardFactoryUtil {
|
|||||||
final Trigger etbTrigger = TriggerHandler.parseTrigger(sbTrig.toString(), card, true);
|
final Trigger etbTrigger = TriggerHandler.parseTrigger(sbTrig.toString(), card, true);
|
||||||
card.addTrigger(etbTrigger);
|
card.addTrigger(etbTrigger);
|
||||||
}
|
}
|
||||||
|
else if (keyword.equals("Epic")) {
|
||||||
if (card.hasKeyword("Epic")) {
|
|
||||||
makeEpic(card);
|
makeEpic(card);
|
||||||
}
|
}
|
||||||
|
else if (keyword.equals("Soulbond")) {
|
||||||
if (card.hasKeyword("Soulbond")) {
|
|
||||||
// Setup ETB trigger for card with Soulbond keyword
|
// Setup ETB trigger for card with Soulbond keyword
|
||||||
final String actualTriggerSelf = "Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | "
|
final String actualTriggerSelf = "Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | "
|
||||||
+ "ValidCard$ Card.Self | Execute$ TrigBondOther | OptionalDecider$ You | "
|
+ "ValidCard$ Card.Self | Execute$ TrigBondOther | OptionalDecider$ You | "
|
||||||
@@ -2437,8 +2451,7 @@ public class CardFactoryUtil {
|
|||||||
card.addTrigger(parsedTriggerOther);
|
card.addTrigger(parsedTriggerOther);
|
||||||
card.setSVar("TrigBondSelf", abStringOther);
|
card.setSVar("TrigBondSelf", abStringOther);
|
||||||
}
|
}
|
||||||
|
else if (keyword.equals("Extort")) {
|
||||||
if (card.hasKeyword("Extort")) {
|
|
||||||
final String extortTrigger = "Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ You | "
|
final String extortTrigger = "Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ You | "
|
||||||
+ "TriggerZones$ Battlefield | Execute$ ExtortOpps | Secondary$ True"
|
+ "TriggerZones$ Battlefield | Execute$ ExtortOpps | Secondary$ True"
|
||||||
+ " | TriggerDescription$ Extort (Whenever you cast a spell, you may pay W/B. If you do, "
|
+ " | TriggerDescription$ Extort (Whenever you cast a spell, you may pay W/B. If you do, "
|
||||||
@@ -2452,8 +2465,7 @@ public class CardFactoryUtil {
|
|||||||
card.setSVar("ExtortGainLife", dbString);
|
card.setSVar("ExtortGainLife", dbString);
|
||||||
card.setSVar("AFLifeLost", "Number$0");
|
card.setSVar("AFLifeLost", "Number$0");
|
||||||
}
|
}
|
||||||
|
else if (keyword.equals("Evolve")) {
|
||||||
if (card.hasKeyword("Evolve")) {
|
|
||||||
final String evolveTrigger = "Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | "
|
final String evolveTrigger = "Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | "
|
||||||
+ " ValidCard$ Creature.YouCtrl+Other | EvolveCondition$ True | "
|
+ " ValidCard$ Creature.YouCtrl+Other | EvolveCondition$ True | "
|
||||||
+ "TriggerZones$ Battlefield | Execute$ EvolveAddCounter | Secondary$ True | "
|
+ "TriggerZones$ Battlefield | Execute$ EvolveAddCounter | Secondary$ True | "
|
||||||
@@ -2466,8 +2478,7 @@ public class CardFactoryUtil {
|
|||||||
card.addTrigger(parsedTrigger);
|
card.addTrigger(parsedTrigger);
|
||||||
card.setSVar("EvolveAddCounter", abString);
|
card.setSVar("EvolveAddCounter", abString);
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Dredge")) {
|
||||||
if (card.hasStartOfKeyword("Dredge")) {
|
|
||||||
final int dredgeAmount = card.getKeywordMagnitude("Dredge");
|
final int dredgeAmount = card.getKeywordMagnitude("Dredge");
|
||||||
|
|
||||||
final String actualRep = "Event$ Draw | ActiveZones$ Graveyard | ValidPlayer$ You | "
|
final String actualRep = "Event$ Draw | ActiveZones$ Graveyard | ValidPlayer$ You | "
|
||||||
@@ -2485,8 +2496,7 @@ public class CardFactoryUtil {
|
|||||||
card.setSVar("DredgeCheckLib", checkSVar);
|
card.setSVar("DredgeCheckLib", checkSVar);
|
||||||
card.addReplacementEffect(ReplacementHandler.parseReplacement(actualRep, card, true));
|
card.addReplacementEffect(ReplacementHandler.parseReplacement(actualRep, card, true));
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Tribute")) {
|
||||||
if (card.hasStartOfKeyword("Tribute")) {
|
|
||||||
final int tributeAmount = card.getKeywordMagnitude("Tribute");
|
final int tributeAmount = card.getKeywordMagnitude("Tribute");
|
||||||
|
|
||||||
final String actualRep = "Event$ Moved | Destination$ Battlefield | ValidCard$ Card.Self |"
|
final String actualRep = "Event$ Moved | Destination$ Battlefield | ValidCard$ Card.Self |"
|
||||||
@@ -2502,8 +2512,7 @@ public class CardFactoryUtil {
|
|||||||
card.setSVar("TributeMoveToPlay", moveToPlay);
|
card.setSVar("TributeMoveToPlay", moveToPlay);
|
||||||
card.addReplacementEffect(ReplacementHandler.parseReplacement(actualRep, card, true));
|
card.addReplacementEffect(ReplacementHandler.parseReplacement(actualRep, card, true));
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Amplify")) {
|
||||||
if (card.hasStartOfKeyword("Amplify")) {
|
|
||||||
// find position of Amplify keyword
|
// find position of Amplify keyword
|
||||||
final int ampPos = card.getKeywordPosition("Amplify");
|
final int ampPos = card.getKeywordPosition("Amplify");
|
||||||
final String[] ampString = card.getKeyword().get(ampPos).split(":");
|
final String[] ampString = card.getKeyword().get(ampPos).split(":");
|
||||||
@@ -2539,12 +2548,9 @@ public class CardFactoryUtil {
|
|||||||
card.setSVar("AmpMagnitude", "SVar$Revealed/Times." + amplifyMagnitude);
|
card.setSVar("AmpMagnitude", "SVar$Revealed/Times." + amplifyMagnitude);
|
||||||
card.setSVar("Revealed", "Remembered$Amount");
|
card.setSVar("Revealed", "Remembered$Amount");
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Equip")) {
|
||||||
if (card.hasStartOfKeyword("Equip")) {
|
|
||||||
// find position of Equip keyword
|
|
||||||
final int equipPos = card.getKeywordPosition("Equip");
|
|
||||||
// Check for additional params such as preferred AI targets
|
// Check for additional params such as preferred AI targets
|
||||||
final String equipString = card.getKeyword().get(equipPos).substring(5);
|
final String equipString = keyword.substring(5);
|
||||||
final String[] equipExtras = equipString.contains("|") ? equipString.split("\\|", 2) : null;
|
final String[] equipExtras = equipString.contains("|") ? equipString.split("\\|", 2) : null;
|
||||||
// Get cost string
|
// Get cost string
|
||||||
String equipCost = "";
|
String equipCost = "";
|
||||||
@@ -2575,10 +2581,8 @@ public class CardFactoryUtil {
|
|||||||
// add ability to instrinic strings so copies/clones create the ability also
|
// add ability to instrinic strings so copies/clones create the ability also
|
||||||
card.getUnparsedAbilities().add(abilityStr.toString());
|
card.getUnparsedAbilities().add(abilityStr.toString());
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Outlast")) {
|
||||||
if (card.hasStartOfKeyword("Outlast")) {
|
final String outlastString = keyword.substring(7);
|
||||||
final int outlastPos = card.getKeywordPosition("Outlast");
|
|
||||||
final String outlastString = card.getKeyword().get(outlastPos).substring(7);
|
|
||||||
final String[] outlastExtras = outlastString.contains("|") ? outlastString.split("\\|", 2) : null;
|
final String[] outlastExtras = outlastString.contains("|") ? outlastString.split("\\|", 2) : null;
|
||||||
// Get cost string
|
// Get cost string
|
||||||
String outlastCost = "";
|
String outlastCost = "";
|
||||||
@@ -2608,10 +2612,8 @@ public class CardFactoryUtil {
|
|||||||
// add ability to instrinic strings so copies/clones create the ability also
|
// add ability to instrinic strings so copies/clones create the ability also
|
||||||
card.getUnparsedAbilities().add(abilityStr.toString());
|
card.getUnparsedAbilities().add(abilityStr.toString());
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Fortify")) {
|
||||||
if (card.hasStartOfKeyword("Fortify")) {
|
final String equipString = keyword.substring(7);
|
||||||
final int equipPos = card.getKeywordPosition("Fortify");
|
|
||||||
final String equipString = card.getKeyword().get(equipPos).substring(7);
|
|
||||||
final String[] equipExtras = equipString.contains("|") ? equipString.split("\\|", 2) : null;
|
final String[] equipExtras = equipString.contains("|") ? equipString.split("\\|", 2) : null;
|
||||||
// Get cost string
|
// Get cost string
|
||||||
String equipCost = "";
|
String equipCost = "";
|
||||||
@@ -2640,15 +2642,13 @@ public class CardFactoryUtil {
|
|||||||
// instantiate attach ability
|
// instantiate attach ability
|
||||||
final SpellAbility sa = AbilityFactory.getAbility(abilityStr.toString(), card);
|
final SpellAbility sa = AbilityFactory.getAbility(abilityStr.toString(), card);
|
||||||
card.addSpellAbility(sa);
|
card.addSpellAbility(sa);
|
||||||
// add ability to instrinic strings so copies/clones create the ability also
|
// add ability to intrinsic strings so copies/clones create the ability also
|
||||||
card.getUnparsedAbilities().add(abilityStr.toString());
|
card.getUnparsedAbilities().add(abilityStr.toString());
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Bestow")) {
|
||||||
if (card.hasStartOfKeyword("Bestow")) {
|
final String[] params = keyword.split(":");
|
||||||
final int bestowPos = card.getKeywordPosition("Bestow");
|
|
||||||
final String[] params = card.getKeyword().get(bestowPos).split(":");
|
|
||||||
final String cost = params[1];
|
final String cost = params[1];
|
||||||
card.removeIntrinsicKeyword(card.getKeyword().get(bestowPos));
|
card.removeIntrinsicKeyword(keyword);
|
||||||
|
|
||||||
final StringBuilder sbAttach = new StringBuilder();
|
final StringBuilder sbAttach = new StringBuilder();
|
||||||
sbAttach.append("SP$ Attach | Cost$ ");
|
sbAttach.append("SP$ Attach | Cost$ ");
|
||||||
@@ -2664,7 +2664,24 @@ public class CardFactoryUtil {
|
|||||||
bestow.setBasicSpell(false);
|
bestow.setBasicSpell(false);
|
||||||
card.addSpellAbility(bestow);
|
card.addSpellAbility(bestow);
|
||||||
card.getUnparsedAbilities().add(sbAttach.toString());
|
card.getUnparsedAbilities().add(sbAttach.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCost
|
||||||
|
if (card.hasSVar("FullCost")) {
|
||||||
|
final SpellAbility sa1 = card.getFirstSpellAbility();
|
||||||
|
if (sa1 != null && sa1.isSpell()) {
|
||||||
|
sa1.setPayCosts(new Cost(card.getSVar("FullCost"), sa1.isAbility()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AltCost
|
||||||
|
String altCost = card.getSVar("AltCost");
|
||||||
|
if (StringUtils.isNotBlank(altCost)) {
|
||||||
|
final SpellAbility sa1 = card.getFirstSpellAbility();
|
||||||
|
if (sa1 != null && sa1.isSpell()) {
|
||||||
|
card.addSpellAbility(makeAltCostAbility(card, altCost, sa1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupEtbKeywords(card);
|
setupEtbKeywords(card);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public final class CardUtil {
|
|||||||
"Enchant", "Protection", "Cumulative upkeep", "Equip", "Buyback",
|
"Enchant", "Protection", "Cumulative upkeep", "Equip", "Buyback",
|
||||||
"Cycling", "Echo", "Kicker", "Flashback", "Madness", "Morph",
|
"Cycling", "Echo", "Kicker", "Flashback", "Madness", "Morph",
|
||||||
"Affinity", "Entwine", "Splice", "Ninjutsu",
|
"Affinity", "Entwine", "Splice", "Ninjutsu",
|
||||||
"Transute", "Replicate", "Recover", "Suspend", "Aura swap",
|
"Transmute", "Replicate", "Recover", "Suspend", "Aura swap",
|
||||||
"Fortify", "Transfigure", "Champion", "Evoke", "Prowl",
|
"Fortify", "Transfigure", "Champion", "Evoke", "Prowl",
|
||||||
"Reinforce", "Unearth", "Level up", "Miracle", "Overload",
|
"Reinforce", "Unearth", "Level up", "Miracle", "Overload",
|
||||||
"Scavenge", "Bestow", "Outlast").build();
|
"Scavenge", "Bestow", "Outlast").build();
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ import forge.util.maps.MapToAmount;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* ManaCostBeingPaid class.
|
* ManaCostBeingPaid class.
|
||||||
@@ -215,6 +217,20 @@ public class ManaCostBeingPaid {
|
|||||||
return unpaidShards.isEmpty();
|
return unpaidShards.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final void setXManaCostPaid(final int xPaid, final String xColor) {
|
||||||
|
int xCost = xPaid * cntX;
|
||||||
|
cntX = 0;
|
||||||
|
|
||||||
|
ManaCostShard increaseShard;
|
||||||
|
if (StringUtils.isEmpty(xColor)) {
|
||||||
|
increaseShard = ManaCostShard.COLORLESS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
increaseShard = ManaCostShard.valueOf(MagicColor.fromName(xColor));
|
||||||
|
}
|
||||||
|
unpaidShards.add(increaseShard, xCost);
|
||||||
|
}
|
||||||
|
|
||||||
public final void increaseColorlessMana(final int manaToAdd) {
|
public final void increaseColorlessMana(final int manaToAdd) {
|
||||||
increaseShard(ManaCostShard.COLORLESS, manaToAdd);
|
increaseShard(ManaCostShard.COLORLESS, manaToAdd);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,8 +131,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
public final AbilityManaPart getManaPartRecursive() {
|
public final AbilityManaPart getManaPartRecursive() {
|
||||||
SpellAbility tail = this;
|
SpellAbility tail = this;
|
||||||
while (tail != null) {
|
while (tail != null) {
|
||||||
if(tail.manaPart != null)
|
if (tail.manaPart != null) {
|
||||||
return tail.manaPart;
|
return tail.manaPart;
|
||||||
|
}
|
||||||
tail = tail.getSubAbility();
|
tail = tail.getSubAbility();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -140,14 +141,17 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
|
|
||||||
public final boolean isManaAbility() {
|
public final boolean isManaAbility() {
|
||||||
// Check whether spell or ability first
|
// Check whether spell or ability first
|
||||||
if (this.isSpell())
|
if (this.isSpell()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
// without a target
|
// without a target
|
||||||
if (this.usesTargeting()) return false;
|
if (this.usesTargeting()) { return false; }
|
||||||
if (getRestrictions() != null && getRestrictions().getPlaneswalker())
|
if (getRestrictions() != null && getRestrictions().getPlaneswalker()) {
|
||||||
return false; //Loyalty ability, not a mana ability.
|
return false; //Loyalty ability, not a mana ability.
|
||||||
if (this.isWrapper() && ((WrappedAbility) this).getTrigger().getMode() != TriggerType.TapsForMana)
|
}
|
||||||
|
if (this.isWrapper() && ((WrappedAbility) this).getTrigger().getMode() != TriggerType.TapsForMana) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return getManaPartRecursive() != null;
|
return getManaPartRecursive() != null;
|
||||||
}
|
}
|
||||||
@@ -157,7 +161,22 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final String getSVar(final String name) {
|
public final String getSVar(final String name) {
|
||||||
return sVars.get(name) != null ? sVars.get(name) : "";
|
String var = sVars.get(name);
|
||||||
|
if (var == null) {
|
||||||
|
var = "";
|
||||||
|
}
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Integer getSVarInt(final String name) {
|
||||||
|
String var = sVars.get(name);
|
||||||
|
if (var != null) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(var);
|
||||||
|
}
|
||||||
|
catch (Exception e) {}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setSVar(final String name, final String value) {
|
public final void setSVar(final String name, final String value) {
|
||||||
@@ -298,18 +317,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
public boolean isSpell() { return false; }
|
public boolean isSpell() { return false; }
|
||||||
public boolean isAbility() { return true; }
|
public boolean isAbility() { return true; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* isMultiKicker.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a boolean.
|
|
||||||
*/
|
|
||||||
public boolean isMultiKicker() {
|
|
||||||
return this.multiKickerManaCost != null && !this.isAnnouncing("Multikicker");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* setIsMorphUp.
|
* setIsMorphUp.
|
||||||
@@ -380,14 +387,14 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getParamOrDefault(String key, String defaultValue) {
|
public String getParamOrDefault(String key, String defaultValue) {
|
||||||
return mapParams == null || !mapParams.containsKey(key) ? defaultValue : mapParams.get(key);
|
return mapParams.containsKey(key) ? mapParams.get(key) : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getParam(String key) {
|
public String getParam(String key) {
|
||||||
return mapParams == null ? null : mapParams.get(key);
|
return mapParams.get(key);
|
||||||
}
|
}
|
||||||
public boolean hasParam(String key) {
|
public boolean hasParam(String key) {
|
||||||
return mapParams == null ? false : mapParams.containsKey(key);
|
return mapParams.containsKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -395,10 +402,8 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
* @param mapParams
|
* @param mapParams
|
||||||
*/
|
*/
|
||||||
public void copyParamsToMap(Map<String, String> mapParams) {
|
public void copyParamsToMap(Map<String, String> mapParams) {
|
||||||
if (null != this.mapParams) {
|
|
||||||
mapParams.putAll(this.mapParams);
|
mapParams.putAll(this.mapParams);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If this is not null, then ability was made in a factory
|
// If this is not null, then ability was made in a factory
|
||||||
public ApiType getApi() {
|
public ApiType getApi() {
|
||||||
@@ -1127,9 +1132,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
}
|
}
|
||||||
|
|
||||||
String[] validTgt = tr.getValidTgts();
|
String[] validTgt = tr.getValidTgts();
|
||||||
if (entity instanceof GameEntity && !((GameEntity) entity).isValid(validTgt, this.getActivatingPlayer(), this.getHostCard()))
|
if (entity instanceof GameEntity && !((GameEntity) entity).isValid(validTgt, this.getActivatingPlayer(), this.getHostCard())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Restrictions coming from target
|
// Restrictions coming from target
|
||||||
return entity.canBeTargetedBy(this);
|
return entity.canBeTargetedBy(this);
|
||||||
@@ -1298,7 +1304,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
while (null != parent.getParent()) {
|
while (null != parent.getParent()) {
|
||||||
parent = parent.getParent();
|
parent = parent.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1351,15 +1356,32 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
*/
|
*/
|
||||||
public boolean isAnnouncing(String variable) {
|
public boolean isAnnouncing(String variable) {
|
||||||
String announce = getParam("Announce");
|
String announce = getParam("Announce");
|
||||||
if (StringUtils.isBlank(announce)) return false;
|
if (StringUtils.isBlank(announce)) { return false; }
|
||||||
|
|
||||||
String[] announcedOnes = TextUtil.split(announce, ',');
|
String[] announcedOnes = TextUtil.split(announce, ',');
|
||||||
for (String a : announcedOnes) {
|
for (String a : announcedOnes) {
|
||||||
if( a.trim().equalsIgnoreCase(variable))
|
if (a.trim().equalsIgnoreCase(variable)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addAnnounceVar(String variable) {
|
||||||
|
String announce = getParam("Announce");
|
||||||
|
if (StringUtils.isBlank(announce)) {
|
||||||
|
mapParams.put("Announce", variable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String[] announcedOnes = TextUtil.split(announce, ',');
|
||||||
|
for (String a : announcedOnes) {
|
||||||
|
if (a.trim().equalsIgnoreCase(variable)) {
|
||||||
|
return; //don't add announce variable that already exists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mapParams.put("Announce", announce + ";" + variable);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isXCost() {
|
public boolean isXCost() {
|
||||||
CostPartMana cm = payCosts != null ? getPayCosts().getCostMana() : null;
|
CostPartMana cm = payCosts != null ? getPayCosts().getCostMana() : null;
|
||||||
return cm != null && cm.getAmountOfX() > 0;
|
return cm != null && cm.getAmountOfX() > 0;
|
||||||
@@ -1486,10 +1508,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
targetChosen.add(card);
|
targetChosen.add(card);
|
||||||
|
|
||||||
final String desc;
|
final String desc;
|
||||||
|
|
||||||
if (!card.isFaceDown()) {
|
if (!card.isFaceDown()) {
|
||||||
desc = this.getHostCard().getName() + " - targeting " + card;
|
desc = this.getHostCard().getName() + " - targeting " + card;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
desc = this.getHostCard().getName() + " - targeting Morph(" + card.getUniqueNumber() + ")";
|
desc = this.getHostCard().getName() + " - targeting Morph(" + card.getUniqueNumber() + ")";
|
||||||
}
|
}
|
||||||
this.setStackDescription(desc);
|
this.setStackDescription(desc);
|
||||||
@@ -1532,7 +1554,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
return ImmutableList.<Card>of();
|
return ImmutableList.<Card>of();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public SpellAbility getSATargetingCard() {
|
public SpellAbility getSATargetingCard() {
|
||||||
return targetChosen.isTargetingAnyCard() ? this : getParentTargetingCard();
|
return targetChosen.isTargetingAnyCard() ? this : getParentTargetingCard();
|
||||||
}
|
}
|
||||||
@@ -1543,8 +1564,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
parent = ((WrappedAbility) parent).getWrappedAbility();
|
parent = ((WrappedAbility) parent).getWrappedAbility();
|
||||||
}
|
}
|
||||||
while (parent != null) {
|
while (parent != null) {
|
||||||
if (parent.targetChosen.isTargetingAnyCard())
|
if (parent.targetChosen.isTargetingAnyCard()) {
|
||||||
return parent;
|
return parent;
|
||||||
|
}
|
||||||
parent = parent.getParent();
|
parent = parent.getParent();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -1674,15 +1696,21 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
final String[] incR = restriction.split("\\.", 2);
|
final String[] incR = restriction.split("\\.", 2);
|
||||||
|
|
||||||
if (incR[0].equals("Spell")) {
|
if (incR[0].equals("Spell")) {
|
||||||
if (!this.isSpell())
|
if (!this.isSpell()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (incR[0].equals("Triggered")) {
|
}
|
||||||
if (!this.isTrigger())
|
}
|
||||||
|
else if (incR[0].equals("Triggered")) {
|
||||||
|
if (!this.isTrigger()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (incR[0].equals("Activated")) {
|
}
|
||||||
if (!(this instanceof AbilityActivated))
|
}
|
||||||
|
else if (incR[0].equals("Activated")) {
|
||||||
|
if (!(this instanceof AbilityActivated)) {
|
||||||
return false;
|
return false;
|
||||||
} else { //not a spell/ability type
|
}
|
||||||
|
}
|
||||||
|
else { //not a spell/ability type
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1811,5 +1839,4 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
this.subAbility.setIntrinsic(i);
|
this.subAbility.setIntrinsic(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -243,11 +243,6 @@ public class WrappedAbility extends Ability implements ISpellAbility {
|
|||||||
return sa.isFlashBackAbility();
|
return sa.isFlashBackAbility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMultiKicker() {
|
|
||||||
return sa.isMultiKicker();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSpell() {
|
public boolean isSpell() {
|
||||||
return sa.isSpell();
|
return sa.isSpell();
|
||||||
|
|||||||
@@ -332,27 +332,15 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
|||||||
// TODO: make working triggered ability
|
// TODO: make working triggered ability
|
||||||
sp.setTotalManaSpent(totManaSpent);
|
sp.setTotalManaSpent(totManaSpent);
|
||||||
AbilityUtils.resolve(sp);
|
AbilityUtils.resolve(sp);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
for (OptionalCost s : sp.getOptionalCosts()) {
|
for (OptionalCost s : sp.getOptionalCosts()) {
|
||||||
source.addOptionalCostPaid(s);
|
source.addOptionalCostPaid(s);
|
||||||
}
|
}
|
||||||
if (sp.isCopied()) {
|
if (sp.isCopied()) {
|
||||||
si = this.push(sp);
|
si = this.push(sp);
|
||||||
} else {
|
|
||||||
if (sp.isMultiKicker()) {
|
|
||||||
final Cost costMultikicker = new Cost(sp.getMultiKickerManaCost(), false);
|
|
||||||
boolean hasPaid = false;
|
|
||||||
do {
|
|
||||||
int mkMagnitude = source.getKickerMagnitude();
|
|
||||||
String prompt = String.format("Multikicker for %s\r\nTimes Kicked: %d\r\n", source, mkMagnitude );
|
|
||||||
hasPaid = activator.getController().payManaOptional(source, costMultikicker, sp, prompt, ManaPaymentPurpose.Multikicker);
|
|
||||||
if (hasPaid) {
|
|
||||||
source.addMultiKickerMagnitude(1);
|
|
||||||
totManaSpent += sp.getPayingMana().size();
|
|
||||||
// TODO: paying mana is replaced by multikicker cost, this should be fixed in the future
|
|
||||||
}
|
|
||||||
} while( hasPaid );
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
if (sp.isSpell() && source.isCreature() && Iterables.any(activator.getCardsIn(ZoneType.Battlefield),
|
if (sp.isSpell() && source.isCreature() && Iterables.any(activator.getCardsIn(ZoneType.Battlefield),
|
||||||
CardPredicates.hasKeyword("As an additional cost to cast creature spells," +
|
CardPredicates.hasKeyword("As an additional cost to cast creature spells," +
|
||||||
" you may pay any amount of mana. If you do, that creature enters " +
|
" you may pay any amount of mana. If you do, that creature enters " +
|
||||||
@@ -394,10 +382,9 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
|||||||
if (sp.isSpell() && (source.hasStartOfKeyword("Replicate")
|
if (sp.isSpell() && (source.hasStartOfKeyword("Replicate")
|
||||||
|| ((source.isInstant() || source.isSorcery()) && Iterables.any(activator.getCardsIn(ZoneType.Battlefield),
|
|| ((source.isInstant() || source.isSorcery()) && Iterables.any(activator.getCardsIn(ZoneType.Battlefield),
|
||||||
CardPredicates.hasKeyword("Each instant and sorcery spell you cast has replicate. The replicate cost is equal to its mana cost."))))) {
|
CardPredicates.hasKeyword("Each instant and sorcery spell you cast has replicate. The replicate cost is equal to its mana cost."))))) {
|
||||||
int magnitude = 0;
|
Integer magnitude = sp.getSVarInt("Replicate");
|
||||||
// TODO: convert multikicker/replicate support in abCost so this
|
if (magnitude == null) {
|
||||||
// doesn't happen here
|
magnitude = 0;
|
||||||
|
|
||||||
final Cost costReplicate = new Cost(source.getManaCost(), false);
|
final Cost costReplicate = new Cost(source.getManaCost(), false);
|
||||||
boolean hasPaid = false;
|
boolean hasPaid = false;
|
||||||
int replicateCMC = source.getManaCost().getCMC();
|
int replicateCMC = source.getManaCost().getCMC();
|
||||||
@@ -409,14 +396,16 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
|||||||
totManaSpent += replicateCMC;
|
totManaSpent += replicateCMC;
|
||||||
}
|
}
|
||||||
} while (hasPaid);
|
} while (hasPaid);
|
||||||
|
}
|
||||||
|
|
||||||
// Replicate Trigger
|
// Replicate Trigger
|
||||||
String effect = String.format("AB$ CopySpellAbility | Cost$ 0 | Defined$ SourceFirstSpell | Amount$ %d", magnitude);
|
String effect = String.format("AB$ CopySpellAbility | Cost$ 0 | Defined$ SourceFirstSpell | Amount$ %d", magnitude);
|
||||||
SpellAbility sa = AbilityFactory.getAbility(effect, source);
|
SpellAbility sa = AbilityFactory.getAbility(effect, source);
|
||||||
sa.setDescription("Replicate - " + source);
|
sa.setDescription("Replicate - " + source);
|
||||||
sa.setTrigger(true);
|
sa.setTrigger(true);
|
||||||
|
sa.setCopied(true);
|
||||||
addSimultaneousStackEntry(sa);
|
addSimultaneousStackEntry(sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -213,6 +213,9 @@ public class QuestPreferencesHandler extends SkinnedPanel {
|
|||||||
pnlShop.add(new FLabel.Builder().text("Maximum Packs").build(), constraints2);
|
pnlShop.add(new FLabel.Builder().text("Maximum Packs").build(), constraints2);
|
||||||
pnlShop.add(new PrefInput(QPref.SHOP_MAX_PACKS, ErrType.SHOP), constraints1);
|
pnlShop.add(new PrefInput(QPref.SHOP_MAX_PACKS, ErrType.SHOP), constraints1);
|
||||||
|
|
||||||
|
pnlShop.add(new FLabel.Builder().text("Minimum Packs").build(), constraints2);
|
||||||
|
pnlShop.add(new PrefInput(QPref.SHOP_MIN_PACKS, ErrType.SHOP), constraints1);
|
||||||
|
|
||||||
pnlShop.add(new FLabel.Builder().text("Starting Packs").build(), constraints2);
|
pnlShop.add(new FLabel.Builder().text("Starting Packs").build(), constraints2);
|
||||||
pnlShop.add(new PrefInput(QPref.SHOP_STARTING_PACKS, ErrType.SHOP), constraints1);
|
pnlShop.add(new PrefInput(QPref.SHOP_STARTING_PACKS, ErrType.SHOP), constraints1);
|
||||||
|
|
||||||
|
|||||||
@@ -351,6 +351,9 @@ public enum VSubmenuQuestPrefs implements IVSubmenu<CSubmenuQuestPrefs> {
|
|||||||
pnlShop.add(new FLabel.Builder().text("Maximum Packs").fontAlign(SwingConstants.RIGHT).build(), constraints2);
|
pnlShop.add(new FLabel.Builder().text("Maximum Packs").fontAlign(SwingConstants.RIGHT).build(), constraints2);
|
||||||
pnlShop.add(new PrefInput(QPref.SHOP_MAX_PACKS, QuestPreferencesErrType.SHOP), constraints1);
|
pnlShop.add(new PrefInput(QPref.SHOP_MAX_PACKS, QuestPreferencesErrType.SHOP), constraints1);
|
||||||
|
|
||||||
|
pnlShop.add(new FLabel.Builder().text("Minimum Packs").fontAlign(SwingConstants.RIGHT).build(), constraints2);
|
||||||
|
pnlShop.add(new PrefInput(QPref.SHOP_MIN_PACKS, QuestPreferencesErrType.SHOP), constraints1);
|
||||||
|
|
||||||
pnlShop.add(new FLabel.Builder().text("Starting Packs").fontAlign(SwingConstants.RIGHT).build(), constraints2);
|
pnlShop.add(new FLabel.Builder().text("Starting Packs").fontAlign(SwingConstants.RIGHT).build(), constraints2);
|
||||||
pnlShop.add(new PrefInput(QPref.SHOP_STARTING_PACKS, QuestPreferencesErrType.SHOP), constraints1);
|
pnlShop.add(new PrefInput(QPref.SHOP_STARTING_PACKS, QuestPreferencesErrType.SHOP), constraints1);
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ public enum CSubmenuConstructed implements ICDoc, IMenuProvider {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
|
|
||||||
MenuUtil.setMenuProvider(this);
|
MenuUtil.setMenuProvider(this);
|
||||||
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@@ -196,8 +195,25 @@ public enum CSubmenuConstructed implements ICDoc, IMenuProvider {
|
|||||||
}
|
}
|
||||||
} // Is it even possible anymore? I think current implementation assigns decks automatically.
|
} // Is it even possible anymore? I think current implementation assigns decks automatically.
|
||||||
|
|
||||||
|
GameType autoGenerateVariant = null;
|
||||||
|
boolean isCommanderMatch = false;
|
||||||
|
if (!variantTypes.isEmpty()) {
|
||||||
|
isCommanderMatch = variantTypes.contains(GameType.Commander);
|
||||||
|
if (!isCommanderMatch) {
|
||||||
|
for (GameType variant : variantTypes) {
|
||||||
|
if (variant.isAutoGenerated()) {
|
||||||
|
autoGenerateVariant = variant;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean checkLegality = FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY);
|
boolean checkLegality = FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY);
|
||||||
if (checkLegality && !variantTypes.contains(GameType.Commander)) { //Commander deck replaces regular deck and is checked later
|
|
||||||
|
//Auto-generated decks don't need to be checked here
|
||||||
|
//Commander deck replaces regular deck and is checked later
|
||||||
|
if (checkLegality && autoGenerateVariant == null && !isCommanderMatch) {
|
||||||
for (final int i : view.getParticipants()) {
|
for (final int i : view.getParticipants()) {
|
||||||
String name = view.getPlayerName(i);
|
String name = view.getPlayerName(i);
|
||||||
String errMsg = GameType.Constructed.getDeckFormat().getDeckConformanceProblem(view.getDeckChooser(i).getPlayer().getDeck());
|
String errMsg = GameType.Constructed.getDeckFormat().getDeckConformanceProblem(view.getDeckChooser(i).getPlayer().getDeck());
|
||||||
@@ -220,9 +236,10 @@ public enum CSubmenuConstructed implements ICDoc, IMenuProvider {
|
|||||||
if (variantTypes.isEmpty()) {
|
if (variantTypes.isEmpty()) {
|
||||||
rp.setTeamNumber(view.getTeam(i));
|
rp.setTeamNumber(view.getTeam(i));
|
||||||
players.add(rp.setPlayer(lobbyPlayer));
|
players.add(rp.setPlayer(lobbyPlayer));
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
Deck deck = null;
|
Deck deck = null;
|
||||||
boolean isCommanderMatch = variantTypes.contains(GameType.Commander);
|
PaperCard vanguardAvatar = null;
|
||||||
if (isCommanderMatch) {
|
if (isCommanderMatch) {
|
||||||
Object selected = view.getCommanderDeckLists().get(i).getSelectedValue();
|
Object selected = view.getCommanderDeckLists().get(i).getSelectedValue();
|
||||||
if (selected instanceof String) {
|
if (selected instanceof String) {
|
||||||
@@ -231,7 +248,8 @@ public enum CSubmenuConstructed implements ICDoc, IMenuProvider {
|
|||||||
if (sel.equals("Random") && comDecks.size() > 0) {
|
if (sel.equals("Random") && comDecks.size() > 0) {
|
||||||
deck = Aggregates.random(comDecks);
|
deck = Aggregates.random(comDecks);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
deck = (Deck) selected;
|
deck = (Deck) selected;
|
||||||
}
|
}
|
||||||
if (deck == null) { //Can be null if player deselects the list selection or chose Generate
|
if (deck == null) { //Can be null if player deselects the list selection or chose Generate
|
||||||
@@ -245,13 +263,19 @@ public enum CSubmenuConstructed implements ICDoc, IMenuProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (autoGenerateVariant != null) {
|
||||||
|
deck = autoGenerateVariant.autoGenerateDeck(rp);
|
||||||
|
CardPool avatarPool = deck.get(DeckSection.Avatar);
|
||||||
|
if (avatarPool != null) {
|
||||||
|
vanguardAvatar = avatarPool.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialise variables for other variants
|
// Initialise variables for other variants
|
||||||
deck = deck == null ? rp.getDeck() : deck;
|
deck = deck == null ? rp.getDeck() : deck;
|
||||||
Iterable<PaperCard> schemes = null;
|
Iterable<PaperCard> schemes = null;
|
||||||
boolean playerIsArchenemy = view.isPlayerArchenemy(i);
|
boolean playerIsArchenemy = view.isPlayerArchenemy(i);
|
||||||
Iterable<PaperCard> planes = null;
|
Iterable<PaperCard> planes = null;
|
||||||
PaperCard vanguardAvatar = null;
|
|
||||||
|
|
||||||
//Archenemy
|
//Archenemy
|
||||||
if (variantTypes.contains(GameType.ArchenemyRumble)
|
if (variantTypes.contains(GameType.ArchenemyRumble)
|
||||||
|
|||||||
@@ -110,13 +110,12 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
// Variants frame and variables
|
// Variants frame and variables
|
||||||
private final Set<GameType> appliedVariants = new TreeSet<GameType>();
|
private final Set<GameType> appliedVariants = new TreeSet<GameType>();
|
||||||
private final FPanel variantsPanel = new FPanel(new MigLayout("insets 10, gapx 10"));
|
private final FPanel variantsPanel = new FPanel(new MigLayout("insets 10, gapx 10"));
|
||||||
private final FCheckBox vntVanguard = new FCheckBox("Vanguard");
|
private final VariantCheckBox vntVanguard = new VariantCheckBox(GameType.Vanguard);
|
||||||
private final FCheckBox vntCommander = new FCheckBox("Commander");
|
private final VariantCheckBox vntMomirBasic = new VariantCheckBox(GameType.MomirBasic);
|
||||||
private final FCheckBox vntPlanechase = new FCheckBox("Planechase");
|
private final VariantCheckBox vntCommander = new VariantCheckBox(GameType.Commander);
|
||||||
private final FCheckBox vntArchenemy = new FCheckBox("Archenemy");
|
private final VariantCheckBox vntPlanechase = new VariantCheckBox(GameType.Planechase);
|
||||||
private String archenemyType = "Classic";
|
private final VariantCheckBox vntArchenemy = new VariantCheckBox(GameType.Archenemy);
|
||||||
private final FComboBoxWrapper<String> comboArchenemy = new FComboBoxWrapper<String>(new String[]{
|
private final VariantCheckBox vntArchenemyRumble = new VariantCheckBox(GameType.ArchenemyRumble);
|
||||||
"Archenemy (Classic - One player is the Archenemy)", "Supervillan Rumble (All players are Archenemies)"});
|
|
||||||
|
|
||||||
// Player frame elements
|
// Player frame elements
|
||||||
private final JPanel playersFrame = new JPanel(new MigLayout("insets 0, gap 0 5, wrap, hidemode 3"));
|
private final JPanel playersFrame = new JPanel(new MigLayout("insets 0, gap 0 5, wrap, hidemode 3"));
|
||||||
@@ -160,22 +159,14 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
//////////////////// Variants Panel ////////////////////
|
//////////////////// Variants Panel ////////////////////
|
||||||
|
|
||||||
// Populate and add variants panel
|
|
||||||
vntVanguard.addItemListener(iListenerVariants);
|
|
||||||
vntCommander.addItemListener(iListenerVariants);
|
|
||||||
vntPlanechase.addItemListener(iListenerVariants);
|
|
||||||
vntArchenemy.addItemListener(iListenerVariants);
|
|
||||||
comboArchenemy.setSelectedIndex(0);
|
|
||||||
comboArchenemy.setEnabled(vntArchenemy.isSelected());
|
|
||||||
comboArchenemy.addActionListener(aeComboListener);
|
|
||||||
|
|
||||||
variantsPanel.setOpaque(false);
|
variantsPanel.setOpaque(false);
|
||||||
variantsPanel.add(newLabel("Variants:"));
|
variantsPanel.add(newLabel("Variants:"));
|
||||||
variantsPanel.add(vntVanguard);
|
variantsPanel.add(vntVanguard);
|
||||||
|
variantsPanel.add(vntMomirBasic);
|
||||||
variantsPanel.add(vntCommander);
|
variantsPanel.add(vntCommander);
|
||||||
variantsPanel.add(vntPlanechase);
|
variantsPanel.add(vntPlanechase);
|
||||||
variantsPanel.add(vntArchenemy);
|
variantsPanel.add(vntArchenemy);
|
||||||
comboArchenemy.addTo(variantsPanel);
|
variantsPanel.add(vntArchenemyRumble);
|
||||||
|
|
||||||
constructedFrame.add(new FScrollPane(variantsPanel, false, true,
|
constructedFrame.add(new FScrollPane(variantsPanel, false, true,
|
||||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
||||||
@@ -459,6 +450,8 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
container.validate();
|
container.validate();
|
||||||
container.repaint();
|
container.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changePlayerFocus(playerWithFocus, currentGameMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return {@link javax.swing.JButton} */
|
/** @return {@link javax.swing.JButton} */
|
||||||
@@ -682,29 +675,62 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public void updateVariantControlsVisibility() {
|
public void updateVariantControlsVisibility() {
|
||||||
// Commander deck replaces basic deck, so hide that
|
boolean isCommanderApplied = false;
|
||||||
deckLabel.setVisible(!appliedVariants.contains(GameType.Commander));
|
boolean isPlanechaseApplied = false;
|
||||||
deckBtn.setVisible(!appliedVariants.contains(GameType.Commander));
|
boolean isVanguardApplied = false;
|
||||||
cmdDeckSelectorBtn.setVisible(appliedVariants.contains(GameType.Commander));
|
boolean isArchenemyApplied = false;
|
||||||
cmdDeckEditor.setVisible(appliedVariants.contains(GameType.Commander));
|
boolean archenemyVisiblity = false;
|
||||||
cmdLabel.setVisible(appliedVariants.contains(GameType.Commander));
|
boolean isDeckBuildingAllowed = true;
|
||||||
|
|
||||||
|
for (GameType variant : appliedVariants) {
|
||||||
|
switch (variant) {
|
||||||
|
case Archenemy:
|
||||||
|
isArchenemyApplied = true;
|
||||||
|
if (playerIsArchenemy) {
|
||||||
|
archenemyVisiblity = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ArchenemyRumble:
|
||||||
|
archenemyVisiblity = true;
|
||||||
|
break;
|
||||||
|
case Commander:
|
||||||
|
isCommanderApplied = true;
|
||||||
|
isDeckBuildingAllowed = false; //Commander deck replaces basic deck, so hide that
|
||||||
|
break;
|
||||||
|
case Planechase:
|
||||||
|
isPlanechaseApplied = true;
|
||||||
|
break;
|
||||||
|
case Vanguard:
|
||||||
|
isVanguardApplied = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (variant.isAutoGenerated()) {
|
||||||
|
isDeckBuildingAllowed = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deckLabel.setVisible(isDeckBuildingAllowed);
|
||||||
|
deckBtn.setVisible(isDeckBuildingAllowed);
|
||||||
|
cmdDeckSelectorBtn.setVisible(isCommanderApplied);
|
||||||
|
cmdDeckEditor.setVisible(isCommanderApplied);
|
||||||
|
cmdLabel.setVisible(isCommanderApplied);
|
||||||
|
|
||||||
boolean archenemyVisiblity = appliedVariants.contains(GameType.ArchenemyRumble)
|
|
||||||
|| (appliedVariants.contains(GameType.Archenemy) && playerIsArchenemy);
|
|
||||||
scmDeckSelectorBtn.setVisible(archenemyVisiblity);
|
scmDeckSelectorBtn.setVisible(archenemyVisiblity);
|
||||||
scmDeckEditor.setVisible(archenemyVisiblity);
|
scmDeckEditor.setVisible(archenemyVisiblity);
|
||||||
scmLabel.setVisible(archenemyVisiblity);
|
scmLabel.setVisible(archenemyVisiblity);
|
||||||
|
|
||||||
teamComboBox.setVisible(!appliedVariants.contains(GameType.Archenemy));
|
teamComboBox.setVisible(!isArchenemyApplied);
|
||||||
aeTeamComboBox.setVisible(appliedVariants.contains(GameType.Archenemy));
|
aeTeamComboBox.setVisible(isArchenemyApplied);
|
||||||
aeTeamComboBox.setEnabled(!(appliedVariants.contains(GameType.Archenemy) && playerIsArchenemy));
|
aeTeamComboBox.setEnabled(!(isArchenemyApplied && playerIsArchenemy));
|
||||||
|
|
||||||
pchDeckSelectorBtn.setVisible(appliedVariants.contains(GameType.Planechase));
|
pchDeckSelectorBtn.setVisible(isPlanechaseApplied);
|
||||||
pchDeckEditor.setVisible(appliedVariants.contains(GameType.Planechase));
|
pchDeckEditor.setVisible(isPlanechaseApplied);
|
||||||
pchLabel.setVisible(appliedVariants.contains(GameType.Planechase));
|
pchLabel.setVisible(isPlanechaseApplied);
|
||||||
|
|
||||||
vgdSelectorBtn.setVisible(appliedVariants.contains(GameType.Vanguard));
|
vgdSelectorBtn.setVisible(isVanguardApplied);
|
||||||
vgdLabel.setVisible(appliedVariants.contains(GameType.Vanguard));
|
vgdLabel.setVisible(isVanguardApplied);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -779,7 +805,8 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
public void toggleIsPlayerArchenemy() {
|
public void toggleIsPlayerArchenemy() {
|
||||||
if (appliedVariants.contains(GameType.Archenemy)) {
|
if (appliedVariants.contains(GameType.Archenemy)) {
|
||||||
playerIsArchenemy = lastArchenemy == index;
|
playerIsArchenemy = lastArchenemy == index;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
playerIsArchenemy = appliedVariants.contains(GameType.ArchenemyRumble);
|
playerIsArchenemy = appliedVariants.contains(GameType.ArchenemyRumble);
|
||||||
}
|
}
|
||||||
updateVariantControlsVisibility();
|
updateVariantControlsVisibility();
|
||||||
@@ -793,7 +820,7 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
scmDeckSelectorBtn.setCommand(new Runnable() {
|
scmDeckSelectorBtn.setCommand(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
currentGameMode = archenemyType.contains("Classic") ? GameType.Archenemy : GameType.ArchenemyRumble;
|
currentGameMode = vntArchenemy.isSelected() ? GameType.Archenemy : GameType.ArchenemyRumble;
|
||||||
scmDeckSelectorBtn.requestFocusInWindow();
|
scmDeckSelectorBtn.requestFocusInWindow();
|
||||||
changePlayerFocus(index, currentGameMode);
|
changePlayerFocus(index, currentGameMode);
|
||||||
}
|
}
|
||||||
@@ -802,7 +829,7 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
scmDeckEditor.setCommand(new UiCommand() {
|
scmDeckEditor.setCommand(new UiCommand() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
currentGameMode = archenemyType.contains("Classic") ? GameType.Archenemy : GameType.ArchenemyRumble;
|
currentGameMode = vntArchenemy.isSelected() ? GameType.Archenemy : GameType.ArchenemyRumble;
|
||||||
Predicate<PaperCard> predSchemes = new Predicate<PaperCard>() {
|
Predicate<PaperCard> predSchemes = new Predicate<PaperCard>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(PaperCard arg0) {
|
public boolean apply(PaperCard arg0) {
|
||||||
@@ -1139,36 +1166,45 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
//========== Various listeners in build order
|
//========== Various listeners in build order
|
||||||
|
|
||||||
/** This listener unlocks the relevant buttons for players
|
@SuppressWarnings("serial")
|
||||||
* and enables/disables archenemy combobox as appropriate. */
|
private class VariantCheckBox extends FCheckBox {
|
||||||
private ItemListener iListenerVariants = new ItemListener() {
|
private final GameType variantType;
|
||||||
|
|
||||||
|
private VariantCheckBox(GameType variantType0) {
|
||||||
|
super(variantType0.toString());
|
||||||
|
|
||||||
|
variantType = variantType0;
|
||||||
|
|
||||||
|
setToolTipText(variantType.getDescription());
|
||||||
|
|
||||||
|
addItemListener(new ItemListener() {
|
||||||
@Override
|
@Override
|
||||||
public void itemStateChanged(ItemEvent arg0) {
|
public void itemStateChanged(ItemEvent e) {
|
||||||
FCheckBox cb = (FCheckBox) arg0.getSource();
|
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||||
GameType variantType = null;
|
|
||||||
|
|
||||||
if (cb == vntVanguard) {
|
|
||||||
variantType = GameType.Vanguard;
|
|
||||||
}
|
|
||||||
else if (cb == vntCommander) {
|
|
||||||
variantType = GameType.Commander;
|
|
||||||
}
|
|
||||||
else if (cb == vntPlanechase) {
|
|
||||||
variantType = GameType.Planechase;
|
|
||||||
}
|
|
||||||
else if (cb == vntArchenemy) {
|
|
||||||
variantType = archenemyType.contains("Classic") ? GameType.Archenemy : GameType.ArchenemyRumble;
|
|
||||||
comboArchenemy.setEnabled(vntArchenemy.isSelected());
|
|
||||||
if (arg0.getStateChange() != ItemEvent.SELECTED) {
|
|
||||||
appliedVariants.remove(GameType.Archenemy);
|
|
||||||
appliedVariants.remove(GameType.ArchenemyRumble);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != variantType) {
|
|
||||||
if (arg0.getStateChange() == ItemEvent.SELECTED) {
|
|
||||||
appliedVariants.add(variantType);
|
appliedVariants.add(variantType);
|
||||||
currentGameMode = variantType;
|
currentGameMode = variantType;
|
||||||
|
|
||||||
|
//ensure other necessary variants are unchecked
|
||||||
|
switch (variantType) {
|
||||||
|
case Archenemy:
|
||||||
|
vntArchenemyRumble.setSelected(false);
|
||||||
|
break;
|
||||||
|
case ArchenemyRumble:
|
||||||
|
vntArchenemy.setSelected(false);
|
||||||
|
break;
|
||||||
|
case Commander:
|
||||||
|
vntMomirBasic.setSelected(false);
|
||||||
|
break;
|
||||||
|
case Vanguard:
|
||||||
|
vntMomirBasic.setSelected(false);
|
||||||
|
break;
|
||||||
|
case MomirBasic:
|
||||||
|
vntCommander.setSelected(false);
|
||||||
|
vntVanguard.setSelected(false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
appliedVariants.remove(variantType);
|
appliedVariants.remove(variantType);
|
||||||
@@ -1176,36 +1212,15 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
currentGameMode = GameType.Constructed;
|
currentGameMode = GameType.Constructed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (PlayerPanel pp : playerPanels) {
|
for (PlayerPanel pp : playerPanels) {
|
||||||
pp.toggleIsPlayerArchenemy();
|
pp.toggleIsPlayerArchenemy();
|
||||||
pp.updateVariantControlsVisibility();
|
|
||||||
}
|
}
|
||||||
changePlayerFocus(playerWithFocus, currentGameMode);
|
changePlayerFocus(playerWithFocus, currentGameMode);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
// Listens to the archenemy combo box
|
|
||||||
private ActionListener aeComboListener = new ActionListener() {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
FComboBox<String> cb = (FComboBox<String>)e.getSource();
|
|
||||||
archenemyType = (String)cb.getSelectedItem();
|
|
||||||
GameType mode = archenemyType.contains("Classic") ? GameType.Archenemy : GameType.ArchenemyRumble;
|
|
||||||
appliedVariants.remove(GameType.Archenemy);
|
|
||||||
appliedVariants.remove(GameType.ArchenemyRumble);
|
|
||||||
appliedVariants.add(mode);
|
|
||||||
|
|
||||||
currentGameMode = mode;
|
|
||||||
for (PlayerPanel pp : playerPanels) {
|
|
||||||
pp.toggleIsPlayerArchenemy();
|
|
||||||
pp.updateVariantControlsVisibility();
|
|
||||||
}
|
}
|
||||||
changePlayerFocus(playerWithFocus, currentGameMode);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
private ActionListener nameListener = new ActionListener() {
|
private ActionListener nameListener = new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -14,6 +14,15 @@ The details previously available by hovering over that rectangle will now appear
|
|||||||
The dialog for the commander replacement effect will now display the commander's name.
|
The dialog for the commander replacement effect will now display the commander's name.
|
||||||
|
|
||||||
|
|
||||||
|
- Momir Basic variant type -
|
||||||
|
Momir Basic is now available as its own variant option on the Constructed screen
|
||||||
|
For this format. each player will automatically be given a deck with 12 of each basic land and the Momir Vig avatar
|
||||||
|
|
||||||
|
|
||||||
|
- Choose value for X mana costs -
|
||||||
|
Now, when playing spells/abilities with X in its mana cost, you will now be prompted for a value for X prior to mana payment, ensuring the final mana cost is calculated properly from cost adjustment effects and allowing using the "Auto" button to pay the entire cost.
|
||||||
|
This also applies to spells with Replicate and Multikicker to allow picking the Replicate or Multikicker amount prior to paying the final mana cost.
|
||||||
|
|
||||||
- Auto-targeting support -
|
- Auto-targeting support -
|
||||||
When playing spells and abilities with the text "target opponent", if you only have one opponent, you will no longer be asked to choose the opponent to target.
|
When playing spells and abilities with the text "target opponent", if you only have one opponent, you will no longer be asked to choose the opponent to target.
|
||||||
When triggered abilities have only one valid target, that target will now be auto-selected.
|
When triggered abilities have only one valid target, that target will now be auto-selected.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Land
|
|||||||
K:CARDNAME enters the battlefield tapped.
|
K:CARDNAME enters the battlefield tapped.
|
||||||
A:AB$ Mana | Cost$ T | Produced$ W U | SpellDescription$ Add {W}{U} to your mana pool.
|
A:AB$ Mana | Cost$ T | Produced$ W U | SpellDescription$ Add {W}{U} to your mana pool.
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
||||||
SVar:TrigReturn:DB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl
|
SVar:TrigReturn:DB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl | AILogic$ NeverBounceItself
|
||||||
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/azorius_chancery.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/azorius_chancery.jpg
|
||||||
Oracle:Azorius Chancery enters the battlefield tapped.\nWhen Azorius Chancery enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {W}{U} to your mana pool.
|
Oracle:Azorius Chancery enters the battlefield tapped.\nWhen Azorius Chancery enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {W}{U} to your mana pool.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Land
|
|||||||
K:CARDNAME enters the battlefield tapped.
|
K:CARDNAME enters the battlefield tapped.
|
||||||
A:AB$ Mana | Cost$ T | Produced$ R W | SpellDescription$ Add {R}{W} to your mana pool.
|
A:AB$ Mana | Cost$ T | Produced$ R W | SpellDescription$ Add {R}{W} to your mana pool.
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
||||||
SVar:TrigReturn:DB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl
|
SVar:TrigReturn:DB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl | AILogic$ NeverBounceItself
|
||||||
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/boros_garrison.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/boros_garrison.jpg
|
||||||
Oracle:Boros Garrison enters the battlefield tapped.\nWhen Boros Garrison enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {R}{W} to your mana pool.
|
Oracle:Boros Garrison enters the battlefield tapped.\nWhen Boros Garrison enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {R}{W} to your mana pool.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Land
|
|||||||
K:CARDNAME enters the battlefield tapped.
|
K:CARDNAME enters the battlefield tapped.
|
||||||
A:AB$ Mana | Cost$ T | Produced$ U B | SpellDescription$ Add {U}{B} to your mana pool.
|
A:AB$ Mana | Cost$ T | Produced$ U B | SpellDescription$ Add {U}{B} to your mana pool.
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
||||||
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl
|
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl | AILogic$ NeverBounceItself
|
||||||
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/dimir_aqueduct.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/dimir_aqueduct.jpg
|
||||||
Oracle:Dimir Aqueduct enters the battlefield tapped.\nWhen Dimir Aqueduct enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {U}{B} to your mana pool.
|
Oracle:Dimir Aqueduct enters the battlefield tapped.\nWhen Dimir Aqueduct enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {U}{B} to your mana pool.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Land
|
|||||||
K:CARDNAME enters the battlefield tapped.
|
K:CARDNAME enters the battlefield tapped.
|
||||||
A:AB$ Mana | Cost$ T | Produced$ B G | SpellDescription$ Add {B}{G} to your mana pool.
|
A:AB$ Mana | Cost$ T | Produced$ B G | SpellDescription$ Add {B}{G} to your mana pool.
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
||||||
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl
|
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl | AILogic$ NeverBounceItself
|
||||||
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/golgari_rot_farm.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/golgari_rot_farm.jpg
|
||||||
Oracle:Golgari Rot Farm enters the battlefield tapped.\nWhen Golgari Rot Farm enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {B}{G} to your mana pool.
|
Oracle:Golgari Rot Farm enters the battlefield tapped.\nWhen Golgari Rot Farm enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {B}{G} to your mana pool.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Land
|
|||||||
K:CARDNAME enters the battlefield tapped.
|
K:CARDNAME enters the battlefield tapped.
|
||||||
A:AB$ Mana | Cost$ T | Produced$ R G | SpellDescription$ Add {R}{G} to your mana pool.
|
A:AB$ Mana | Cost$ T | Produced$ R G | SpellDescription$ Add {R}{G} to your mana pool.
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
||||||
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl
|
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl | AILogic$ NeverBounceItself
|
||||||
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/gruul_turf.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/gruul_turf.jpg
|
||||||
Oracle:Gruul Turf enters the battlefield tapped.\nWhen Gruul Turf enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {R}{G} to your mana pool.
|
Oracle:Gruul Turf enters the battlefield tapped.\nWhen Gruul Turf enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {R}{G} to your mana pool.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Land
|
|||||||
K:CARDNAME enters the battlefield tapped.
|
K:CARDNAME enters the battlefield tapped.
|
||||||
A:AB$ Mana | Cost$ T | Produced$ U R | SpellDescription$ Add {U}{R} to your mana pool.
|
A:AB$ Mana | Cost$ T | Produced$ U R | SpellDescription$ Add {U}{R} to your mana pool.
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
||||||
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl
|
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl | AILogic$ NeverBounceItself
|
||||||
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/izzet_boilerworks.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/izzet_boilerworks.jpg
|
||||||
Oracle:Izzet Boilerworks enters the battlefield tapped.\nWhen Izzet Boilerworks enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {U}{R} to your mana pool.
|
Oracle:Izzet Boilerworks enters the battlefield tapped.\nWhen Izzet Boilerworks enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {U}{R} to your mana pool.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ManaCost:no cost
|
|||||||
Types:Land
|
Types:Land
|
||||||
K:CARDNAME enters the battlefield tapped.
|
K:CARDNAME enters the battlefield tapped.
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
||||||
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl
|
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl | AILogic$ NeverBounceItself
|
||||||
A:AB$ Mana | Cost$ T | Produced$ W B | SpellDescription$ Add {W}{B} to your mana pool.
|
A:AB$ Mana | Cost$ T | Produced$ W B | SpellDescription$ Add {W}{B} to your mana pool.
|
||||||
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/orzhov_basilica.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/orzhov_basilica.jpg
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Land
|
|||||||
K:CARDNAME enters the battlefield tapped.
|
K:CARDNAME enters the battlefield tapped.
|
||||||
A:AB$ Mana | Cost$ T | Produced$ B R | SpellDescription$ Add {B}{R} to your mana pool.
|
A:AB$ Mana | Cost$ T | Produced$ B R | SpellDescription$ Add {B}{R} to your mana pool.
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
||||||
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl
|
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl | AILogic$ NeverBounceItself
|
||||||
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/rakdos_carnarium.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/rakdos_carnarium.jpg
|
||||||
Oracle:Rakdos Carnarium enters the battlefield tapped.\nWhen Rakdos Carnarium enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {B}{R} to your mana pool.
|
Oracle:Rakdos Carnarium enters the battlefield tapped.\nWhen Rakdos Carnarium enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {B}{R} to your mana pool.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Land
|
|||||||
K:CARDNAME enters the battlefield tapped.
|
K:CARDNAME enters the battlefield tapped.
|
||||||
A:AB$ Mana | Cost$ T | Produced$ G W | SpellDescription$ Add {G}{W} to your mana pool.
|
A:AB$ Mana | Cost$ T | Produced$ G W | SpellDescription$ Add {G}{W} to your mana pool.
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
||||||
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl
|
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl | AILogic$ NeverBounceItself
|
||||||
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/selesnya_sanctuary.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/selesnya_sanctuary.jpg
|
||||||
Oracle:Selesnya Sanctuary enters the battlefield tapped.\nWhen Selesnya Sanctuary enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {G}{W} to your mana pool.
|
Oracle:Selesnya Sanctuary enters the battlefield tapped.\nWhen Selesnya Sanctuary enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {G}{W} to your mana pool.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Land
|
|||||||
K:CARDNAME enters the battlefield tapped.
|
K:CARDNAME enters the battlefield tapped.
|
||||||
A:AB$ Mana | Cost$ T | Produced$ G U | SpellDescription$ Add {G}{U} to your mana pool.
|
A:AB$ Mana | Cost$ T | Produced$ G U | SpellDescription$ Add {G}{U} to your mana pool.
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME enters the battlefield, return a land you control to its owner's hand.
|
||||||
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl
|
SVar:TrigReturn:AB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Cost$ 0 | Hidden$ True | Mandatory$ True | ChangeType$ Land.YouCtrl | AILogic$ NeverBounceItself
|
||||||
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
SVar:NeedsToPlay:Land.Basic+YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/simic_growth_chamber.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/simic_growth_chamber.jpg
|
||||||
Oracle:Simic Growth Chamber enters the battlefield tapped.\nWhen Simic Growth Chamber enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {G}{U} to your mana pool.
|
Oracle:Simic Growth Chamber enters the battlefield tapped.\nWhen Simic Growth Chamber enters the battlefield, return a land you control to its owner's hand.\n{T}: Add {G}{U} to your mana pool.
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
|||||||
private final Object zoneToRestore;
|
private final Object zoneToRestore;
|
||||||
|
|
||||||
private boolean bPaid = false;
|
private boolean bPaid = false;
|
||||||
private Boolean canPayManaCost = null;
|
protected Boolean canPayManaCost = null;
|
||||||
|
|
||||||
private boolean locked = false;
|
private boolean locked = false;
|
||||||
|
|
||||||
@@ -343,7 +343,7 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runAsAi(Runnable proc) {
|
protected void runAsAi(Runnable proc) {
|
||||||
player.runWithController(proc, new PlayerControllerAi(game, player, player.getOriginalLobbyPlayer()));
|
player.runWithController(proc, new PlayerControllerAi(game, player, player.getOriginalLobbyPlayer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ import com.google.common.base.Predicate;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
import forge.FThreads;
|
import forge.FThreads;
|
||||||
import forge.card.MagicColor;
|
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.card.mana.ManaCostShard;
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameActionUtil;
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.GameLogEntryType;
|
import forge.game.GameLogEntryType;
|
||||||
@@ -27,7 +25,6 @@ import forge.game.zone.ZoneType;
|
|||||||
import forge.match.input.InputPayMana;
|
import forge.match.input.InputPayMana;
|
||||||
import forge.match.input.InputPayManaOfCostPayment;
|
import forge.match.input.InputPayManaOfCostPayment;
|
||||||
import forge.match.input.InputPayManaSimple;
|
import forge.match.input.InputPayManaSimple;
|
||||||
import forge.match.input.InputPayManaX;
|
|
||||||
import forge.match.input.InputSelectCardsFromList;
|
import forge.match.input.InputSelectCardsFromList;
|
||||||
import forge.util.Lang;
|
import forge.util.Lang;
|
||||||
import forge.util.gui.SGuiChoose;
|
import forge.util.gui.SGuiChoose;
|
||||||
@@ -635,8 +632,9 @@ public class HumanPlay {
|
|||||||
prompt = source + "\n" + promptCurrent;
|
prompt = source + "\n" + promptCurrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( sourceAbility != null )
|
if (sourceAbility != null) {
|
||||||
sourceAbility.clearManaPaid();
|
sourceAbility.clearManaPaid();
|
||||||
|
}
|
||||||
boolean paid = p.getController().payManaCost(cost.getCostMana(), sourceAbility, prompt, false);
|
boolean paid = p.getController().payManaCost(cost.getCostMana(), sourceAbility, prompt, false);
|
||||||
if (!paid) {
|
if (!paid) {
|
||||||
p.getManaPool().refundManaPaid(sourceAbility);
|
p.getManaPool().refundManaPaid(sourceAbility);
|
||||||
@@ -692,24 +690,32 @@ public class HumanPlay {
|
|||||||
final Card source = ability.getHostCard();
|
final Card source = ability.getHostCard();
|
||||||
ManaCostBeingPaid toPay = new ManaCostBeingPaid(realCost, mc.getRestiction());
|
ManaCostBeingPaid toPay = new ManaCostBeingPaid(realCost, mc.getRestiction());
|
||||||
|
|
||||||
boolean xWasBilled = false;
|
|
||||||
String xInCard = source.getSVar("X");
|
String xInCard = source.getSVar("X");
|
||||||
if (mc.getAmountOfX() > 0 && !"Count$xPaid".equals(xInCard)) { // announce X will overwrite whatever was in card script
|
if (mc.getAmountOfX() > 0 && !"Count$xPaid".equals(xInCard)) { // announce X will overwrite whatever was in card script
|
||||||
// this currently only works for things about Targeted object
|
int xPaid = AbilityUtils.calculateAmount(source, "X", ability);
|
||||||
int xCost = AbilityUtils.calculateAmount(source, "X", ability) * mc.getAmountOfX();
|
toPay.setXManaCostPaid(xPaid, ability.getParam("XColor"));
|
||||||
byte xColor = MagicColor.fromName(ability.hasParam("XColor") ? ability.getParam("XColor") : "1");
|
source.setXManaCostPaid(xPaid);
|
||||||
toPay.increaseShard(ManaCostShard.valueOf(xColor), xCost);
|
|
||||||
xWasBilled = true;
|
|
||||||
}
|
|
||||||
int timesMultikicked = ability.getHostCard().getKickerMagnitude();
|
|
||||||
if ( timesMultikicked > 0 && ability.isAnnouncing("Multikicker")) {
|
|
||||||
ManaCost mkCost = ability.getMultiKickerManaCost();
|
|
||||||
for(int i = 0; i < timesMultikicked; i++)
|
|
||||||
toPay.addManaCost(mkCost);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( isActivatedSa )
|
int timesMultikicked = source.getKickerMagnitude();
|
||||||
|
if (timesMultikicked > 0 && ability.isAnnouncing("Multikicker")) {
|
||||||
|
ManaCost mkCost = ability.getMultiKickerManaCost();
|
||||||
|
for (int i = 0; i < timesMultikicked; i++) {
|
||||||
|
toPay.addManaCost(mkCost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer replicate = ability.getSVarInt("Replicate");
|
||||||
|
if (replicate != null) {
|
||||||
|
ManaCost rCost = source.getManaCost();
|
||||||
|
for (int i = 0; i < replicate; i++) {
|
||||||
|
toPay.addManaCost(rCost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isActivatedSa) {
|
||||||
ManaCostAdjustment.adjust(toPay, ability, false);
|
ManaCostAdjustment.adjust(toPay, ability, false);
|
||||||
|
}
|
||||||
|
|
||||||
InputPayMana inpPayment;
|
InputPayMana inpPayment;
|
||||||
if (ability.isOffering() && ability.getSacrificedAsOffering() == null) {
|
if (ability.isOffering() && ability.getSacrificedAsOffering() == null) {
|
||||||
@@ -727,19 +733,6 @@ public class HumanPlay {
|
|||||||
source.setColorsPaid(toPay.getColorsPaid());
|
source.setColorsPaid(toPay.getColorsPaid());
|
||||||
source.setSunburstValue(toPay.getSunburst());
|
source.setSunburstValue(toPay.getSunburst());
|
||||||
}
|
}
|
||||||
if (mc.getAmountOfX() > 0) {
|
|
||||||
if (!ability.isAnnouncing("X") && !xWasBilled) {
|
|
||||||
source.setXManaCostPaid(0);
|
|
||||||
inpPayment = new InputPayManaX(controller, ability, mc.getAmountOfX(), mc.canXbe0());
|
|
||||||
inpPayment.showAndWait();
|
|
||||||
if (!inpPayment.isPaid()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int x = AbilityUtils.calculateAmount(source, "X", ability);
|
|
||||||
source.setXManaCostPaid(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle convoke and offerings
|
// Handle convoke and offerings
|
||||||
if (ability.isOffering() && ability.getSacrificedAsOffering() != null) {
|
if (ability.isOffering() && ability.getSacrificedAsOffering() != null) {
|
||||||
|
|||||||
@@ -196,6 +196,14 @@ public class HumanPlaySpellAbility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean announceValuesLikeX() {
|
private boolean announceValuesLikeX() {
|
||||||
|
if (ability.isCopied()) { return true; } //don't re-announce for spell copies
|
||||||
|
|
||||||
|
boolean needX = true;
|
||||||
|
boolean allowZero = !ability.hasParam("XCantBe0");
|
||||||
|
CostPartMana manaCost = ability.getPayCosts().getCostMana();
|
||||||
|
PlayerController controller = ability.getActivatingPlayer().getController();
|
||||||
|
Card card = ability.getHostCard();
|
||||||
|
|
||||||
// Announcing Requirements like Choosing X or Multikicker
|
// Announcing Requirements like Choosing X or Multikicker
|
||||||
// SA Params as comma delimited list
|
// SA Params as comma delimited list
|
||||||
String announce = ability.getParam("Announce");
|
String announce = ability.getParam("Announce");
|
||||||
@@ -204,28 +212,39 @@ public class HumanPlaySpellAbility {
|
|||||||
String varName = aVar.trim();
|
String varName = aVar.trim();
|
||||||
|
|
||||||
boolean isX = "X".equalsIgnoreCase(varName);
|
boolean isX = "X".equalsIgnoreCase(varName);
|
||||||
CostPartMana manaCost = ability.getPayCosts().getCostMana();
|
if (isX) { needX = false; }
|
||||||
boolean allowZero = !ability.hasParam("XCantBe0") && (!isX || manaCost == null || manaCost.canXbe0());
|
|
||||||
|
|
||||||
Integer value = ability.getActivatingPlayer().getController().announceRequirements(ability, varName, allowZero);
|
Integer value = controller.announceRequirements(ability, varName, allowZero && (!isX || manaCost == null || manaCost.canXbe0()));
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ability.setSVar(varName, value.toString());
|
ability.setSVar(varName, value.toString());
|
||||||
if ("Multikicker".equals(varName)) {
|
if ("Multikicker".equals(varName)) {
|
||||||
ability.getHostCard().setKickerMagnitude(value);
|
card.setKickerMagnitude(value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ability.getHostCard().setSVar(varName, value.toString());
|
card.setSVar(varName, value.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needX && manaCost != null && manaCost.getAmountOfX() > 0) {
|
||||||
|
Integer value = controller.announceRequirements(ability, "X", allowZero && manaCost.canXbe0());
|
||||||
|
if (value == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ability.setSVar("X", value.toString());
|
||||||
|
card.setSVar("X", value.toString());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean announceType() {
|
|
||||||
// Announcing Requirements like choosing creature type or number
|
// Announcing Requirements like choosing creature type or number
|
||||||
|
private boolean announceType() {
|
||||||
|
if (ability.isCopied()) { return true; } //don't re-announce for spell copies
|
||||||
|
|
||||||
String announce = ability.getParam("AnnounceType");
|
String announce = ability.getParam("AnnounceType");
|
||||||
PlayerController pc = ability.getActivatingPlayer().getController();
|
PlayerController pc = ability.getActivatingPlayer().getController();
|
||||||
if (announce != null) {
|
if (announce != null) {
|
||||||
|
|||||||
@@ -665,11 +665,12 @@ public final class QuestUtilCards {
|
|||||||
final int startPacks = this.qpref.getPrefInt(QPref.SHOP_STARTING_PACKS);
|
final int startPacks = this.qpref.getPrefInt(QPref.SHOP_STARTING_PACKS);
|
||||||
final int winsForPack = this.qpref.getPrefInt(QPref.SHOP_WINS_FOR_ADDITIONAL_PACK);
|
final int winsForPack = this.qpref.getPrefInt(QPref.SHOP_WINS_FOR_ADDITIONAL_PACK);
|
||||||
final int maxPacks = this.qpref.getPrefInt(QPref.SHOP_MAX_PACKS);
|
final int maxPacks = this.qpref.getPrefInt(QPref.SHOP_MAX_PACKS);
|
||||||
|
final int minPacks = this.qpref.getPrefInt(QPref.SHOP_MIN_PACKS);
|
||||||
|
|
||||||
int level = this.qc.getAchievements().getLevel();
|
int level = this.qc.getAchievements().getLevel();
|
||||||
final int levelPacks = level > 0 ? startPacks / level : startPacks;
|
final int levelPacks = level > 0 ? startPacks / level : startPacks;
|
||||||
final int winPacks = this.qc.getAchievements().getWin() / winsForPack;
|
final int winPacks = this.qc.getAchievements().getWin() / winsForPack;
|
||||||
final int totalPacks = Math.min(levelPacks + winPacks, maxPacks);
|
final int totalPacks = Math.min(Math.max(levelPacks + winPacks, minPacks), maxPacks);
|
||||||
|
|
||||||
|
|
||||||
SealedProduct.Template tpl = getShopBoosterTemplate();
|
SealedProduct.Template tpl = getShopBoosterTemplate();
|
||||||
|
|||||||
@@ -135,7 +135,8 @@ public class QuestPreferences extends PreferencesStore<QuestPreferences.QPref> i
|
|||||||
WINS_UNLOCK_SET("20"),
|
WINS_UNLOCK_SET("20"),
|
||||||
|
|
||||||
// Maximum amount of "Packs" opened by the Shop and available as singles
|
// Maximum amount of "Packs" opened by the Shop and available as singles
|
||||||
SHOP_MAX_PACKS("6"),
|
SHOP_MAX_PACKS("7"),
|
||||||
|
SHOP_MIN_PACKS("3"),
|
||||||
|
|
||||||
// Rarity distribution of Singles in an Opened Shop Pack
|
// Rarity distribution of Singles in an Opened Shop Pack
|
||||||
SHOP_SINGLES_COMMON("7"),
|
SHOP_SINGLES_COMMON("7"),
|
||||||
@@ -145,7 +146,7 @@ public class QuestPreferences extends PreferencesStore<QuestPreferences.QPref> i
|
|||||||
// How many wins it takes to open an additional pack in the shop
|
// How many wins it takes to open an additional pack in the shop
|
||||||
SHOP_WINS_FOR_ADDITIONAL_PACK("10"),
|
SHOP_WINS_FOR_ADDITIONAL_PACK("10"),
|
||||||
// How many packs the shop start with.
|
// How many packs the shop start with.
|
||||||
SHOP_STARTING_PACKS("4");
|
SHOP_STARTING_PACKS("5");
|
||||||
|
|
||||||
private final String strDefaultVal;
|
private final String strDefaultVal;
|
||||||
|
|
||||||
@@ -313,7 +314,7 @@ public class QuestPreferences extends PreferencesStore<QuestPreferences.QPref> i
|
|||||||
return "Value too large (maximum 15).";
|
return "Value too large (maximum 15).";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SHOP_WINS_FOR_ADDITIONAL_PACK: case SHOP_MAX_PACKS:
|
case SHOP_WINS_FOR_ADDITIONAL_PACK: case SHOP_MAX_PACKS: case SHOP_MIN_PACKS:
|
||||||
if (val < 1) {
|
if (val < 1) {
|
||||||
return "Value too small (minimum 1).";
|
return "Value too small (minimum 1).";
|
||||||
} else if (val > 25) {
|
} else if (val > 25) {
|
||||||
|
|||||||
@@ -99,12 +99,15 @@ public class SGuiChoose {
|
|||||||
|
|
||||||
// Get Integer in range
|
// Get Integer in range
|
||||||
public static Integer getInteger(final IGuiBase gui, final String message) {
|
public static Integer getInteger(final IGuiBase gui, final String message) {
|
||||||
return getInteger(gui, message, 0, Integer.MAX_VALUE);
|
return getInteger(gui, message, 0, Integer.MAX_VALUE, false);
|
||||||
}
|
}
|
||||||
public static Integer getInteger(final IGuiBase gui, final String message, int min) {
|
public static Integer getInteger(final IGuiBase gui, final String message, int min) {
|
||||||
return getInteger(gui, message, min, Integer.MAX_VALUE);
|
return getInteger(gui, message, min, Integer.MAX_VALUE, false);
|
||||||
}
|
}
|
||||||
public static Integer getInteger(final IGuiBase gui, final String message, int min, int max) {
|
public static Integer getInteger(final IGuiBase gui, final String message, int min, int max) {
|
||||||
|
return getInteger(gui, message, min, max, false);
|
||||||
|
}
|
||||||
|
public static Integer getInteger(final IGuiBase gui, final String message, int min, int max, boolean sortDesc) {
|
||||||
if (max <= min) { return min; } //just return min if max <= min
|
if (max <= min) { return min; } //just return min if max <= min
|
||||||
|
|
||||||
//force cutting off after 100 numbers at most
|
//force cutting off after 100 numbers at most
|
||||||
@@ -117,9 +120,16 @@ public class SGuiChoose {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Integer[] choices = new Integer[count];
|
final Integer[] choices = new Integer[count];
|
||||||
|
if (sortDesc) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
choices[count - i - 1] = Integer.valueOf(i + min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
choices[i] = Integer.valueOf(i + min);
|
choices[i] = Integer.valueOf(i + min);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return SGuiChoose.oneOrNone(gui, message, choices);
|
return SGuiChoose.oneOrNone(gui, message, choices);
|
||||||
}
|
}
|
||||||
public static Integer getInteger(final IGuiBase gui, final String message, int min, int max, int cutoff) {
|
public static Integer getInteger(final IGuiBase gui, final String message, int min, int max, int cutoff) {
|
||||||
|
|||||||
Reference in New Issue
Block a user