diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java index 877a75af6a9..d05d10c0111 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java @@ -341,7 +341,7 @@ public class ComputerUtilMana { continue; } - if (canPayShardWithSpellAbility(toPay, ai, paymentChoice, sa, checkCosts)) { + if (canPayShardWithSpellAbility(toPay, ai, paymentChoice, sa, checkCosts, cost.getXManaCostPaidByColor())) { return paymentChoice; } } @@ -547,7 +547,7 @@ public class ComputerUtilMana { } // get a mana of this type from floating, bail if none available - final Mana mana = getMana(ai, part, sa, cost.getSourceRestriction(), (byte) -1); + final Mana mana = getMana(ai, part, sa, cost.getSourceRestriction(), (byte) -1, cost.getXManaCostPaidByColor()); if (mana != null) { if (ai.getManaPool().tryPayCostWithMana(sa, cost, mana, false)) { manaSpentToPay.add(0, mana); @@ -936,7 +936,7 @@ public class ComputerUtilMana { } // get a mana of this type from floating, bail if none available - final Mana mana = getMana(ai, part, sa, cost.getSourceRestriction(), hasConverge ? cost.getColorsPaid() : -1); + final Mana mana = getMana(ai, part, sa, cost.getSourceRestriction(), hasConverge ? cost.getColorsPaid() : -1, cost.getXManaCostPaidByColor()); if (mana != null) { if (ai.getManaPool().tryPayCostWithMana(sa, cost, mana, test)) { manaSpentToPay.add(0, mana); @@ -965,8 +965,10 @@ public class ComputerUtilMana { * a {@link forge.game.spellability.SpellAbility} object. * @return a {@link forge.game.mana.Mana} object. */ - private static Mana getMana(final Player ai, final ManaCostShard shard, final SpellAbility saBeingPaidFor, String restriction, final byte colorsPaid) { - final List> weightedOptions = selectManaToPayFor(ai.getManaPool(), shard, saBeingPaidFor, restriction, colorsPaid); + private static Mana getMana(final Player ai, final ManaCostShard shard, final SpellAbility saBeingPaidFor, + String restriction, final byte colorsPaid, Map xManaCostPaidByColor) { + final List> weightedOptions = selectManaToPayFor(ai.getManaPool(), shard, + saBeingPaidFor, restriction, colorsPaid, xManaCostPaidByColor); // Exclude border case if (weightedOptions.isEmpty()) { @@ -1015,9 +1017,13 @@ public class ComputerUtilMana { } private static List> selectManaToPayFor(final ManaPool manapool, final ManaCostShard shard, - final SpellAbility saBeingPaidFor, String restriction, final byte colorsPaid) { + final SpellAbility saBeingPaidFor, String restriction, final byte colorsPaid, Map xManaCostPaidByColor) { final List> weightedOptions = new ArrayList<>(); for (final Mana thisMana : manapool) { + if (shard == ManaCostShard.COLORED_X && !ManaCostBeingPaid.canColoredXShardBePaidByColor(MagicColor.toShortString(thisMana.getColor()), xManaCostPaidByColor)) { + continue; + } + if (!manapool.canPayForShardWithColor(shard, thisMana.getColor())) { continue; } @@ -1093,7 +1099,7 @@ public class ComputerUtilMana { } } - private static boolean canPayShardWithSpellAbility(ManaCostShard toPay, Player ai, SpellAbility ma, SpellAbility sa, boolean checkCosts) { + private static boolean canPayShardWithSpellAbility(ManaCostShard toPay, Player ai, SpellAbility ma, SpellAbility sa, boolean checkCosts, Map xManaCostPaidByColor) { final Card sourceCard = ma.getHostCard(); if (isManaSourceReserved(ai, sourceCard, sa)) { @@ -1131,6 +1137,10 @@ public class ComputerUtilMana { if (m.isComboMana()) { for (String s : m.getComboColors().split(" ")) { + if (toPay == ManaCostShard.COLORED_X && !ManaCostBeingPaid.canColoredXShardBePaidByColor(s, xManaCostPaidByColor)) { + continue; + } + if ("Any".equals(s) || ai.getManaPool().canPayForShardWithColor(toPay, ManaAtom.fromName(s))) return true; } @@ -1141,6 +1151,9 @@ public class ComputerUtilMana { Set reflected = CardUtil.getReflectableManaColors(ma); for (byte c : MagicColor.WUBRG) { + if (toPay == ManaCostShard.COLORED_X && !ManaCostBeingPaid.canColoredXShardBePaidByColor(MagicColor.toShortString(c), xManaCostPaidByColor)) { + continue; + } if (ai.getManaPool().canPayForShardWithColor(toPay, c) && reflected.contains(MagicColor.toLongString(c))) { m.setExpressChoice(MagicColor.toShortString(c)); return true; @@ -1148,6 +1161,16 @@ public class ComputerUtilMana { } return false; } + + if (toPay == ManaCostShard.COLORED_X) { + for (String s : m.mana().split(" ")) { + if (ManaCostBeingPaid.canColoredXShardBePaidByColor(s, xManaCostPaidByColor)) { + return true; + } + } + return false; + } + return true; } @@ -1434,17 +1457,26 @@ public class ComputerUtilMana { // Tack xMana Payments into mana here if X is a set value if (cost.getXcounter() > 0 || extraMana > 0) { int manaToAdd = 0; + int xCounter = cost.getXcounter(); if (test && extraMana > 0) { - final int multiplicator = Math.max(cost.getXcounter(), 1); + final int multiplicator = Math.max(xCounter, 1); manaToAdd = extraMana * multiplicator; } else { - manaToAdd = AbilityUtils.calculateAmount(card, "X", sa) * cost.getXcounter(); + manaToAdd = AbilityUtils.calculateAmount(card, "X", sa) * xCounter; } - cost.increaseShard(ManaCostShard.parseNonGeneric(sa.getParamOrDefault("XColor", "1")), manaToAdd); + String xColor = sa.getParamOrDefault("XColor", "1"); + if (card.hasKeyword("Spend only colored mana on X. No more than one mana of each color may be spent this way.")) { + xColor = "WUBRGX"; + } + if (xCounter > 0) { + cost.setXManaCostPaid(manaToAdd / xCounter, xColor); + } else { + cost.increaseShard(ManaCostShard.parseNonGeneric(xColor), manaToAdd); + } if (!test) { - sa.setXManaCostPaid(manaToAdd / cost.getXcounter()); + sa.setXManaCostPaid(manaToAdd / xCounter); } } diff --git a/forge-core/src/main/java/forge/card/CardType.java b/forge-core/src/main/java/forge/card/CardType.java index 525e929b94e..c2172c1058f 100644 --- a/forge-core/src/main/java/forge/card/CardType.java +++ b/forge-core/src/main/java/forge/card/CardType.java @@ -91,6 +91,7 @@ public final class CardType implements Comparable, CardTypeView { public enum Supertype { Basic, Elite, + Host, Legendary, Snow, Ongoing, diff --git a/forge-core/src/main/java/forge/card/MagicColor.java b/forge-core/src/main/java/forge/card/MagicColor.java index 408b00d8080..13a73fb55d1 100644 --- a/forge-core/src/main/java/forge/card/MagicColor.java +++ b/forge-core/src/main/java/forge/card/MagicColor.java @@ -138,23 +138,11 @@ public final class MagicColor { public static final ImmutableList BASIC_LANDS = ImmutableList.of("Plains", "Island", "Swamp", "Mountain", "Forest"); public static final ImmutableList SNOW_LANDS = ImmutableList.of("Snow-Covered Plains", "Snow-Covered Island", "Snow-Covered Swamp", "Snow-Covered Mountain", "Snow-Covered Forest"); public static final ImmutableMap ANY_COLOR_CONVERSION = new ImmutableMap.Builder() - .put("ManaColorConversion", "Additive") - .put("WhiteConversion", "Color") - .put("BlueConversion", "Color") - .put("BlackConversion", "Color") - .put("RedConversion", "Color") - .put("GreenConversion", "Color") - .put("ColorlessConversion", "Color") + .put("ManaConversion", "AnyType->AnyColor") .build(); public static final ImmutableMap ANY_TYPE_CONVERSION = new ImmutableMap.Builder() - .put("ManaColorConversion", "Additive") - .put("WhiteConversion", "Type") - .put("BlueConversion", "Type") - .put("BlackConversion", "Type") - .put("RedConversion", "Type") - .put("GreenConversion", "Type") - .put("ColorlessConversion", "Type") + .put("ManaConversion", "AnyType->AnyType") .build(); /** * Private constructor to prevent instantiation. diff --git a/forge-core/src/main/java/forge/card/mana/ManaAtom.java b/forge-core/src/main/java/forge/card/mana/ManaAtom.java index 951f7fbf776..f04a90ac6f4 100644 --- a/forge-core/src/main/java/forge/card/mana/ManaAtom.java +++ b/forge-core/src/main/java/forge/card/mana/ManaAtom.java @@ -59,6 +59,18 @@ public abstract class ManaAtom { return 0; // generic } + public static byte fromConversion(String s) { + switch (s) { + case "AnyColor": return ALL_MANA_COLORS; + case "AnyType": return ALL_MANA_TYPES; + } + byte b = 0; + for (char c : s.toCharArray()) { + b |= fromName(c); + } + return b; + } + public static int getIndexOfFirstManaType(final byte color){ for (int i = 0; i < MANATYPES.length; i++) { if ((color & MANATYPES[i]) != 0) { diff --git a/forge-core/src/main/java/forge/card/mana/ManaCostShard.java b/forge-core/src/main/java/forge/card/mana/ManaCostShard.java index d4533f1abc5..a0141250fc0 100644 --- a/forge-core/src/main/java/forge/card/mana/ManaCostShard.java +++ b/forge-core/src/main/java/forge/card/mana/ManaCostShard.java @@ -64,7 +64,10 @@ public enum ManaCostShard { PR(ManaAtom.RED | ManaAtom.OR_2_LIFE, "P/R", "PR"), PG(ManaAtom.GREEN | ManaAtom.OR_2_LIFE, "P/G", "PG"), - X(ManaAtom.IS_X, "X"); + X(ManaAtom.IS_X, "X"), + + // Colored only X, each color can be used to pay for this only once (for Emblazoned Golem) + COLORED_X(ManaAtom.WHITE | ManaAtom.BLUE | ManaAtom.BLACK | ManaAtom.RED | ManaAtom.GREEN | ManaAtom.IS_X, "1"); private final int shard; @@ -297,7 +300,7 @@ public enum ManaCostShard { } public boolean isColor(byte colorCode) { - return (colorCode & this.shard) > 0; + return (colorCode & this.shard) > 0; } public boolean canBePaidWithManaOfColor(byte colorCode) { diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index d010dd87c18..f9e56d059a3 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -1496,17 +1496,45 @@ public class AbilityUtils { else if (unlessCost.equals("ChosenNumber")) { cost = new Cost(new ManaCost(new ManaCostParser(String.valueOf(source.getChosenNumber()))), true); } - else if (unlessCost.equals("RememberedCostMinus2")) { - Card rememberedCard = (Card) source.getFirstRemembered(); - if (rememberedCard == null) { + else if (unlessCost.startsWith("DefinedCost")) { + CardCollection definedCards = AbilityUtils.getDefinedCards(sa.getHostCard(), unlessCost.split("_")[1], sa); + if (definedCards.isEmpty()) { sa.resolve(); resolveSubAbilities(sa, game); return; } - ManaCostBeingPaid newCost = new ManaCostBeingPaid(rememberedCard.getManaCost()); - newCost.decreaseGenericMana(2); + Card card = definedCards.getFirst(); + ManaCostBeingPaid newCost = new ManaCostBeingPaid(card.getManaCost()); + // Check if there's a third underscore for cost modifying + if (unlessCost.split("_").length == 3) { + String modifier = unlessCost.split("_")[2]; + if (modifier.startsWith("Minus")) { + newCost.decreaseGenericMana(Integer.parseInt(modifier.substring(5))); + } else { + newCost.increaseGenericMana(Integer.parseInt(modifier.substring(4))); + } + } cost = new Cost(newCost.toManaCost(), true); } + else if (unlessCost.startsWith("DefinedSACost")) { + FCollection definedSAs = AbilityUtils.getDefinedSpellAbilities(sa.getHostCard(), unlessCost.split("_")[1], sa); + if (definedSAs.isEmpty()) { + sa.resolve(); + resolveSubAbilities(sa, game); + return; + } + Card host = definedSAs.getFirst().getHostCard(); + if (host.getManaCost() == null) { + cost = new Cost(ManaCost.ZERO, true); + } else { + int xCount = host.getManaCost().countX(); + int xPaid = host.getXManaCostPaid() * xCount; + ManaCostBeingPaid toPay = new ManaCostBeingPaid(host.getManaCost()); + toPay.decreaseShard(ManaCostShard.X, xCount); + toPay.increaseGenericMana(xPaid); + cost = new Cost(toPay.toManaCost(), true); + } + } else if (!StringUtils.isBlank(sa.getSVar(unlessCost)) || !StringUtils.isBlank(source.getSVar(unlessCost))) { // check for X costs (stored in SVars int xCost = calculateAmount(source, TextUtil.fastReplace(sa.getParam("UnlessCost"), @@ -1864,30 +1892,19 @@ public class AbilityUtils { } public static final void applyManaColorConversion(ManaConversionMatrix matrix, final Map params) { - String conversionType = params.get("ManaColorConversion"); + String conversion = params.get("ManaConversion"); - // Choices are Additives(OR) or Restrictive(AND) - boolean additive = "Additive".equals(conversionType); + for (String pair : conversion.split(" ")) { + // Check if conversion is additive or restrictive and how to split + boolean additive = pair.contains("->"); + String[] sides = pair.split(additive ? "->" : "<-"); - for(String c : MagicColor.Constant.COLORS_AND_COLORLESS) { - // Use the strings from MagicColor, since that's how the Script will be coming in as - String key = StringUtils.capitalize(c) + "Conversion"; - if (params.containsKey(key)) { - String convertTo = params.get(key); - byte convertByte = 0; - if ("Type".equals(convertTo)) { - // IMPORTANT! We need to use Mana Color here not Card Color. - convertByte = ManaAtom.ALL_MANA_TYPES; - } else if ("Color".equals(convertTo)) { - // IMPORTANT! We need to use Mana Color here not Card Color. - convertByte = ManaAtom.ALL_MANA_COLORS; - } else { - for (final String convertColor : convertTo.split(",")) { - convertByte |= ManaAtom.fromName(convertColor); - } + if (sides[0].equals("AnyColor") || sides[0].equals("AnyType")) { + for (byte c : (sides[0].equals("AnyColor") ? MagicColor.WUBRG : MagicColor.WUBRGC)) { + matrix.adjustColorReplacement(c, ManaAtom.fromConversion(sides[1]), additive); } - // AdjustColorReplacement has two different matrices handling final mana conversion under the covers - matrix.adjustColorReplacement(ManaAtom.fromName(c), convertByte, additive); + } else { + matrix.adjustColorReplacement(ManaAtom.fromConversion(sides[0]), ManaAtom.fromConversion(sides[1]), additive); } } } diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 80fb8a21888..04523f5b091 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1915,6 +1915,9 @@ public class Card extends GameEntity implements Comparable, IHasSVars { s.append(" on it."); } sbLong.append(s).append("\r\n"); + } else if (keyword.startsWith("ManaConvert")) { + final String[] k = keyword.split(":"); + sbLong.append(k[2]).append("\r\n"); } else if (keyword.startsWith("Protection:") || keyword.startsWith("DeckLimit")) { final String[] k = keyword.split(":"); sbLong.append(k[2]).append("\r\n"); diff --git a/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java b/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java index 488645a784d..889aa5baa82 100644 --- a/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java +++ b/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java @@ -240,7 +240,7 @@ public class ManaCostBeingPaid { public final boolean isNeeded(final Mana paid, final ManaPool pool) { for (ManaCostShard shard : unpaidShards.keySet()) { - if (canBePaidWith(shard, paid, pool)) { + if (canBePaidWith(shard, paid, pool, xManaCostPaidByColor)) { return true; } } @@ -260,7 +260,7 @@ public class ManaCostBeingPaid { shard = ManaCostShard.GENERIC; } else { - shard = ManaCostShard.valueOf(ManaAtom.fromName(xColor)); + shard = ManaCostShard.parseNonGeneric(xColor); } increaseShard(shard, xCost, true); } @@ -441,6 +441,10 @@ public class ManaCostBeingPaid { Predicate predCanBePaid = new Predicate() { @Override public boolean apply(ManaCostShard ms) { + // Check Colored X and see if the color is already used + if (ms == ManaCostShard.COLORED_X && !canColoredXShardBePaidByColor(MagicColor.toShortString(colorMask), xManaCostPaidByColor)) { + return false; + } return pool.canPayForShardWithColor(ms, colorMask); } }; @@ -465,7 +469,7 @@ public class ManaCostBeingPaid { Predicate predCanBePaid = new Predicate() { @Override public boolean apply(ManaCostShard ms) { - return canBePaidWith(ms, mana, pool); + return canBePaidWith(ms, mana, pool, xManaCostPaidByColor); } }; @@ -552,7 +556,14 @@ public class ManaCostBeingPaid { return 5; } - private static boolean canBePaidWith(final ManaCostShard shard, final Mana mana, final ManaPool pool) { + public static boolean canColoredXShardBePaidByColor(String color, Map xManaCostPaidByColor) { + if (xManaCostPaidByColor != null && xManaCostPaidByColor.get(color) != null) { + return false; + } + return true; + } + + private static boolean canBePaidWith(final ManaCostShard shard, final Mana mana, final ManaPool pool, Map xManaCostPaidByColor) { if (shard.isSnow() && !mana.isSnow()) { return false; } @@ -565,6 +576,11 @@ public class ManaCostBeingPaid { return true; } + // Check Colored X and see if the color is already used + if (shard == ManaCostShard.COLORED_X && !canColoredXShardBePaidByColor(MagicColor.toShortString(mana.getColor()), xManaCostPaidByColor)) { + return false; + } + byte color = mana.getColor(); return pool.canPayForShardWithColor(shard, color); } diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 6ab8c76dd63..b5dd3af1353 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -3127,6 +3127,8 @@ public class Player extends GameEntity implements Comparable { int deckSize = getCardsIn(ZoneType.Library).size(); int minSize = game.getMatch().getRules().getGameType().getDeckFormat().getMainRange().getMinimum(); + game.getAction().checkStaticAbilities(false); + for (final Card c : getCardsIn(ZoneType.Sideboard)) { for (KeywordInterface inst : c.getKeywords()) { if (!(inst instanceof Companion)) { diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java index 13bc3222651..84dd3759c70 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -591,7 +591,7 @@ public final class StaticAbilityContinuous { p.setMaxHandSize(p.getMaxHandSize() + rmax); } - if (params.containsKey("ManaColorConversion")) { + if (params.containsKey("ManaConversion")) { AbilityUtils.applyManaColorConversion(p.getManaPool(), params); } } diff --git a/forge-gui/res/cardsfolder/a/adorable_kitten.txt b/forge-gui/res/cardsfolder/a/adorable_kitten.txt new file mode 100644 index 00000000000..edd5abb289d --- /dev/null +++ b/forge-gui/res/cardsfolder/a/adorable_kitten.txt @@ -0,0 +1,8 @@ +Name:Adorable Kitten +ManaCost:W +Types:Host Creature Cat +PT:1/1 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRoll | Host$ True | TriggerDescription$ When this creature enters the battlefield, roll a six-sided die. You gain life equal to the result. +SVar:TrigRoll:DB$ RollDice | ResultSVar$ Result | SubAbility$ DBLife +SVar:DBLife:DB$ GainLife | LifeAmount$ Result +Oracle:When this creature enters the battlefield, roll a six-sided die. You gain life equal to the result. diff --git a/forge-gui/res/cardsfolder/a/angelic_rocket.txt b/forge-gui/res/cardsfolder/a/angelic_rocket.txt new file mode 100644 index 00000000000..7ed8b9ecdbf --- /dev/null +++ b/forge-gui/res/cardsfolder/a/angelic_rocket.txt @@ -0,0 +1,8 @@ +Name:Angelic Rocket +ManaCost:8 +Types:Artifact Creature Angel +PT:4/4 +K:Flying +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDestroy | OptionalDecider$ You | Host$ True | TriggerDescription$ When this creature enters the battlefield, you may destroy target nonland permanent. +SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Permanent.nonland | TgtPrompt$ Select target permanent. +Oracle:Flying\nWhen this creature enters the battlefield, you may destroy target nonland permanent. diff --git a/forge-gui/res/cardsfolder/b/big_boa_constrictor.txt b/forge-gui/res/cardsfolder/b/big_boa_constrictor.txt new file mode 100644 index 00000000000..6ed4f67e10e --- /dev/null +++ b/forge-gui/res/cardsfolder/b/big_boa_constrictor.txt @@ -0,0 +1,8 @@ +Name:Big Boa Constrictor +ManaCost:3 B +Types:Host Creature Snake +PT:3/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRoll | Host$ True | TriggerDescription$ When this creature enters the battlefield, roll a six-sided die. Target opponent loses life equal to the result. +SVar:TrigRoll:DB$ RollDice | ResultSVar$ Result | SubAbility$ DBLife +SVar:DBLife:DB$ LoseLife | ValidTgts$ Opponent | LifeAmount$ Result +Oracle:When this creature enters the battlefield, roll a six-sided die. Target opponent loses life equal to the result. diff --git a/forge-gui/res/cardsfolder/b/bumbling_pangolin.txt b/forge-gui/res/cardsfolder/b/bumbling_pangolin.txt new file mode 100644 index 00000000000..1454639c10a --- /dev/null +++ b/forge-gui/res/cardsfolder/b/bumbling_pangolin.txt @@ -0,0 +1,7 @@ +Name:Bumbling Pangolin +ManaCost:3 R +Types:Host Creature Pangolin Beast +PT:2/2 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDestroy | OptionalDecider$ You | Host$ True | TriggerDescription$ When this creature enters the battlefield, you may destroy target artifact. +SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Artifact | TgtPrompt$ Select target artifact. +Oracle:When this creature enters the battlefield, you may destroy target artifact. diff --git a/forge-gui/res/cardsfolder/c/celestial_dawn.txt b/forge-gui/res/cardsfolder/c/celestial_dawn.txt index 0321d16c721..beb7c498d4f 100644 --- a/forge-gui/res/cardsfolder/c/celestial_dawn.txt +++ b/forge-gui/res/cardsfolder/c/celestial_dawn.txt @@ -4,9 +4,8 @@ Types:Enchantment S:Mode$ Continuous | Affected$ Land.YouCtrl | AddType$ Plains | RemoveLandTypes$ True | Description$ Lands you control are Plains. S:Mode$ Continuous | Affected$ Card.YouOwn+nonLand | SetColor$ White | AffectedZone$ Hand,Library,Graveyard,Exile,Command | Description$ Nonland permanents you control are white. The same is true for spells you control and nonland cards you own that aren't on the battlefield. S:Mode$ Continuous | Affected$ Card.YouCtrl+nonLand | SetColor$ White | AffectedZone$ Battlefield,Stack -S:Mode$ Continuous | Affected$ You | ManaColorConversion$ Additive | WhiteConversion$ Color | Description$ You may spend white mana as though it were mana of any color. -S:Mode$ Continuous | Affected$ You | ManaColorConversion$ Restrictive | BlueConversion$ Colorless | BlackConversion$ Colorless | RedConversion$ Colorless | GreenConversion$ Colorless | ColorlessConversion$ Colorless | Description$ You may spend other mana only as though it were colorless mana. +S:Mode$ Continuous | Affected$ You | ManaConversion$ W->AnyColor | Description$ You may spend white mana as though it were mana of any color. +S:Mode$ Continuous | Affected$ You | ManaConversion$ UBRG<-C | Description$ You may spend other mana only as though it were colorless mana. SVar:NonStackingEffect:True AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/celestial_dawn.jpg Oracle:Lands you control are Plains.\nNonland permanents you control are white. The same is true for spells you control and nonland cards you own that aren't on the battlefield.\nYou may spend white mana as though it were mana of any color. You may spend other mana only as though it were colorless mana. diff --git a/forge-gui/res/cardsfolder/c/chromatic_orrery.txt b/forge-gui/res/cardsfolder/c/chromatic_orrery.txt index 4dd331d7a08..25716f02691 100755 --- a/forge-gui/res/cardsfolder/c/chromatic_orrery.txt +++ b/forge-gui/res/cardsfolder/c/chromatic_orrery.txt @@ -1,7 +1,7 @@ Name:Chromatic Orrery ManaCost:7 Types:Legendary Artifact -S:Mode$ Continuous | Affected$ You | ManaColorConversion$ Additive | WhiteConversion$ Color | BlueConversion$ Color | BlackConversion$ Color | RedConversion$ Color | GreenConversion$ Color | ColorlessConversion$ Color | Description$ You may spend mana as though it were mana of any color. +S:Mode$ Continuous | Affected$ You | ManaConversion$ AnyType->AnyColor | Description$ You may spend mana as though it were mana of any color. SVar:NonStackingEffect:True A:AB$ Mana | Cost$ T | Produced$ C | Amount$ 5 | SpellDescription$ Add {C}{C}{C}{C}{C}. A:AB$ Draw | Cost$ 5 T | NumCards$ X | SpellDescription$ Draw a card for each color among permanents you control. diff --git a/forge-gui/res/cardsfolder/c/common_iguana.txt b/forge-gui/res/cardsfolder/c/common_iguana.txt new file mode 100644 index 00000000000..92680dd4d11 --- /dev/null +++ b/forge-gui/res/cardsfolder/c/common_iguana.txt @@ -0,0 +1,8 @@ +Name:Common Iguana +ManaCost:1 R +Types:Host Creature Lizard +PT:1/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Self | Execute$ TrigDiscard | Host$ True | TriggerDescription$ When this creature enters the battlefield, you may discard a card. If you do, draw a card. +SVar:TrigDiscard:AB$ Draw | Cost$ Discard<1/Card> | NumCards$ 1 +DeckHas:Ability$Discard +Oracle:When this creature enters the battlefield, you may discard a card. If you do, draw a card. diff --git a/forge-gui/res/cardsfolder/d/dirty_rat.txt b/forge-gui/res/cardsfolder/d/dirty_rat.txt new file mode 100644 index 00000000000..581f70c6f91 --- /dev/null +++ b/forge-gui/res/cardsfolder/d/dirty_rat.txt @@ -0,0 +1,7 @@ +Name:Dirty Rat +ManaCost:1 B +Types:Host Creature Rat +PT:1/1 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDiscard | Host$ True | TriggerDescription$ When this creature enters the battlefield, target opponent discards a card. +SVar:TrigDiscard:DB$Discard | ValidTgts$ Opponent | TgtPrompt$ Select an opponent | NumCards$ 1 | Mode$ TgtChoose +Oracle:When this creature enters the battlefield, target opponent discards a card. diff --git a/forge-gui/res/cardsfolder/e/eager_beaver.txt b/forge-gui/res/cardsfolder/e/eager_beaver.txt new file mode 100644 index 00000000000..afb14591cbc --- /dev/null +++ b/forge-gui/res/cardsfolder/e/eager_beaver.txt @@ -0,0 +1,7 @@ +Name:Eager Beaver +ManaCost:2 G +Types:Host Creature Beaver +PT:3/2 +T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigUntap | OptionalDecider$ You | Host$ True | TriggerDescription$ When this creature enters the battlefield, you may untap target permanent. +SVar:TrigUntap:DB$ Untap | ValidTgts$ Permanent +Oracle:When this creature enters the battlefield, you may untap target permanent. diff --git a/forge-gui/res/cardsfolder/e/emblazoned_golem.txt b/forge-gui/res/cardsfolder/e/emblazoned_golem.txt new file mode 100644 index 00000000000..16c4155ec10 --- /dev/null +++ b/forge-gui/res/cardsfolder/e/emblazoned_golem.txt @@ -0,0 +1,11 @@ +Name:Emblazoned Golem +ManaCost:2 +Types:Artifact Creature Golem +PT:1/2 +K:Kicker:X +K:Spend only colored mana on X. No more than one mana of each color may be spent this way. +K:etbCounter:P1P1:X:CheckSVar$ WasKicked:If CARDNAME was kicked, it enters the battlefield with X +1/+1 counters on it. +SVar:X:Count$xPaid +SVar:WasKicked:Count$Kicked.1.0 +DeckHas:Ability$Counters +Oracle:Kicker {X} (You may pay an additional {X} as you cast this spell.)\nSpend only colored mana on X. No more than one mana of each color may be spent this way.\nIf Emblazoned Golem was kicked, it enters the battlefield with X +1/+1 counters on it. diff --git a/forge-gui/res/cardsfolder/f/false_dawn.txt b/forge-gui/res/cardsfolder/f/false_dawn.txt index 53556221349..486b751db56 100644 --- a/forge-gui/res/cardsfolder/f/false_dawn.txt +++ b/forge-gui/res/cardsfolder/f/false_dawn.txt @@ -5,6 +5,6 @@ A:SP$ Effect | Cost$ 1 W | ReplacementEffects$ FDRep | StaticAbilities$ FDManaCo SVar:DBDraw:DB$ Draw | NumCards$ 1 SVar:FDRep:Event$ ProduceMana | ActiveZones$ Command | ValidCard$ Card.YouCtrl | ReplaceWith$ ProduceW | Description$ Spells and abilities you control that would add colored mana add that much white mana instead. SVar:ProduceW:DB$ ReplaceMana | ReplaceColor$ W -SVar:FDManaConvertion:Mode$ Continuous | EffectZone$ Command | Affected$ You | ManaColorConversion$ Additive | WhiteConversion$ Color | Description$ You may spend white mana as though it were mana of any color. +SVar:FDManaConvertion:Mode$ Continuous | EffectZone$ Command | Affected$ You | ManaConversion$ W->AnyColor | Description$ You may spend white mana as though it were mana of any color. AI:RemoveDeck:All Oracle:Until end of turn, spells and abilities you control that would add colored mana instead add that much white mana. Until end of turn, you may spend white mana as though it were mana of any color.\nDraw a card. diff --git a/forge-gui/res/cardsfolder/f/feisty_stegosaurus.txt b/forge-gui/res/cardsfolder/f/feisty_stegosaurus.txt new file mode 100644 index 00000000000..b272fc03020 --- /dev/null +++ b/forge-gui/res/cardsfolder/f/feisty_stegosaurus.txt @@ -0,0 +1,8 @@ +Name:Feisty Stegosaurus +ManaCost:4 R +Types:Host Creature Dinosaur +PT:2/1 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRoll | Host$ True | TriggerDescription$ When this creature enters the battlefield, roll a six-sided die. This creature deals damage equal to the result to target creature an opponent controls. +SVar:TrigRoll:DB$ RollDice | ResultSVar$ Result | SubAbility$ DBDamage +SVar:DBDamage:DB$ DealDamage | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls | NumDmg$ Result +Oracle:When this creature enters the battlefield, roll a six-sided die. This creature deals damage equal to the result to target creature an opponent controls. diff --git a/forge-gui/res/cardsfolder/f/flash.txt b/forge-gui/res/cardsfolder/f/flash.txt index 70df31d4ff3..4b2ddd374da 100644 --- a/forge-gui/res/cardsfolder/f/flash.txt +++ b/forge-gui/res/cardsfolder/f/flash.txt @@ -2,8 +2,7 @@ Name:Flash ManaCost:1 U Types:Instant A:SP$ ChangeZone | Cost$ 1 U | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature | ChangeNum$ 1 | SubAbility$ DBSac | RememberChanged$ True | SpellDescription$ You may put a creature card from your hand onto the battlefield. If you do, sacrifice it unless you pay its mana cost reduced by up to {2}. -SVar:DBSac:DB$ SacrificeAll | Defined$ Remembered | UnlessCost$ RememberedCostMinus2 | UnlessPayer$ You | SubAbility$ DBCleanup +SVar:DBSac:DB$ SacrificeAll | Defined$ Remembered | UnlessCost$ DefinedCost_Remembered_Minus2 | UnlessPayer$ You | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/flash.jpg Oracle:You may put a creature card from your hand onto the battlefield. If you do, sacrifice it unless you pay its mana cost reduced by up to {2}. diff --git a/forge-gui/res/cardsfolder/g/gnome_made_engine.txt b/forge-gui/res/cardsfolder/g/gnome_made_engine.txt new file mode 100644 index 00000000000..353864f1165 --- /dev/null +++ b/forge-gui/res/cardsfolder/g/gnome_made_engine.txt @@ -0,0 +1,7 @@ +Name:Gnome-Made Engine +ManaCost:4 +Types:Artifact Host Creature Construct +PT:2/2 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | Host$ True | TriggerDescription$ When this creature enters the battlefield, create a 1/1 colorless Gnome artifact creature token. +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_1_1_a_gnome | TokenOwner$ TriggeredCardController +Oracle:When this creature enters the battlefield, create a 1/1 colorless Gnome artifact creature token. diff --git a/forge-gui/res/cardsfolder/i/ice_cave.txt b/forge-gui/res/cardsfolder/i/ice_cave.txt index 1057a2c36d6..db3a2b44a3e 100644 --- a/forge-gui/res/cardsfolder/i/ice_cave.txt +++ b/forge-gui/res/cardsfolder/i/ice_cave.txt @@ -2,6 +2,5 @@ Name:Ice Cave ManaCost:3 U U Types:Enchantment T:Mode$ SpellCast | ValidCard$ Card | TriggerZones$ Battlefield | Execute$ TrigCounter | TriggerDescription$ Whenever a player casts a spell, any other player may pay that spell's mana cost. If a player does, counter the spell. (Mana cost includes color.) -SVar:TrigCounter:DB$ Counter | Defined$ TriggeredSpellAbility | UnlessCost$ TriggeredSpellManaCost | UnlessPayer$ NonTriggeredCardController | UnlessSwitched$ True -SVar:Picture:http://www.wizards.com/global/images/magic/general/ice_cave.jpg +SVar:TrigCounter:DB$ Counter | Defined$ TriggeredSpellAbility | UnlessCost$ DefinedSACost_TriggeredSpellAbility | UnlessPayer$ NonTriggeredCardController | UnlessSwitched$ True Oracle:Whenever a player casts a spell, any other player may pay that spell's mana cost. If a player does, counter the spell. (Mana cost includes color.) diff --git a/forge-gui/res/cardsfolder/k/kaboom.txt b/forge-gui/res/cardsfolder/k/kaboom.txt index 4e875c2b23f..d569f2288e1 100644 --- a/forge-gui/res/cardsfolder/k/kaboom.txt +++ b/forge-gui/res/cardsfolder/k/kaboom.txt @@ -1,12 +1,14 @@ Name:Kaboom! ManaCost:4 R Types:Sorcery -A:SP$ RepeatEach | Cost$ 4 R | ValidTgts$ Player | TargetMin$ 0 | TargetMax$ Maxplayer | RepeatPlayers$ Targeted | RepeatSubAbility$ DBDigUntil | StackDescription$ SpellDescription | SpellDescription$ Choose any number of target players. For each of those players, reveal cards from the top of your library until you reveal a nonland card, Kaboom! deals damage equal to that card's converted mana cost to that player, then you put the revealed cards on the bottom of your library in any order. -SVar:DBDigUntil:DB$ DigUntil | Defined$ You | Valid$ Card.nonLand | ValidDescription$ nonland card | FoundDestination$ Library | FoundLibraryPosition$ -1 | RevealedDestination$ Library | RevealedLibraryPosition$ -1 | RememberFound$ True | SubAbility$ DBDmg -SVar:DBDmg:DB$ DealDamage | Defined$ Player.IsRemembered | NumDmg$ X | SubAbility$ DBCleanup -SVar:DBCleanup:DB$Cleanup | ClearRemembered$ True -SVar:X:Remembered$CardManaCost -SVar:Maxplayer:PlayerCountPlayers$Amount +A:SP$ RepeatEach | Cost$ 4 R | ValidTgts$ Player | TargetMin$ 0 | TargetMax$ MaxTgt | RepeatTargeted$ Targeted | RepeatSubAbility$ DBDigUntil | StackDescription$ SpellDescription | SpellDescription$ Choose any number of target players or planeswalkers. For each of them, reveal cards from the top of your library until you reveal a nonland card, Kaboom! deals damage equal to that card's converted mana cost to that player or planeswalker, then you put the revealed cards on the bottom of your library in any order. +SVar:DBDigUntil:DB$ DigUntil | Defined$ You | Valid$ Card.nonLand | ValidDescription$ nonland card | FoundDestination$ Library | FoundLibraryPosition$ -1 | RevealedDestination$ Library | RevealedLibraryPosition$ -1 | ImprintFound$ True | SubAbility$ DBDmg +SVar:DBDmg:DB$ DealDamage | Defined$ Remembered | NumDmg$ X | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearImprinted$ True +SVar:X:Imprinted$CardManaCost +SVar:MaxTgt:SVar$MaxPl/Plus.MaxPW +SVar:MaxPl:PlayerCountPlayers$Amount +SVar:MaxPW:Count$Valid Planeswalker AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/kaboom!.jpg Oracle:Choose any number of target players or planeswalkers. For each of them, reveal cards from the top of your library until you reveal a nonland card, Kaboom! deals damage equal to that card's converted mana cost to that player or planeswalker, then you put the revealed cards on the bottom of your library in any order. diff --git a/forge-gui/res/cardsfolder/l/labro_bot.txt b/forge-gui/res/cardsfolder/l/labro_bot.txt new file mode 100644 index 00000000000..4db662b2404 --- /dev/null +++ b/forge-gui/res/cardsfolder/l/labro_bot.txt @@ -0,0 +1,7 @@ +Name:Labro Bot +ManaCost:5 +Types:Artifact Host Creature Dog +PT:3/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChangeZone | Host$ True | TriggerDescription$ When this creature enters the battlefield, return target host card or card with augment from your graveyard to your hand. +SVar:TrigChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | ValidTgts$ Host.YouOwn,Card.YouOwn+withAugment +Oracle:When this creature enters the battlefield, return target host card or card with augment from your graveyard to your hand. diff --git a/forge-gui/res/cardsfolder/m/makeshift_mannequin.txt b/forge-gui/res/cardsfolder/m/makeshift_mannequin.txt index 7a933f5d392..c9b1daececb 100644 --- a/forge-gui/res/cardsfolder/m/makeshift_mannequin.txt +++ b/forge-gui/res/cardsfolder/m/makeshift_mannequin.txt @@ -2,7 +2,7 @@ Name:Makeshift Mannequin ManaCost:3 B Types:Instant A:SP$ ChangeZone | Cost$ 3 B | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature from your graveyard | Origin$ Graveyard | Destination$ Battlefield | WithCounters$ MANNEQUIN_1 | RememberChanged$ True | SubAbility$ DBEffect | SpellDescription$ Return target creature card from your graveyard to the battlefield with a mannequin counter on it. For as long as that creature has a mannequin counter on it, it has "When this creature becomes the target of a spell or ability, sacrifice it." -SVar:DBEffect:DB$ Effect | RememberObjects$ RememberedCard | StaticAbilities$ MannequinStatic | SubAbility$ DBCleanup | ForgetOnMoved$ Battlefield | ForgetCounter$ MANNEQUIN +SVar:DBEffect:DB$ Effect | RememberObjects$ RememberedCard | StaticAbilities$ MannequinStatic | Duration$ Permanent | SubAbility$ DBCleanup | ForgetOnMoved$ Battlefield | ForgetCounter$ MANNEQUIN SVar:MannequinStatic:Mode$ Continuous | EffectZone$ Command | Affected$ Card.IsRemembered | AddTrigger$ MannequinBecomesTarget | Description$ For as long as that creature has a mannequin counter on it, it has "When this creature becomes the target of a spell or ability, sacrifice it." SVar:MannequinBecomesTarget:Mode$ BecomesTarget | ValidTarget$ Card.Self | TriggerZones$ Battlefield | Execute$ MakeshiftSac | TriggerDescription$ When CARDNAME becomes the target of a spell or ability, sacrifice it. SVar:MakeshiftSac:DB$Sacrifice | Defined$ Self diff --git a/forge-gui/res/cardsfolder/m/manascape_refractor.txt b/forge-gui/res/cardsfolder/m/manascape_refractor.txt index f22e8d8f583..fca84714a4b 100755 --- a/forge-gui/res/cardsfolder/m/manascape_refractor.txt +++ b/forge-gui/res/cardsfolder/m/manascape_refractor.txt @@ -2,12 +2,7 @@ Name:Manascape Refractor ManaCost:3 Types:Artifact K:CARDNAME enters the battlefield tapped. -K:ManaConvert:Black:All -K:ManaConvert:Blue:All -K:ManaConvert:Green:All -K:ManaConvert:Red:All -K:ManaConvert:White:All +K:ManaConvert:AnyType->AnyColor:You may spend mana as though it were mana of any color to pay the activation costs of CARDNAME's abilities. S:Mode$ Continuous | Affected$ Card.Self | EffectZone$ Battlefield | GainsAbilitiesOf$ Land | Description$ CARDNAME has all activated abilities of all lands on the battlefield. -Text:You may spend mana as though it were mana of any color to pay the activation costs of CARDNAME's abilities. AI:RemoveDeck:All Oracle:Manascape Refractor enters the battlefield tapped.\nManascape Refractor has all activated abilities of all lands on the battlefield.\nYou may spend mana as though it were mana of any color to pay the activation costs of Manascape Refractor's abilities. diff --git a/forge-gui/res/cardsfolder/m/mer_man.txt b/forge-gui/res/cardsfolder/m/mer_man.txt new file mode 100644 index 00000000000..4057c218567 --- /dev/null +++ b/forge-gui/res/cardsfolder/m/mer_man.txt @@ -0,0 +1,7 @@ +Name:Mer Man +ManaCost:4 U +Types:Host Creature Human Fish +PT:3/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDraw | OptionalDecider$ You | Host$ True | TriggerDescription$ When this creature enters the battlefield, you may draw a card. +SVar:TrigDraw:DB$Draw | Defined$ You | NumCards$ 1 +Oracle:When this creature enters the battlefield, you may draw a card. diff --git a/forge-gui/res/cardsfolder/m/moritte_of_the_frost.txt b/forge-gui/res/cardsfolder/m/moritte_of_the_frost.txt index eb1efceb5bb..dd07f697657 100644 --- a/forge-gui/res/cardsfolder/m/moritte_of_the_frost.txt +++ b/forge-gui/res/cardsfolder/m/moritte_of_the_frost.txt @@ -4,7 +4,7 @@ Types:Legendary Snow Creature Shapeshifter PT:0/0 K:Changeling K:ETBReplacement:Copy:DBCopy:Optional -SVar:DBCopy:DB$ Clone | Choices$ Permanent.Other+YouCtrl | AddTypes$ Legendary,Snow | SubAbility$ DBConditionEffect | AddKeywords$ Changeling (This card is every creature type.) | SpellDescription$ You may have Moritte of the Frost enter the battlefield as a copy of a permanent you control, except it’s legendary and snow in addition to its other types and, if it’s a creature, it enters with two additional +1/+1 counters on it and has changeling. +SVar:DBCopy:DB$ Clone | Choices$ Permanent.Other+YouCtrl | AddTypes$ Legendary & Snow | SubAbility$ DBConditionEffect | AddKeywords$ Changeling (This card is every creature type.) | SpellDescription$ You may have Moritte of the Frost enter the battlefield as a copy of a permanent you control, except it’s legendary and snow in addition to its other types and, if it’s a creature, it enters with two additional +1/+1 counters on it and has changeling. SVar:DBConditionEffect:DB$ Effect | RememberObjects$ Self | Name$ Moritte of the Frost Effect | ReplacementEffects$ ETBCreat SVar:ETBCreat:Event$ Moved | ValidCard$ Creature.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | Description$ If it’s a creature, it enters with two additional +1/+1 counters on it. SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ 2 | SubAbility$ ToBattlefield diff --git a/forge-gui/res/cardsfolder/m/mother_kangaroo.txt b/forge-gui/res/cardsfolder/m/mother_kangaroo.txt new file mode 100644 index 00000000000..d8aa60670bb --- /dev/null +++ b/forge-gui/res/cardsfolder/m/mother_kangaroo.txt @@ -0,0 +1,8 @@ +Name:Mother Kangaroo +ManaCost:4 G +Types:Host Creature Kangaroo +PT:1/1 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRoll | Host$ True | TriggerDescription$ When this creature enters the battlefield, roll a six-sided die. Put a number of +1/+1 counters on this creature equal to the result. +SVar:TrigRoll:DB$ RollDice | ResultSVar$ Result | SubAbility$ DBCounters +SVar:DBCounters:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ Result +Oracle:When this creature enters the battlefield, roll a six-sided die. Put a number of +1/+1 counters on this creature equal to the result. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/m/mycosynth_lattice.txt b/forge-gui/res/cardsfolder/m/mycosynth_lattice.txt index bff1493b4cc..e56f91f4a87 100644 --- a/forge-gui/res/cardsfolder/m/mycosynth_lattice.txt +++ b/forge-gui/res/cardsfolder/m/mycosynth_lattice.txt @@ -3,8 +3,7 @@ ManaCost:6 Types:Artifact S:Mode$ Continuous | Affected$ Permanent | AddType$ Artifact | Description$ All permanents are artifact in addition to their other types. S:Mode$ Continuous| Affected$ Card | SetColor$ Colorless | AffectedZone$ Battlefield,Hand,Library,Graveyard,Exile,Stack,Command | Description$ All cards that aren't on the battlefield, spells, and permanents are colorless. -S:Mode$ Continuous | Affected$ Player | ManaColorConversion$ Additive | WhiteConversion$ Color | BlueConversion$ Color | BlackConversion$ Color | RedConversion$ Color | GreenConversion$ Color | ColorlessConversion$ Color | Description$ Players may spend mana as though it were mana of any color. +S:Mode$ Continuous | Affected$ Player | ManaConversion$ AnyType->AnyColor | Description$ Players may spend mana as though it were mana of any color. SVar:NonStackingEffect:True AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/mycosynth_lattice.jpg Oracle:All permanents are artifacts in addition to their other types.\nAll cards that aren't on the battlefield, spells, and permanents are colorless.\nPlayers may spend mana as though it were mana of any color. diff --git a/forge-gui/res/cardsfolder/n/numbing_jellyfish.txt b/forge-gui/res/cardsfolder/n/numbing_jellyfish.txt new file mode 100644 index 00000000000..bbc4043a999 --- /dev/null +++ b/forge-gui/res/cardsfolder/n/numbing_jellyfish.txt @@ -0,0 +1,8 @@ +Name:Numbing Jellyfish +ManaCost:3 U +Types:Host Creature Jellyfish +PT:2/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRoll | Host$ True | TriggerDescription$ When this creature enters the battlefield, roll a six-sided die. Target player mills X cards, where X is the result. +SVar:TrigRoll:DB$ RollDice | ResultSVar$ Result | SubAbility$ DBMill +SVar:DBMill:DB$ Mill | ValidTgts$ Player | NumCards$ Result +Oracle:When this creature enters the battlefield, roll a six-sided die. Target player mills X cards, where X is the result. diff --git a/forge-gui/res/cardsfolder/q/quicksilver_elemental.txt b/forge-gui/res/cardsfolder/q/quicksilver_elemental.txt index 5735e9f915c..7ad2d66ebed 100644 --- a/forge-gui/res/cardsfolder/q/quicksilver_elemental.txt +++ b/forge-gui/res/cardsfolder/q/quicksilver_elemental.txt @@ -2,9 +2,8 @@ Name:Quicksilver Elemental ManaCost:3 U U Types:Creature Elemental PT:3/4 -K:ManaConvert:Blue:All +K:ManaConvert:U->AnyColor:You may spend blue mana as though it were mana of any color to pay the activation costs of CARDNAME's abilities. A:AB$ Effect | Cost$ U | ValidTgts$ Creature | TgtZone$ Battlefield | TgtPrompt$ Select target creature card | StaticAbilities$ STSteal | RememberObjects$ Targeted | SpellDescription$ CARDNAME gains all activated abilities of target creature until end of turn. -SVar:STSteal:Mode$ Continuous | Affected$ EffectSource | EffectZone$ Command | GainsAbilitiesOfDefined$ RememberedLKI | Description$ Quicksilver Elemental gains all activated abilities of that card until end of turn. +SVar:STSteal:Mode$ Continuous | Affected$ Card.EffectSource | EffectZone$ Command | GainsAbilitiesOfDefined$ RememberedLKI | Description$ Quicksilver Elemental gains all activated abilities of that card until end of turn. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/quicksilver_elemental.jpg Oracle:{U}: Quicksilver Elemental gains all activated abilities of target creature until end of turn. (If any of the abilities use that creature's name, use this creature's name instead.)\nYou may spend blue mana as though it were mana of any color to pay the activation costs of Quicksilver Elemental's abilities. diff --git a/forge-gui/res/cardsfolder/s/shaggy_camel.txt b/forge-gui/res/cardsfolder/s/shaggy_camel.txt new file mode 100644 index 00000000000..4e3ae314de0 --- /dev/null +++ b/forge-gui/res/cardsfolder/s/shaggy_camel.txt @@ -0,0 +1,8 @@ +Name:Shaggy Camel +ManaCost:3 W +Types:Host Creature Camel +PT:3/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPumpAll | Host$ True | TriggerDescription$ When this creature enters the battlefield, creatures you control get +1/+1 until end of turn. +SVar:TrigPumpAll:DB$ PumpAll | ValidCards$ Creature.YouCtrl | NumAtt$ +1 | NumDef$ +1 +SVar:PlayMain1:TRUE +Oracle:When this creature enters the battlefield, creatures you control get +1/+1 until end of turn. diff --git a/forge-gui/res/cardsfolder/s/stinging_scorpion.txt b/forge-gui/res/cardsfolder/s/stinging_scorpion.txt new file mode 100644 index 00000000000..61d7e5cb32c --- /dev/null +++ b/forge-gui/res/cardsfolder/s/stinging_scorpion.txt @@ -0,0 +1,8 @@ +Name:Stinging Scorpion +ManaCost:4 B +Types:Host Creature Scorpion +PT:3/2 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | Host$ True | TriggerDescription$ When this creature enters the battlefield, target creature an opponent controls gets -1/-1 until end of turn. +SVar:TrigPump:DB$ Pump | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls. | NumAtt$ -1 | NumDef$ -1 | IsCurse$ True +SVar:PlayMain1:TRUE +Oracle:When this creature enters the battlefield, target creature an opponent controls gets -1/-1 until end of turn. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/s/sunglasses_of_urza.txt b/forge-gui/res/cardsfolder/s/sunglasses_of_urza.txt index 62d4c2dd3bf..5cb606b55e5 100644 --- a/forge-gui/res/cardsfolder/s/sunglasses_of_urza.txt +++ b/forge-gui/res/cardsfolder/s/sunglasses_of_urza.txt @@ -1,8 +1,6 @@ Name:Sunglasses of Urza ManaCost:3 Types:Artifact -S:Mode$ Continuous | Affected$ You | ManaColorConversion$ Additive | WhiteConversion$ Red | Description$ You may spend white mana as though it were red mana. -AI:RemoveDeck:Random +S:Mode$ Continuous | Affected$ You | ManaConversion$ W->R | Description$ You may spend white mana as though it were red mana. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/sunglasses_of_urza.jpg Oracle:You may spend white mana as though it were red mana. diff --git a/forge-gui/res/cardsfolder/upcoming/revival_experiment.txt b/forge-gui/res/cardsfolder/upcoming/revival_experiment.txt new file mode 100644 index 00000000000..1480317778a --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/revival_experiment.txt @@ -0,0 +1,14 @@ +Name:Revival Experiment +ManaCost:4 B G +Types:Sorcery +A:SP$ ChangeZone | Cost$ 4 B G | ChangeType$ Creature.YouOwn | Origin$ Graveyard | Destination$ Battlefield | Hidden$ True | Chooser$ You | ChangeNum$ 1 | RememberChanged$ True | SubAbility$ ChoosePlaneswalker +SVar:ChoosePlaneswalker:DB$ ChangeZone | ChangeType$ Planeswalker.YouOwn | Origin$ Graveyard | Destination$ Battlefield | Hidden$ True | Chooser$ You | ChangeNum$ 1 | RememberChanged$ True | SubAbility$ ChooseArtifact +SVar:ChooseArtifact:DB$ ChangeZone | ChangeType$ Artifact.YouOwn | Origin$ Graveyard | Destination$ Battlefield | Hidden$ True | Chooser$ You | ChangeNum$ 1 | RememberChanged$ True | SubAbility$ ChooseEnchantment +SVar:ChooseEnchantment:DB$ ChangeZone | ChangeType$ Enchantment.YouOwn | Origin$ Graveyard | Destination$ Battlefield | Hidden$ True | Chooser$ You | ChangeNum$ 1 | RememberChanged$ True | SubAbility$ ChooseLand +SVar:ChooseLand:DB$ ChangeZone | ChangeType$ Land.YouOwn | Origin$ Graveyard | Destination$ Battlefield | Hidden$ True | Chooser$ You | ChangeNum$ 1 | RememberChanged$ True | SubAbility$ DBLoseLife +SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ Y | SubAbility$ DBChange +SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | StackDescription$ None +SVar:X:Remembered$Amount +SVar:Y:SVar$X/Times.3 +DeckHas:Ability$Graveyard +Oracle:For each permanent type, return up to one card of that type from your graveyard to the battlefield. You lose 3 life for each card returned this way. Exile Revival Experiment. diff --git a/forge-gui/res/cardsfolder/v/voracious_vacuum.txt b/forge-gui/res/cardsfolder/v/voracious_vacuum.txt new file mode 100644 index 00000000000..95362de5ce8 --- /dev/null +++ b/forge-gui/res/cardsfolder/v/voracious_vacuum.txt @@ -0,0 +1,7 @@ +Name:Voracious Vacuum +ManaCost:3 +Types:Artifact Host Creature Construct +PT:1/1 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPut | Host$ True | TriggerDescription$ When this creature enters the battlefield, put a +1/+1 counter on target creature. +SVar:TrigPut:DB$PutCounter | ValidTgts$ Creature | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ 1 +Oracle:When this creature enters the battlefield, put a +1/+1 counter on target creature. diff --git a/forge-gui/res/cardsfolder/w/wild_crocodile.txt b/forge-gui/res/cardsfolder/w/wild_crocodile.txt new file mode 100644 index 00000000000..be4fdb52153 --- /dev/null +++ b/forge-gui/res/cardsfolder/w/wild_crocodile.txt @@ -0,0 +1,7 @@ +Name:Wild Crocodile +ManaCost:1 G +Types:Host Creature Crocodile +PT:1/1 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChange | Host$ True | TriggerDescription$ When this creature enters the battlefield, search your library for a basic land card, reveal it, put it into your hand, then shuffle your library. +SVar:TrigChange:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Land.Basic | ChangeNum$ 1 +Oracle:When this creature enters the battlefield, search your library for a basic land card, reveal it, put it into your hand, then shuffle your library. diff --git a/forge-gui/res/editions/Commander 2021.txt b/forge-gui/res/editions/Commander 2021.txt index ee4103e36ed..13286349526 100644 --- a/forge-gui/res/editions/Commander 2021.txt +++ b/forge-gui/res/editions/Commander 2021.txt @@ -283,15 +283,39 @@ Type=Other 338 R Angel of the Ruins 339 R Archaeomancer's Map 340 R Bronze Guardian +341 R Combat Calligrapher 342 R Digsite Engineer 343 R Excavation Technique +344 R Guardian Archon 345 R Losheel, Clockwork Scholar 346 R Monologue Tax +347 R Nils, Discipline Enforcer +348 R Promise of Loyalty +349 R Scholarship Sponsor +350 R Commander's Insight +351 R Curiosity Crafter 352 R Dazzling Sphinx +353 R Deekah, Fractal Theorist 354 R Inspiring Refrain 355 R Muse Vortex 356 R Octavia, Living Thesis +357 R Perplexing Test +358 R Replication Technique 359 R Sly Instigator +360 R Spawning Kraken +361 R Theoretical Duplication +362 R Author of Shadows +363 R Blight Mound +364 R Bold Plagiarist +365 R Cunning Rhetoric +366 R Essence Pulse +367 R Fain, the Broker +368 R Incarnation Technique +369 R Keen Duelist +370 R Marshland Bloodcaster +371 R Stinging Study +372 R Tivash, Gloom Summoner +373 R Veinwitch Coven 374 R Audacious Reshapers 375 R Battlemage's Bracers 376 R Creative Technique @@ -304,9 +328,27 @@ Type=Other 383 R Rousing Refrain 384 R Ruin Grinder 385 R Surge to Victory -400 R Reinterpret -402 R Wake the Past 386 R Blossoming Bogbeast +387 R Ezzaroot Channeler +388 R Fractal Harness +389 R Guardian Augmenter +390 R Healing Technique +391 R Paradox Zone +392 R Pest Infestation +393 R Ruxa, Patient Professor +394 R Sequence Engine +395 R Sproutback Trudge +396 R Trudge Garden +397 R Yedora, Grave Gardener +398 R Inkshield +399 R Oversimplify +400 R Reinterpret +401 R Revival Experiment +402 R Wake the Past +403 R Elementalist's Palette +404 R Geometric Nexus +405 R Tempting Contract +406 R Triplicate Titan +407 R Witch's Clinic 408 C Tranquil Thicket 409 R Yavimaya Coast - diff --git a/forge-gui/res/editions/Unsanctioned.txt b/forge-gui/res/editions/Unsanctioned.txt index 79219364c8a..0ed775d941b 100644 --- a/forge-gui/res/editions/Unsanctioned.txt +++ b/forge-gui/res/editions/Unsanctioned.txt @@ -8,7 +8,7 @@ Type=Funny Border=Silver [cards] -1 C Adorable // Kitten +1 C Adorable Kitten 2 C AWOL 3 U Emcee 4 R Flavor Judge diff --git a/forge-gui/res/editions/Unstable.txt b/forge-gui/res/editions/Unstable.txt index c23f15323fe..a83388e68ae 100644 --- a/forge-gui/res/editions/Unstable.txt +++ b/forge-gui/res/editions/Unstable.txt @@ -30,12 +30,12 @@ U Knight of the Kitchen Sink F 14 U Midlife Upgrade 15 R Oddly Uneven 16 C Old Guard -17 C Ordinary // Pony +17 C Ordinary Pony 18 U Rhino- 19 C Riveting Rigger 20 R Rules Lawyer 21 C Sacrifice Play -22 C Shaggy // Camel +22 C Shaggy Camel 23 U Side Quest 24 C Success! 25 U Teacher's Pet @@ -43,7 +43,7 @@ U Knight of the Kitchen Sink F 27 C Blurry Beeble 28 C Chipper Chopper 29 R Clocknapper -30 C Crafty // Octopus +30 C Crafty Octopus 31 U Crow Storm 32 C Defective Detective 33 U Five-Finger Discount @@ -52,13 +52,13 @@ U Knight of the Kitchen Sink F 36 R Incite Insight 37 U Kindly Cognician 38 C Magic Word -39 C Mer // Man +39 C Mer Man 40 U More or Less C Novellamental C Novellamental C Novellamental C Novellamental -42 C Numbing // Jellyfish +42 C Numbing Jellyfish 43 U S.N.E.A.K. Dispatcher 44 U Socketed Sprocketer 45 C Spell Suck @@ -72,9 +72,9 @@ R Very Cryptic Command D R Very Cryptic Command E R Very Cryptic Command F 50 C Wall of Fortune -51 C Big Boa // Constrictor +51 C Big Boa Constrictor 52 C capital offense -53 C Dirty // Rat +53 C Dirty Rat C Extremely Slow Zombie C Extremely Slow Zombie C Extremely Slow Zombie @@ -101,16 +101,16 @@ U Sly Spy F 69 R Spike, Tournament Grinder 70 U Squirrel-Powered Scheme 71 C Steady-Handed Mook -72 C Stinging // Scorpion +72 C Stinging Scorpion 73 C Subcontract 74 M Summon the Pack 75 U Zombified 76 R The Big Idea 77 C Box of Free-Range Goblins -78 C Bumbling // Pangolin -79 C Common // Iguana +78 C Bumbling Pangolin +79 C Common Iguana 80 R The Countdown Is at One -81 C Feisty // Stegosaurus +81 C Feisty Stegosaurus U Garbage Elemental A U Garbage Elemental B U Garbage Elemental C @@ -147,7 +147,7 @@ C Beast in Show 104 U Chittering Doom 105 U Clever Combo 106 U Druid of the Sacred Beaker -107 C Eager // Beaver +107 C Eager Beaver 108 R Earl of Squirrel 109 U First Pick 110 U Ground Pounder @@ -161,7 +161,7 @@ R Ineffable Blessing E R Ineffable Blessing F 114 C Joyride Rigger 115 U Monkey- -116 C Mother // Kangaroo +116 C Mother Kangaroo 117 C Multi-Headed 118 C Really Epic Punch 119 C Selfie Preservation @@ -170,7 +170,7 @@ R Ineffable Blessing F 122 U Slaying Mantis 123 C Squirrel Dealer 124 U Steamflogger Service Rep -125 C Wild // Crocodile +125 C Wild Crocodile 126 C Willing Test Subject 127 M Baron Von Count 128 R Better Than One @@ -184,7 +184,7 @@ R Ineffable Blessing F 136 M Urza, Academy Headmaster 137 R X 138 R Mary O'Kill -139 R Angelic // Rocket +139 R Angelic Rocket 140 U Border Guardian 141 U Buzzing Whack-a-Doodle 142 U Clock of DOOOOOOOOOOOOM! @@ -201,11 +201,11 @@ R Everythingamajig C R Everythingamajig D R Everythingamajig E R Everythingamajig F -148 C Gnome-Made // Engine +148 C Gnome-Made Engine 149 R Handy Dandy Clone Machine 150 R Kindslaver 151 U Krark's Other Thumb -152 U Labro // Bot +152 U Labro Bot 153 U Lobe Lobber 154 C Mad Science Fair Project 155 R Modular Monstrosity @@ -217,7 +217,7 @@ R Everythingamajig F 161 U Steam-Powered 162 U Steel Squirrel 163 M Sword of Dungeons & Dragons -164 C Voracious // Vacuum +164 C Voracious Vacuum C Secret Base C Secret Base C Secret Base diff --git a/forge-gui/res/lists/TypeLists.txt b/forge-gui/res/lists/TypeLists.txt index 8c9a3180c44..367e45a1743 100644 --- a/forge-gui/res/lists/TypeLists.txt +++ b/forge-gui/res/lists/TypeLists.txt @@ -130,6 +130,7 @@ Insect:Insects Jackal:Jackals Jellyfish:Jellyfishes Juggernaut:Juggernauts +Kangaroo:Kangaroos Kavu:Kavu Killbot:Killbots Kirin:Kirins diff --git a/forge-gui/src/main/java/forge/gamemodes/limited/ArchetypeDeckBuilder.java b/forge-gui/src/main/java/forge/gamemodes/limited/ArchetypeDeckBuilder.java index 098ed65da1c..cfc3600f746 100644 --- a/forge-gui/src/main/java/forge/gamemodes/limited/ArchetypeDeckBuilder.java +++ b/forge-gui/src/main/java/forge/gamemodes/limited/ArchetypeDeckBuilder.java @@ -8,6 +8,7 @@ import forge.deck.io.Archetype; import forge.game.GameFormat; import forge.item.PaperCard; import forge.model.FModel; + import org.apache.commons.lang3.tuple.Pair; public class ArchetypeDeckBuilder extends CardThemedDeckBuilder{ diff --git a/forge-gui/src/main/java/forge/player/HumanPlay.java b/forge-gui/src/main/java/forge/player/HumanPlay.java index d116656f420..f8f2f87b0a5 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlay.java +++ b/forge-gui/src/main/java/forge/player/HumanPlay.java @@ -708,13 +708,17 @@ public class HumanPlay { ManaCostBeingPaid toPay = new ManaCostBeingPaid(realCost, mc.getRestiction()); String xInCard = source.getSVar("X"); + String xColor = ability.getParam("XColor"); + if (source.hasKeyword("Spend only colored mana on X. No more than one mana of each color may be spent this way.")) { + xColor = "WUBRGX"; + } if (mc.getAmountOfX() > 0 && !"Count$xPaid".equals(xInCard)) { // announce X will overwrite whatever was in card script int xPaid = AbilityUtils.calculateAmount(source, "X", ability); - toPay.setXManaCostPaid(xPaid, ability.getParam("XColor")); + toPay.setXManaCostPaid(xPaid, xColor); ability.setXManaCostPaid(xPaid); } else if (ability.getXManaCostPaid() != null) { //ensure pre-announced X value retained - toPay.setXManaCostPaid(ability.getXManaCostPaid(), ability.getParam("XColor")); + toPay.setXManaCostPaid(ability.getXManaCostPaid(), xColor); } int timesMultikicked = source.getKickerMagnitude(); diff --git a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java index cccc0f3c3df..ad2e95121f6 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java +++ b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java @@ -93,11 +93,10 @@ public class HumanPlaySpellAbility { ability = GameActionUtil.addExtraKeywordCost(ability); if (ability.isSpell() && !ability.isCopied()) { // These hidden keywords should only apply on the Stack - final Card host = ability.getHostCard(); - if (host.hasKeyword("May spend mana as though it were mana of any type to cast CARDNAME") + if (c.hasKeyword("May spend mana as though it were mana of any type to cast CARDNAME") || (option != null && option.isIgnoreManaCostType())) { manaTypeConversion = true; - } else if (host.hasKeyword("May spend mana as though it were mana of any color to cast CARDNAME") + } else if (c.hasKeyword("May spend mana as though it were mana of any color to cast CARDNAME") || (option != null && option.isIgnoreManaCostColor())) { manaColorConversion = true; } @@ -127,13 +126,12 @@ public class HumanPlaySpellAbility { if (ability.isAbility() && ability.isActivatedAbility()) { final Map params = Maps.newHashMap(); - params.put("ManaColorConversion", "Additive"); for (KeywordInterface inst : c.getKeywords()) { String keyword = inst.getOriginal(); if (keyword.startsWith("ManaConvert")) { final String[] k = keyword.split(":"); - params.put(k[1] + "Conversion", k[2]); + params.put("ManaConversion", k[1]); keywordColor = true; } } diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index f36bf4a921d..92128f2890b 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -396,6 +396,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont canChooseZero = false; } } + if (ability.getHostCard().hasKeyword("Spend only colored mana on X. No more than one mana of each color may be spent this way.")) { + max = 5; + } } final int min = canChooseZero ? 0 : 1;