diff --git a/forge-ai/pom.xml b/forge-ai/pom.xml index 86ceb211dab..b84adeea7d5 100644 --- a/forge-ai/pom.xml +++ b/forge-ai/pom.xml @@ -6,7 +6,7 @@ forge forge - 1.6.27-SNAPSHOT + 1.6.28-SNAPSHOT forge-ai diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index c775ed2e00c..89dfbcc4252 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -99,6 +99,8 @@ public class ComputerUtil { sa.resetPaidHash(); } + sa = GameActionUtil.addExtraKeywordCost(sa); + if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { CharmEffect.makeChoices(sa); } @@ -208,9 +210,9 @@ public class ComputerUtil { } // this is used for AI's counterspells - public static final boolean playStack(final SpellAbility sa, final Player ai, final Game game) { + public static final boolean playStack(SpellAbility sa, final Player ai, final Game game) { sa.setActivatingPlayer(ai); - if (!ComputerUtilCost.canPayCost(sa, ai)) + if (!ComputerUtilCost.canPayCost(sa, ai)) return false; final Card source = sa.getHostCard(); @@ -220,6 +222,9 @@ public class ComputerUtil { sa.setLastStateGraveyard(game.getLastStateGraveyard()); sa.setHostCard(game.getAction().moveToStack(source, sa)); } + + sa = GameActionUtil.addExtraKeywordCost(sa); + final Cost cost = sa.getPayCosts(); if (cost == null) { ComputerUtilMana.payManaCost(ai, sa); @@ -249,13 +254,15 @@ public class ComputerUtil { } public static final boolean playSpellAbilityWithoutPayingManaCost(final Player ai, final SpellAbility sa, final Game game) { - final SpellAbility newSA = sa.copyWithNoManaCost(); + SpellAbility newSA = sa.copyWithNoManaCost(); newSA.setActivatingPlayer(ai); if (!CostPayment.canPayAdditionalCosts(newSA.getPayCosts(), newSA)) { return false; } + newSA = GameActionUtil.addExtraKeywordCost(newSA); + final Card source = newSA.getHostCard(); if (newSA.isSpell() && !source.isCopiedSpell()) { source.setCastSA(newSA); @@ -275,7 +282,7 @@ public class ComputerUtil { return true; } - public static final void playNoStack(final Player ai, final SpellAbility sa, final Game game) { + public static final void playNoStack(final Player ai, SpellAbility sa, final Game game) { sa.setActivatingPlayer(ai); // TODO: We should really restrict what doesn't use the Stack if (ComputerUtilCost.canPayCost(sa, ai)) { @@ -287,6 +294,8 @@ public class ComputerUtil { sa.setHostCard(game.getAction().moveToStack(source, sa)); } + sa = GameActionUtil.addExtraKeywordCost(sa); + final Cost cost = sa.getPayCosts(); if (cost == null) { ComputerUtilMana.payManaCost(ai, sa); diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index df01caaf238..ab9be7a2d7c 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -25,6 +25,7 @@ import forge.game.card.*; import forge.game.card.CardPredicates.Presets; import forge.game.combat.Combat; import forge.game.cost.*; +import forge.game.keyword.KeywordInterface; import forge.game.mana.Mana; import forge.game.mana.ManaConversionMatrix; import forge.game.mana.ManaCostBeingPaid; @@ -1253,4 +1254,25 @@ public class PlayerControllerAi extends PlayerController { // Always true? return true; } + + @Override + public int chooseNumberForKeywordCost(SpellAbility sa, Cost cost, KeywordInterface keyword, String prompt, + int max) { + // TODO: improve the logic depending on the keyword and the playability of the cost-modified SA (enough targets present etc.) + int chosenAmount = 0; + + Cost costSoFar = sa.getPayCosts() != null ? sa.getPayCosts().copy() : Cost.Zero; + + for (int i = 0; i < max; i++) { + costSoFar.add(cost); + SpellAbility fullCostSa = sa.copyWithDefinedCost(costSoFar); + if (ComputerUtilCost.canPayCost(fullCostSa, player)) { + chosenAmount++; + } else { + break; + } + } + + return chosenAmount; + } } diff --git a/forge-core/pom.xml b/forge-core/pom.xml index b7a37945a7b..6d1913363d1 100644 --- a/forge-core/pom.xml +++ b/forge-core/pom.xml @@ -6,7 +6,7 @@ forge forge - 1.6.27-SNAPSHOT + 1.6.28-SNAPSHOT forge-core diff --git a/forge-game/pom.xml b/forge-game/pom.xml index 7b6e798417a..898e378a0a9 100644 --- a/forge-game/pom.xml +++ b/forge-game/pom.xml @@ -6,7 +6,7 @@ forge forge - 1.6.27-SNAPSHOT + 1.6.28-SNAPSHOT forge-game diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index c655377090c..4c0d1e54542 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -29,7 +29,9 @@ import forge.game.card.CardPlayOption.PayManaCost; import forge.game.cost.Cost; import forge.game.keyword.KeywordInterface; import forge.game.player.Player; +import forge.game.player.PlayerController; import forge.game.spellability.*; +import forge.game.trigger.Trigger; import forge.game.zone.ZoneType; import forge.util.TextUtil; import org.apache.commons.lang3.StringUtils; @@ -250,11 +252,6 @@ public final class GameActionUtil { if (keyword.startsWith("Buyback")) { final Cost cost = new Cost(keyword.substring(8), false); costs.add(new OptionalCostValue(OptionalCost.Buyback, cost)); - } else if (keyword.equals("Conspire")) { - final String conspireCost = "tapXType<2/Creature.SharesColorWith/" + - "untapped creature you control that shares a color with " + source.getName() + ">"; - final Cost cost = new Cost(conspireCost, false); - costs.add(new OptionalCostValue(OptionalCost.Conspire, cost)); } else if (keyword.startsWith("Entwine")) { String[] k = keyword.split(":"); final Cost cost = new Cost(k[1], false); @@ -301,15 +298,11 @@ public final class GameActionUtil { } final SpellAbility result = sa.copy(); for (OptionalCostValue v : list) { - // need to copy cost, otherwise it does alter the original - result.setPayCosts(result.getPayCosts().copy().add(v.getCost())); + result.getPayCosts().add(v.getCost()); result.addOptionalCost(v.getType()); // add some extra logic, try to move it to other parts switch (v.getType()) { - case Conspire: - result.addConspireInstance(); - break; case Retrace: case Jumpstart: result.getRestrictions().setZone(ZoneType.Graveyard); @@ -363,6 +356,71 @@ public final class GameActionUtil { return abilities; } + public static SpellAbility addExtraKeywordCost(final SpellAbility sa) { + if (!sa.isSpell() || sa.isCopied()) { + return sa; + } + SpellAbility result = null; + final Card host = sa.getHostCard(); + final PlayerController pc = sa.getActivatingPlayer().getController(); + + host.getGame().getAction().checkStaticAbilities(false); + + boolean reset = false; + + for (KeywordInterface ki : host.getKeywords()) { + final String o = ki.getOriginal(); + if (o.equals("Conspire")) { + Trigger tr = Iterables.getFirst(ki.getTriggers(), null); + if (tr != null) { + final String conspireCost = "tapXType<2/Creature.SharesColorWith/" + + "untapped creature you control that shares a color with " + host.getName() + ">"; + final Cost cost = new Cost(conspireCost, false); + String str = "Pay for Conspire? " + cost.toSimpleString(); + + boolean v = pc.addKeywordCost(sa, cost, ki, str); + tr.setSVar("Conspire", v ? "1" : "0"); + + if (v) { + if (result == null) { + result = sa.copy(); + } + result.getPayCosts().add(cost); + reset = true; + } + } + } else if (o.startsWith("Replicate")) { + Trigger tr = Iterables.getFirst(ki.getTriggers(), null); + if (tr != null) { + String costStr = o.split(":")[1]; + final Cost cost = new Cost(costStr, false); + + String str = "Choose Amount for Replicate: " + cost.toSimpleString(); + + int v = pc.chooseNumberForKeywordCost(sa, cost, ki, str, Integer.MAX_VALUE); + + tr.setSVar("ReplicateAmount", String.valueOf(v)); + tr.getOverridingAbility().setSVar("ReplicateAmount", String.valueOf(v)); + + for (int i = 0; i < v; i++) { + if (result == null) { + result = sa.copy(); + } + result.getPayCosts().add(cost); + reset = true; + } + } + } + } + + // reset active Trigger + if (reset) { + host.getGame().getTriggerHandler().resetActiveTriggers(false); + } + + return result != null ? result : sa; + } + private static boolean hasUrzaLands(final Player p) { final CardCollectionView landsControlled = p.getCardsIn(ZoneType.Battlefield); return Iterables.any(landsControlled, Predicates.and(CardPredicates.isType("Urza's"), CardPredicates.isType("Mine"))) 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 72ac2d57344..d1e4633ea37 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -1843,7 +1843,11 @@ public class AbilityUtils { public static SpellAbility addSpliceEffects(final SpellAbility sa) { final Card source = sa.getHostCard(); final Player player = sa.getActivatingPlayer(); - + + if (!sa.isSpell() || source.isCopiedSpell()) { + return sa; + } + final CardCollectionView hand = player.getCardsIn(ZoneType.Hand); if (hand.isEmpty()) { 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 2c52dc2a270..20797fb1b74 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1905,13 +1905,14 @@ public class Card extends GameEntity implements Comparable { } sb.append(keywordsToText(getUnhiddenKeywords(state))); - // Process replacement effects first so that ETB tabbed can be printed + // Process replacement effects first so that "enters the battlefield tapped" + // and "as ~ enters the battlefield, choose...", etc can be printed // here. The rest will be printed later. StringBuilder replacementEffects = new StringBuilder(); for (final ReplacementEffect replacementEffect : state.getReplacementEffects()) { if (!replacementEffect.isSecondary()) { String text = replacementEffect.toString(); - if (text.equals("CARDNAME enters the battlefield tapped.")) { + if (text.contains("enters the battlefield")) { sb.append(text).append("\r\n"); } else { replacementEffects.append(text).append("\r\n"); diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index a6e70c9eae6..a53d25c23ad 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -2361,11 +2361,12 @@ public class CardFactoryUtil { inst.addTrigger(parsedTrigger); inst.addTrigger(parsedTrigReturn); } else if (keyword.equals("Conspire")) { - final String trigScript = "Mode$ SpellCast | ValidCard$ Card.Self | Conspire$ True | Secondary$ True | TriggerDescription$ Copy CARDNAME if its conspire cost was paid"; + final String trigScript = "Mode$ SpellCast | ValidCard$ Card.Self | CheckSVar$ Conspire | Secondary$ True | TriggerDescription$ Copy CARDNAME if its conspire cost was paid"; final String abString = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ 1"; final Trigger conspireTrigger = TriggerHandler.parseTrigger(trigScript, card, intrinsic); conspireTrigger.setOverridingAbility(AbilityFactory.getAbility(abString, card)); + conspireTrigger.setSVar("Conspire", "0"); inst.addTrigger(conspireTrigger); } else if (keyword.startsWith("Cumulative upkeep")) { final String[] k = keyword.split(":"); @@ -2942,6 +2943,17 @@ public class CardFactoryUtil { + " exile CARDNAME. | Secondary$ True"; final Trigger myTrigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic); inst.addTrigger(myTrigger); + } else if (keyword.startsWith("Replicate")) { + final String trigScript = "Mode$ SpellCast | ValidCard$ Card.Self | CheckSVar$ ReplicateAmount | Secondary$ True | TriggerDescription$ Copy CARDNAME for each time you paid its replicate cost"; + final String abString = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ ReplicateAmount"; + + final Trigger replicateTrigger = TriggerHandler.parseTrigger(trigScript, card, intrinsic); + final SpellAbility replicateAbility = AbilityFactory.getAbility(abString, card); + replicateAbility.setSVar("ReplicateAmount", "0"); + replicateTrigger.setOverridingAbility(replicateAbility); + replicateTrigger.setSVar("ReplicateAmount", "0"); + inst.addTrigger(replicateTrigger); + } else if (keyword.startsWith("Ripple")) { final String[] k = keyword.split(":"); final String num = k[1]; @@ -4225,9 +4237,6 @@ public class CardFactoryUtil { sa.setTemporary(!intrinsic); inst.addSpellAbility(sa); - - } else if (keyword.startsWith("Replicate")) { - card.getFirstSpellAbility().addAnnounceVar("Replicate"); } else if (keyword.startsWith("Scavenge")) { final String[] k = keyword.split(":"); final String manacost = k[1]; diff --git a/forge-game/src/main/java/forge/game/player/PlayerController.java b/forge-game/src/main/java/forge/game/player/PlayerController.java index fc0c09a2625..eb432ef4d5e 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -19,6 +19,7 @@ import forge.game.combat.Combat; import forge.game.cost.Cost; import forge.game.cost.CostPart; import forge.game.cost.CostPartMana; +import forge.game.keyword.KeywordInterface; import forge.game.mana.Mana; import forge.game.mana.ManaConversionMatrix; import forge.game.replacement.ReplacementEffect; @@ -47,7 +48,6 @@ public abstract class PlayerController { DeclareBlocker, Echo, Multikicker, - Replicate, CumulativeUpkeep, } @@ -182,6 +182,11 @@ public abstract class PlayerController { public abstract CardCollection chooseCardsToDiscardToMaximumHandSize(int numDiscard); public abstract boolean payManaOptional(Card card, Cost cost, SpellAbility sa, String prompt, ManaPaymentPurpose purpose); + public abstract int chooseNumberForKeywordCost(SpellAbility sa, Cost cost, KeywordInterface keyword, String prompt, int max); + public boolean addKeywordCost(SpellAbility sa, Cost cost, KeywordInterface keyword, String prompt) { + return chooseNumberForKeywordCost(sa, cost, keyword, prompt, 1) == 1; + } + public abstract int chooseNumber(SpellAbility sa, String title, int min, int max); public abstract int chooseNumber(SpellAbility sa, String title, List values, Player relatedPlayer); public int chooseNumber(SpellAbility sa, String string, int min, int max, Map params) { diff --git a/forge-game/src/main/java/forge/game/spellability/OptionalCost.java b/forge-game/src/main/java/forge/game/spellability/OptionalCost.java index 64976a1670b..536edca813f 100644 --- a/forge-game/src/main/java/forge/game/spellability/OptionalCost.java +++ b/forge-game/src/main/java/forge/game/spellability/OptionalCost.java @@ -5,7 +5,6 @@ package forge.game.spellability; * */ public enum OptionalCost { - Conspire("Conspire"), Buyback("Buyback"), Entwine("Entwine"), Kicker1("Kicker"), diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 60c6426cc85..6b9045a22fd 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -144,7 +144,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit private CardCollection tappedForConvoke = new CardCollection(); private Card sacrificedAsOffering = null; private Card sacrificedAsEmerge = null; - private int conspireInstances = 0; private AbilityManaPart manaPart = null; @@ -301,9 +300,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } public boolean canPlayWithOptionalCost(OptionalCostValue opt) { - SpellAbility saCopy = this.copy(); - saCopy = GameActionUtil.addOptionalCosts(saCopy, Lists.newArrayList(opt)); - return saCopy.canPlay(); + return GameActionUtil.addOptionalCosts(this, Lists.newArrayList(opt)).canPlay(); } public boolean isPossible() { @@ -1700,19 +1697,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit return ForgeScript.spellAbilityHasProperty(this, property, sourceController, source, spellAbility); } - // Methods enabling multiple instances of conspire - public void addConspireInstance() { - conspireInstances++; - } - - public void subtractConspireInstance() { - conspireInstances--; - } - - public int getConspireInstances() { - return conspireInstances; - } // End of Conspire methods - public boolean isCumulativeupkeep() { return cumulativeupkeep; } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java b/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java index c516ebcb748..0dc88c7c789 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java @@ -32,7 +32,6 @@ import forge.game.card.CardLists; import forge.game.card.CardUtil; import forge.game.cost.Cost; import forge.game.player.Player; -import forge.game.spellability.OptionalCost; import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.TargetChoices; @@ -216,18 +215,6 @@ public class TriggerSpellAbilityCast extends Trigger { } } - if (hasParam("Conspire")) { - if (!spellAbility.isOptionalCostPaid(OptionalCost.Conspire)) { - return false; - } - if (spellAbility.getConspireInstances() == 0) { - return false; - } else { - spellAbility.subtractConspireInstance(); - //System.out.println("Conspire instances left = " + spellAbility.getConspireInstances()); - } - } - if (hasParam("Outlast")) { if (!spellAbility.isOutlast()) { return false; diff --git a/forge-game/src/main/java/forge/game/zone/MagicStack.java b/forge-game/src/main/java/forge/game/zone/MagicStack.java index 0c3907380c9..df1ace5a315 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -38,7 +38,6 @@ import forge.card.mana.ManaCost; import forge.game.Game; import forge.game.GameLogEntryType; import forge.game.GameObject; -import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.card.Card; @@ -58,7 +57,6 @@ import forge.game.player.PlayerController.ManaPaymentPurpose; import forge.game.replacement.ReplacementEffect; import forge.game.replacement.ReplacementHandler; import forge.game.replacement.ReplacementLayer; -import forge.game.spellability.AbilitySub; import forge.game.spellability.AbilityStatic; import forge.game.spellability.OptionalCost; import forge.game.spellability.Spell; @@ -319,35 +317,6 @@ public class MagicStack /* extends MyObservable */ implements Iterablejar -Xms1024m -Xmx1536m - 1.6.26.001 + 1.6.27.001 keystore alias storepass @@ -19,7 +19,7 @@ forge forge - 1.6.27-SNAPSHOT + 1.6.28-SNAPSHOT forge-gui-android diff --git a/forge-gui-desktop/pom.xml b/forge-gui-desktop/pom.xml index a46c9d91fd3..9d7e5e8dc9d 100644 --- a/forge-gui-desktop/pom.xml +++ b/forge-gui-desktop/pom.xml @@ -4,7 +4,7 @@ forge forge - 1.6.27-SNAPSHOT + 1.6.28-SNAPSHOT forge-gui-desktop diff --git a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java index 2e7bfcafb12..b34414575e6 100644 --- a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java +++ b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java @@ -29,6 +29,7 @@ import forge.game.combat.CombatUtil; import forge.game.cost.Cost; import forge.game.cost.CostPart; import forge.game.cost.CostPartMana; +import forge.game.keyword.KeywordInterface; import forge.game.mana.Mana; import forge.game.mana.ManaConversionMatrix; import forge.game.mana.ManaCostBeingPaid; @@ -695,4 +696,11 @@ public class PlayerControllerForTests extends PlayerController { return false; } + @Override + public int chooseNumberForKeywordCost(SpellAbility sa, Cost cost, KeywordInterface keyword, String prompt, + int max) { + // TODO Auto-generated method stub + return 0; + } + } diff --git a/forge-gui-ios/pom.xml b/forge-gui-ios/pom.xml index 6cf49bae10c..c5b17b60e00 100644 --- a/forge-gui-ios/pom.xml +++ b/forge-gui-ios/pom.xml @@ -6,13 +6,13 @@ jar -Xms128m -Xmx2048m - 1.6.26.001 + 1.6.27.001 forge forge - 1.6.27-SNAPSHOT + 1.6.28-SNAPSHOT forge-gui-ios diff --git a/forge-gui-mobile-dev/pom.xml b/forge-gui-mobile-dev/pom.xml index 72e6d85ba06..0495a297461 100644 --- a/forge-gui-mobile-dev/pom.xml +++ b/forge-gui-mobile-dev/pom.xml @@ -4,7 +4,7 @@ forge forge - 1.6.27-SNAPSHOT + 1.6.28-SNAPSHOT forge-gui-mobile-dev diff --git a/forge-gui-mobile/pom.xml b/forge-gui-mobile/pom.xml index 00726e8d5dc..20a2f4d148d 100644 --- a/forge-gui-mobile/pom.xml +++ b/forge-gui-mobile/pom.xml @@ -4,7 +4,7 @@ forge forge - 1.6.27-SNAPSHOT + 1.6.28-SNAPSHOT forge-gui-mobile diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index cb2b1720c95..d24e17319b4 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -34,7 +34,7 @@ import java.util.List; import java.util.Stack; public class Forge implements ApplicationListener { - public static final String CURRENT_VERSION = "1.6.26.001"; + public static final String CURRENT_VERSION = "1.6.27.001"; private static final ApplicationListener app = new Forge(); private static Clipboard clipboard; diff --git a/forge-gui/pom.xml b/forge-gui/pom.xml index d93a5621274..4e4c32c1e39 100644 --- a/forge-gui/pom.xml +++ b/forge-gui/pom.xml @@ -4,7 +4,7 @@ forge forge - 1.6.27-SNAPSHOT + 1.6.28-SNAPSHOT forge-gui diff --git a/forge-gui/release-files/ANNOUNCEMENTS.txt b/forge-gui/release-files/ANNOUNCEMENTS.txt index 6bd195c4d11..79d5f6697c0 100644 --- a/forge-gui/release-files/ANNOUNCEMENTS.txt +++ b/forge-gui/release-files/ANNOUNCEMENTS.txt @@ -1,7 +1,4 @@ #Add one announcement per line -Modern Horizons is here! -London Mulligans are here! (And on by default) -You can sideboard for the AI now, just turn on the preference. -New net deck categories are available via genetic algorithms and metagame top decks. +M20 pre-release! [b]Forge now requires Java 8 (or newer). You will not be able to start the game if you are not yet running Java 8.[/b] We have a Discord server for hanging out with Forge devs and other Forge fans. Feel free to [url=https://discord.gg/3v9JCVr]jump on in and say hi[/url]! \ No newline at end of file diff --git a/forge-gui/release-files/CHANGES.txt b/forge-gui/release-files/CHANGES.txt index e0db99a6c8a..05f0bf1829e 100644 --- a/forge-gui/release-files/CHANGES.txt +++ b/forge-gui/release-files/CHANGES.txt @@ -1,5 +1,2 @@ - Bug fixes - As always, this release of Forge features an assortment of bug fixes and improvements based on user feedback during the previous release run. - -- Random Modern World - -Just like the random standard world, there is now also a random modern world for quest mode that includes randomly generated deck archetypes and is limited to the modern card pool diff --git a/forge-gui/res/blockdata/printsheets.txt b/forge-gui/res/blockdata/printsheets.txt index 800c2b01023..e7091fba6c9 100644 --- a/forge-gui/res/blockdata/printsheets.txt +++ b/forge-gui/res/blockdata/printsheets.txt @@ -1524,3 +1524,33 @@ Oakenform Prized Unicorn Titanic Growth Woodland Mystic + +Bloodfell Caves +Blossoming Sands +Dismal Backwater +Jungle Hollow +Rugged Highlands +Scoured Barrens +Swiftwater Cliffs +Thornwood Falls +Tranquil Cove +Wind-Scarred Crag +Evolving Wilds + +[M20 Lands] +5 Bloodfell Caves|M20 +5 Blossoming Sands|M20 +5 Dismal Backwater|M20 +5 Jungle Hollow|M20 +5 Rugged Highlands|M20 +5 Scoured Barrens|M20 +5 Swiftwater Cliffs|M20 +5 Thornwood Falls|M20 +5 Tranquil Cove|M20 +5 Wind-Scarred Crag|M20 +5 Evolving Wilds +13 Forest|M20 +13 Island|M20 +13 Mountain|M20 +13 Plains|M20 +13 Swamp|M20 \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/a/aggressive_mammoth.txt b/forge-gui/res/cardsfolder/a/aggressive_mammoth.txt index de871da6862..d3305938085 100644 --- a/forge-gui/res/cardsfolder/a/aggressive_mammoth.txt +++ b/forge-gui/res/cardsfolder/a/aggressive_mammoth.txt @@ -3,5 +3,6 @@ ManaCost:3 G G G Types:Creature Elephant K:Trample S:Mode$ Continuous | Affected$ Creature.Other+YouCtrl | AddKeyword$ Trample | Description$ Other creatures you control have trample. +SVar:PlayMain1:TRUE Oracle:Trample (This creature can deal excess combat damage to the player or planeswalker it's attacking.)\nOther creatures you control have trample. PT:8/8 \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/a/ajani_inspiring_leader.txt b/forge-gui/res/cardsfolder/a/ajani_inspiring_leader.txt index 652df1bd506..4baf969b48e 100644 --- a/forge-gui/res/cardsfolder/a/ajani_inspiring_leader.txt +++ b/forge-gui/res/cardsfolder/a/ajani_inspiring_leader.txt @@ -7,5 +7,5 @@ SVar:DBPutCounter:DB$ PutCounter | CounterType$ P1P1 | CounterNum$ 2 | TargetMin A:AB$ ChangeZone | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBGainLife | SpellDescription$ Exile target creature. Its controller gains 2 life. SVar:DBGainLife:DB$ GainLife | Defined$ TargetedController | LifeAmount$ 2 A:AB$ PumpAll | Cost$ SubCounter<10/LOYALTY> | Planeswalker$ True | ValidCards$ Creature.YouCtrl | KW$ Flying & Double Strike | SpellDescription$ Creatures you control gain flying and double strike until end of turn. -DeckHas:Ability$Counters +DeckHas:Ability$Counters & Ability$LifeGain Oracle:[+2]: You gain 2 life. Put two +1/+1 counters on up to one target creature.\n[−3]: Exile target creature. Its controller gains 2 life.\n[−10]: Creatures you control gain flying and double strike until end of turn. diff --git a/forge-gui/res/cardsfolder/a/ajani_strength_of_the_pride.txt b/forge-gui/res/cardsfolder/a/ajani_strength_of_the_pride.txt index 76aa84ce9a1..fabd6d8c857 100644 --- a/forge-gui/res/cardsfolder/a/ajani_strength_of_the_pride.txt +++ b/forge-gui/res/cardsfolder/a/ajani_strength_of_the_pride.txt @@ -6,7 +6,7 @@ A:AB$ GainLife | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | LifeAmount$ SVar:NumCreatures:Count$Valid Creature.YouCtrl/Plus.NumPlaneswalkers SVar:NumPlaneswalkers:Count$Valid Planeswalker.YouCtrl A:AB$ Token | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | TokenScript$ ajanis_pridemate | LegacyImage$ ajanis pridemate m20 | SpellDescription$ Create a 2/2 white Cat Soldier creature token named Ajani's Pridemate with "Whenever you gain life, put a +1/+1 counter on Ajani's Pridemate." -DeckHas:Ability$Token +DeckHas:Ability$Token & Ability$Counters & Ability$LifeGain A:AB$ ChangeZoneAll | Cost$ SubCounter<0/LOYALTY> | ConditionCheckSVar$ CurLife | ConditionSVarCompare$ GEInitLife | References$ CurLife,InitLife | Planeswalker$ True | Ultimate$ True | ChangeType$ Card.Self,Creature.OppCtrl,Artifact.OppCtrl | Origin$ Battlefield | Destination$ Exile | SpellDescription$ If you have at least 15 life more than your starting life total, exile CARDNAME and each artifact and creature your opponents control. SVar:CurLife:Count$YourLifeTotal SVar:InitLife:Count$YourStartingLife/Plus.15 diff --git a/forge-gui/res/cardsfolder/a/ancestral_blade.txt b/forge-gui/res/cardsfolder/a/ancestral_blade.txt index 2898ee1cf52..03dd56627e3 100644 --- a/forge-gui/res/cardsfolder/a/ancestral_blade.txt +++ b/forge-gui/res/cardsfolder/a/ancestral_blade.txt @@ -6,7 +6,6 @@ SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_soldier | TokenOw SVar:DBAttach:DB$ Attach | Defined$ Remembered | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True DeckHas:Ability$Token -DeckHints:Type$White | Soldier S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 1 | AddToughness$ 1 | Description$ Equipped creature gets +1/+1. K:Equip:1 Oracle:When Ancestral Blade enters the battlefield, create a 1/1 white Soldier creature token, then attach Ancestral Blade to it.\nEquipped creature gets +1/+1.\nEquip {1} ({1}: Attach to target creature you control. Equip only as a sorcery.) diff --git a/forge-gui/res/cardsfolder/b/barkhide_troll.txt b/forge-gui/res/cardsfolder/b/barkhide_troll.txt index 06ed81c5086..0f7e4a35d9c 100644 --- a/forge-gui/res/cardsfolder/b/barkhide_troll.txt +++ b/forge-gui/res/cardsfolder/b/barkhide_troll.txt @@ -4,4 +4,5 @@ Types:Creature Troll PT:2/2 K:etbCounter:P1P1:1 A:AB$ Pump | Cost$ 1 SubCounter<1/P1P1> | KW$ Hexproof | Defined$ Self | SpellDescription$ CARDNAME gains hexproof until end of turn. +DeckHas:Ability$Counters Oracle:Barkhide Troll enters the battlefield with a +1/+1 counter on it.\n{1}, Remove a +1/+1 counter from Barkhide Troll: Barkhide Troll gains hexproof until end of turn. (It can't be the target of spells or abilities your opponents control.) diff --git a/forge-gui/res/cardsfolder/b/bishop_of_wings.txt b/forge-gui/res/cardsfolder/b/bishop_of_wings.txt index a78439a98e8..41424a50c5a 100644 --- a/forge-gui/res/cardsfolder/b/bishop_of_wings.txt +++ b/forge-gui/res/cardsfolder/b/bishop_of_wings.txt @@ -4,8 +4,7 @@ Types:Creature Human Cleric PT:1/4 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Angel.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigGainLife | TriggerDescription$ Whenever an Angel enters the battlefield under your control, you gain 4 life. SVar:TrigGainLife:DB$GainLife | Defined$ You | LifeAmount$ 4 -DeckHas:Ability$LifeGain T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Angel.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever an Angel you control dies, create a 1/1 white Spirit creature token with flying. SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_spirit_flying | TokenOwner$ You | LegacyImage$ w 1 1 spirit flying m20 -DeckHas:Ability$Token +DeckHas:Ability$Token & Ability$LifeGain Oracle:Whenever an Angel enters the battlefield under your control, you gain 4 life.\nWhenever an Angel you control dies, create a 1/1 white Spirit creature token with flying. diff --git a/forge-gui/res/cardsfolder/b/blood_burglar.txt b/forge-gui/res/cardsfolder/b/blood_burglar.txt index 47e1cb4fc9a..5708f2486b3 100644 --- a/forge-gui/res/cardsfolder/b/blood_burglar.txt +++ b/forge-gui/res/cardsfolder/b/blood_burglar.txt @@ -3,4 +3,5 @@ ManaCost:1 B Types:Creature Vampire Rogue PT:2/2 S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Lifelink | Condition$ PlayerTurn | Description$ As long as it's your turn, CARDNAME has lifelink. +DeckHas:Ability$LifeGain Oracle:As long as it's your turn, Blood Burglar has lifelink. (Damage dealt by this creature also causes you to gain that much life.) diff --git a/forge-gui/res/cardsfolder/b/bloodsoaked_altar.txt b/forge-gui/res/cardsfolder/b/bloodsoaked_altar.txt index 216e101d04a..ce386a4740e 100644 --- a/forge-gui/res/cardsfolder/b/bloodsoaked_altar.txt +++ b/forge-gui/res/cardsfolder/b/bloodsoaked_altar.txt @@ -3,5 +3,6 @@ ManaCost:4 B B Types:Artifact A:AB$ Token | Cost$ T PayLife<2> Discard<1/Card> Sac<1/Creature> | LegacyImage$ b 5 5 demon flying m20 | TokenAmount$ 1 | TokenScript$ b_5_5_demon_flying | TokenOwner$ You | SorcerySpeed$ True | SpellDescription$ Create a 5/5 black Demon creature token with flying. Activate this ability only any time you could play a sorcery. SVar:AIPreference:DiscardCost$Card +DeckHas:Ability$Token AI:RemoveDeck:Random Oracle:{T}, Pay 2 life, Discard a card, Sacrifice a creature: Create a 5/5 black Demon creature token with flying. Activate this ability only any time you could play a sorcery. diff --git a/forge-gui/res/cardsfolder/b/bloodthirsty_aerialist.txt b/forge-gui/res/cardsfolder/b/bloodthirsty_aerialist.txt index 3784f32537e..3889df4ab83 100644 --- a/forge-gui/res/cardsfolder/b/bloodthirsty_aerialist.txt +++ b/forge-gui/res/cardsfolder/b/bloodthirsty_aerialist.txt @@ -6,4 +6,5 @@ K:Flying T:Mode$ LifeGained | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever you gain life, put a +1/+1 counter on CARDNAME. SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 DeckHints:Ability$LifeGain +DeckHas:Ability$Counters Oracle:Flying\nWhenever you gain life, put a +1/+1 counter on Bloodthirsty Aerialist. diff --git a/forge-gui/res/cardsfolder/b/bone_splinters.txt b/forge-gui/res/cardsfolder/b/bone_splinters.txt index bc81b5a5ce1..7cce439a522 100644 --- a/forge-gui/res/cardsfolder/b/bone_splinters.txt +++ b/forge-gui/res/cardsfolder/b/bone_splinters.txt @@ -2,6 +2,7 @@ Name:Bone Splinters ManaCost:B Types:Sorcery A:SP$ Destroy | Cost$ B Sac<1/Creature> | ValidTgts$ Creature | TgtPrompt$ Select target creature | SpellDescription$ Destroy target creature. +SVar:AICostPreference:SacCost$Creature.Token,Creature.cmcLE2 AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/bone_splinters.jpg Oracle:As an additional cost to cast this spell, sacrifice a creature.\nDestroy target creature. diff --git a/forge-gui/res/cardsfolder/b/boneclad_necromancer.txt b/forge-gui/res/cardsfolder/b/boneclad_necromancer.txt index d60409f2d1b..ec893d367bd 100644 --- a/forge-gui/res/cardsfolder/b/boneclad_necromancer.txt +++ b/forge-gui/res/cardsfolder/b/boneclad_necromancer.txt @@ -6,4 +6,5 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creatu SVar:TrigExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Creature | SubAbility$ DBToken | RememberChanged$ True SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ b_2_2_zombie | TokenOwner$ You | LegacyImage$ b 2 2 zombie m20 | ConditionDefined$ Remembered | ConditionPresent$ Card.Creature | ConditionCompare$ EQ1 | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +DeckHas:Ability$Token Oracle:When Boneclad Necromancer enters the battlefield, you may exile target creature card from a graveyard. If you do, create a 2/2 black Zombie creature token. diff --git a/forge-gui/res/cardsfolder/b/brineborn_cutthroat.txt b/forge-gui/res/cardsfolder/b/brineborn_cutthroat.txt index 4ee68eadee2..84ba7a1c872 100644 --- a/forge-gui/res/cardsfolder/b/brineborn_cutthroat.txt +++ b/forge-gui/res/cardsfolder/b/brineborn_cutthroat.txt @@ -5,4 +5,5 @@ PT:2/1 K:Flash T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | OpponentTurn$ True | Execute$ TrigPutCounter | TriggerDescription$ Whenever you cast a spell during an opponent's turn, put a +1/+1 counter on CARDNAME. SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 +DeckHas:Ability$Counters Oracle:Flash (You may cast this spell any time you could cast an instant.)\nWhenever you cast a spell during an opponent's turn, put a +1/+1 counter on Brineborn Cutthroat. diff --git a/forge-gui/res/cardsfolder/c/chandra_acolyte_of_flame.txt b/forge-gui/res/cardsfolder/c/chandra_acolyte_of_flame.txt index b277c7fda9b..c03f8abcbec 100644 --- a/forge-gui/res/cardsfolder/c/chandra_acolyte_of_flame.txt +++ b/forge-gui/res/cardsfolder/c/chandra_acolyte_of_flame.txt @@ -11,4 +11,5 @@ SVar:Play:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Car SVar:DBEffect:DB$ Effect | RememberObjects$ Targeted | ExileOnMoved$ Stack | ReplacementEffects$ ReplaceGraveyard | SVars$ MoveExile SVar:ReplaceGraveyard:Event$ Moved | ValidCard$ Card.IsRemembered | Origin$ Stack | Destination$ Graveyard | ReplaceWith$ MoveExile | Description$ If that card would be put into your graveyard this turn, exile it instead. SVar:MoveExile:DB$ ChangeZone | Defined$ ReplacedCard | Origin$ Stack | Destination$ Exile +DeckHas:Ability$Token Oracle:[0]: Put a loyalty counter on each red planeswalker you control.\n[0]: Create two 1/1 red Elemental creature tokens. They gain haste. Sacrifice them at the beginning of the next end step.\n:[-2]: You may cast target instant or sorcery with mana cost 3 or less card from your graveyard this turn. If that card would be put into your graveyard this turn, exile it instead. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/c/chandra_novice_pyromancer.txt b/forge-gui/res/cardsfolder/c/chandra_novice_pyromancer.txt index 52f8e122955..06426f87c62 100644 --- a/forge-gui/res/cardsfolder/c/chandra_novice_pyromancer.txt +++ b/forge-gui/res/cardsfolder/c/chandra_novice_pyromancer.txt @@ -5,4 +5,5 @@ Loyalty:5 A:AB$ PumpAll | Cost$ AddCounter<1/LOYALTY> | ValidCards$ Elemental.YouCtrl | NumAtt$ +2 | NumDef$ +0 | Planeswalker$ True | AILogic$ Always | SpellDescription$ Elementals you control get +2/+0 until end of turn. A:AB$ Mana | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | Produced$ R | Amount$ 2 | SpellDescription$ Add {R}{R}. A:AB$ DealDamage | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to any target. +DeckHints:Type$Elemental Oracle:[+1]: Elementals you control get +2/+0 until end of turn.\n[-1]: Add {R}{R}.\n[-2]: Chandra, Novice Pyromancer deals 2 damage to any target. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/c/chandras_spitfire.txt b/forge-gui/res/cardsfolder/c/chandras_spitfire.txt index 93d14a31c34..252b322d28f 100644 --- a/forge-gui/res/cardsfolder/c/chandras_spitfire.txt +++ b/forge-gui/res/cardsfolder/c/chandras_spitfire.txt @@ -3,7 +3,7 @@ ManaCost:2 R Types:Creature Elemental PT:1/3 K:Flying -T:Mode$ DamageDone | ValidSource$ Card | CombatDamage$ False | ValidTarget$ Opponent | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever an opponent is dealt noncombat damage, CARDNAME gets +3/+0 until end of turn. +T:Mode$ DamageDone | ValidSource$ Card,Emblem | CombatDamage$ False | ValidTarget$ Opponent | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever an opponent is dealt noncombat damage, CARDNAME gets +3/+0 until end of turn. SVar:TrigPump:DB$Pump | NumAtt$ +3 | NumDef$ +0 | Defined$ Self SVar:Picture:http://www.wizards.com/global/images/magic/general/chandras_spitfire.jpg Oracle:Flying\nWhenever an opponent is dealt noncombat damage, Chandra's Spitfire gets +3/+0 until end of turn. diff --git a/forge-gui/res/cardsfolder/c/creeping_trailblazer.txt b/forge-gui/res/cardsfolder/c/creeping_trailblazer.txt index 1f415d2e2da..71a41814542 100644 --- a/forge-gui/res/cardsfolder/c/creeping_trailblazer.txt +++ b/forge-gui/res/cardsfolder/c/creeping_trailblazer.txt @@ -7,4 +7,5 @@ SVar:PlayMain1:TRUE A:AB$ Pump | Cost$ 2 R G | NumAtt$ +X | NumDef$ +X | References$ X | SpellDescription$ CARDNAME gets +1/+1 until end of turn for each Elemental you control. SVar:X:Count$Valid Elemental.YouCtrl SVar:BuffedBy:Card.Elemental +DeckHints:Type$Elemental Oracle:Other Elementals you control get +1/+0.\n{2}{R}{G}: Creeping Trailblazer gets +1/+1 until end of turn for each Elemental you control. diff --git a/forge-gui/res/cardsfolder/d/dawning_angel.txt b/forge-gui/res/cardsfolder/d/dawning_angel.txt index 46bdea8b405..9fd103adfb7 100644 --- a/forge-gui/res/cardsfolder/d/dawning_angel.txt +++ b/forge-gui/res/cardsfolder/d/dawning_angel.txt @@ -5,4 +5,5 @@ PT:3/2 K:Flying T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigGainLife | TriggerDescription$ When CARDNAME enters the battlefield, you gain 4 life. SVar:TrigGainLife:DB$GainLife | LifeAmount$ 4 +DeckHas:Ability$LifeGain Oracle:Flying\nWhen Dawning Angel enters the battlefield, you gain 4 life. diff --git a/forge-gui/res/cardsfolder/d/diamond_knight.txt b/forge-gui/res/cardsfolder/d/diamond_knight.txt index 23b969d35c2..b25cea49b23 100644 --- a/forge-gui/res/cardsfolder/d/diamond_knight.txt +++ b/forge-gui/res/cardsfolder/d/diamond_knight.txt @@ -8,4 +8,5 @@ SVar:ChooseColor:DB$ ChooseColor | Defined$ You | SpellDescription$ As CARDNAME T:Mode$ SpellCast | ValidCard$ Card.ChosenColor | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever you cast a spell of the chosen color, put a +1/+1 counter on CARDNAME. SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 SVar:BuffedBy:Card.ChosenColor +DeckHas:Ability$Counters Oracle:Vigilance (Attacking doesn't cause this creature to tap.)\nAs Diamond Knight enters the battlefield, choose a color.\nWhenever you cast a spell of the chosen color, put a +1/+1 counter on Diamond Knight. diff --git a/forge-gui/res/cardsfolder/d/djinn_illuminatus.txt b/forge-gui/res/cardsfolder/d/djinn_illuminatus.txt index cf02c158cb2..c62da9fcf16 100644 --- a/forge-gui/res/cardsfolder/d/djinn_illuminatus.txt +++ b/forge-gui/res/cardsfolder/d/djinn_illuminatus.txt @@ -3,7 +3,7 @@ ManaCost:5 UR UR Types:Creature Djinn PT:3/5 K:Flying -K:Each instant and sorcery spell you cast has replicate. The replicate cost is equal to its mana cost. +S:Mode$ Continuous | AddKeyword$ Replicate:CardManaCost | Affected$ Instant.YouCtrl,Sorcery.YouCtrl | AffectedZone$ Stack | EffectZone$ Battlefield | Description$ Each instant and sorcery spell you cast has replicate. The replicate cost is equal to its mana cost. (When you cast it, copy it for each time you paid its replicate cost. You may choose new targets for the copies.) AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/djinn_illuminatus.jpg Oracle:Flying\nEach instant and sorcery spell you cast has replicate. The replicate cost is equal to its mana cost. (When you cast it, copy it for each time you paid its replicate cost. You may choose new targets for the copies.) diff --git a/forge-gui/res/cardsfolder/f/ferocious_pup.txt b/forge-gui/res/cardsfolder/f/ferocious_pup.txt index 84e4a842f81..b4d9366ee39 100644 --- a/forge-gui/res/cardsfolder/f/ferocious_pup.txt +++ b/forge-gui/res/cardsfolder/f/ferocious_pup.txt @@ -4,4 +4,5 @@ Types:Creature Wolf PT:0/1 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a 2/2 green Wolf creature token. SVar:TrigToken:DB$ Token | LegacyImage$ g 2 2 wolf m20 | TokenAmount$ 1 | TokenScript$ g_2_2_wolf | TokenOwner$ You +DeckHas:Ability$Token Oracle:When Ferocious Pup enters the battlefield, create a 2/2 green Wolf creature token. diff --git a/forge-gui/res/cardsfolder/f/field_of_the_dead.txt b/forge-gui/res/cardsfolder/f/field_of_the_dead.txt index 80b86abe1df..0f2d594a78e 100644 --- a/forge-gui/res/cardsfolder/f/field_of_the_dead.txt +++ b/forge-gui/res/cardsfolder/f/field_of_the_dead.txt @@ -7,4 +7,5 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.S T:Mode$ ChangesZone | TriggerZones$ Battlefield | CheckSVar$ X | SVarCompare$ GE7 | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.YouCtrl | Execute$ TrigToken | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another land enters the battlefield under your control, if you control seven or more lands with different names, create a 2/2 black Zombie creature token. SVar:TrigToken:DB$ Token | TokenScript$ b_2_2_zombie | TokenOwner$ You | TokenAmount$ 1 | LegacyImage$ b 2 2 zombie m20 SVar:X:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield +DeckHas:Ability$Token Oracle:Field of the Dead enters the battlefield tapped.\n{T}: Add {C}.\nWhenever Field of the Dead or another land enters the battlefield under your control, if you control seven or more lands with different names, create a 2/2 black Zombie creature token. diff --git a/forge-gui/res/cardsfolder/g/gift_of_paradise.txt b/forge-gui/res/cardsfolder/g/gift_of_paradise.txt index 614ee8b1ad4..8015e59da5d 100644 --- a/forge-gui/res/cardsfolder/g/gift_of_paradise.txt +++ b/forge-gui/res/cardsfolder/g/gift_of_paradise.txt @@ -7,5 +7,6 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.S SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 3 S:Mode$ Continuous | Affected$ Card.EnchantedBy | AddAbility$ AbundantGrowthTap | Description$ Enchanted land has "{T}: Add two mana of any one color." SVar:AbundantGrowthTap:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 2 | SpellDescription$ Add two mana of any one color. +DeckHas:Ability$LifeGain SVar:Picture:http://www.wizards.com/global/images/magic/general/gift_of_paradise.jpg Oracle:Enchant land\nWhen Gift of Paradise enters the battlefield, you gain 3 life.\nEnchanted land has "{T}: Add two mana of any one color." \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/g/goblin_ringleader.txt b/forge-gui/res/cardsfolder/g/goblin_ringleader.txt index 3c65ae8b8da..e5007673f84 100644 --- a/forge-gui/res/cardsfolder/g/goblin_ringleader.txt +++ b/forge-gui/res/cardsfolder/g/goblin_ringleader.txt @@ -5,5 +5,6 @@ PT:2/2 K:Haste T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigDig | TriggerDescription$ When CARDNAME enters the battlefield, reveal the top four cards of your library. Put all Goblin cards revealed this way into your hand and the rest on the bottom of your library in any order. SVar:TrigDig:DB$Dig | DigNum$ 4 | Reveal$ True | ChangeNum$ All | ChangeValid$ Goblin +DeckHints:Type$Goblin SVar:Picture:http://resources.wizards.com/magic/cards/ap/en-us/card27664.jpg Oracle:Haste\nWhen Goblin Ringleader enters the battlefield, reveal the top four cards of your library. Put all Goblin cards revealed this way into your hand and the rest on the bottom of your library in any order. diff --git a/forge-gui/res/cardsfolder/g/gorging_vulture.txt b/forge-gui/res/cardsfolder/g/gorging_vulture.txt index 3be0c5cbabe..b98189d5911 100644 --- a/forge-gui/res/cardsfolder/g/gorging_vulture.txt +++ b/forge-gui/res/cardsfolder/g/gorging_vulture.txt @@ -8,5 +8,5 @@ SVar:TrigMill:DB$ Mill | NumCards$ 4 | Defined$ You | RememberMilled$ True | Sub SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ X | References$ X | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:Remembered$Valid Card.Creature -DeckHas:Ability$Graveyard +DeckHas:Ability$Graveyard & Ability$LifeGain Oracle:Flying\nWhen Gorging Vulture enters the battlefield, put the top four cards of your library into your graveyard. You gain 1 life for each creature card put into your graveyard this way. diff --git a/forge-gui/res/cardsfolder/h/healer_of_the_glade.txt b/forge-gui/res/cardsfolder/h/healer_of_the_glade.txt index 60e31adda80..65a4ca8c881 100644 --- a/forge-gui/res/cardsfolder/h/healer_of_the_glade.txt +++ b/forge-gui/res/cardsfolder/h/healer_of_the_glade.txt @@ -4,4 +4,5 @@ Types:Creature Elemental PT:1/2 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigGainLife | TriggerDescription$ When CARDNAME enters the battlefield, you gain 3 life. SVar:TrigGainLife:DB$GainLife | LifeAmount$ 3 +DeckHas:Ability$LifeGain Oracle:When Healer of the Glade enters the battlefield, you gain 3 life. diff --git a/forge-gui/res/cardsfolder/h/herald_of_the_sun.txt b/forge-gui/res/cardsfolder/h/herald_of_the_sun.txt index fe1c7e158f2..edff98a7a5d 100644 --- a/forge-gui/res/cardsfolder/h/herald_of_the_sun.txt +++ b/forge-gui/res/cardsfolder/h/herald_of_the_sun.txt @@ -4,4 +4,5 @@ Types:Creature Angel PT:4/4 K:Flying A:AB$ PutCounter | Cost$ 3 W | ValidTgts$ Creature.Other+withFlying | TgtPrompt$ Select another target creature with flying | CounterType$ P1P1 | CounterNum$ 1 | SpellDescription$ Put a +1/+1 counter on another target creature with flying. +DeckHas:Ability$Counters Oracle:Flying\n{3}{W}: Put a +1/+1 counter on another target creature with flying. diff --git a/forge-gui/res/cardsfolder/h/howling_giant.txt b/forge-gui/res/cardsfolder/h/howling_giant.txt index 24d81a87233..c20a5c12e06 100644 --- a/forge-gui/res/cardsfolder/h/howling_giant.txt +++ b/forge-gui/res/cardsfolder/h/howling_giant.txt @@ -5,4 +5,5 @@ PT:5/5 K:Reach T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create two 2/2 green Wolf creature tokens. SVar:TrigToken:DB$ Token | LegacyImage$ g 2 2 wolf m20 | TokenAmount$ 2 | TokenScript$ g_2_2_wolf | TokenOwner$ You +DeckHas:Ability$Token Oracle:Reach (This creature can block creatures with flying.)\nWhen Howling Giant enters the battlefield, create two 2/2 green Wolf creature tokens. diff --git a/forge-gui/res/cardsfolder/i/ironroot_warlord.txt b/forge-gui/res/cardsfolder/i/ironroot_warlord.txt index 2696a579c5d..0aaa55103de 100644 --- a/forge-gui/res/cardsfolder/i/ironroot_warlord.txt +++ b/forge-gui/res/cardsfolder/i/ironroot_warlord.txt @@ -5,4 +5,5 @@ PT:*/5 S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | Description$ CARDNAME's power is equal to the number of creatures you control. SVar:X:Count$Valid Creature.YouCtrl A:AB$ Token | Cost$ 3 G W | TokenAmount$ 1 | TokenScript$ w_1_1_soldier | TokenOwner$ You | LegacyImage$ w 1 1 soldier m20 | SpellDescription$ Create a 1/1 white Soldier creature token. +DeckHas:Ability$Token Oracle:Ironroot Warlord's power is equal to the number of creatures you control.\n{3}{G}{W}: Create a 1/1 white Soldier creature token. diff --git a/forge-gui/res/cardsfolder/k/kethis_the_hidden_hand.txt b/forge-gui/res/cardsfolder/k/kethis_the_hidden_hand.txt index 4c2732049c8..f09e6e8f538 100644 --- a/forge-gui/res/cardsfolder/k/kethis_the_hidden_hand.txt +++ b/forge-gui/res/cardsfolder/k/kethis_the_hidden_hand.txt @@ -5,4 +5,5 @@ PT:3/4 S:Mode$ ReduceCost | ValidCard$ Legendary | Type$ Spell | Activator$ You | Amount$ 1 | Description$ Legendary spells you cast cost {1} less to cast. A:AB$ Animate | Cost$ ExileFromGrave<2/Card.Legendary/legendary card> | staticAbilities$ Play | Defined$ ValidGraveyard Card.Legendary+YouOwn | SpellDescription$ Until end of turn, each legendary card in your graveyard gains "You may pay this card from your graveyard." SVar:Play:Mode$ Continuous | Affected$ Card.Self | EffectZone$ Graveyard | MayPlay$ True | Description$ You may pay this card from your graveyard. +DeckHints:Type$Legendary Oracle:Legendary spells you cast cost {1} less to cast.\nExile two legendary cards from your graveyard: Until end of turn, each legendary card in your graveyard gains "You may pay this card from your graveyard." diff --git a/forge-gui/res/cardsfolder/k/knight_of_the_ebon_legion.txt b/forge-gui/res/cardsfolder/k/knight_of_the_ebon_legion.txt index 266cd2f3479..0a79ffe99f5 100644 --- a/forge-gui/res/cardsfolder/k/knight_of_the_ebon_legion.txt +++ b/forge-gui/res/cardsfolder/k/knight_of_the_ebon_legion.txt @@ -6,4 +6,5 @@ A:AB$ Pump | Cost$ 2 B | NumAtt$ +3 | NumDef$ +3 | Defined$ Self | KW$ Deathtouc T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | CheckSVar$ X | SVarCompare$ GE4 | Execute$ TrigPutCounter | TriggerDescription$ At the beginning of your end step, if a player lost 4 or more life this turn, put a +1/+1 counter on CARDNAME. (Damage causes loss of life.) SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 SVar:X:PlayerCountOpponents$HighestLifeLostThisTurn +DeckHas:Ability$Counters Oracle:{2}{B}: Knight of the Ebon Legion gets +3/+3 and gains deathtouch until end of turn.\nAt the beginning of your end step, if a player lost 4 or more life this turn, put a +1/+1 counter on Knight of the Ebon Legion. (Damage causes loss of life.) diff --git a/forge-gui/res/cardsfolder/k/kykar_winds_fury.txt b/forge-gui/res/cardsfolder/k/kykar_winds_fury.txt index c92855307a2..fffc8968a2d 100644 --- a/forge-gui/res/cardsfolder/k/kykar_winds_fury.txt +++ b/forge-gui/res/cardsfolder/k/kykar_winds_fury.txt @@ -6,5 +6,6 @@ K:Flying T:Mode$ SpellCast | ValidCard$ Card.nonCreature | ValidActivatingPlayer$ You | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast a noncreature spell, create a 1/1 white Spirit creature token with flying. SVar:TrigToken:DB$ Token | LegacyImage$ w 1 1 spirit flying m20 | TokenAmount$ 1 | TokenScript$ w_1_1_spirit_flying | TokenOwner$ You SVar:BuffedBy:Card.nonCreature+nonLand +DeckHas:Ability$Counters A:AB$ Mana | Cost$ Sac<1/Spirit> | Produced$ R | SpellDescription$ Add {R}. Oracle:Flying\nWhenever you cast a noncreature spell, create a 1/1 white Spirit creature token with flying.\nSacrifice a Spirit: Add {R}. diff --git a/forge-gui/res/cardsfolder/l/leyline_of_abundance.txt b/forge-gui/res/cardsfolder/l/leyline_of_abundance.txt index 4bf5babc1db..fae11fd2ebd 100644 --- a/forge-gui/res/cardsfolder/l/leyline_of_abundance.txt +++ b/forge-gui/res/cardsfolder/l/leyline_of_abundance.txt @@ -6,4 +6,5 @@ SVar:FromHand:DB$ ChangeZone | Defined$ Self | Origin$ Hand | Destination$ Battl T:Mode$ TapsForMana | ValidCard$ Creature | Execute$ TrigMana | TriggerZones$ Battlefield | Static$ True | TriggerDescription$ Whenever you tap a creature for mana, add an additional {G}. SVar:TrigMana:DB$ Mana | Produced$ G A:AB$ PutCounterAll | Cost$ 6 G G | ValidCards$ Creature.YouCtrl | CounterType$ P1P1 | CounterNum$ 1 | SpellDescription$ Put a +1/+1 counter on each creature you control. +DeckHas:Ability$Counters Oracle:If Leyline of Abundance is in your opening hand, you may begin the game with it on the battlefield.\nWhenever you tap a creature for mana, add an additional {G}.\n{6}{G}{G}: Put a +1/+1 counter on each creature you control. diff --git a/forge-gui/res/cardsfolder/m/mask_of_immolation.txt b/forge-gui/res/cardsfolder/m/mask_of_immolation.txt index 56db5646f28..9ce881b7435 100644 --- a/forge-gui/res/cardsfolder/m/mask_of_immolation.txt +++ b/forge-gui/res/cardsfolder/m/mask_of_immolation.txt @@ -9,5 +9,6 @@ S:Mode$ Continuous | Affected$ Card.EquippedBy | AddAbility$ Damage | AddSVar$ T SVar:Damage:AB$DealDamage | Cost$ Sac<1/CARDNAME> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to any target. SVar:NonStackingAttachEffect:True AI:RemoveDeck:All +DeckHas:Ability$Token K:Equip:2 Oracle:When Mask of Immolation enters the battlefield, create a 1/1 red Elemental creature token, then attach Mask of Immolation to it.\nEquipped creature has "Sacrifice this creature: It deals 1 damage to any target."\nEquip {2} ({2}: Attach to target creature you control. Equip only as a sorcery.) diff --git a/forge-gui/res/cardsfolder/m/master_splicer.txt b/forge-gui/res/cardsfolder/m/master_splicer.txt index d2db060bd22..8299d0b7927 100644 --- a/forge-gui/res/cardsfolder/m/master_splicer.txt +++ b/forge-gui/res/cardsfolder/m/master_splicer.txt @@ -5,5 +5,6 @@ PT:1/1 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a 3/3 colorless Golem artifact creature token. SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_3_3_a_golem | TokenOwner$ You | LegacyImage$ c 3 3 a golem nph S:Mode$ Continuous | Affected$ Creature.Golem+YouCtrl | AddPower$ 1 | AddToughness$ 1 | Description$ Golem creatures you control get +1/+1. +DeckHas:Ability$Token SVar:Picture:http://www.wizards.com/global/images/magic/general/master_splicer.jpg Oracle:When Master Splicer enters the battlefield, create a 3/3 colorless Golem artifact creature token.\nGolem creatures you control get +1/+1. diff --git a/forge-gui/res/cardsfolder/m/masterful_replication.txt b/forge-gui/res/cardsfolder/m/masterful_replication.txt index 865b7646d4c..3a53e31ec8d 100644 --- a/forge-gui/res/cardsfolder/m/masterful_replication.txt +++ b/forge-gui/res/cardsfolder/m/masterful_replication.txt @@ -8,4 +8,5 @@ SVar:DBRepeat:DB$ RepeatEach | RepeatCards$ Artifact.YouCtrl+IsNotImprinted | Re SVar:DBClone:DB$ Clone | Defined$ Imprinted | CloneTarget$ Remembered | Duration$ UntilEndOfTurn SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True AI:RemoveDeck:All +DeckHas:Ability$Token Oracle:Choose one —\n• Create two 3/3 colorless Golem artifact creature tokens.\n• Choose target artifact you control. Each other artifact you control becomes a copy of that artifact until end of turn. diff --git a/forge-gui/res/cardsfolder/m/moldervine_reclamation.txt b/forge-gui/res/cardsfolder/m/moldervine_reclamation.txt index f764399c6de..4d159d2656d 100644 --- a/forge-gui/res/cardsfolder/m/moldervine_reclamation.txt +++ b/forge-gui/res/cardsfolder/m/moldervine_reclamation.txt @@ -4,4 +4,5 @@ Types:Enchantment T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigGainLife | TriggerDescription$ Whenever a creature you control dies, you gain 1 life and draw a card. SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1 | SubAbility$ DBDraw SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 1 +DeckHas:Ability$LifeGain Oracle:Whenever a creature you control dies, you gain 1 life and draw a card. diff --git a/forge-gui/res/cardsfolder/m/moment_of_heroism.txt b/forge-gui/res/cardsfolder/m/moment_of_heroism.txt index 309cf067507..e2440096773 100644 --- a/forge-gui/res/cardsfolder/m/moment_of_heroism.txt +++ b/forge-gui/res/cardsfolder/m/moment_of_heroism.txt @@ -2,5 +2,6 @@ Name:Moment of Heroism ManaCost:1 W Types:Instant A:SP$ Pump | Cost$ 1 W | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +2 | NumDef$ +2 | KW$ Lifelink | SpellDescription$ Target creature gets +2/+2 and gains lifelink until end of turn. +DeckHas:Ability$LifeGain SVar:Picture:http://www.wizards.com/global/images/magic/general/moment_of_heroism.jpg Oracle:Target creature gets +2/+2 and gains lifelink until end of turn. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/m/mu_yanling_sky_dancer.txt b/forge-gui/res/cardsfolder/m/mu_yanling_sky_dancer.txt index 0810630293c..e3de7f8e057 100644 --- a/forge-gui/res/cardsfolder/m/mu_yanling_sky_dancer.txt +++ b/forge-gui/res/cardsfolder/m/mu_yanling_sky_dancer.txt @@ -9,4 +9,5 @@ A:AB$ Effect | Cost$ SubCounter<8/LOYALTY> | Planeswalker$ True | Ultimate$ True SVar:STDraw:Mode$ Continuous | EffectZone$ Command | Affected$ Island.YouCtrl | AddAbility$ AnimateIsland | Description$ Islands you control have "{T}: Draw a card". SVar:AnimateIsland:AB$ Draw | Cost$ T | NumCards$ 1 | SpellDescription$ Draw a card. SVar:PlayMain1:TRUE +DeckHas:Ability$Token Oracle:[+2]: Until your next turn, up to one target creature gets -2/-0 and loses flying.\n[-3]: Create a 4/4 blue Elemental Bird creature token with flying.\n[-8]: You get an emblem with "Islands you control have '{T}: Draw a card'." diff --git a/forge-gui/res/cardsfolder/n/nightpack_ambusher.txt b/forge-gui/res/cardsfolder/n/nightpack_ambusher.txt index f24a8d3009a..c775cc7ee5a 100644 --- a/forge-gui/res/cardsfolder/n/nightpack_ambusher.txt +++ b/forge-gui/res/cardsfolder/n/nightpack_ambusher.txt @@ -8,4 +8,6 @@ SVar:PlayMain1:TRUE T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | CheckSVar$ X | SVarCompare$ EQ0 | References$ X | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ At the beginning of your end step, if you didn't cast a spell this turn, create a 2/2 green Wolf creature token. SVar:TrigToken:DB$ Token | TokenOwner$ You | TokenScript$ g_2_2_wolf | LegacyImage$ g 2 2 wolf m20 | TokenAmount$ 1 SVar:X:Count$ThisTurnCast_Card.YouCtrl +DeckHints:Type$Wolf & Type$Werewolf +DeckHas:Ability$Token Oracle:Flash\nOther Wolves and Werewolves you control get +1/+1.\nAt the beginning of your end step, if you didn't cast a spell this turn, create a 2/2 green Wolf creature token. diff --git a/forge-gui/res/cardsfolder/n/noxious_grasp.txt b/forge-gui/res/cardsfolder/n/noxious_grasp.txt index 7a515074f6a..72d6d64418c 100644 --- a/forge-gui/res/cardsfolder/n/noxious_grasp.txt +++ b/forge-gui/res/cardsfolder/n/noxious_grasp.txt @@ -4,4 +4,5 @@ Types:Instant A:SP$ Destroy | Cost$ 1 B | ValidTgts$ Creature.White,Planeswalker.White,Creature.Green,Planeswalker.Green | TgtPrompt$ Select target creature or planeswalker that's green or white | SubAbility$ DBGainLife | SpellDescription$ Destroy target creature or planeswalker that's green or white. You gain 1 life. SVar:DBGainLife:DB$GainLife | Defined$ You | LifeAmount$ 1 | SpellDescription$ You gain 1 life. AI:RemoveDeck:Random +DeckHas:Ability$LifeGain Oracle:Destroy target creature or planeswalker that's green or white. You gain 1 life. diff --git a/forge-gui/res/cardsfolder/o/omnath_locus_of_the_roil.txt b/forge-gui/res/cardsfolder/o/omnath_locus_of_the_roil.txt index d25390eee27..8c75b3fe602 100644 --- a/forge-gui/res/cardsfolder/o/omnath_locus_of_the_roil.txt +++ b/forge-gui/res/cardsfolder/o/omnath_locus_of_the_roil.txt @@ -8,4 +8,6 @@ SVar:X:Count$Valid Elemental.YouCtrl T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever a land enters the battlefield under your control, put a +1/+1 counter on target Elemental you control. If you control eight or more lands, draw a card. SVar:TrigPutCounter:DB$ PutCounter | ValidTgts$ Elemental.YouCtrl | TgtPrompt$ Select target Elemental you control | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBDraw SVar:DBDraw:DB$ Draw | NumCards$ 1 | Defined$ You | ConditionPresent$ Land.YouCtrl | ConditionCompare$ GE8 +DeckHas:Ability$Counters +DeckHints:Type$Elemental Oracle:When Omnath, Locus of the Roil enters the battlefield, it deals damage to any target equal to the number of Elementals you control.\nWhenever a land enters the battlefield under your control, put a +1/+1 counter on target Elemental you control. If you control eight or more lands, draw a card. diff --git a/forge-gui/res/cardsfolder/o/overgrowth_elemental.txt b/forge-gui/res/cardsfolder/o/overgrowth_elemental.txt index e4f9bd656e7..92ec9848fd8 100644 --- a/forge-gui/res/cardsfolder/o/overgrowth_elemental.txt +++ b/forge-gui/res/cardsfolder/o/overgrowth_elemental.txt @@ -11,4 +11,5 @@ T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1 | SubAbility$ DBPutCounter SVar:DBPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ConditionDefined$ TriggeredCardLKICopy | ConditionPresent$ Creature.Elemental DeckHas:Ability$Counters +DeckHints:Type$Elemental Oracle:When Overgrowth Elemental enters the battlefield, put a +1/+1 counter on another target Elemental you control.\nWhenever another creature you control dies, you gain 1 life. If that creature was an Elemental, put a +1/+1 counter on Overgrowth Elemental. diff --git a/forge-gui/res/cardsfolder/r/raise_the_alarm.txt b/forge-gui/res/cardsfolder/r/raise_the_alarm.txt index 990896161e0..0fd1c6faef9 100644 --- a/forge-gui/res/cardsfolder/r/raise_the_alarm.txt +++ b/forge-gui/res/cardsfolder/r/raise_the_alarm.txt @@ -2,5 +2,6 @@ Name:Raise the Alarm ManaCost:1 W Types:Instant A:SP$ Token | Cost$ 1 W | TokenAmount$ 2 | TokenScript$ w_1_1_soldier | TokenOwner$ You | LegacyImage$ w 1 1 soldier mrd | SpellDescription$ Create two 1/1 white Soldier creature tokens. +DeckHas:Ability$Token SVar:Picture:http://resources.wizards.com/magic/cards/mrd/en-us/card48103.jpg Oracle:Create two 1/1 white Soldier creature tokens. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/r/rapacious_dragon.txt b/forge-gui/res/cardsfolder/r/rapacious_dragon.txt index 4f477e7dba7..cda6d8db57b 100644 --- a/forge-gui/res/cardsfolder/r/rapacious_dragon.txt +++ b/forge-gui/res/cardsfolder/r/rapacious_dragon.txt @@ -5,4 +5,5 @@ PT:3/3 K:Flying T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ DBTreasureTokens | TriggerDescription$ When CARDNAME enters the battlefield, create two Treasure tokens. SVar:DBTreasureTokens:DB$ Token | TokenAmount$ 2 | TokenScript$ c_a_treasure_sac | TokenOwner$ You | LegacyImage$ c a treasure sac m20 +DeckHas:Ability$Token Oracle:Flying\nWhen Rapacious Dragon enters the battlefield, create two Treasure tokens. (They're artifacts with "{T}, Sacrifice this artifact: Add one mana of any color.") diff --git a/forge-gui/res/cardsfolder/s/savage_gorger.txt b/forge-gui/res/cardsfolder/s/savage_gorger.txt index 58d43cb810c..a299505c527 100644 --- a/forge-gui/res/cardsfolder/s/savage_gorger.txt +++ b/forge-gui/res/cardsfolder/s/savage_gorger.txt @@ -6,4 +6,5 @@ K:Flying T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | CheckSVar$ X | References$ X | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, if an opponent lost life this turn, put a +1/+1 counter on CARDNAME. (Damage causes loss of life.) SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 SVar:X:Count$LifeOppsLostThisTurn +DeckHas:Ability$Counters Oracle:Flying\nAt the beginning of your upkeep, if an opponent lost life this turn, put a +1/+1 counter on Savage Gorger. (Damage causes loss of life.) diff --git a/forge-gui/res/cardsfolder/s/scampering_scorcher.txt b/forge-gui/res/cardsfolder/s/scampering_scorcher.txt index 3111e892162..b3b522f5514 100644 --- a/forge-gui/res/cardsfolder/s/scampering_scorcher.txt +++ b/forge-gui/res/cardsfolder/s/scampering_scorcher.txt @@ -5,4 +5,5 @@ PT:1/1 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create two 1/1 red Elemental creature tokens. Elementals you control gain haste until end of turn. SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ r_1_1_elemental | TokenOwner$ You | LegacyImage$ r 1 1 elemental m20 | SubAbility$ DBPump SVar:DBPump:DB$ PumpAll | ValidCards$ Elemental.YouCtrl | KW$ Haste +DeckHas:Ability$Token Oracle:When Scampering Scorcher enters the battlefield, create two 1/1 red Elemental creature tokens. Elementals you control gain haste until end of turn. (They can attack and {T} this turn.) diff --git a/forge-gui/res/cardsfolder/s/skeleton_archer.txt b/forge-gui/res/cardsfolder/s/skeleton_archer.txt index cfc91904174..410a52fb128 100644 --- a/forge-gui/res/cardsfolder/s/skeleton_archer.txt +++ b/forge-gui/res/cardsfolder/s/skeleton_archer.txt @@ -4,4 +4,4 @@ Types:Creature Skeleton Archer PT:3/3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDealDamage | TriggerDescription$ When CARDNAME enters the battlefield, it deals 1 damage to any target. SVar:TrigDealDamage:DB$DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 -Oracle:When CARDNAME enters the battlefield, it deals 1 damage to any target. \ No newline at end of file +Oracle:When Skeleton Archer enters the battlefield, it deals 1 damage to any target. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/s/skyknight_vanguard.txt b/forge-gui/res/cardsfolder/s/skyknight_vanguard.txt index f22a0b2d563..195069db641 100644 --- a/forge-gui/res/cardsfolder/s/skyknight_vanguard.txt +++ b/forge-gui/res/cardsfolder/s/skyknight_vanguard.txt @@ -6,4 +6,5 @@ K:Flying T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME attacks, create a 1/1 white Soldier creature token that's tapped and attacking. SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_soldier | TokenOwner$ You | TokenTapped$ True | TokenAttacking$ True | LegacyImage$ w 1 1 soldier m20 SVar:HasAttackEffect:TRUE +DeckHas:Ability$Token Oracle:Flying\nWhenever Skyknight Vanguard attacks, create a 1/1 white Soldier creature token that's tapped and attacking. diff --git a/forge-gui/res/cardsfolder/s/sorin_imperious_bloodlord.txt b/forge-gui/res/cardsfolder/s/sorin_imperious_bloodlord.txt index d5772da2870..28be18e45ea 100644 --- a/forge-gui/res/cardsfolder/s/sorin_imperious_bloodlord.txt +++ b/forge-gui/res/cardsfolder/s/sorin_imperious_bloodlord.txt @@ -11,5 +11,6 @@ SVar:DBGainLife:DB$ GainLife | LifeAmount$ 3 SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True A:AB$ ChangeZone | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.Vampire | ChangeNum$ 1 | SpellDescription$ You may put a vampire creature card from your hand onto the battlefield. SVar:PlayMain1:TRUE +DeckHas:Ability$Counters DeckHints:Type$Vampire Oracle:[+1]: Target creature you control gains deathtouch and lifelink until end of turn. If it's a Vampire, put a +1/+1 counter on it.\n[+1]: You may sacrifice a Vampire. When you do, Sorin, Imperious Bloodlord deals 3 damage to any target and you gain 3 life.\n[-3]: You may put a vampire creature card from your hand onto the battlefield. diff --git a/forge-gui/res/cardsfolder/s/soulmender.txt b/forge-gui/res/cardsfolder/s/soulmender.txt index 0e6ce662c31..dbcd606512f 100644 --- a/forge-gui/res/cardsfolder/s/soulmender.txt +++ b/forge-gui/res/cardsfolder/s/soulmender.txt @@ -3,5 +3,6 @@ ManaCost:W Types:Creature Human Cleric PT:1/1 A:AB$ GainLife | Cost$ T | Defined$ You | LifeAmount$ 1 | SpellDescription$ You gain 1 life. +DeckHas:Ability$LifeGain SVar:Picture:http://www.wizards.com/global/images/magic/general/soulmender.jpg Oracle:{T}: You gain 1 life. diff --git a/forge-gui/res/cardsfolder/s/squad_captain.txt b/forge-gui/res/cardsfolder/s/squad_captain.txt index 5bcc64343ac..31f716bfa4e 100644 --- a/forge-gui/res/cardsfolder/s/squad_captain.txt +++ b/forge-gui/res/cardsfolder/s/squad_captain.txt @@ -5,4 +5,5 @@ PT:2/2 K:Vigilance K:etbCounter:P1P1:X:no Condition:CARDNAME enters the battlefield with a +1/+1 counter on it for each other creature you control. SVar:X:Count$LastStateBattlefield Creature.Other+YouCtrl +DeckHas:Ability$Counters Oracle:Vigilance (Attacking doesn't cause this creature to tap.)\nSquad Captain enters the battlefield with a +1/+1 counter on it for each other creature you control. diff --git a/forge-gui/res/cardsfolder/s/starfield_mystic.txt b/forge-gui/res/cardsfolder/s/starfield_mystic.txt index 9ce30ccf4ce..8626457993c 100644 --- a/forge-gui/res/cardsfolder/s/starfield_mystic.txt +++ b/forge-gui/res/cardsfolder/s/starfield_mystic.txt @@ -5,4 +5,6 @@ PT:2/2 S:Mode$ ReduceCost | ValidCard$ Enchantment | Type$ Spell | Activator$ You | Amount$ 1 | Description$ Enchantment spells you cast cost {1} less to cast. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever an enchantment you control is put into a graveyard from the battlefield, put a +1/+1 counter on CARDNAME. SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 +DeckHas:Ability$Counters +DeckNeeds:Type$Enchantment Oracle:Enchantment spells you cast cost {1} less to cast.\nWhenever an enchantment you control is put into a graveyard from the battlefield, put a +1/+1 counter on Starfield Mystic. diff --git a/forge-gui/res/cardsfolder/s/steadfast_sentry.txt b/forge-gui/res/cardsfolder/s/steadfast_sentry.txt index d301eedeb1f..1486a0f738e 100644 --- a/forge-gui/res/cardsfolder/s/steadfast_sentry.txt +++ b/forge-gui/res/cardsfolder/s/steadfast_sentry.txt @@ -5,4 +5,5 @@ PT:3/2 K:Vigilance T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigPutCounter | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, put a +1/+1 counter on target creature you control. SVar:TrigPutCounter:DB$PutCounter | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | CounterType$ P1P1 | CounterNum$ 1 +DeckHas:Ability$Counters Oracle:Vigilance (Attacking doesn't cause this creature to tap.)\nWhen Steadfast Sentry dies, put a +1/+1 counter on target creature you control. diff --git a/forge-gui/res/cardsfolder/s/steel_overseer.txt b/forge-gui/res/cardsfolder/s/steel_overseer.txt index 17e9a1837af..90afb9e2ca7 100644 --- a/forge-gui/res/cardsfolder/s/steel_overseer.txt +++ b/forge-gui/res/cardsfolder/s/steel_overseer.txt @@ -3,5 +3,6 @@ ManaCost:2 Types:Artifact Creature Construct PT:1/1 A:AB$ PutCounterAll | Cost$ T | ValidCards$ Artifact.Creature+YouCtrl | CounterType$ P1P1 | CounterNum$ 1 | SpellDescription$ Put a +1/+1 counter on each artifact creature you control. +DeckHas:Ability$Counters SVar:Picture:http://www.wizards.com/global/images/magic/general/steel_overseer.jpg Oracle:{T}: Put a +1/+1 counter on each artifact creature you control. diff --git a/forge-gui/res/cardsfolder/s/stream_of_thought.txt b/forge-gui/res/cardsfolder/s/stream_of_thought.txt index ebd7a385175..ec98aa466ef 100644 --- a/forge-gui/res/cardsfolder/s/stream_of_thought.txt +++ b/forge-gui/res/cardsfolder/s/stream_of_thought.txt @@ -1,7 +1,7 @@ Name:Stream of Thought ManaCost:U Types:Sorcery -A:SP$ Mill | Cost$ U | NumCards$ 4 | ValidTgts$ Player | TgtPrompt$ Choose a player | RememberMilled$ True | SubAbility$ DBChangeZone | SpellDescription$ Target player puts the top four cards of their library into their graveyard. You shuffle up to four cards from your graveyard into your library. -SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Library | DefinedPlayer$ You | Hidden$ True | ChangeNum$ 4 | ChangeType$ Card.YouOwn | Shuffle$ True K:Replicate:2 U U +A:SP$ Mill | Cost$ U | NumCards$ 4 | ValidTgts$ Player | TgtPrompt$ Choose a player | SubAbility$ DBChangeZone | SpellDescription$ Target player puts the top four cards of their library into their graveyard. You shuffle up to four cards from your graveyard into your library. +SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Library | DefinedPlayer$ You | Hidden$ True | ChangeNum$ 4 | ChangeType$ Card.YouOwn | Shuffle$ True Oracle:Target player puts the top four cards of their library into their graveyard. You shuffle up to four cards from your graveyard into your library.\nReplicate {2}{U}{U} (When you cast this spell, copy it for each time you paid the replicate cost. You may choose new targets for the copies.) diff --git a/forge-gui/res/cardsfolder/t/thicket_crasher.txt b/forge-gui/res/cardsfolder/t/thicket_crasher.txt index b30e6e0c90b..9e65e78b3b2 100644 --- a/forge-gui/res/cardsfolder/t/thicket_crasher.txt +++ b/forge-gui/res/cardsfolder/t/thicket_crasher.txt @@ -3,7 +3,7 @@ ManaCost:3 G Types:Creature Elemental Rhino PT:4/3 K:Trample -DeckHints:Name$Nissa's Encouragement | Nissa, Genesis Mage | Forest S:Mode$ Continuous | Affected$ Elemental.Other+YouCtrl | AddKeyword$ Trample | Description$ Other Elementals you control have trample. SVar:PlayMain1:TRUE +DeckHints:Type$Elemental Oracle:Trample (This creature can deal excess combat damage to the player or planeswalker it's attacking.)\nOther Elementals you control have trample. diff --git a/forge-gui/res/cardsfolder/t/twinblade_paladin.txt b/forge-gui/res/cardsfolder/t/twinblade_paladin.txt index 803e8a7f78e..7a5fc554c33 100644 --- a/forge-gui/res/cardsfolder/t/twinblade_paladin.txt +++ b/forge-gui/res/cardsfolder/t/twinblade_paladin.txt @@ -5,6 +5,7 @@ PT:3/3 T:Mode$ LifeGained | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever you gain life, put a +1/+1 counter on CARDNAME. SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 DeckHints:Ability$LifeGain +DeckHas:Ability$Counters S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Double Strike | CheckSVar$ X | SVarCompare$ GE25 | Description$ As long as you have 25 or more life, CARDNAME has double strike. (It deals both first-strike and regular combat damage.) SVar:X:Count$YourLifeTotal Oracle:Whenever you gain life, put a +1/+1 counter on Twinblade Paladin.\nAs long as you have 25 or more life, Twinblade Paladin has double strike. (It deals both first-strike and regular combat damage.) diff --git a/forge-gui/res/cardsfolder/u/unholy_indenture.txt b/forge-gui/res/cardsfolder/u/unholy_indenture.txt index 53523d260d2..649ad543836 100644 --- a/forge-gui/res/cardsfolder/u/unholy_indenture.txt +++ b/forge-gui/res/cardsfolder/u/unholy_indenture.txt @@ -5,4 +5,5 @@ K:Enchant creature A:SP$ Attach | Cost$ 2 B | ValidTgts$ Creature | AILogic$ Pump T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.AttachedBy | Execute$ TrigChange | TriggerDescription$ When enchanted creature dies, return that card to the battlefield under your control with a +1/+1 counter on it. SVar:TrigChange:DB$ChangeZone | Origin$ Graveyard | Destination$ Battlefield | WithCounters$ P1P1 | Defined$ TriggeredCard +DeckHas:Ability$Counters Oracle:Enchant creature\nWhen enchanted creature dies, return that card to the battlefield under your control with a +1/+1 counter on it. diff --git a/forge-gui/res/cardsfolder/v/veil_of_summer.txt b/forge-gui/res/cardsfolder/v/veil_of_summer.txt index a5ae33498f9..54941da97e1 100644 --- a/forge-gui/res/cardsfolder/v/veil_of_summer.txt +++ b/forge-gui/res/cardsfolder/v/veil_of_summer.txt @@ -8,4 +8,5 @@ SVar:DBPump:DB$ Pump | Defined$ You | KW$ Hexproof:Card.Black:black & Hexproof:C SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Permanent.YouCtrl | KW$ Hexproof:Card.Black:black & Hexproof:Card.Blue:blue SVar:X:Count$ThisTurnCast_Card.OppCtrl+Blue,Card.OppCtrl+Black AI:RemoveDeck:Random +DeckHints:Color$Blue|Black Oracle:Draw a card if an opponent has cast a blue or black spell this turn. Spells you control can't be countered this turn. You and permanents you control gain hexproof from blue and from black until end of turn. (You and they can't be the targets of blue or black spells or abilities your opponents control.) diff --git a/forge-gui/res/cardsfolder/v/vengeful_warchief.txt b/forge-gui/res/cardsfolder/v/vengeful_warchief.txt index a6195a1d90f..9acc552df10 100644 --- a/forge-gui/res/cardsfolder/v/vengeful_warchief.txt +++ b/forge-gui/res/cardsfolder/v/vengeful_warchief.txt @@ -4,4 +4,5 @@ Types:Creature Orc Warrior PT:4/4 T:Mode$ LifeLost | ValidPlayer$ You | TriggerZones$ Battlefield | FirstTime$ True | Execute$ TrigPutCounter | TriggerDescription$ Whenever you lose life for the first time each turn, put a +1/+1 counter on CARDNAME. (Damage causes loss of life.) SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 +DeckHas:Ability$Counters Oracle:Whenever you lose life for the first time each turn, put a +1/+1 counter on Vengeful Warchief. (Damage causes loss of life.) diff --git a/forge-gui/res/cardsfolder/v/vivien_arkbow_ranger.txt b/forge-gui/res/cardsfolder/v/vivien_arkbow_ranger.txt index 110d9530b17..ce40905783d 100644 --- a/forge-gui/res/cardsfolder/v/vivien_arkbow_ranger.txt +++ b/forge-gui/res/cardsfolder/v/vivien_arkbow_ranger.txt @@ -8,5 +8,5 @@ A:AB$ Pump | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidTgts$ Creat SVar:SoulsDamage:DB$ DealDamage | ValidTgts$ Creature,Planeswalker | AILogic$ PowerDmg | TgtPrompt$ Select target creature or planeswalker | NumDmg$ X | References$ X | DamageSource$ ParentTarget SVar:X:ParentTargeted$CardPower A:AB$ ChangeZone | Cost$ SubCounter<5/LOYALTY> | Planeswalker$ True | Origin$ Sideboard | Destination$ Hand | ChangeType$ Creature.YouOwn | ChangeNum$ 1 | SpellDescription$ You may choose a creature card you own from outside the game, reveal it, and put it into your hand. -AI:RemoveDeck:Random +DeckHas:Ability$Counters Oracle:[+1]: Distribute two +1/+1 counters among up to two target creatures. They gain trample until end of turn.\n[−3]: Target creature you control deals damage equal to its power to target creature or planeswalker.\n[−5]: You may choose a creature card you own from outside the game, reveal it, and put it into your hand. diff --git a/forge-gui/res/cardsfolder/v/vivien_natures_avenger.txt b/forge-gui/res/cardsfolder/v/vivien_natures_avenger.txt index 4e82befaa94..6b12b06e574 100644 --- a/forge-gui/res/cardsfolder/v/vivien_natures_avenger.txt +++ b/forge-gui/res/cardsfolder/v/vivien_natures_avenger.txt @@ -5,4 +5,5 @@ Loyalty:3 A:AB$ PutCounter | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | CounterNum$ 3 | CounterType$ P1P1 | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature | TgtPrompt$ Select target creature | SpellDescription$ Put three +1/+1 counters on up to one target creature. A:AB$ DigUntil | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | Valid$ Card.Creature | ValidDescription$ creature | FoundDestination$ Hand | RevealedDestination$ Library | RevealedLibraryPosition$ -1 | RevealRandomOrder$ True | FoundDestination$ Hand | SpellDescription$ Reveal cards from the top of your library until you reveal a creature card. Put that card into your hand and the rest on the bottom of your library in a random order. A:AB$ Pump | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +10 | NumDef$ +10 | KW$ Trample | SpellDescription$ Target creature gets +10/+10 and gains trample until end of turn. +DeckHas:Ability$Counters Oracle:[+1]: Put three +1/+1 counters on up to one target creature.\n[−1]: Reveal cards from the top of your library until you reveal a creature card. Put that card into your hand and the rest on the bottom of your library in a random order.\n[−6]: Target creature gets +10/+10 and gains trample until end of turn. diff --git a/forge-gui/res/cardsfolder/w/wolfkin_bond.txt b/forge-gui/res/cardsfolder/w/wolfkin_bond.txt index 435f9ec103e..704ab5108ea 100644 --- a/forge-gui/res/cardsfolder/w/wolfkin_bond.txt +++ b/forge-gui/res/cardsfolder/w/wolfkin_bond.txt @@ -6,5 +6,6 @@ A:SP$ Attach | Cost$ 4 G | ValidTgts$ Creature | AILogic$ Pump T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a 2/2 green Wolf creature token. SVar:TrigToken:DB$ Token | TokenScript$ g_2_2_wolf | LegacyImage$ g 2 2 wolf emn | TokenOwner$ You | TokenAmount$ 1 S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 2 | AddToughness$ 2 | Description$ Enchanted creature gets +2/+2. +DeckHas:Ability$Token SVar:Picture:http://www.wizards.com/global/images/magic/general/wolfkin_bond.jpg Oracle:Enchant creature\nWhen Wolfkin Bond enters the battlefield, create a 2/2 green Wolf creature token.\nEnchanted creature gets +2/+2. diff --git a/forge-gui/res/cardsfolder/w/woodland_mystic.txt b/forge-gui/res/cardsfolder/w/woodland_mystic.txt new file mode 100644 index 00000000000..bdb6a423aed --- /dev/null +++ b/forge-gui/res/cardsfolder/w/woodland_mystic.txt @@ -0,0 +1,6 @@ +Name:Woodland Mystic +ManaCost:1 G +Types:Creature Elf Druid +PT:1/1 +A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G}. +Oracle:{T}: Add {G}. diff --git a/forge-gui/res/cardsfolder/w/wort_the_raidmother.txt b/forge-gui/res/cardsfolder/w/wort_the_raidmother.txt index 10ab4a1b4d3..09936e7191a 100644 --- a/forge-gui/res/cardsfolder/w/wort_the_raidmother.txt +++ b/forge-gui/res/cardsfolder/w/wort_the_raidmother.txt @@ -4,6 +4,6 @@ Types:Legendary Creature Goblin Shaman PT:3/3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ WortETB | TriggerDescription$ When CARDNAME enters the battlefield, create two 1/1 red and green Goblin Warrior creature tokens. SVar:WortETB:DB$ Token | TokenAmount$ 2 | TokenScript$ rg_1_1_goblin_warrior | TokenOwner$ You -S:Mode$ Continuous | AddKeyword$ Conspire | Affected$ Instant.Green+YouCtrl,Instant.Red+YouCtrl,Sorcery.Red+YouCtrl,Sorcery.Green+YouCtrl | AffectedZone$ Stack,Graveyard,Hand,Library,Exile | EffectZone$ Battlefield | Description$ Each red or green instant or sorcery spell you cast has conspire. (As you cast the spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose new targets for the copy.) +S:Mode$ Continuous | AddKeyword$ Conspire | Affected$ Instant.Green+YouCtrl,Instant.Red+YouCtrl,Sorcery.Red+YouCtrl,Sorcery.Green+YouCtrl | AffectedZone$ Stack | EffectZone$ Battlefield | Description$ Each red or green instant or sorcery spell you cast has conspire. (As you cast the spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose new targets for the copy.) SVar:Picture:http://www.wizards.com/global/images/magic/general/wort_the_raidmother.jpg Oracle:When Wort, the Raidmother enters the battlefield, create two 1/1 red and green Goblin Warrior creature tokens.\nEach red or green instant or sorcery spell you cast has conspire. (As you cast the spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose new targets for the copy.) diff --git a/forge-gui/res/editions/Magic 2020.txt b/forge-gui/res/editions/Magic 2020.txt index 1270cac852c..89184a08add 100644 --- a/forge-gui/res/editions/Magic 2020.txt +++ b/forge-gui/res/editions/Magic 2020.txt @@ -5,7 +5,7 @@ Name=Core Set 2020 MciCode=m20 Type=Core BoosterCovers=3 -Booster=10 Common:!fromSheet("M20 Secret Cards"), 3 Uncommon:!fromSheet("M20 Secret Cards"), 1 RareMythic:!fromSheet("M20 Secret Cards"), 1 BasicLand +Booster=10 Common:!fromSheet("M20 Secret Cards"), 3 Uncommon:!fromSheet("M20 Secret Cards"), 1 RareMythic:!fromSheet("M20 Secret Cards"), 1 fromSheet("M20 Lands") [cards] 1 C Aerial Assault diff --git a/forge-gui/src/main/java/forge/player/HumanPlay.java b/forge-gui/src/main/java/forge/player/HumanPlay.java index f1899e7c155..77ab312396c 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlay.java +++ b/forge-gui/src/main/java/forge/player/HumanPlay.java @@ -103,10 +103,8 @@ public class HumanPlay { // System.out.println("Playing:" + sa.getDescription() + " of " + sa.getHostCard() + " new = " + newAbility); if (newAbility) { - Cost abCost = sa.getPayCosts() == null ? new Cost("0", sa.isAbility()) : sa.getPayCosts(); - CostPayment payment = new CostPayment(abCost, sa); - final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa, payment); + final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa); if (!req.playAbility(true, false, false)) { if (flippedToCast && !castFaceDown) { source.turnFaceDown(true); @@ -199,9 +197,8 @@ public class HumanPlay { } sa = AbilityUtils.addSpliceEffects(sa); } - final CostPayment payment = new CostPayment(sa.getPayCosts(), sa); - final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa, payment); + final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa); req.playAbility(mayChooseNewTargets, true, false); } else { @@ -231,7 +228,7 @@ public class HumanPlay { sa.setActivatingPlayer(player); if (sa.getPayCosts() != null) { - final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa, new CostPayment(sa.getPayCosts(), sa)); + final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa); req.playAbility(!useOldTargets, false, true); } diff --git a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java index c349a80de42..d02362f46cc 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java +++ b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java @@ -23,6 +23,7 @@ import forge.card.CardStateName; import forge.card.CardType; import forge.card.MagicColor; import forge.game.Game; +import forge.game.GameActionUtil; import forge.game.GameObject; import forge.game.ability.AbilityUtils; import forge.game.card.Card; @@ -53,13 +54,11 @@ import java.util.Map; */ public class HumanPlaySpellAbility { private final PlayerControllerHuman controller; - private final SpellAbility ability; - private final CostPayment payment; + private SpellAbility ability; - public HumanPlaySpellAbility(final PlayerControllerHuman controller0, final SpellAbility ability0, final CostPayment payment0) { + public HumanPlaySpellAbility(final PlayerControllerHuman controller0, final SpellAbility ability0) { controller = controller0; ability = ability0; - payment = payment0; } public final boolean playAbility(final boolean mayChooseTargets, final boolean isFree, final boolean skipStack) { @@ -116,6 +115,11 @@ public class HumanPlaySpellAbility { ability.resetPaidHash(); } + ability = GameActionUtil.addExtraKeywordCost(ability); + + Cost abCost = ability.getPayCosts() == null ? new Cost("0", ability.isAbility()) : ability.getPayCosts(); + CostPayment payment = new CostPayment(abCost, ability); + // TODO Apply this to the SAStackInstance instead of the Player if (manaTypeConversion) { AbilityUtils.applyManaColorConversion(payment, MagicColor.Constant.ANY_TYPE_CONVERSION); @@ -155,7 +159,7 @@ public class HumanPlaySpellAbility { if (!prerequisitesMet) { if (!ability.isTrigger()) { - rollbackAbility(fromZone, fromState, zonePosition); + rollbackAbility(fromZone, fromState, zonePosition, payment); if (ability.getHostCard().isMadness()) { // if a player failed to play madness cost, move the card to graveyard Card newCard = game.getAction().moveToGraveyard(c, null); @@ -240,7 +244,7 @@ public class HumanPlaySpellAbility { } } - private void rollbackAbility(final Zone fromZone, final CardStateName fromState, final int zonePosition) { + private void rollbackAbility(final Zone fromZone, final CardStateName fromState, final int zonePosition, CostPayment payment) { // cancel ability during target choosing final Game game = ability.getActivatingPlayer().getGame(); diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 4a7a109d68d..8cf6f495b0f 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -30,6 +30,7 @@ import forge.game.cost.Cost; import forge.game.cost.CostPart; import forge.game.cost.CostPartMana; import forge.game.keyword.Keyword; +import forge.game.keyword.KeywordInterface; import forge.game.mana.Mana; import forge.game.mana.ManaConversionMatrix; import forge.game.player.*; @@ -2930,5 +2931,19 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont return InputConfirm.confirm(this, (SpellAbility)null, "Do you want to scry?"); } + @Override + public int chooseNumberForKeywordCost(SpellAbility sa, Cost cost, KeywordInterface keyword, String prompt, + int max) { + if (max <= 0) { + return 0; + } + if (max == 1) { + return InputConfirm.confirm(this, sa, prompt) ? 1 : 0; + } + + Integer v = getGui().getInteger(prompt, 0, max, 9); + return v == null ? 0 : v.intValue(); + } + } diff --git a/pom.xml b/pom.xml index c3d837508c5..d3d17cf28d0 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ forge pom Forge Parent - 1.6.27-SNAPSHOT + 1.6.28-SNAPSHOT Forge lets you play the card game Magic: The Gathering against a computer opponent using all of the rules.