diff --git a/.gitignore b/.gitignore index b80af62f19b..1f236e77908 100644 --- a/.gitignore +++ b/.gitignore @@ -1,229 +1,77 @@ -/*.idea +# Ignore IDEA config files + +*.idea *.iml -/*.tmp -/.metadata -/.recommenders -forge-ai/target -forge-core/target -forge-game/target +*.tmp +.metadata +.recommenders + + +# Ignore Eclipse config files + +.settings +.classpath +.project + +# Ignore VS Code config files + +.vscode/settings.json +.vscode/launch.json + + +# Ignore NetBeans config files + +nbactions.xml + + +# Ignore binaries, temp files and test output, everywhere + +target +test-output +bin +gen +*.log + + +# TODO: specify what these ignores are for (releasing?) + +forge.profile.properties +/jgv.txt +pom.xml.next +pom.xml.releaseBackup +pom.xml.tag +release.properties + + +# Ignore mobile-related resources + +forge-gui-android/res/*/* +!forge-gui-android/res/*/ic_launcher.png +!forge-gui-android/res/*/ic_launcher*.png +!forge-gui-android/res/layout/main.xml forge-gui-android/*.keystore -forge-gui-android/assets/fallback_skin/Thumbs.db -forge-gui-android/bin -forge-gui-android/gen -forge-gui-android/res/Thumbs.db -forge-gui-android/res/bin -forge-gui-android/res/drawable-hdpi/Thumbs.db -forge-gui-android/res/drawable-hdpi/bin -forge-gui-android/res/drawable-hdpi/gen -forge-gui-android/res/drawable-hdpi/target -forge-gui-android/res/drawable-ldpi/Thumbs.db -forge-gui-android/res/drawable-ldpi/bin -forge-gui-android/res/drawable-ldpi/gen -forge-gui-android/res/drawable-ldpi/target -forge-gui-android/res/drawable-mdpi/Thumbs.db -forge-gui-android/res/drawable-mdpi/bin -forge-gui-android/res/drawable-mdpi/gen -forge-gui-android/res/drawable-mdpi/target -forge-gui-android/res/drawable-xhdpi/Thumbs.db -forge-gui-android/res/drawable-xhdpi/bin -forge-gui-android/res/drawable-xhdpi/gen -forge-gui-android/res/drawable-xhdpi/target -forge-gui-android/res/drawable-xxhdpi/Thumbs.db -forge-gui-android/res/drawable-xxhdpi/bin -forge-gui-android/res/drawable-xxhdpi/gen -forge-gui-android/res/drawable-xxhdpi/target -forge-gui-android/res/gen -forge-gui-android/res/layout/Thumbs.db -forge-gui-android/res/layout/bin -forge-gui-android/res/layout/gen -forge-gui-android/res/layout/target -forge-gui-android/res/target -forge-gui-android/res/values/Thumbs.db -forge-gui-android/res/values/bin -forge-gui-android/res/values/gen -forge-gui-android/res/values/target -forge-gui-android/target -forge-gui-desktop/target -forge-gui-ios/target -forge-gui-mobile-dev/bin -forge-gui-mobile-dev/fallback_skin/Thumbs.db +forge-gui-android/**/Thumbs.db +forge-gui-mobile-dev/**/Thumbs.db forge-gui-mobile-dev/res -forge-gui-mobile-dev/target forge-gui-mobile-dev/testAssets -forge-gui-mobile/bin -forge-gui-mobile/target -forge-gui/forge.profile.properties -forge-gui/res/*.log -forge-gui/res/PerSetTrackingResults + forge-gui/res/cardsfolder/*.bat + +forge-gui/res/PerSetTrackingResults forge-gui/res/decks forge-gui/res/layouts forge-gui/res/pics* forge-gui/res/pics_product + +forge-gui/res/skins/**/PerSetTrackingResults +forge-gui/res/skins/**/decks +forge-gui/res/skins/**/layouts +forge-gui/res/skins/**/pics* +forge-gui/res/skins/**/pics_product + forge-gui/res/quest/world/1996-05[!!-~]Ice[!!-~]Age/duels/.directory -forge-gui/res/skins/*.log -forge-gui/res/skins/PerSetTrackingResults -forge-gui/res/skins/Thumbs.db -forge-gui/res/skins/arabian_nights/*.log -forge-gui/res/skins/arabian_nights/PerSetTrackingResults -forge-gui/res/skins/arabian_nights/Thumbs.db -forge-gui/res/skins/arabian_nights/decks -forge-gui/res/skins/arabian_nights/layouts -forge-gui/res/skins/arabian_nights/pics* -forge-gui/res/skins/arabian_nights/pics_product -forge-gui/res/skins/comic/*.log -forge-gui/res/skins/comic/PerSetTrackingResults -forge-gui/res/skins/comic/Thumbs.db -forge-gui/res/skins/comic/decks -forge-gui/res/skins/comic/layouts -forge-gui/res/skins/comic/pics* -forge-gui/res/skins/comic/pics_product -forge-gui/res/skins/dark_ascension/*.log -forge-gui/res/skins/dark_ascension/PerSetTrackingResults -forge-gui/res/skins/dark_ascension/Thumbs.db -forge-gui/res/skins/dark_ascension/decks -forge-gui/res/skins/dark_ascension/layouts -forge-gui/res/skins/dark_ascension/pics* -forge-gui/res/skins/dark_ascension/pics_product -forge-gui/res/skins/decks -forge-gui/res/skins/default/*.log -forge-gui/res/skins/default/PerSetTrackingResults -forge-gui/res/skins/default/Thumbs.db -forge-gui/res/skins/default/decks -forge-gui/res/skins/default/layouts -forge-gui/res/skins/default/pics* -forge-gui/res/skins/default/pics_product -forge-gui/res/skins/firebloom/*.log -forge-gui/res/skins/firebloom/PerSetTrackingResults -forge-gui/res/skins/firebloom/Thumbs.db -forge-gui/res/skins/firebloom/decks -forge-gui/res/skins/firebloom/layouts -forge-gui/res/skins/firebloom/pics* -forge-gui/res/skins/firebloom/pics_product -forge-gui/res/skins/inferno/*.log -forge-gui/res/skins/inferno/PerSetTrackingResults -forge-gui/res/skins/inferno/Thumbs.db -forge-gui/res/skins/inferno/decks -forge-gui/res/skins/inferno/layouts -forge-gui/res/skins/inferno/pics* -forge-gui/res/skins/inferno/pics_product -forge-gui/res/skins/innistrad/*.log -forge-gui/res/skins/innistrad/PerSetTrackingResults -forge-gui/res/skins/innistrad/Thumbs.db -forge-gui/res/skins/innistrad/decks -forge-gui/res/skins/innistrad/layouts -forge-gui/res/skins/innistrad/pics* -forge-gui/res/skins/innistrad/pics_product -forge-gui/res/skins/journeyman/*.log -forge-gui/res/skins/journeyman/PerSetTrackingResults -forge-gui/res/skins/journeyman/Thumbs.db -forge-gui/res/skins/journeyman/decks -forge-gui/res/skins/journeyman/layouts -forge-gui/res/skins/journeyman/pics* -forge-gui/res/skins/journeyman/pics_product -forge-gui/res/skins/kamigawa/*.log -forge-gui/res/skins/kamigawa/PerSetTrackingResults -forge-gui/res/skins/kamigawa/Thumbs.db -forge-gui/res/skins/kamigawa/decks -forge-gui/res/skins/kamigawa/layouts -forge-gui/res/skins/kamigawa/pics* -forge-gui/res/skins/kamigawa/pics_product -forge-gui/res/skins/layouts -forge-gui/res/skins/marble_blue/*.log -forge-gui/res/skins/marble_blue/PerSetTrackingResults -forge-gui/res/skins/marble_blue/Thumbs.db -forge-gui/res/skins/marble_blue/decks -forge-gui/res/skins/marble_blue/layouts -forge-gui/res/skins/marble_blue/pics* -forge-gui/res/skins/marble_blue/pics_product -forge-gui/res/skins/metalcraft/*.log -forge-gui/res/skins/metalcraft/PerSetTrackingResults -forge-gui/res/skins/metalcraft/Thumbs.db -forge-gui/res/skins/metalcraft/decks -forge-gui/res/skins/metalcraft/layouts -forge-gui/res/skins/metalcraft/pics* -forge-gui/res/skins/metalcraft/pics_product -forge-gui/res/skins/mythic_rare/*.log -forge-gui/res/skins/mythic_rare/PerSetTrackingResults -forge-gui/res/skins/mythic_rare/Thumbs.db -forge-gui/res/skins/mythic_rare/decks -forge-gui/res/skins/mythic_rare/layouts -forge-gui/res/skins/mythic_rare/pics* -forge-gui/res/skins/mythic_rare/pics_product -forge-gui/res/skins/phyrexia/*.log -forge-gui/res/skins/phyrexia/PerSetTrackingResults -forge-gui/res/skins/phyrexia/Thumbs.db -forge-gui/res/skins/phyrexia/decks -forge-gui/res/skins/phyrexia/layouts -forge-gui/res/skins/phyrexia/pics* -forge-gui/res/skins/phyrexia/pics_product -forge-gui/res/skins/pics* -forge-gui/res/skins/pics_product -forge-gui/res/skins/ravnica/*.log -forge-gui/res/skins/ravnica/PerSetTrackingResults -forge-gui/res/skins/ravnica/Thumbs.db -forge-gui/res/skins/ravnica/decks -forge-gui/res/skins/ravnica/layouts -forge-gui/res/skins/ravnica/pics* -forge-gui/res/skins/ravnica/pics_product -forge-gui/res/skins/rebel/*.log -forge-gui/res/skins/rebel/PerSetTrackingResults -forge-gui/res/skins/rebel/Thumbs.db -forge-gui/res/skins/rebel/decks -forge-gui/res/skins/rebel/layouts -forge-gui/res/skins/rebel/pics* -forge-gui/res/skins/rebel/pics_product -forge-gui/res/skins/sleeping_forest/*.log -forge-gui/res/skins/sleeping_forest/PerSetTrackingResults -forge-gui/res/skins/sleeping_forest/Thumbs.db -forge-gui/res/skins/sleeping_forest/decks -forge-gui/res/skins/sleeping_forest/layouts -forge-gui/res/skins/sleeping_forest/pics* -forge-gui/res/skins/sleeping_forest/pics_product -forge-gui/res/skins/smith/*.log -forge-gui/res/skins/smith/PerSetTrackingResults -forge-gui/res/skins/smith/Thumbs.db -forge-gui/res/skins/smith/decks -forge-gui/res/skins/smith/layouts -forge-gui/res/skins/smith/pics* -forge-gui/res/skins/smith/pics_product -forge-gui/res/skins/the_dale/*.log -forge-gui/res/skins/the_dale/PerSetTrackingResults -forge-gui/res/skins/the_dale/Thumbs.db -forge-gui/res/skins/the_dale/decks -forge-gui/res/skins/the_dale/layouts -forge-gui/res/skins/the_dale/pics* -forge-gui/res/skins/the_dale/pics_product -forge-gui/res/skins/the_simpsons/*.log -forge-gui/res/skins/the_simpsons/PerSetTrackingResults -forge-gui/res/skins/the_simpsons/Thumbs.db -forge-gui/res/skins/the_simpsons/decks -forge-gui/res/skins/the_simpsons/layouts -forge-gui/res/skins/the_simpsons/pics* -forge-gui/res/skins/the_simpsons/pics_product -forge-gui/res/skins/zendikar/*.log -forge-gui/res/skins/zendikar/PerSetTrackingResults -forge-gui/res/skins/zendikar/Thumbs.db -forge-gui/res/skins/zendikar/decks -forge-gui/res/skins/zendikar/layouts -forge-gui/res/skins/zendikar/pics* -forge-gui/res/skins/zendikar/pics_product -forge-gui/target + forge-gui/tools/AllCards.json forge-gui/tools/EditionTrackingResults forge-gui/tools/PerSetTrackingResults -forge-gui/tools/oracleScript.log -/forge.profile.properties -/jgv.txt -/nbactions.xml -/pom.xml.next -/pom.xml.releaseBackup -/pom.xml.tag -/release.properties -/target -/test-output -.settings -.classpath -.project -.vscode/settings.json -.vscode/launch.json + diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 035a4cecb4c..7ce9a83c61c 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -2103,9 +2103,9 @@ public class AiController { return filterList(list, CardTraitPredicates.hasParam("AiLogic", logic)); } - public List chooseModeForAbility(SpellAbility sa, int min, int num, boolean allowRepeat) { + public List chooseModeForAbility(SpellAbility sa, List possible, int min, int num, boolean allowRepeat) { if (simPicker != null) { - return simPicker.chooseModeForAbility(sa, min, num, allowRepeat); + return simPicker.chooseModeForAbility(sa, possible, min, num, allowRepeat); } return null; } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index bc1cc527832..60e0f02c05d 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -101,7 +101,9 @@ public class ComputerUtil { sa = GameActionUtil.addExtraKeywordCost(sa); if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { - CharmEffect.makeChoices(sa); + if (!CharmEffect.makeChoices(sa)) { + return false; + } } if (chooseTargets != null) { chooseTargets.run(); @@ -261,7 +263,9 @@ public class ComputerUtil { newSA.setHostCard(game.getAction().moveToStack(source, sa)); if (newSA.getApi() == ApiType.Charm && !newSA.isWrapper()) { - CharmEffect.makeChoices(newSA); + if (!CharmEffect.makeChoices(sa)) { + return false; + } } } diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index 1f4e66b3198..94c9582e2d7 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -800,8 +800,8 @@ public class PlayerControllerAi extends PlayerController { } @Override - public List chooseModeForAbility(SpellAbility sa, int min, int num, boolean allowRepeat) { - List result = brains.chooseModeForAbility(sa, min, num, allowRepeat); + public List chooseModeForAbility(SpellAbility sa, List possible, int min, int num, boolean allowRepeat) { + List result = brains.chooseModeForAbility(sa, possible, min, num, allowRepeat); if (result != null) { return result; } diff --git a/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java b/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java index b33948b293b..b64a1fd84c5 100644 --- a/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java @@ -251,7 +251,7 @@ public class AnimateAi extends SpellAbilityAi { && sa.getTargetRestrictions() != null && sa.getTargetRestrictions().getMinTargets(sa.getHostCard(), sa) == 0; - final CardType types = new CardType(); + final CardType types = new CardType(true); if (sa.hasParam("Types")) { types.addAll(Arrays.asList(sa.getParam("Types").split(","))); } @@ -340,6 +340,14 @@ public class AnimateAi extends SpellAbilityAi { // select the worst of the best final Card worst = ComputerUtilCard.getWorstAI(maxList); + if (worst.isLand()) { + // e.g. Clan Guildmage, make sure we're not using the same land we want to animate to activate the ability + this.holdAnimatedTillMain2(ai, worst); + if (!ComputerUtilMana.canPayManaCost(sa, ai, 0)) { + this.releaseHeldTillMain2(ai, worst); + return false; + } + } this.rememberAnimatedThisTurn(ai, worst); sa.getTargets().add(worst); return true; @@ -383,12 +391,12 @@ public class AnimateAi extends SpellAbilityAi { } } - final CardType types = new CardType(); + final CardType types = new CardType(true); if (sa.hasParam("Types")) { types.addAll(Arrays.asList(sa.getParam("Types").split(","))); } - final CardType removeTypes = new CardType(); + final CardType removeTypes = new CardType(true); if (sa.hasParam("RemoveTypes")) { removeTypes.addAll(Arrays.asList(sa.getParam("RemoveTypes").split(","))); } @@ -564,4 +572,12 @@ public class AnimateAi extends SpellAbilityAi { public static boolean isAnimatedThisTurn(Player ai, Card c) { return AiCardMemory.isRememberedCard(ai, c, AiCardMemory.MemorySet.ANIMATED_THIS_TURN); } + + private void holdAnimatedTillMain2(Player ai, Card c) { + AiCardMemory.rememberCard(ai, c, AiCardMemory.MemorySet.HELD_MANA_SOURCES_FOR_MAIN2); + } + + private void releaseHeldTillMain2(Player ai, Card c) { + AiCardMemory.forgetCard(ai, c, AiCardMemory.MemorySet.HELD_MANA_SOURCES_FOR_MAIN2); + } } diff --git a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java index 296a695b871..8835fc47e33 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java @@ -2,7 +2,9 @@ package forge.ai.ability; import com.google.common.collect.Lists; import forge.ai.*; +import forge.game.ability.AbilityUtils; import forge.game.ability.effects.CharmEffect; +import forge.game.card.Card; import forge.game.player.Player; import forge.game.spellability.AbilitySub; import forge.game.spellability.SpellAbility; @@ -19,10 +21,13 @@ public class CharmAi extends SpellAbilityAi { // sa is Entwined, no need for extra logic if (sa.isEntwine()) { return true; - } + } + + final Card source = sa.getHostCard(); + + final int num = AbilityUtils.calculateAmount(source, sa.getParamOrDefault("CharmNum", "1"), sa); + final int min = sa.hasParam("MinCharmNum") ? AbilityUtils.calculateAmount(source, sa.getParamOrDefault("MinCharmNum", "1"), sa) : num; - final int num = Integer.parseInt(sa.hasParam("CharmNum") ? sa.getParam("CharmNum") : "1"); - final int min = sa.hasParam("MinCharmNum") ? Integer.parseInt(sa.getParam("MinCharmNum")) : num; boolean timingRight = sa.isTrigger(); //is there a reason to play the charm now? // Reset the chosen list otherwise it will be locked in forever by earlier calls diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java index 2f3b0c5b67a..75ca4487057 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java @@ -1,26 +1,20 @@ package forge.ai.ability; import com.google.common.base.Predicates; -import com.google.common.collect.Lists; -import forge.ai.AiCardMemory; -import forge.ai.ComputerUtilAbility; -import forge.ai.ComputerUtilCard; -import forge.ai.ComputerUtilMana; -import forge.ai.SpellAbilityAi; +import forge.ai.*; import forge.card.CardType; import forge.game.ability.AbilityUtils; -import forge.game.card.Card; -import forge.game.card.CardCollection; -import forge.game.card.CardCollectionView; -import forge.game.card.CardLists; -import forge.game.card.CardPredicates; +import forge.game.ability.ApiType; +import forge.game.card.*; import forge.game.keyword.Keyword; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; import forge.util.Aggregates; -import java.util.List; + +import java.util.HashSet; +import java.util.Set; public class ChooseTypeAi extends SpellAbilityAi { @Override @@ -31,6 +25,8 @@ public class ChooseTypeAi extends SpellAbilityAi { if (ComputerUtilAbility.getAbilitySourceName(sa).equals("Mirror Entity Avatar")) { return doMirrorEntityLogic(aiPlayer, sa); } + } else if ("MostProminentOppControls".equals(sa.getParam("AILogic"))) { + return !chooseType(sa, aiPlayer.getOpponents().getCardsIn(ZoneType.Battlefield)).isEmpty(); } return doTriggerAINoCost(aiPlayer, sa, false); @@ -44,27 +40,11 @@ public class ChooseTypeAi extends SpellAbilityAi { return false; } - CardCollectionView otb = aiPlayer.getCardsIn(ZoneType.Battlefield); - List valid = Lists.newArrayList(CardType.getAllCreatureTypes()); - - String chosenType = ComputerUtilCard.getMostProminentType(otb, valid); + String chosenType = chooseType(sa, aiPlayer.getCardsIn(ZoneType.Battlefield)); if (chosenType.isEmpty()) { - // Account for the situation when only changelings are on the battlefield - boolean allChangeling = false; - for (Card c : otb) { - if (c.isCreature() && c.hasStartOfKeyword(Keyword.CHANGELING.toString())) { - chosenType = Aggregates.random(valid); // just choose a random type for changelings - allChangeling = true; - break; - } - } - - if (!allChangeling) { - // Still empty, probably no creatures on board - return false; - } + return false; } - + int maxX = ComputerUtilMana.determineMaxAffordableX(aiPlayer, sa); int avgPower = 0; @@ -127,4 +107,40 @@ public class ChooseTypeAi extends SpellAbilityAi { return true; } + private String chooseType(SpellAbility sa, CardCollectionView cards) { + Set valid = new HashSet<>(); + + if (sa.getSubAbility() != null && sa.getSubAbility().getApi() == ApiType.PumpAll + && sa.getSubAbility().isCurse() && sa.getSubAbility().hasParam("NumDef")) { + final SpellAbility pumpSa = sa.getSubAbility(); + final int defense = AbilityUtils.calculateAmount(sa.getHostCard(), pumpSa.getParam("NumDef"), pumpSa); + for (Card c : cards) { + if (c.isCreature() && c.getNetToughness() <= -defense) { + valid.addAll(c.getType().getCreatureTypes()); + } + } + } else { + valid.addAll(CardType.getAllCreatureTypes()); + } + + String chosenType = ComputerUtilCard.getMostProminentType(cards, valid); + if (chosenType.isEmpty()) { + // Account for the situation when only changelings are on the battlefield + boolean allChangeling = false; + for (Card c : cards) { + if (c.isCreature() && c.hasStartOfKeyword(Keyword.CHANGELING.toString())) { + chosenType = Aggregates.random(valid); // just choose a random type for changelings + allChangeling = true; + break; + } + } + + if (!allChangeling) { + // Still empty, probably no creatures on board + return ""; + } + } + + return chosenType; + } } diff --git a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java index e93a4b5ebfc..b63d0314eba 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java +++ b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java @@ -9,7 +9,6 @@ import forge.ai.ability.ExploreAi; import forge.ai.simulation.GameStateEvaluator.Score; import forge.game.Game; import forge.game.ability.ApiType; -import forge.game.ability.effects.CharmEffect; import forge.game.card.*; import forge.game.phase.PhaseType; import forge.game.player.Player; @@ -371,14 +370,12 @@ public class SpellAbilityPicker { return bestScore; } - public List chooseModeForAbility(SpellAbility sa, int min, int num, boolean allowRepeat) { + public List chooseModeForAbility(SpellAbility sa, List choices, int min, int num, boolean allowRepeat) { if (interceptor != null) { - List choices = CharmEffect.makePossibleOptions(sa); return interceptor.chooseModesForAbility(choices, min, num, allowRepeat); } if (plan != null && plan.getSelectedDecision() != null && plan.getSelectedDecision().modes != null) { Plan.Decision decision = plan.getSelectedDecision(); - List choices = CharmEffect.makePossibleOptions(sa); // TODO: Validate that there's no discrepancies between choices and modes? List plannedModes = SpellAbilityChoicesIterator.getModeCombination(choices, decision.modes); if (plan.getSelectedDecision().targets != null) { diff --git a/forge-core/src/main/java/forge/ImageKeys.java b/forge-core/src/main/java/forge/ImageKeys.java index fe8d43bf31d..38530ce45a5 100644 --- a/forge-core/src/main/java/forge/ImageKeys.java +++ b/forge-core/src/main/java/forge/ImageKeys.java @@ -150,6 +150,9 @@ public final class ImageKeys { // try with upper case set file = findFile(dir, setlessFilename + "_" + setCode.toUpperCase()); if (file != null) { return file; } + // try with lower case set + file = findFile(dir, setlessFilename + "_" + setCode.toLowerCase()); + if (file != null) { return file; } // try without set name file = findFile(dir, setlessFilename); if (file != null) { return file; } diff --git a/forge-core/src/main/java/forge/card/CardEdition.java b/forge-core/src/main/java/forge/card/CardEdition.java index 13d2ad422cf..c69b165d995 100644 --- a/forge-core/src/main/java/forge/card/CardEdition.java +++ b/forge-core/src/main/java/forge/card/CardEdition.java @@ -123,6 +123,7 @@ public final class CardEdition implements Comparable { // immutable private String additionalUnlockSet = ""; private boolean smallSetOverride = false; private String boosterMustContain = ""; + private String boosterReplaceSlotFromPrintSheet = ""; private boolean doublePickToStartRound = false; private final CardInSet[] cards; private final Map tokenNormalized; @@ -193,6 +194,7 @@ public final class CardEdition implements Comparable { // immutable public boolean getSmallSetOverride() { return smallSetOverride; } public boolean getDoublePickToStartRound() { return doublePickToStartRound; } public String getBoosterMustContain() { return boosterMustContain; } + public String getBoosterReplaceSlotFromPrintSheet() { return boosterReplaceSlotFromPrintSheet; } public CardInSet[] getCards() { return cards; } public boolean isModern() { return getDate().after(parseDate("2003-07-27")); } //8ED and above are modern except some promo cards and others @@ -382,6 +384,7 @@ public final class CardEdition implements Comparable { // immutable res.doublePickToStartRound = section.getBoolean("DoublePick", false); // for "small" sets with over 200 cards (e.g. Eldritch Moon) res.boosterMustContain = section.get("BoosterMustContain", ""); // e.g. Dominaria guaranteed legendary creature + res.boosterReplaceSlotFromPrintSheet = section.get("BoosterReplaceSlotFromPrintSheet", ""); // e.g. Zendikar Rising guaranteed double-faced card return res; } diff --git a/forge-core/src/main/java/forge/card/CardRules.java b/forge-core/src/main/java/forge/card/CardRules.java index c759785b37a..1023b6a13d4 100644 --- a/forge-core/src/main/java/forge/card/CardRules.java +++ b/forge-core/src/main/java/forge/card/CardRules.java @@ -487,7 +487,7 @@ public final class CardRules implements ICardCharacteristics { if ("T".equals(key)) { this.faces[this.curFace].addTrigger(value); } else if ("Types".equals(key)) { - this.faces[this.curFace].setType(CardType.parse(value)); + this.faces[this.curFace].setType(CardType.parse(value, false)); } else if ("Text".equals(key) && !"no text".equals(value) && StringUtils.isNotBlank(value)) { this.faces[this.curFace].setNonAbilityText(value); } @@ -557,7 +557,7 @@ public final class CardRules implements ICardCharacteristics { CardAiHints cah = new CardAiHints(true, true, true, null, null, null); CardFace[] faces = { new CardFace(name), null}; faces[0].setColor(ColorSet.fromMask(0)); - faces[0].setType(CardType.parse("")); + faces[0].setType(CardType.parse("", false)); faces[0].setOracleText("This card is not supported by Forge. Whenever you start a game with this card, it will be bugged."); faces[0].setNonAbilityText("This card is not supported by Forge.\nWhenever you start a game with this card, it will be bugged."); faces[0].assignMissingFields(); diff --git a/forge-core/src/main/java/forge/card/CardType.java b/forge-core/src/main/java/forge/card/CardType.java index 09d6abbd2f9..a7af692822c 100644 --- a/forge-core/src/main/java/forge/card/CardType.java +++ b/forge-core/src/main/java/forge/card/CardType.java @@ -50,7 +50,9 @@ import forge.util.Settable; public final class CardType implements Comparable, CardTypeView { private static final long serialVersionUID = 4629853583167022151L; - public static final CardTypeView EMPTY = new CardType(); + public static final CardTypeView EMPTY = new CardType(false); + + public static final String AllCreatureTypes = "AllCreatureTypes"; public enum CoreType { Artifact(true), @@ -109,11 +111,14 @@ public final class CardType implements Comparable, CardTypeView { private final Set coreTypes = EnumSet.noneOf(CoreType.class); private final Set supertypes = EnumSet.noneOf(Supertype.class); private final Set subtypes = Sets.newLinkedHashSet(); + private boolean incomplete = false; private transient String calculatedType = null; - public CardType() { + public CardType(boolean incomplete) { + this.incomplete = incomplete; } - public CardType(final Iterable from0) { + public CardType(final Iterable from0, boolean incomplete) { + this.incomplete = incomplete; addAll(from0); } public CardType(final CardType from0) { @@ -152,6 +157,7 @@ public final class CardType implements Comparable, CardTypeView { changed = true; } } + sanisfySubtypes(); return changed; } public boolean addAll(final CardType type) { @@ -159,6 +165,7 @@ public final class CardType implements Comparable, CardTypeView { if (coreTypes.addAll(type.coreTypes)) { changed = true; } if (supertypes.addAll(type.supertypes)) { changed = true; } if (subtypes.addAll(type.subtypes)) { changed = true; } + sanisfySubtypes(); return changed; } public boolean addAll(final CardTypeView type) { @@ -166,6 +173,7 @@ public final class CardType implements Comparable, CardTypeView { if (Iterables.addAll(coreTypes, type.getCoreTypes())) { changed = true; } if (Iterables.addAll(supertypes, type.getSupertypes())) { changed = true; } if (Iterables.addAll(subtypes, type.getSubtypes())) { changed = true; } + sanisfySubtypes(); return changed; } @@ -175,6 +183,7 @@ public final class CardType implements Comparable, CardTypeView { if (supertypes.removeAll(type.supertypes)) { changed = true; } if (subtypes.removeAll(type.subtypes)) { changed = true; } if (changed) { + sanisfySubtypes(); calculatedType = null; return true; } @@ -211,6 +220,7 @@ public final class CardType implements Comparable, CardTypeView { } if (changed) { + sanisfySubtypes(); calculatedType = null; } return changed; @@ -223,7 +233,7 @@ public final class CardType implements Comparable, CardTypeView { } boolean changed = Iterables.removeIf(subtypes, Predicates.IS_CREATURE_TYPE); // need to remove AllCreatureTypes too when setting Creature Type - if (subtypes.remove("AllCreatureTypes")) { + if (subtypes.remove(AllCreatureTypes)) { changed = true; } subtypes.addAll(ctypes); @@ -252,7 +262,7 @@ public final class CardType implements Comparable, CardTypeView { final Set creatureTypes = Sets.newHashSet(); if (isCreature() || isTribal()) { for (final String t : subtypes) { - if (isACreatureType(t) || t.equals("AllCreatureTypes")) { + if (isACreatureType(t) || t.equals(AllCreatureTypes)) { creatureTypes.add(t); } } @@ -302,7 +312,7 @@ public final class CardType implements Comparable, CardTypeView { } @Override public boolean hasSubtype(final String subtype) { - if (isACreatureType(subtype) && subtypes.contains("AllCreatureTypes")) { + if (isACreatureType(subtype) && subtypes.contains(AllCreatureTypes)) { return true; } return subtypes.contains(subtype); @@ -315,7 +325,7 @@ public final class CardType implements Comparable, CardTypeView { creatureType = toMixedCase(creatureType); if (!isACreatureType(creatureType)) { return false; } - return subtypes.contains(creatureType) || subtypes.contains("AllCreatureTypes"); + return subtypes.contains(creatureType) || subtypes.contains(AllCreatureTypes); } private static String toMixedCase(final String s) { if (s.isEmpty()) { @@ -485,7 +495,7 @@ public final class CardType implements Comparable, CardTypeView { if (ct.isRemoveCreatureTypes()) { Iterables.removeIf(newType.subtypes, Predicates.IS_CREATURE_TYPE); // need to remove AllCreatureTypes too when removing creature Types - newType.subtypes.remove("AllCreatureTypes"); + newType.subtypes.remove(AllCreatureTypes); } if (ct.isRemoveArtifactTypes()) { Iterables.removeIf(newType.subtypes, Predicates.IS_ARTIFACT_TYPE); @@ -503,29 +513,37 @@ public final class CardType implements Comparable, CardTypeView { } // sanisfy subtypes if (newType != null && !newType.subtypes.isEmpty()) { - if (!newType.isCreature() && !newType.isTribal()) { - Iterables.removeIf(newType.subtypes, Predicates.IS_CREATURE_TYPE); - newType.subtypes.remove("AllCreatureTypes"); - } - if (!newType.isLand()) { - Iterables.removeIf(newType.subtypes, Predicates.IS_LAND_TYPE); - } - if (!newType.isArtifact()) { - Iterables.removeIf(newType.subtypes, Predicates.IS_ARTIFACT_TYPE); - } - if (!newType.isEnchantment()) { - Iterables.removeIf(newType.subtypes, Predicates.IS_ENCHANTMENT_TYPE); - } - if (!newType.isInstant() && !newType.isSorcery()) { - Iterables.removeIf(newType.subtypes, Predicates.IS_SPELL_TYPE); - } - if (!newType.isPlaneswalker() && !newType.isEmblem()) { - Iterables.removeIf(newType.subtypes, Predicates.IS_WALKER_TYPE); - } + newType.sanisfySubtypes(); } return newType == null ? this : newType; } + public void sanisfySubtypes() { + // incomplete types are used for changing effects + if (this.incomplete) { + return; + } + if (!isCreature() && !isTribal()) { + Iterables.removeIf(subtypes, Predicates.IS_CREATURE_TYPE); + subtypes.remove(AllCreatureTypes); + } + if (!isLand()) { + Iterables.removeIf(subtypes, Predicates.IS_LAND_TYPE); + } + if (!isArtifact()) { + Iterables.removeIf(subtypes, Predicates.IS_ARTIFACT_TYPE); + } + if (!isEnchantment()) { + Iterables.removeIf(subtypes, Predicates.IS_ENCHANTMENT_TYPE); + } + if (!isInstant() && !isSorcery()) { + Iterables.removeIf(subtypes, Predicates.IS_SPELL_TYPE); + } + if (!isPlaneswalker() && !isEmblem()) { + Iterables.removeIf(subtypes, Predicates.IS_WALKER_TYPE); + } + } + @Override public Iterator iterator() { final Iterator coreTypeIterator = coreTypes.iterator(); @@ -560,7 +578,64 @@ public final class CardType implements Comparable, CardTypeView { return toString().compareTo(o.toString()); } - public boolean sharesSubtypeWith(final CardType ctOther) { + public boolean sharesCreaturetypeWith(final CardTypeView ctOther) { + if (ctOther == null) { + return false; + } + if (this.subtypes.contains(AllCreatureTypes) && ctOther.hasSubtype(AllCreatureTypes)) { + return true; + } + for (final String type : getCreatureTypes()) { + if (ctOther.hasCreatureType(type)) { + return true; + } + } + return false; + } + + public boolean sharesLandTypeWith(final CardTypeView ctOther) { + if (ctOther == null) { + return false; + } + + for (final String type : getLandTypes()) { + if (ctOther.hasSubtype(type)) { + return true; + } + } + return false; + } + + public boolean sharesPermanentTypeWith(final CardTypeView ctOther) { + if (ctOther == null) { + return false; + } + + for (final CoreType type : getCoreTypes()) { + if (type.isPermanent && ctOther.hasType(type)) { + return true; + } + } + return false; + } + + public boolean sharesCardTypeWith(final CardTypeView ctOther) { + if (ctOther == null) { + return false; + } + + for (final CoreType type : getCoreTypes()) { + if (ctOther.hasType(type)) { + return true; + } + } + return false; + } + + public boolean sharesSubtypeWith(final CardTypeView ctOther) { + if (ctOther == null) { + return false; + } for (final String t : ctOther.getSubtypes()) { if (hasSubtype(t)) { return true; @@ -569,11 +644,11 @@ public final class CardType implements Comparable, CardTypeView { return false; } - public static CardType parse(final String typeText) { + public static CardType parse(final String typeText, boolean incomplete) { // Most types and subtypes, except "Serra's Realm" and // "Bolas's Meditation Realm" consist of only one word final char space = ' '; - final CardType result = new CardType(); + final CardType result = new CardType(incomplete); int iTypeStart = 0; int iSpace = typeText.indexOf(space); @@ -593,7 +668,7 @@ public final class CardType implements Comparable, CardTypeView { } public static CardType combine(final CardType a, final CardType b) { - final CardType result = new CardType(); + final CardType result = new CardType(false); result.supertypes.addAll(a.supertypes); result.supertypes.addAll(b.supertypes); result.coreTypes.addAll(a.coreTypes); diff --git a/forge-core/src/main/java/forge/card/CardTypeView.java b/forge-core/src/main/java/forge/card/CardTypeView.java index b1c01369b2b..e9b65aeac81 100644 --- a/forge-core/src/main/java/forge/card/CardTypeView.java +++ b/forge-core/src/main/java/forge/card/CardTypeView.java @@ -19,6 +19,12 @@ public interface CardTypeView extends Iterable, Serializable { boolean hasSupertype(Supertype supertype); boolean hasSubtype(String subtype); boolean hasCreatureType(String creatureType); + + public boolean sharesCreaturetypeWith(final CardTypeView ctOther); + public boolean sharesLandTypeWith(final CardTypeView ctOther); + public boolean sharesPermanentTypeWith(final CardTypeView ctOther); + public boolean sharesCardTypeWith(final CardTypeView ctOther); + boolean isPermanent(); boolean isCreature(); boolean isPlaneswalker(); diff --git a/forge-core/src/main/java/forge/item/generation/BoosterGenerator.java b/forge-core/src/main/java/forge/item/generation/BoosterGenerator.java index 8f5d18715d6..6610e94aee9 100644 --- a/forge-core/src/main/java/forge/item/generation/BoosterGenerator.java +++ b/forge-core/src/main/java/forge/item/generation/BoosterGenerator.java @@ -339,6 +339,11 @@ public class BoosterGenerator { if (!boosterMustContain.isEmpty()) { ensureGuaranteedCardInBooster(result, template, boosterMustContain); } + + String boosterReplaceSlotFromPrintSheet = edition.getBoosterReplaceSlotFromPrintSheet(); + if(!boosterReplaceSlotFromPrintSheet.isEmpty()) { + replaceCardFromExtraSheet(result, boosterReplaceSlotFromPrintSheet); + } } return result; @@ -390,27 +395,69 @@ public class BoosterGenerator { if (!possibleCards.isEmpty()) { PaperCard toAdd = Aggregates.random(possibleCards); - PaperCard toRepl = null; - CardRarity tgtRarity = toAdd.getRarity(); - - // remove the first card of the same rarity, replace it with toAdd. Keep the foil state. - for (PaperCard repl : result) { - if (repl.getRarity() == tgtRarity) { - toRepl = repl; - break; - } - } - if (toRepl != null) { - if (toRepl.isFoil()) { - toAdd = StaticData.instance().getCommonCards().getFoiled(toAdd); - } - result.remove(toRepl); - result.add(toAdd); - } + BoosterGenerator.replaceCard(result, toAdd); } } } + /** + * Replaces an already present card in the booster with a card from the supplied print sheet. + * Nothing is replaced if there is no matching rarity found. + * @param booster in which a card gets replaced + * @param printSheetKey + */ + public static void replaceCardFromExtraSheet(List booster, String printSheetKey) { + PrintSheet replacementSheet = StaticData.instance().getPrintSheets().get(printSheetKey); + PaperCard toAdd = replacementSheet.random(1, false).get(0); + BoosterGenerator.replaceCard(booster, toAdd); + } + + /** + * Replaces an already present card with the supplied card of the same (or similar in case or rare/mythic) + * rarity in the supplied booster. Nothing is replaced if there is no matching rarity found. + * @param booster in which a card gets replaced + * @param toAdd new card which replaces a card in the booster + */ + public static void replaceCard(List booster, PaperCard toAdd) { + Predicate rarityPredicate = null; + switch(toAdd.getRarity()){ + case BasicLand: + rarityPredicate = Presets.IS_BASIC_LAND; + break; + case Common: + rarityPredicate = Presets.IS_COMMON; + break; + case Uncommon: + rarityPredicate = Presets.IS_UNCOMMON; + break; + case Rare: + case MythicRare: + rarityPredicate = Presets.IS_RARE_OR_MYTHIC; + break; + default: + rarityPredicate = Presets.IS_SPECIAL; + } + + PaperCard toReplace = null; + // Find first card in booster that matches the rarity + for (PaperCard card : booster) { + if(rarityPredicate.apply(card)) { + toReplace = card; + break; + } + } + + // Replace card if match is found + if (toReplace != null) { + // Keep the foil state + if (toReplace.isFoil()) { + toAdd = StaticData.instance().getCommonCards().getFoiled(toAdd); + } + booster.remove(toReplace); + booster.add(toAdd); + } + } + public static void addCardsFromExtraSheet(List dest, String printSheetKey) { PrintSheet extraSheet = getPrintSheet(printSheetKey); diff --git a/forge-game/src/main/java/forge/game/Game.java b/forge-game/src/main/java/forge/game/Game.java index 47997c1b8bc..ec4f8aa927d 100644 --- a/forge-game/src/main/java/forge/game/Game.java +++ b/forge-game/src/main/java/forge/game/Game.java @@ -20,9 +20,12 @@ package forge.game; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.HashBasedTable; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; +import com.google.common.collect.Table; import com.google.common.eventbus.EventBus; import forge.card.CardRarity; import forge.card.CardStateName; @@ -53,6 +56,8 @@ import forge.util.Visitor; import java.util.*; +import org.apache.commons.lang3.tuple.Pair; + /** * Represents the state of a single game, a new instance is created for each game. */ @@ -86,6 +91,8 @@ public class Game { private Map attackedThisTurn = Maps.newHashMap(); private Map attackedLastTurn = Maps.newHashMap(); + private Table>> countersAddedThisTurn = HashBasedTable.create(); + private Player monarch = null; private Player monarchBeginTurn = null; @@ -939,4 +946,46 @@ public class Game { } return result; } + + public void onCleanupPhase() { + clearCounterAddedThisTurn(); + for (Player player : getPlayers()) { + player.onCleanupPhase(); + } + } + + public void addCounterAddedThisTurn(Player putter, CounterType cType, Card card, Integer value) { + if (putter == null || card == null || value <= 0) { + return; + } + List> result = countersAddedThisTurn.get(cType, putter); + if (result == null) { + result = Lists.newArrayList(); + } + result.add(Pair.of(CardUtil.getLKICopy(card), value)); + if (!countersAddedThisTurn.contains(cType, putter)) { + countersAddedThisTurn.put(cType, putter, result); + } + } + + public int getCounterAddedThisTurn(CounterType cType, String validPlayer, String validCard, Card source, Player sourceController, SpellAbility spellAbility) { + int result = 0; + if (!countersAddedThisTurn.containsRow(cType)) { + return result; + } + for (Map.Entry>> e : countersAddedThisTurn.row(cType).entrySet()) { + if (e.getKey().isValid(validPlayer.split(","), sourceController, source, spellAbility)) { + for (Pair p : e.getValue()) { + if (p.getKey().isValid(validCard.split(","), sourceController, source, spellAbility)) { + result += p.getValue(); + } + } + } + } + return result; + } + + public void clearCounterAddedThisTurn() { + countersAddedThisTurn.clear(); + } } diff --git a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java index e5bfcd5100f..f388eb60c1c 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java @@ -286,7 +286,7 @@ public final class AbilityFactory { spellAbility.setDescription(sb.toString()); } else if (api == ApiType.Charm) { - spellAbility.setDescription(CharmEffect.makeSpellDescription(spellAbility)); + spellAbility.setDescription(CharmEffect.makeFormatedDescription(spellAbility)); } else { spellAbility.setDescription(""); } 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 939d23a9e35..c40b4eb64ea 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -374,7 +374,7 @@ public class AbilityUtils { if (StringUtils.isBlank(amount)) { return 0; } if (card == null) { return 0; } final Player player = card.getController(); - final Game game = player.getGame(); + final Game game = player == null ? card.getGame() : player.getGame(); // Strip and save sign for calculations final boolean startsWithPlus = amount.charAt(0) == '+'; @@ -1593,6 +1593,8 @@ public class AbilityUtils { final String[] sq; sq = l[0].split("\\."); + final Game game = c.getGame(); + if (ctb != null) { // Count$Compare .. if (sq[0].startsWith("Compare")) { @@ -1776,6 +1778,13 @@ public class AbilityUtils { } } } + + if (l[0].startsWith("CountersAddedThisTurn")) { + final String[] parts = l[0].split(" "); + CounterType cType = CounterType.getType(parts[1]); + + return CardFactoryUtil.doXMath(game.getCounterAddedThisTurn(cType, parts[2], parts[3], c, sa.getActivatingPlayer(), sa), expr, c); + } } } return CardFactoryUtil.xCount(c, s2); diff --git a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java index ae557bfd3fe..86a45af2f81 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -78,14 +78,17 @@ public abstract class SpellAbilityEffect { // Own description String stackDesc = params.get("StackDescription"); if (stackDesc != null) { - if ("SpellDescription".equalsIgnoreCase(stackDesc)) { // by typing "none" they want to suppress output + // by typing "SpellDescription" they want to bypass the Effect's string builder + if ("SpellDescription".equalsIgnoreCase(stackDesc)) { if (params.get("SpellDescription") != null) { - sb.append(TextUtil.fastReplace(params.get("SpellDescription"), - "CARDNAME", sa.getHostCard().getName())); - } - if (sa.getTargets() != null && !sa.getTargets().getTargets().isEmpty()) { - sb.append(" (Targeting: ").append(sa.getTargets().getTargets()).append(")"); - } + String currentName = (sa.getHostCard().getName()); + String desc1 = TextUtil.fastReplace(params.get("SpellDescription"), "CARDNAME", currentName); + String desc = TextUtil.fastReplace(desc1, "NICKNAME", currentName.split(",")[0]); + sb.append(desc); + } + if (sa.getTargets() != null && !sa.getTargets().getTargets().isEmpty()) { + sb.append(" (Targeting: ").append(sa.getTargets().getTargets()).append(")"); + } } else if (!"None".equalsIgnoreCase(stackDesc)) { // by typing "none" they want to suppress output makeSpellDescription(sa, sb, stackDesc); } @@ -147,7 +150,11 @@ public abstract class SpellAbilityEffect { if ("}".equals(t)) { isPlainText = true; continue; } if (isPlainText) { - sb.append(TextUtil.fastReplace(t, "CARDNAME", sa.getHostCard().getName())); + if(t.startsWith("NICKNAME")) { + sb.append(TextUtil.fastReplace(t,"NICKNAME", sa.getHostCard().getName().split(",")[0])); + } else { + sb.append(TextUtil.fastReplace(t, "CARDNAME", sa.getHostCard().getName())); + } } else { final List objs; if (t.startsWith("p:")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java index 9e23a7a7183..d777368c2d6 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java @@ -51,12 +51,12 @@ public class AnimateAllEffect extends AnimateEffectBase { final boolean permanent = sa.hasParam("Permanent"); - final CardType types = new CardType(); + final CardType types = new CardType(true); if (sa.hasParam("Types")) { types.addAll(Arrays.asList(sa.getParam("Types").split(","))); } - final CardType removeTypes = new CardType(); + final CardType removeTypes = new CardType(true); if (sa.hasParam("RemoveTypes")) { removeTypes.addAll(Arrays.asList(sa.getParam("RemoveTypes").split(","))); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java index b319e84f37f..8be2736c313 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java @@ -64,12 +64,12 @@ public class AnimateEffect extends AnimateEffectBase { final boolean permanent = sa.hasParam("Permanent"); - final CardType types = new CardType(); + final CardType types = new CardType(true); if (sa.hasParam("Types")) { types.addAll(Arrays.asList(sa.getParam("Types").split(","))); } - final CardType removeTypes = new CardType(); + final CardType removeTypes = new CardType(true); if (sa.hasParam("RemoveTypes")) { removeTypes.addAll(Arrays.asList(sa.getParam("RemoveTypes").split(","))); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index 2238fabfdca..f8ca17ec578 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -36,7 +36,9 @@ import forge.util.collect.FCollection; import forge.util.collect.FCollectionView; import forge.util.Localizer; import forge.util.CardTranslation; +import org.apache.commons.lang3.StringUtils; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -201,6 +203,26 @@ public class ChangeZoneEffect extends SpellAbilityEffect { } } sb.append(" Then shuffle that library."); + } else if (origin.equals("Sideboard")) { + sb.append(chooserNames); + //currently Reveal is always True in ChangeZone + if (sa.hasParam("Reveal")) { + sb.append(" may reveal ").append(num).append(" ").append(type).append(" from outside the game and put "); + if (num == 1) { + sb.append("it "); + } else { + sb.append("them "); + } + sb.append("into their ").append(destination.toLowerCase()).append("."); + } else { + if (sa.hasParam("Mandatory")) { + sb.append(" puts "); + } else { + sb.append(" may put "); + } + sb.append(num).append(" ").append(type).append(" from outside the game into their "); + sb.append(destination.toLowerCase()).append("."); + } } else if (origin.equals("Hand")) { sb.append(chooserNames); if (!chooserNames.equals(fetcherNames)) { @@ -282,7 +304,6 @@ public class ChangeZoneEffect extends SpellAbilityEffect { } final StringBuilder sbTargets = new StringBuilder(); - Iterable tgts; if (sa.usesTargeting()) { tgts = sa.getTargets().getTargetCards(); @@ -290,10 +311,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { // otherwise add self to list and go from there tgts = sa.knownDetermineDefined(sa.getParam("Defined")); } - - for (final Card c : tgts) { - sbTargets.append(" ").append(c); - } + sbTargets.append(" ").append(StringUtils.join(tgts, ", ")); final String targetname = sbTargets.toString(); @@ -302,12 +320,16 @@ public class ChangeZoneEffect extends SpellAbilityEffect { final String fromGraveyard = " from the graveyard"; if (destination.equals(ZoneType.Battlefield)) { - sb.append("Put").append(targetname); if (ZoneType.Graveyard.equals(origin)) { - sb.append(fromGraveyard); + sb.append("Return").append(targetname); + } else { + sb.append("Put").append(targetname); + } + if (ZoneType.Graveyard.equals(origin)) { + sb.append(fromGraveyard).append(" to the battlefield"); + } else { + sb.append(" onto the battlefield"); } - - sb.append(" onto the battlefield"); if (sa.hasParam("Tapped")) { sb.append(" tapped"); } @@ -1159,9 +1181,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { } if (sa.hasParam("FaceDownAddType")) { - for (String type : sa.getParam("FaceDownAddType").split(",")) { - c.addType(type); - } + c.addType(Arrays.asList(sa.getParam("FaceDownAddType").split(" & "))); } if (sa.hasParam("FaceDownPower") || sa.hasParam("FaceDownToughness") diff --git a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java index faed7543bcc..652d7728a33 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java @@ -20,27 +20,24 @@ public class CharmEffect extends SpellAbilityEffect { public static List makePossibleOptions(final SpellAbility sa) { final Card source = sa.getHostCard(); - Iterable restriction = null; + List restriction = null; if (sa.hasParam("ChoiceRestriction")) { String rest = sa.getParam("ChoiceRestriction"); - if (rest.equals("NotRemembered")) { - restriction = source.getRemembered(); + if (rest.equals("ThisGame")) { + restriction = source.getChosenModesGame(sa); + } else if (rest.equals("ThisTurn")) { + restriction = source.getChosenModesTurn(sa); } } - + int indx = 0; List choices = Lists.newArrayList(sa.getAdditionalAbilityList("Choices")); if (restriction != null) { List toRemove = Lists.newArrayList(); - for (Object o : restriction) { - if (o instanceof AbilitySub) { - String abText = ((AbilitySub)o).getDescription(); - for (AbilitySub ch : choices) { - if (ch.getDescription().equals(abText)) { - toRemove.add(ch); - } - } + for (AbilitySub ch : choices) { + if (restriction.contains(ch.getDescription())) { + toRemove.add(ch); } } choices.removeAll(toRemove); @@ -54,55 +51,24 @@ public class CharmEffect extends SpellAbilityEffect { return choices; } - public static String makeSpellDescription(SpellAbility sa) { - int num = Integer.parseInt(sa.getParamOrDefault("CharmNum", "1")); - int min = Integer.parseInt(sa.getParamOrDefault("MinCharmNum", String.valueOf(num))); - boolean repeat = sa.hasParam("CanRepeatModes"); - boolean random = sa.hasParam("Random"); - boolean oppChooses = "Opponent".equals(sa.getParam("Chooser")); - - List list = CharmEffect.makePossibleOptions(sa); - - StringBuilder sb = new StringBuilder(); - sb.append(sa.getCostDescription()); - sb.append(oppChooses ? "An opponent chooses " : "Choose "); - - if (num == min) { - sb.append(Lang.getNumeral(num)); - } else if (min == 0) { - sb.append("up to ").append(Lang.getNumeral(num)); - } else { - sb.append(Lang.getNumeral(min)).append(" or ").append(list.size() == 2 ? "both" : "more"); - } - - if (random) { - sb.append("at random."); - } - if (repeat) { - sb.append(". You may choose the same mode more than once."); - } - sb.append(" - "); - int i = 0; - for (AbilitySub sub : list) { - if (i > 0) { - sb.append("; "); - } - sb.append(sub.getParam("SpellDescription")); - ++i; - } - - return sb.toString(); - } - public static String makeFormatedDescription(SpellAbility sa) { - int num = Integer.parseInt(sa.getParamOrDefault("CharmNum", "1")); - int min = Integer.parseInt(sa.getParamOrDefault("MinCharmNum", String.valueOf(num))); + Card source = sa.getHostCard(); + + List list = CharmEffect.makePossibleOptions(sa); + final int num; + // hotfix for Vindictive Lich when using getCardForUi + if (source.getController() == null && sa.getParamOrDefault("CharmNum", "1").contains("MaxUniqueOpponents")) { + // using getCardForUi game is not set, so can't guess max charm + num = Integer.MAX_VALUE; + } else { + num = Math.min(AbilityUtils.calculateAmount(source, sa.getParamOrDefault("CharmNum", "1"), sa), list.size()); + } + final int min = sa.hasParam("MinCharmNum") ? AbilityUtils.calculateAmount(source, sa.getParamOrDefault("MinCharmNum", "1"), sa) : num; + boolean repeat = sa.hasParam("CanRepeatModes"); boolean random = sa.hasParam("Random"); boolean oppChooses = "Opponent".equals(sa.getParam("Chooser")); - List list = CharmEffect.makePossibleOptions(sa); - StringBuilder sb = new StringBuilder(); sb.append(sa.getCostDescription()); sb.append(oppChooses ? "An opponent chooses " : "Choose "); @@ -117,8 +83,10 @@ public class CharmEffect extends SpellAbilityEffect { if (sa.hasParam("ChoiceRestriction")) { String rest = sa.getParam("ChoiceRestriction"); - if (rest.equals("NotRemembered")) { + if (rest.equals("ThisGame")) { sb.append(" that hasn't been chosen"); + } else if (rest.equals("ThisTurn")) { + sb.append(" that hasn't been chosen this turn"); } } @@ -163,39 +131,52 @@ public class CharmEffect extends SpellAbilityEffect { //this resets all previous choices sa.setSubAbility(null); + List choices = makePossibleOptions(sa); + // Entwine does use all Choices if (sa.isEntwine()) { - chainAbilities(sa, makePossibleOptions(sa)); - return true; - } - - final int num = sa.hasParam("CharmNumOnResolve") ? - AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("CharmNumOnResolve"), sa) - : Integer.parseInt(sa.getParamOrDefault("CharmNum", "1")); - final int min = sa.hasParam("MinCharmNum") ? Integer.parseInt(sa.getParam("MinCharmNum")) : num; - - if (sa.hasParam("Random")) { - chainAbilities(sa, Aggregates.random(makePossibleOptions(sa), num)); + chainAbilities(sa, choices); return true; } Card source = sa.getHostCard(); Player activator = sa.getActivatingPlayer(); + + final int num = Math.min(AbilityUtils.calculateAmount(source, sa.getParamOrDefault("CharmNum", "1"), sa), choices.size()); + final int min = sa.hasParam("MinCharmNum") ? AbilityUtils.calculateAmount(source, sa.getParamOrDefault("MinCharmNum", "1"), sa) : num; + + // if the amount of choices is smaller than min then they can't be chosen + if (min > choices.size()) { + return false; + } + + if (sa.hasParam("Random")) { + chainAbilities(sa, Aggregates.random(choices, num)); + return true; + } + Player chooser = sa.getActivatingPlayer(); if (sa.hasParam("Chooser")) { // Three modal cards require you to choose a player to make the modal choice' // Two of these also reference the chosen player during the spell effect - - //String choosers = sa.getParam("Chooser"); + + //String choosers = sa.getParam("Chooser"); FCollection opponents = activator.getOpponents(); // all cards have Choser$ Opponent, so it's hardcoded here chooser = activator.getController().chooseSingleEntityForEffect(opponents, sa, "Choose an opponent", null); source.setChosenPlayer(chooser); } - - List chosen = chooser.getController().chooseModeForAbility(sa, min, num, sa.hasParam("CanRepeatModes")); + + List chosen = chooser.getController().chooseModeForAbility(sa, choices, min, num, sa.hasParam("CanRepeatModes")); chainAbilities(sa, chosen); - return chosen != null && !chosen.isEmpty(); + + // trigger without chosen modes are removed from stack + if (sa.isTrigger()) { + return chosen != null && !chosen.isEmpty(); + } + + // for spells and activated abilities it is possible to chose zero if minCharmNum allows it + return true; } private static void chainAbilities(SpellAbility sa, List chosen) { @@ -239,7 +220,7 @@ public class CharmEffect extends SpellAbilityEffect { // add Clone to Tail of sa sa.appendSubAbility(clone); } - + } diff --git a/forge-game/src/main/java/forge/game/ability/effects/StoreSVarEffect.java b/forge-game/src/main/java/forge/game/ability/effects/StoreSVarEffect.java index 2e47464d155..e2130936495 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/StoreSVarEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/StoreSVarEffect.java @@ -38,7 +38,7 @@ public class StoreSVarEffect extends SpellAbilityEffect { int value = 0; if (type.equals("Count")) { - value = CardFactoryUtil.xCount(source, expr); + value = AbilityUtils.xCount(source, expr, sa); } else if (type.equals("Number")) { value = Integer.valueOf(expr); 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 d26f2fc876f..3d3d6b7379e 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -26,7 +26,6 @@ import forge.ImageKeys; import forge.StaticData; import forge.card.*; import forge.card.CardDb.SetPreference; -import forge.card.CardType.CoreType; import forge.card.mana.ManaCost; import forge.card.mana.ManaCostParser; import forge.game.*; @@ -34,7 +33,6 @@ import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; -import forge.game.ability.effects.CharmEffect; import forge.game.combat.Combat; import forge.game.cost.Cost; import forge.game.cost.CostSacrifice; @@ -280,6 +278,11 @@ public class Card extends GameEntity implements Comparable { private final Table numberTurnActivationsStatic = HashBasedTable.create(); private final Table numberGameActivationsStatic = HashBasedTable.create(); + private final Map> chosenModesTurn = Maps.newHashMap(); + private final Map> chosenModesGame = Maps.newHashMap(); + + private final Table> chosenModesTurnStatic = HashBasedTable.create(); + private final Table> chosenModesGameStatic = HashBasedTable.create(); // Enumeration for CMC request types public enum SplitCMCMode { @@ -664,6 +667,7 @@ public class Card extends GameEntity implements Comparable { } facedown = false; + updateStateForView(); //fixes cards with backside viewable // need to run faceup commands, currently // it does cleanup the modified facedown state if (result) { @@ -1239,7 +1243,7 @@ public class Card extends GameEntity implements Comparable { final int loyaltyBefore = getCurrentLoyalty(); setCounters(counterType, newValue); - getController().addCounterToPermThisTurn(counterType, addAmount); + getGame().addCounterAddedThisTurn(source, counterType, this, addAmount); view.updateCounters(this); //fire card stats changed event if p/t bonuses or loyalty changed from added counters @@ -1267,7 +1271,8 @@ public class Card extends GameEntity implements Comparable { } } else { setCounters(counterType, newValue); - getController().addCounterToPermThisTurn(counterType, addAmount); + + getGame().addCounterAddedThisTurn(source, counterType, this, addAmount); view.updateCounters(this); } if (newValue <= 0) { @@ -1714,8 +1719,7 @@ public class Card extends GameEntity implements Comparable { final String costString2 = keyword.split(":")[2]; final Cost cost1 = new Cost(costString1, false); final Cost cost2 = new Cost(costString2, false); - sbLong.append("As an additional cost to cast ") - .append(getName()).append(", ") + sbLong.append("As an additional cost to cast this spell, ") .append(cost1.toSimpleString()) .append(" or pay ") .append(cost2.toSimpleString()) @@ -2070,8 +2074,9 @@ public class Card extends GameEntity implements Comparable { } final Card host = stAb.getHostCard(); if (isValid(stAb.getParam("ValidAttacker").split(","), host.getController(), host, null)) { - String desc = stAb.toString(); - desc = TextUtil.fastReplace(desc, "CARDNAME", host.getName()); + String currentName = (host.getName()); + String desc1 = TextUtil.fastReplace(stAb.toString(), "CARDNAME", currentName); + String desc = TextUtil.fastReplace(desc1,"NICKNAME", currentName.split(",")[0]); if (host.getEffectSource() != null) { desc = TextUtil.fastReplace(desc, "EFFECTSOURCE", host.getEffectSource().getName()); } @@ -2203,8 +2208,7 @@ public class Card extends GameEntity implements Comparable { final String[] k = keyword.split(":"); final Cost cost1 = new Cost(k[1], false); final Cost cost2 = new Cost(k[2], false); - sbBefore.append("As an additional cost to cast ") - .append(state.getName()).append(", ") + sbBefore.append("As an additional cost to cast this spell, ") .append(cost1.toSimpleString()) .append(" or pay ") .append(cost2.toSimpleString()) @@ -2325,14 +2329,7 @@ public class Card extends GameEntity implements Comparable { private String formatSpellAbility(final SpellAbility sa) { final StringBuilder sb = new StringBuilder(); - final String elementText = sa.toString(); - - //Determine if a card has multiple choices, then format it in an easier to read list. - if (ApiType.Charm.equals(sa.getApi())) { - sb.append(CharmEffect.makeFormatedDescription(sa)); - } else { - sb.append(elementText).append("\r\n"); - } + sb.append(sa.toString()).append("\r\n"); return sb.toString(); } @@ -3100,6 +3097,10 @@ public class Card extends GameEntity implements Comparable { currentState.addType(type0); } + public final void addType(final Iterable type0) { + currentState.addType(type0); + } + public final void removeType(final CardType.Supertype st) { currentState.removeType(st); } @@ -3197,11 +3198,11 @@ public class Card extends GameEntity implements Comparable { CardType addType = null; CardType removeType = null; if (types != null) { - addType = new CardType(types); + addType = new CardType(types, true); } if (removeTypes != null) { - removeType = new CardType(removeTypes); + removeType = new CardType(removeTypes, true); } addChangedCardTypes(addType, removeType, removeSuperTypes, removeCardTypes, removeSubTypes, @@ -3962,7 +3963,7 @@ public class Card extends GameEntity implements Comparable { public final void addChangedTextTypeWord(final String originalWord, final String newWord, final Long timestamp) { changedTextTypes.add(timestamp, originalWord, newWord); if (getType().hasSubtype(originalWord)) { - addChangedCardTypes(CardType.parse(newWord), CardType.parse(originalWord), + addChangedCardTypes(CardType.parse(newWord, true), CardType.parse(originalWord, true), false, false, false, false, false, false, false, timestamp); } updateKeywordsChangedText(timestamp); @@ -4603,84 +4604,34 @@ public class Card extends GameEntity implements Comparable { if (c1 == null) { return false; } - - for (final String type : getType().getCreatureTypes()) { - if (type.equals("AllCreatureTypes") && c1.hasACreatureType()) { - return true; - } - if (c1.getType().hasCreatureType(type)) { - return true; - } - } - return false; + return getType().sharesCreaturetypeWith(c1.getType()); } public final boolean sharesLandTypeWith(final Card c1) { if (c1 == null) { return false; } - - for (final String type : getType().getLandTypes()) { - if (c1.getType().hasSubtype(type)) { - return true; - } - } - return false; + return getType().sharesLandTypeWith(c1.getType()); } public final boolean sharesPermanentTypeWith(final Card c1) { if (c1 == null) { return false; } - - for (final CoreType type : getType().getCoreTypes()) { - if (type.isPermanent && c1.getType().hasType(type)) { - return true; - } - } - return false; + return getType().sharesPermanentTypeWith(c1.getType()); } public final boolean sharesCardTypeWith(final Card c1) { - for (final CoreType type : getType().getCoreTypes()) { - if (c1.getType().hasType(type)) { - return true; - } + if (c1 == null) { + return false; } - return false; - } - - public final boolean sharesTypeWith(final Card c1) { - for (final String type : getType()) { - if (c1.getType().hasStringType(type)) { - return true; - } - } - return false; + return getType().sharesCardTypeWith(c1.getType()); } public final boolean sharesControllerWith(final Card c1) { return c1 != null && getController().equals(c1.getController()); } - public final boolean hasACreatureType() { - for (final String type : getType().getSubtypes()) { - if (forge.card.CardType.isACreatureType(type) || type.equals("AllCreatureTypes")) { - return true; - } - } - return false; - } - - public final boolean hasALandType() { - for (final String type : getType().getSubtypes()) { - if (forge.card.CardType.isALandType(type) || forge.card.CardType.isABasicLandType(type)) { - return true; - } - } - return false; - } - public final boolean hasABasicLandType() { for (final String type : getType().getSubtypes()) { if (forge.card.CardType.isABasicLandType(type)) { @@ -5316,8 +5267,8 @@ public class Card extends GameEntity implements Comparable { public final void animateBestow(final boolean updateView) { bestowTimestamp = getGame().getNextTimestamp(); - addChangedCardTypes(new CardType(Collections.singletonList("Aura")), - new CardType(Collections.singletonList("Creature")), + addChangedCardTypes(new CardType(Collections.singletonList("Aura"), true), + new CardType(Collections.singletonList("Creature"), true), false, false, false, false, false, false, true, bestowTimestamp, updateView); addChangedCardKeywords(Collections.singletonList("Enchant creature"), Lists.newArrayList(), false, false, bestowTimestamp, updateView); @@ -5915,6 +5866,7 @@ public class Card extends GameEntity implements Comparable { clearBlockedThisTurn(); resetMayPlayTurn(); resetExtertedThisTurn(); + resetChosenModeTurn(); } public boolean hasETBTrigger(final boolean drawbackOnly) { @@ -6045,6 +5997,15 @@ public class Card extends GameEntity implements Comparable { } } + if (isPermanent() && !isLand() && source.getActivatingPlayer().hasKeyword("You can't sacrifice nonland permanents to cast spells or activate abilities.")) { + Cost srcCost = source.getPayCosts(); + if (srcCost != null) { + if (srcCost.hasSpecificCostType(CostSacrifice.class)) { + return false; + } + } + } + return getController().canSacrificeBy(source); } @@ -6582,6 +6543,94 @@ public class Card extends GameEntity implements Comparable { numberTurnActivationsStatic.clear(); } + public List getChosenModesTurn(SpellAbility ability) { + SpellAbility original = null; + SpellAbility root = ability.getRootAbility(); + + // because trigger spell abilities are copied, try to get original one + if (root.isTrigger()) { + original = root.getTrigger().getOverridingAbility(); + } else { + original = ability.getOriginalAbility(); + if (original == null) { + original = ability; + } + } + + if (ability.getGrantorStatic() != null) { + return chosenModesTurnStatic.get(original, ability.getGrantorStatic()); + } + return chosenModesTurn.get(original); + } + public List getChosenModesGame(SpellAbility ability) { + SpellAbility original = null; + SpellAbility root = ability.getRootAbility(); + + // because trigger spell abilities are copied, try to get original one + if (root.isTrigger()) { + original = root.getTrigger().getOverridingAbility(); + } else { + original = ability.getOriginalAbility(); + if (original == null) { + original = ability; + } + } + + if (ability.getGrantorStatic() != null) { + return chosenModesGameStatic.get(original, ability.getGrantorStatic()); + } + return chosenModesGame.get(original); + } + + public void addChosenModes(SpellAbility ability, String mode) { + SpellAbility original = null; + SpellAbility root = ability.getRootAbility(); + + // because trigger spell abilities are copied, try to get original one + if (root.isTrigger()) { + original = root.getTrigger().getOverridingAbility(); + } else { + original = ability.getOriginalAbility(); + if (original == null) { + original = ability; + } + } + + if (ability.getGrantorStatic() != null) { + List result = chosenModesTurnStatic.get(original, ability.getGrantorStatic()); + if (result == null) { + result = Lists.newArrayList(); + chosenModesTurnStatic.put(original, ability.getGrantorStatic(), result); + } + result.add(mode); + result = chosenModesGameStatic.get(original, ability.getGrantorStatic()); + if (result == null) { + result = Lists.newArrayList(); + chosenModesGameStatic.put(original, ability.getGrantorStatic(), result); + } + result.add(mode); + } else { + List result = chosenModesTurn.get(original); + if (result == null) { + result = Lists.newArrayList(); + chosenModesTurn.put(original, result); + } + result.add(mode); + + result = chosenModesGame.get(original); + if (result == null) { + result = Lists.newArrayList(); + chosenModesGame.put(original, result); + } + result.add(mode); + } + } + + public void resetChosenModeTurn() { + chosenModesTurn.clear(); + chosenModesTurnStatic.clear(); + } + public int getPlaneswalkerAbilityActivated() { return planeswalkerAbilityActivated; } diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index bfcb56b02a8..d73dae2bc8f 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -587,7 +587,7 @@ public class CardFactory { String shortColors = ""; if (sa.hasParam("AddTypes")) { - types.addAll(Arrays.asList(sa.getParam("AddTypes").split(","))); + types.addAll(Arrays.asList(sa.getParam("AddTypes").split(" & "))); } if (sa.hasParam("AddKeywords")) { @@ -654,9 +654,7 @@ public class CardFactory { state.removeType(CardType.Supertype.Legendary); } - for (final String type : types) { - state.addType(type); - } + state.addType(types); if (creatureTypes != null) { state.setCreatureTypes(creatureTypes); @@ -731,7 +729,8 @@ public class CardFactory { String name = TextUtil.fastReplace( TextUtil.fastReplace(host.getName(), ",", ""), " ", "_").toLowerCase(); - state.setImageKey(ImageKeys.getTokenKey("embalm_" + name)); + String set = host.getSetCode().toLowerCase(); + state.setImageKey(ImageKeys.getTokenKey("embalm_" + name + "_" + set)); } if (sa.hasParam("Eternalize") && out.isEternalized()) { @@ -744,7 +743,8 @@ public class CardFactory { String name = TextUtil.fastReplace( TextUtil.fastReplace(host.getName(), ",", ""), " ", "_").toLowerCase(); - state.setImageKey(ImageKeys.getTokenKey("eternalize_" + name)); + String set = host.getSetCode().toLowerCase(); + state.setImageKey(ImageKeys.getTokenKey("eternalize_" + name + "_" + set)); } // set the host card for copied replacement effects @@ -793,7 +793,7 @@ public class CardFactory { if (sa.hasParam("SetCreatureTypes")) { // currently only Changeling and similar should be affected by that // other cards using AddType$ ChosenType should not - if (sta.hasParam("AddType") && "AllCreatureTypes".equals(sta.getParam("AddType"))) { + if (sta.hasParam("AddType") && CardType.AllCreatureTypes.equals(sta.getParam("AddType"))) { state.removeStaticAbility(sta); } } 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 d1f5edd6eef..ade6156cdc5 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -841,14 +841,6 @@ public class CardFactoryUtil { return doXMath(maxNum, m, c); } - // Count$CountersAddedToPermYouCtrl - if (l[0].startsWith("CountersAddedToPermYouCtrl")) { - final String[] components = l[0].split(" ", 2); - final CounterType counterType = CounterType.getType(components[1]); - int n = cc.getCounterToPermThisTurn(counterType); - return doXMath(n, m, c); - } - if (l[0].startsWith("CommanderCastFromCommandZone")) { // only used by Opal Palace, and it does add the trigger to the card return doXMath(cc.getCommanderCast(c), m, c); @@ -1124,7 +1116,7 @@ public class CardFactoryUtil { for (Card card : cards) { Iterables.addAll(creatTypes, card.getType().getCreatureTypes()); } - int n = creatTypes.contains("AllCreatureTypes") ? CardType.getAllCreatureTypes().size() : creatTypes.size(); + int n = creatTypes.contains(CardType.AllCreatureTypes) ? CardType.getAllCreatureTypes().size() : creatTypes.size(); return doXMath(n, m, c); } @@ -1206,7 +1198,7 @@ public class CardFactoryUtil { // Figure out how to count each class separately. for (Card card : adventurers) { Set creatureTypes = card.getType().getCreatureTypes(); - boolean anyType = creatureTypes.contains("AllCreatureTypes"); + boolean anyType = creatureTypes.contains(CardType.AllCreatureTypes); creatureTypes.retainAll(partyTypes); if (anyType || creatureTypes.size() == 4) { @@ -2005,7 +1997,7 @@ public class CardFactoryUtil { // Remove Duplicated types final Set creatureTypes = c.getType().getCreatureTypes(); for (String creatureType : creatureTypes) { - if (creatureType.equals("AllCreatureTypes")) { + if (creatureType.equals(CardType.AllCreatureTypes)) { allCreatureType++; } else { @@ -2913,7 +2905,7 @@ public class CardFactoryUtil { final String repeatStr = "DB$ RepeatEach | RepeatPlayers$ OpponentsOtherThanDefendingPlayer | ChangeZoneTable$ True"; - final String copyStr = "DB$ CopyPermanent | Defined$ Self | Tapped$ True | Optional$ True | TokenAttacking$ Remembered" + final String copyStr = "DB$ CopyPermanent | Defined$ Self | TokenTapped$ True | Optional$ True | TokenAttacking$ Remembered" + " | ChoosePlayerOrPlaneswalker$ True | ImprintTokens$ True"; final String delTrigStr = "DB$ DelayedTrigger | Mode$ Phase | Phase$ EndCombat | RememberObjects$ Imprinted" @@ -4693,8 +4685,10 @@ public class CardFactoryUtil { } altCostSA.setRestrictions(restriction); - final String costDescription = params.containsKey("Description") ? params.get("Description") - : TextUtil.concatWithSpace("You may", abCost.toStringAlt(),"rather than pay", TextUtil.addSuffix(card.getName(),"'s mana cost.")); + String costDescription = TextUtil.fastReplace(params.get("Description"),"CARDNAME", card.getName()); + if (costDescription.isEmpty()) { + costDescription = TextUtil.concatWithSpace("You may", abCost.toStringAlt(), "rather than pay", TextUtil.addSuffix(card.getName(), "'s mana cost.")); + } altCostSA.setDescription(costDescription); if (params.containsKey("References")) { diff --git a/forge-game/src/main/java/forge/game/card/CardState.java b/forge-game/src/main/java/forge/game/card/CardState.java index b11c967504e..6563317225b 100644 --- a/forge-game/src/main/java/forge/game/card/CardState.java +++ b/forge-game/src/main/java/forge/game/card/CardState.java @@ -48,7 +48,7 @@ import io.sentry.event.BreadcrumbBuilder; public class CardState extends GameObject { private String name = ""; - private CardType type = new CardType(); + private CardType type = new CardType(false); private ManaCost manaCost = ManaCost.NO_COST; private byte color = MagicColor.COLORLESS; private int basePower = 0; @@ -116,6 +116,11 @@ public class CardState extends GameObject { view.updateType(this); } } + public final void addType(Iterable type0) { + if (type.addAll(type0)) { + view.updateType(this); + } + } public final void setType(final CardType type0) { if (type0 == type) { // Logic below would incorrectly clear the type if it's the same object. diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java index f917130d190..3bf6a1c092d 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -327,7 +327,7 @@ public final class CardUtil { } public static CardState getFaceDownCharacteristic(Card c) { - final CardType type = new CardType(); + final CardType type = new CardType(false); type.add("Creature"); final CardState ret = new CardState(c, CardStateName.FaceDown); @@ -337,7 +337,8 @@ public final class CardUtil { ret.setName(""); ret.setType(type); - ret.setImageKey(ImageKeys.getTokenKey(ImageKeys.MORPH_IMAGE)); + //show hidden if exiled facedown + ret.setImageKey(ImageKeys.getTokenKey(c.isInZone(ZoneType.Exile) ? ImageKeys.HIDDEN_CARD : ImageKeys.MORPH_IMAGE)); return ret; } diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java index 57ba9fa06db..d753c8acdcf 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -134,6 +134,18 @@ public class CardView extends GameEntityView { return get(TrackableProperty.SplitCard); } + public boolean isDoubleFacedCard() { + return get(TrackableProperty.DoubleFaced); + } + + public boolean isAdventureCard() { + return get(TrackableProperty.Adventure); + } + + public boolean isModalCard() { + return get(TrackableProperty.Modal); + } + /* public boolean isTransformed() { return getCurrentState().getState() == CardStateName.Transformed; @@ -678,6 +690,12 @@ public class CardView extends GameEntityView { public CardStateView getAlternateState() { return get(TrackableProperty.AlternateState); } + + public boolean hasBackSide() { + return get(TrackableProperty.HasBackSide); + } + public String getBackSideName() { return get(TrackableProperty.BackSideName); } + CardStateView createAlternateState(final CardStateName state0) { return new CardStateView(getId(), state0, tracker); } @@ -685,6 +703,10 @@ public class CardView extends GameEntityView { public CardStateView getState(final boolean alternate0) { return alternate0 ? getAlternateState() : getCurrentState(); } + void updateBackSide(String stateName, boolean hasBackSide) { + set(TrackableProperty.HasBackSide, hasBackSide); + set(TrackableProperty.BackSideName, stateName); + } void updateState(Card c) { updateName(c); updateDamage(c); @@ -694,6 +716,13 @@ public class CardView extends GameEntityView { set(TrackableProperty.SplitCard, isSplitCard); set(TrackableProperty.FlipCard, c.isFlipCard()); set(TrackableProperty.Facedown, c.isFaceDown()); + set(TrackableProperty.Adventure, c.isAdventureCard()); + set(TrackableProperty.DoubleFaced, c.isDoubleFaced()); + set(TrackableProperty.Modal, c.isModal()); + + //backside + if (c.getAlternateState()!=null) + updateBackSide(c.getAlternateState().getName(), c.hasBackSide()); final Card cloner = c.getCloner(); @@ -733,6 +762,9 @@ public class CardView extends GameEntityView { alternateState = c.getState(CardStateName.Original); } + if (c.hasBackSide() && isFaceDown()) //fixes facedown cards with backside... + alternateState = c.getState(CardStateName.Original); + if (alternateState == null) { set(TrackableProperty.AlternateState, null); } diff --git a/forge-game/src/main/java/forge/game/cost/Cost.java b/forge-game/src/main/java/forge/game/cost/Cost.java index 46c2ab66987..1c175b57428 100644 --- a/forge-game/src/main/java/forge/game/cost/Cost.java +++ b/forge-game/src/main/java/forge/game/cost/Cost.java @@ -706,7 +706,7 @@ public class Cost implements Serializable { boolean first = true; if (bFlag) { - cost.append("As an additional cost to cast CARDNAME, "); + cost.append("As an additional cost to cast this spell, "); } else { // usually no additional mana cost for spells // only three Alliances cards have additional mana costs, but they @@ -724,7 +724,11 @@ public class Cost implements Serializable { if (!first) { cost.append(" and "); } - cost.append(part.toString()); + if (bFlag) { + cost.append(StringUtils.uncapitalize(part.toString())); + } else { + cost.append(part.toString()); + } first = false; } diff --git a/forge-game/src/main/java/forge/game/keyword/Keyword.java b/forge-game/src/main/java/forge/game/keyword/Keyword.java index afadbc71ff8..d810408411c 100644 --- a/forge-game/src/main/java/forge/game/keyword/Keyword.java +++ b/forge-game/src/main/java/forge/game/keyword/Keyword.java @@ -46,7 +46,7 @@ public enum Keyword { DOUBLE_STRIKE("Double Strike", SimpleKeyword.class, true, "This creature deals both first-strike and regular combat damage."), DREDGE("Dredge", KeywordWithAmount.class, false, "If you would draw a card, instead you may put exactly {%d:card} from the top of your library into your graveyard. If you do, return this card from your graveyard to your hand. Otherwise, draw a card."), ECHO("Echo", KeywordWithCost.class, false, "At the beginning of your upkeep, if this permanent came under your control since the beginning of your last upkeep, sacrifice it unless you pay %s."), - EMBALM("Embalm", KeywordWithCost.class, false, "Create a token that's a copy of this card, except it's white, it has no mana cost, and it's a Zombie in addition to its other types. Embalm only as a sorcery."), + EMBALM("Embalm", KeywordWithCost.class, false, "%s, Exile this card from your graveyard: Create a token that's a copy of this card, except it's white, it has no mana cost, and it's a Zombie in addition to its other types. Embalm only as a sorcery."), EMERGE("Emerge", KeywordWithCost.class, false, "You may cast this spell by sacrificing a creature and paying the emerge cost reduced by that creature's converted mana cost."), ENCHANT("Enchant", KeywordWithType.class, false, "Target a %s as you cast this. This card enters the battlefield attached to that %s."), ENTWINE("Entwine", KeywordWithCost.class, true, "You may choose all modes of this spell instead of just one. If you do, you pay an additional %s."), @@ -54,7 +54,7 @@ public enum Keyword { EQUIP("Equip", Equip.class, false, "%s: Attach to target %s you control. Equip only as a sorcery."), ESCAPE("Escape", KeywordWithCost.class, false, "You may cast this card from your graveyard for its escape cost."), ESCALATE("Escalate", KeywordWithCost.class, true, "Pay this cost for each mode chosen beyond the first."), - ETERNALIZE("Eternalize", KeywordWithCost.class, false, "Create a token that's a copy of this card, except it's black, it's 4/4, it has no mana cost, and it's a Zombie in addition to its other types. Eternalize only as a sorcery."), + ETERNALIZE("Eternalize", KeywordWithCost.class, false, "%s, Exile this card from your graveyard: Create a token that's a copy of this card, except it's black, it's 4/4, it has no mana cost, and it's a Zombie in addition to its other types. Eternalize only as a sorcery."), EVOKE("Evoke", KeywordWithCost.class, false, "You may cast this spell for its evoke cost. If you do, it's sacrificed when it enters the battlefield."), EVOLVE("Evolve", SimpleKeyword.class, false, "Whenever a creature enters the battlefield under your control, if that creature has greater power or toughness than this creature, put a +1/+1 counter on this creature."), EXALTED("Exalted", SimpleKeyword.class, false, "Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn."), @@ -109,7 +109,7 @@ public enum Keyword { PERSIST("Persist", SimpleKeyword.class, false, "When this creature dies, if it had no -1/-1 counters on it, return it to the battlefield under its owner's control with a -1/-1 counter on it."), PHASING("Phasing", SimpleKeyword.class, true, "This phases in or out before you untap during each of your untap steps. While it's phased out, it's treated as though it doesn't exist."), POISONOUS("Poisonous", KeywordWithAmount.class, false, "Whenever this creature deals combat damage to a player, that player gets {%d:poison counter}."), - PRESENCE("Presence", KeywordWithType.class, false, "As an additional cost to cast CARDNAME, you may reveal a %s card from your hand."), + PRESENCE("Presence", KeywordWithType.class, false, "As an additional cost to cast this spell, you may reveal a %s card from your hand."), PROTECTION("Protection", Protection.class, false, "This creature can't be blocked, targeted, dealt damage, or equipped/enchanted by %s."), PROVOKE("Provoke", SimpleKeyword.class, false, "Whenever this creature attacks, you may have target creature defending player controls untap and block it if able."), PROWESS("Prowess", SimpleKeyword.class, false, "Whenever you cast a noncreature spell, this creature gets +1/+1 until end of turn."), diff --git a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java index 85d5c500d95..42a01547121 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java @@ -501,9 +501,7 @@ public class PhaseHandler implements java.io.Serializable { bPreventCombatDamageThisTurn = false; if (!bRepeatCleanup) { // only call onCleanupPhase when Cleanup is not repeated - for (Player player : game.getPlayers()) { - player.onCleanupPhase(); - } + game.onCleanupPhase(); setPlayerTurn(handleNextTurn()); // "Trigger" for begin turn to get around a phase skipping final Map runParams = AbilityKey.newMap(); 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 3637fc98ca2..2503a669e52 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -114,8 +114,6 @@ public class Player extends GameEntity implements Comparable { private CardCollection sacrificedThisTurn = new CardCollection(); - private Map countersAddedtoPermThisTurn = Maps.newHashMap(); - /** A list of tokens not in play, but on their way. * This list is kept in order to not break ETB-replacement * on tokens. */ @@ -2119,7 +2117,7 @@ public class Player extends GameEntity implements Comparable { } public final boolean hasProwl(final String type) { - if (prowl.contains("AllCreatureTypes")) { + if (prowl.contains(CardType.AllCreatureTypes)) { return true; } return prowl.contains(type); @@ -2289,20 +2287,6 @@ public class Player extends GameEntity implements Comparable { sacrificedThisTurn.clear(); } - public final void addCounterToPermThisTurn(final CounterType type, final int x) { - countersAddedtoPermThisTurn.put(type, getCounterToPermThisTurn(type) + x); - } - - public final Integer getCounterToPermThisTurn(final CounterType type) { - if (countersAddedtoPermThisTurn.containsKey(type)) - return countersAddedtoPermThisTurn.get(type); - return 0; - } - - public final void resetCounterToPermThisTurn() { - countersAddedtoPermThisTurn.clear(); - } - public final int getSpellsCastThisTurn() { return spellsCastThisTurn; } @@ -2521,7 +2505,6 @@ public class Player extends GameEntity implements Comparable { resetSurveilThisTurn(); resetCycledThisTurn(); resetSacrificedThisTurn(); - resetCounterToPermThisTurn(); clearAssignedDamage(); resetAttackersDeclaredThisTurn(); resetAttackedOpponentsThisTurn(); 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 2fb8eaf7d5f..1b7c860296d 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -213,7 +213,7 @@ public abstract class PlayerController { public abstract boolean chooseFlipResult(SpellAbility sa, Player flipper, boolean[] results, boolean call); public abstract Card chooseProtectionShield(GameEntity entityBeingDamaged, List options, Map choiceMap); - public abstract List chooseModeForAbility(SpellAbility sa, int min, int num, boolean allowRepeat); + public abstract List chooseModeForAbility(SpellAbility sa, List possible, int min, int num, boolean allowRepeat); public abstract byte chooseColor(String message, SpellAbility sa, ColorSet colors); public abstract byte chooseColorAllowColorless(String message, Card c, ColorSet colors); diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceDamage.java b/forge-game/src/main/java/forge/game/replacement/ReplaceDamage.java index f6eaa9325fe..a5ce0550ef2 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplaceDamage.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceDamage.java @@ -17,6 +17,7 @@ */ package forge.game.replacement; +import forge.game.GameEntity; import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.card.Card; @@ -47,6 +48,7 @@ public class ReplaceDamage extends ReplacementEffect { */ @Override public boolean canReplace(Map runParams) { + if (!(runParams.containsKey(AbilityKey.Prevention) == (hasParam("PreventionEffect") || hasParam("Prevent")))) { return false; } @@ -117,10 +119,15 @@ public class ReplaceDamage extends ReplacementEffect { return false; } - // check for DamageRedirection, the Thing where the damage is redirected to must be a creature or planeswalker or a player if (hasParam("DamageTarget")) { + //Lava Burst and Whippoorwill check + SpellAbility cause = (SpellAbility) runParams.get(AbilityKey.Cause); + GameEntity affected = (GameEntity) runParams.get(AbilityKey.Affected); + if (((cause != null) && (cause.hasParam("NoRedirection")) || (affected.hasKeyword("Damage that would be dealt to CARDNAME can't be redirected.")))) { + return false; + } + // check for DamageRedirection, the Thing where the damage is redirected to must be a creature or planeswalker or a player String def = getParam("DamageTarget"); - for (Player p : AbilityUtils.getDefinedPlayers(hostCard, def, null)) { if (!p.getGame().getPlayers().contains(p)) { return false; diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java index 3e96fd46275..06e6bdc95d4 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java @@ -216,6 +216,12 @@ public abstract class ReplacementEffect extends TriggerReplacementBase { if (desc.contains("CARDNAME")) { desc = TextUtil.fastReplace(desc, "CARDNAME", getHostCard().toString()); } + if (desc.contains("EFFECTSOURCE")) { + desc = TextUtil.fastReplace(desc, "EFFECTSOURCE", getHostCard().getEffectSource().toString()); + } + if (desc.contains("NICKNAME")) { + desc = TextUtil.fastReplace(desc, "NICKNAME", getHostCard().toString().split(",")[0]); + } return desc; } else { return ""; 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 11035b6a2b1..70be5f60696 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -699,6 +699,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit String desc = node.getDescription(); if (node.getHostCard() != null) { desc = TextUtil.fastReplace(desc, "CARDNAME", node.getHostCard().getName()); + desc = TextUtil.fastReplace(desc,"NICKNAME",node.getHostCard().getName().split(",")[0]); if (node.getOriginalHost() != null) { desc = TextUtil.fastReplace(desc, "ORIGINALHOST", node.getOriginalHost().getName()); } diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java index febcf7b5275..76c73ae0c70 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java @@ -216,6 +216,7 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone if (hasParam("Description") && !this.isSuppressed()) { String desc = getParam("Description"); desc = TextUtil.fastReplace(desc, "CARDNAME", this.hostCard.getName()); + desc = TextUtil.fastReplace(desc, "NICKNAME", this.hostCard.getName().split(",")[0]); return desc; } else { diff --git a/forge-game/src/main/java/forge/game/trigger/Trigger.java b/forge-game/src/main/java/forge/game/trigger/Trigger.java index 2f39ff3b0e5..4f4bc714c13 100644 --- a/forge-game/src/main/java/forge/game/trigger/Trigger.java +++ b/forge-game/src/main/java/forge/game/trigger/Trigger.java @@ -111,11 +111,9 @@ public abstract class Trigger extends TriggerReplacementBase { if (hasParam("TriggerDescription") && !this.isSuppressed()) { StringBuilder sb = new StringBuilder(); - String desc = getParam("TriggerDescription"); - if(active) - desc = TextUtil.fastReplace(desc, "CARDNAME", getHostCard().toString()); - else - desc = TextUtil.fastReplace(desc, "CARDNAME", getHostCard().getName()); + String currentName = (getHostCard().getName()); + String desc1 = TextUtil.fastReplace(getParam("TriggerDescription"),"CARDNAME", currentName); + String desc = TextUtil.fastReplace(desc1,"NICKNAME", currentName.split(",")[0]); if (getHostCard().getEffectSource() != null) { if(active) desc = TextUtil.fastReplace(desc, "EFFECTSOURCE", getHostCard().getEffectSource().toString()); diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index b8a03d637a2..06d31a5e0d9 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -575,6 +575,8 @@ public class TriggerHandler { sa.setStackDescription(sa.toString()); if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { + // need to be set for demonic pact to look for chosen modes + sa.setTrigger(regtrig); if (!CharmEffect.makeChoices(sa)) { // 603.3c If no mode is chosen, the ability is removed from the stack. return; 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 17933b95a88..d0b4873a19e 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -246,9 +246,9 @@ public class MagicStack /* extends MyObservable */ implements Iterable { pnlDifficulty.add(new PrefInput(QPref.PENALTY_LOSS, QuestPreferencesErrType.DIFFICULTY), fieldConstraints + ", wrap"); pnlDifficulty.add(new FLabel.Builder().text(localizer.getMessage("lblMoreDuelChoices")).fontAlign(SwingConstants.RIGHT).build(), labelConstraints); pnlDifficulty.add(new PrefInput(QPref.MORE_DUEL_CHOICES, QuestPreferencesErrType.DIFFICULTY), fieldConstraints + ", wrap"); + pnlDifficulty.add(new FLabel.Builder().text(localizer.getMessage("lblWildOpponentMultiplier")).fontAlign(SwingConstants.RIGHT).build(), labelConstraints); + pnlDifficulty.add(new PrefInput(QPref.WILD_OPPONENTS_MULTIPLIER, QuestPreferencesErrType.DIFFICULTY), fieldConstraints + ", wrap"); + pnlDifficulty.add(new FLabel.Builder().text(localizer.getMessage("lblWildOpponentNumber")).fontAlign(SwingConstants.RIGHT).build(), labelConstraints); + pnlDifficulty.add(new PrefInput(QPref.WILD_OPPONENTS_NUMBER, QuestPreferencesErrType.DIFFICULTY), fieldConstraints + ", wrap"); } private void populateBooster() { pnlBooster.setOpaque(false); diff --git a/forge-gui-desktop/src/main/java/forge/view/SimulateMatch.java b/forge-gui-desktop/src/main/java/forge/view/SimulateMatch.java index a680839fcb4..49e3a1a6acc 100644 --- a/forge-gui-desktop/src/main/java/forge/view/SimulateMatch.java +++ b/forge-gui-desktop/src/main/java/forge/view/SimulateMatch.java @@ -202,7 +202,12 @@ public class SimulateMatch { System.out.println(l); } - System.out.println(String.format("\nGame %d ended in %d ms. %s has won!\n", 1+iGame, sw.getTime(), g1.getOutcome().getWinningLobbyPlayer().getName())); + // If both players life totals to 0 in a single turn, the game should end in a draw + if(g1.getOutcome().isDraw()){ + System.out.println(String.format("Game %d ended in a Draw! Took %d ms.", 1+iGame, sw.getTime())); + } else { + System.out.println(String.format("\nGame %d ended in %d ms. %s has won!\n", 1+iGame, sw.getTime(), g1.getOutcome().getWinningLobbyPlayer().getName())); + } } private static void simulateTournament(Map> params, GameRules rules, boolean outputGamelog) { 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 b4d0ef9dc7f..fa806fab900 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 @@ -446,7 +446,7 @@ public class PlayerControllerForTests extends PlayerController { } @Override - public List chooseModeForAbility(SpellAbility sa, int min, int num, boolean allowRepeat) { + public List chooseModeForAbility(SpellAbility sa, List possible, int min, int num, boolean allowRepeat) { throw new IllegalStateException("Erring on the side of caution here..."); } diff --git a/forge-gui-ios/src/forge/ios/Main.java b/forge-gui-ios/src/forge/ios/Main.java index 57fe63bc77c..948adfc66fe 100644 --- a/forge-gui-ios/src/forge/ios/Main.java +++ b/forge-gui-ios/src/forge/ios/Main.java @@ -32,8 +32,8 @@ public class Main extends IOSApplication.Delegate { config.useAccelerometer = false; config.useCompass = false; ForgePreferences prefs = FModel.getPreferences(); - boolean propertyConfig = prefs != null && prefs.getPrefBoolean(ForgePreferences.FPref.UI_NETPLAY_COMPAT); - final ApplicationListener app = Forge.getApp(new IOSClipboard(), new IOSAdapter(), assetsDir, propertyConfig, false); + boolean propertyConfig = prefs != null && prefs.getPrefBoolean(ForgePreferences.FPref.UI_NETPLAY_COMPAT);//todo get totalRAM + final ApplicationListener app = Forge.getApp(new IOSClipboard(), new IOSAdapter(), assetsDir, propertyConfig, false, 0); final IOSApplication iosApp = new IOSApplication(app, config); return iosApp; } diff --git a/forge-gui-mobile-dev/src/forge/app/Main.java b/forge-gui-mobile-dev/src/forge/app/Main.java index 620209f7d74..9b84d0fa53c 100644 --- a/forge-gui-mobile-dev/src/forge/app/Main.java +++ b/forge-gui-mobile-dev/src/forge/app/Main.java @@ -96,8 +96,8 @@ public class Main { ForgePreferences prefs = FModel.getPreferences(); boolean propertyConfig = prefs != null && prefs.getPrefBoolean(ForgePreferences.FPref.UI_NETPLAY_COMPAT); - new LwjglApplication(Forge.getApp(new LwjglClipboard(), new DesktopAdapter(switchOrientationFile), - desktopMode ? desktopModeAssetsDir : assetsDir, propertyConfig, false), config); + new LwjglApplication(Forge.getApp(new LwjglClipboard(), new DesktopAdapter(switchOrientationFile),//todo get totalRAM + desktopMode ? desktopModeAssetsDir : assetsDir, propertyConfig, false, 0), config); } private static class DesktopAdapter implements IDeviceAdapter { diff --git a/forge-gui-mobile/src/forge/CachedCardImage.java b/forge-gui-mobile/src/forge/CachedCardImage.java index d10b1dea577..29ad190f341 100644 --- a/forge-gui-mobile/src/forge/CachedCardImage.java +++ b/forge-gui-mobile/src/forge/CachedCardImage.java @@ -27,8 +27,7 @@ public abstract class CachedCardImage implements ImageFetcher.Callback { } public void fetch() { - Texture image = ImageCache.getImage(key, false); - if (image == null) { + if (!ImageCache.imageKeyFileExists(key)) { fetcher.fetchImage(key, this); } } diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index 5fd62b0e4c0..882bf66d0dc 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -37,7 +37,6 @@ import forge.util.Localizer; import forge.util.Utils; import java.io.File; -import java.io.FileFilter; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; @@ -71,14 +70,21 @@ public class Forge implements ApplicationListener { public static boolean hdbuttons = false; public static boolean hdstart = false; public static boolean isPortraitMode = false; + public static boolean gameInProgress = false; + public static int cacheSize = 400; + public static int totalDeviceRAM = 0; - public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0, boolean value, boolean androidOrientation) { + public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0, boolean value, boolean androidOrientation, int totalRAM) { if (GuiBase.getInterface() == null) { clipboard = clipboard0; deviceAdapter = deviceAdapter0; GuiBase.setInterface(new GuiMobile(assetDir0)); GuiBase.enablePropertyConfig(value); isPortraitMode = androidOrientation; + totalDeviceRAM = totalRAM; + //increase cacheSize for devices with RAM more than 5GB, default is 400. Some phones have more than 10GB RAM (Mi 10, OnePlus 8, S20, etc..) + if (totalDeviceRAM>5000) //devices with more than 10GB RAM will have 1000 Cache size, 700 Cache size for morethan 5GB RAM + cacheSize = totalDeviceRAM>10000 ? 1000: 700; } return app; } @@ -142,8 +148,18 @@ public class Forge implements ApplicationListener { splashScreen.getProgressBar().setDescription(localizer.getMessage("lblFinishingStartup")); //add reminder to preload - if (enablePreloadExtendedArt) - splashScreen.getProgressBar().setDescription(localizer.getMessage("lblPreloadExtendedArt")); + if (enablePreloadExtendedArt) { + if(totalDeviceRAM>0) + splashScreen.getProgressBar().setDescription(localizer.getMessage("lblPreloadExtendedArt")+"\nDetected RAM: " +totalDeviceRAM+"MB. Cache size: "+cacheSize); + else + splashScreen.getProgressBar().setDescription(localizer.getMessage("lblPreloadExtendedArt")); + } else { + if(totalDeviceRAM>0) + splashScreen.getProgressBar().setDescription(localizer.getMessage("lblFinishingStartup")+"\nDetected RAM: " +totalDeviceRAM+"MB. Cache size: "+cacheSize); + else + splashScreen.getProgressBar().setDescription(localizer.getMessage("lblFinishingStartup")); + } + Gdx.app.postRunnable(new Runnable() { @Override public void run() { @@ -160,25 +176,17 @@ public class Forge implements ApplicationListener { private void preloadExtendedArt() { if (!enablePreloadExtendedArt) return; - List keys = new ArrayList<>(); - File[] directories = new File(ForgeConstants.CACHE_CARD_PICS_DIR).listFiles(new FileFilter() { - @Override - public boolean accept(File file) { - if (!file.getName().startsWith("MPS_")) - return false; - return file.isDirectory(); - } - }); - for (File folder : directories) { - File[] files = new File(folder.toString()).listFiles(); - for (File file : files) { - if (file.isFile()) { - keys.add(folder.getName() + "/" +file.getName().replace(".jpg","").replace(".png","")); - } - } + List borderlessCardlistkeys = FileUtil.readFile(ForgeConstants.BORDERLESS_CARD_LIST_FILE); + if(borderlessCardlistkeys.isEmpty()) + return; + List filteredkeys = new ArrayList<>(); + for (String cardname : borderlessCardlistkeys){ + File image = new File(ForgeConstants.CACHE_CARD_PICS_DIR+ForgeConstants.PATH_SEPARATOR+cardname+".jpg"); + if (image.exists()) + filteredkeys.add(cardname); } - if (!keys.isEmpty()) - ImageCache.preloadCache((Iterable)keys); + if (!filteredkeys.isEmpty()) + ImageCache.preloadCache(filteredkeys); } private void afterDbLoaded() { @@ -402,11 +410,17 @@ public class Forge implements ApplicationListener { } private static void setCurrentScreen(FScreen screen0) { + String toNewScreen = screen0 != null ? screen0.toString() : ""; + String previousScreen = currentScreen != null ? currentScreen.toString() : ""; + + gameInProgress = toNewScreen.toLowerCase().contains("match") || previousScreen.toLowerCase().contains("match"); + boolean dispose = toNewScreen.toLowerCase().contains("homescreen"); try { endKeyInput(); //end key input before switching screens ForgeAnimation.endAll(); //end all active animations before switching screens try { - ImageCache.disposeTexture(); + if(dispose) + ImageCache.disposeTexture(); } catch (Exception ex) { diff --git a/forge-gui-mobile/src/forge/Graphics.java b/forge-gui-mobile/src/forge/Graphics.java index 695634e659c..a783f1f9674 100644 --- a/forge-gui-mobile/src/forge/Graphics.java +++ b/forge-gui-mobile/src/forge/Graphics.java @@ -566,17 +566,25 @@ public class Graphics { } public float getfloatAlphaComposite() { return alphaComposite; } - - public void drawBorderImage(FImage image, Color color, float x, float y, float w, float h, boolean tint) { - image.draw(this, x, y, w, h); + public void drawBorderImage(FImage image, Color borderColor, Color tintColor, float x, float y, float w, float h, boolean tint) { + float oldalpha = alphaComposite; if(tint){ - float oldalpha = alphaComposite; - setAlphaComposite(0.8f); - drawRoundRect(2f, Color.WHITE, x, y, w, h, (h-w)/12); - setAlphaComposite(1f); - fillRoundRect(color, x, y, w, h, (h-w)/12); - setAlphaComposite(oldalpha); + drawRoundRect(2f, borderLining(borderColor.toString()), x, y, w, h, (h-w)/12); + fillRoundRect(tintColor, x, y, w, h, (h-w)/12); + } else { + image.draw(this, x, y, w, h); + fillRoundRect(borderColor, x, y, w, h, (h-w)/10);//show corners edges } + setAlphaComposite(oldalpha); + } + public void drawborderImage(Color borderColor, float x, float y, float w, float h) { + float oldalpha = alphaComposite; + fillRoundRect(borderColor, x, y, w, h, (h-w)/12); + setAlphaComposite(oldalpha); + } + public void drawImage(FImage image, Color borderColor, float x, float y, float w, float h) { + image.draw(this, x, y, w, h); + fillRoundRect(borderColor, x+1, y+1, w-1.5f, h-1.5f, (h-w)/10);//used by zoom let some edges show... } public void drawImage(FImage image, float x, float y, float w, float h) { drawImage(image, x, y, w, h, false); @@ -733,4 +741,13 @@ public class Graphics { public float adjustY(float y, float height) { return regionHeight - y - bounds.y - height; //flip y-axis } + public Color borderLining(String c){ + if (c == null || c == "") + return Color.valueOf("#fffffd"); + int c_r = Integer.parseInt(c.substring(0,2),16); + int c_g = Integer.parseInt(c.substring(2,4),16); + int c_b = Integer.parseInt(c.substring(4,6),16); + int brightness = ((c_r * 299) + (c_g * 587) + (c_b * 114)) / 1000; + return brightness > 155 ? Color.valueOf("#171717") : Color.valueOf("#fffffd"); + } } diff --git a/forge-gui-mobile/src/forge/assets/FSkin.java b/forge-gui-mobile/src/forge/assets/FSkin.java index 520c5e6a05c..9f716df533a 100644 --- a/forge-gui-mobile/src/forge/assets/FSkin.java +++ b/forge-gui-mobile/src/forge/assets/FSkin.java @@ -27,10 +27,10 @@ import forge.screens.SplashScreen; import forge.toolbox.FProgressBar; public class FSkin { - private static final Map images = new HashMap<>(); - private static final Map avatars = new HashMap<>(); - private static final Map sleeves = new HashMap<>(); - private static final Map borders = new HashMap<>(); + private static final Map images = new HashMap<>(512); + private static final Map avatars = new HashMap<>(150); + private static final Map sleeves = new HashMap<>(64); + private static final Map borders = new HashMap<>(2); private static Array allSkins; private static FileHandle preferredDir; @@ -275,6 +275,20 @@ public class FSkin { } } pxPreferredAvatars.dispose(); + } else if (!FSkin.preferredName.isEmpty()){ + //workaround bug crash fix if missing sprite avatar on preferred theme for quest tournament... + //i really don't know why it needs to populate the avatars twice.... needs investigation + final int pw = pxDefaultAvatars.getWidth(); + final int ph = pxDefaultAvatars.getHeight(); + + for (int j = 0; j < ph; j += 100) { + for (int i = 0; i < pw; i += 100) { + if (i == 0 && j == 0) { continue; } + pxTest = new Color(pxDefaultAvatars.getPixel(i + 50, j + 50)); + if (pxTest.a == 0) { continue; } + FSkin.avatars.put(counter++, new TextureRegion(txDefaultAvatars, i, j, 100, 100)); + } + } } final int aw = pxDefaultAvatars.getWidth(); diff --git a/forge-gui-mobile/src/forge/assets/ImageCache.java b/forge-gui-mobile/src/forge/assets/ImageCache.java index bf85d66b8fb..95e6d9a0345 100644 --- a/forge-gui-mobile/src/forge/assets/ImageCache.java +++ b/forge-gui-mobile/src/forge/assets/ImageCache.java @@ -27,23 +27,27 @@ import com.google.common.cache.LoadingCache; import com.google.common.cache.RemovalCause; import com.google.common.cache.RemovalListener; import com.google.common.cache.RemovalNotification; +import forge.Forge; import forge.ImageKeys; import forge.card.CardEdition; import forge.card.CardRenderer; +import forge.deck.Deck; import forge.game.card.CardView; import forge.game.player.IHasIcon; -import forge.item.IPaperCard; import forge.item.InventoryItem; +import forge.item.PaperCard; import forge.model.FModel; import forge.properties.ForgeConstants; import forge.util.ImageUtil; +import forge.util.TextUtil; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import java.io.File; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; /** @@ -65,7 +69,7 @@ public class ImageCache { private static final Set missingIconKeys = new HashSet<>(); private static final LoadingCache cache = CacheBuilder.newBuilder() - .maximumSize(400) + .maximumSize(Forge.cacheSize) .expireAfterAccess(15, TimeUnit.MINUTES) .removalListener(new RemovalListener() { @Override @@ -73,13 +77,14 @@ public class ImageCache { if(removalNotification.wasEvicted()||removalNotification.getCause() == RemovalCause.EXPIRED) { removalNotification.getValue().dispose(); } + CardRenderer.clearcardArtCache(); } }) .build(new ImageLoader()); public static final Texture defaultImage; public static FImage BlackBorder = FSkinImage.IMG_BORDER_BLACK; public static FImage WhiteBorder = FSkinImage.IMG_BORDER_WHITE; - private static final Map Borders = new HashMap<>(); + private static final Map> imageBorder = new HashMap<>(1024); private static boolean imageLoaded, delayLoadRequested; public static void allowSingleLoad() { @@ -102,13 +107,13 @@ public class ImageCache { cache.invalidateAll(); cache.cleanUp(); missingIconKeys.clear(); - Borders.clear(); } public static void disposeTexture(){ for (Texture t: cache.asMap().values()) { if (!t.toString().contains("pics/icons")) //fixes quest avatars black texture. todo: filter textures that are safe to dispose... - t.dispose(); + if(!t.toString().contains("@")) //generated texture don't need to be disposed manually + t.dispose(); } CardRenderer.clearcardArtCache(); clear(); @@ -132,6 +137,39 @@ public class ImageCache { return new FTextureImage(icon); } + /** + * checks the card image exists from the disk. + */ + public static boolean imageKeyFileExists(String imageKey) { + if (StringUtils.isEmpty(imageKey)) + return false; + + if (imageKey.length() < 2) + return false; + + final String prefix = imageKey.substring(0, 2); + + if (prefix.equals(ImageKeys.CARD_PREFIX)) { + PaperCard paperCard = ImageUtil.getPaperCardFromImageKey(imageKey); + if (paperCard == null) + return false; + + final boolean backFace = imageKey.endsWith(ImageKeys.BACKFACE_POSTFIX); + final String cardfilename = ImageUtil.getImageKey(paperCard, backFace, true); + if (!new File(ForgeConstants.CACHE_CARD_PICS_DIR + "/" + cardfilename + ".jpg").exists()) + if (!new File(ForgeConstants.CACHE_CARD_PICS_DIR + "/" + cardfilename + ".png").exists()) + if (!new File(ForgeConstants.CACHE_CARD_PICS_DIR + "/" + TextUtil.fastReplace(cardfilename,".full", ".fullborder") + ".jpg").exists()) + return false; + } else if (prefix.equals(ImageKeys.TOKEN_PREFIX)) { + final String tokenfilename = imageKey.substring(2) + ".jpg"; + + if (!new File(ForgeConstants.CACHE_TOKEN_PICS_DIR, tokenfilename).exists()) + return false; + } + + return true; + } + /** * This requests the original unscaled image from the cache for the given key. * If the image does not exist then it can return a default image if desired. @@ -185,19 +223,27 @@ public class ImageCache { if (useDefaultIfNotFound) { image = defaultImage; cache.put(imageKey, defaultImage); - if (Borders.get(image) == null) - Borders.put(image, false); //black border + if (imageBorder.get(image.toString()) == null) + imageBorder.put(image.toString(), Pair.of(Color.valueOf("#171717").toString(), false)); //black border } } return image; } public static void preloadCache(Iterable keys) { - try { - cache.getAll(keys); - } catch (ExecutionException e) { - e.printStackTrace(); + for (String imageKey : keys){ + if(getImage(imageKey, false) == null) + System.err.println("could not load card image:"+imageKey); } } + public static void preloadCache(Deck deck) { + if(deck == null||!Forge.enablePreloadExtendedArt) + return; + for (PaperCard p : deck.getAllCardsInASinglePool().toFlatList()) { + if (getImage(p.getImageKey(false),false) == null) + System.err.println("could not load card image:"+p.toString()); + } + + } public static TextureRegion croppedBorderImage(Texture image) { if (!image.toString().contains(".fullborder.")) return new TextureRegion(image); @@ -208,24 +254,10 @@ public class ImageCache { int ry = Math.round((image.getHeight() - rh)/2f)-2; return new TextureRegion(image, rx, ry, rw, rh); } - public static Color borderColor(IPaperCard c) { - if (c == null) + public static Color borderColor(Texture t) { + if (t == null) return Color.valueOf("#171717"); - - CardEdition ed = FModel.getMagicDb().getEditions().get(c.getEdition()); - if (ed != null && ed.isWhiteBorder()) - return Color.valueOf("#fffffd"); - return Color.valueOf("#171717"); - } - public static Color borderColor(CardView c) { - if (c == null) - return Color.valueOf("#171717"); - - CardView.CardStateView state = c.getCurrentState(); - CardEdition ed = FModel.getMagicDb().getEditions().get(state.getSetCode()); - if (ed != null && ed.isWhiteBorder() && state.getFoilIndex() == 0) - return Color.valueOf("#fffffd"); - return Color.valueOf("#171717"); + return Color.valueOf(imageBorder.get(t.toString()).getLeft()); } public static int getFSkinBorders(CardView c) { if (c == null) @@ -240,21 +272,21 @@ public class ImageCache { public static boolean isBorderlessCardArt(Texture t) { return ImageLoader.isBorderless(t); } - public static void updateBorders(Texture t, boolean val){ - Borders.put(t, val); + public static void updateBorders(String textureString, Pair colorPair){ + imageBorder.put(textureString, colorPair); } - public static FImage getBorder(Texture t) { - if (Borders.get(t) == null) + public static FImage getBorder(String textureString) { + if (imageBorder.get(textureString) == null) return BlackBorder; - return Borders.get(t) ? WhiteBorder : BlackBorder; + return imageBorder.get(textureString).getRight() ? WhiteBorder : BlackBorder; } - public static FImage getBorderImage(Texture t, boolean canshow) { + public static FImage getBorderImage(String textureString, boolean canshow) { if (!canshow) return BlackBorder; - return getBorder(t); + return getBorder(textureString); } - public static FImage getBorderImage(Texture t) { - return getBorder(t); + public static FImage getBorderImage(String textureString) { + return getBorder(textureString); } public static Color getTint(CardView c) { if (c == null) diff --git a/forge-gui-mobile/src/forge/assets/ImageLoader.java b/forge-gui-mobile/src/forge/assets/ImageLoader.java index 064300ae635..75da8087fc8 100644 --- a/forge-gui-mobile/src/forge/assets/ImageLoader.java +++ b/forge-gui-mobile/src/forge/assets/ImageLoader.java @@ -1,7 +1,7 @@ package forge.assets; import java.io.File; -import java.util.ArrayList; +import java.util.List; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Color; @@ -14,142 +14,15 @@ import forge.FThreads; import forge.Forge; import forge.ImageKeys; +import forge.properties.ForgeConstants; +import forge.util.FileUtil; import forge.util.TextUtil; +import org.apache.commons.lang3.tuple.Pair; import static forge.assets.ImageCache.croppedBorderImage; final class ImageLoader extends CacheLoader { - private static ArrayList borderlessCardlistKey = new ArrayList() { - {//TODO: load the values from text list instead of hardcoded - add("2XM/Academy Ruins2.fullborder"); - add("2XM/Atraxa, Praetors' Voice2.fullborder"); - add("2XM/Avacyn, Angel of Hope2.fullborder"); - add("2XM/Batterskull2.fullborder"); - add("2XM/Blightsteel Colossus2.fullborder"); - add("2XM/Blood Moon2.fullborder"); - add("2XM/Brainstorm2.fullborder"); - add("2XM/Chrome Mox2.fullborder"); - add("2XM/Council's Judgment2.fullborder"); - add("2XM/Crop Rotation2.fullborder"); - add("2XM/Cyclonic Rift2.fullborder"); - add("2XM/Dark Confidant2.fullborder"); - add("2XM/Doubling Season2.fullborder"); - add("2XM/Expedition Map2.fullborder"); - add("2XM/Exploration2.fullborder"); - add("2XM/Fatal Push2.fullborder"); - add("2XM/Force of Will2.fullborder"); - add("2XM/Goblin Guide2.fullborder"); - add("2XM/Jace, the Mind Sculptor2.fullborder"); - add("2XM/Kaalia of the Vast2.fullborder"); - add("2XM/Karn Liberated2.fullborder"); - add("2XM/Lightning Greaves2.fullborder"); - add("2XM/Mana Crypt2.fullborder"); - add("2XM/Meddling Mage2.fullborder"); - add("2XM/Mox Opal2.fullborder"); - add("2XM/Noble Hierarch2.fullborder"); - add("2XM/Phyrexian Metamorph2.fullborder"); - add("2XM/Sneak Attack2.fullborder"); - add("2XM/Stoneforge Mystic2.fullborder"); - add("2XM/Sword of Body and Mind2.fullborder"); - add("2XM/Sword of Feast and Famine2.fullborder"); - add("2XM/Sword of Fire and Ice2.fullborder"); - add("2XM/Sword of Light and Shadow2.fullborder"); - add("2XM/Sword of War and Peace2.fullborder"); - add("2XM/Thoughtseize2.fullborder"); - add("2XM/Toxic Deluge2.fullborder"); - add("2XM/Urza's Mine2.fullborder"); - add("2XM/Urza's Power Plant2.fullborder"); - add("2XM/Urza's Tower2.fullborder"); - add("2XM/Wurmcoil Engine2.fullborder"); - add("ELD/Garruk, Cursed Huntsman2.fullborder"); - add("ELD/Oko, Thief of Crowns2.fullborder"); - add("ELD/The Royal Scions2.fullborder"); - add("IKO/Brokkos, Apex of Forever2.fullborder"); - add("IKO/Brokkos, Apex of Forever3.fullborder"); - add("IKO/Crystalline Giant3.fullborder"); - add("IKO/Cubwarden2.fullborder"); - add("IKO/Dirge Bat2.fullborder"); - add("IKO/Dirge Bat3.fullborder"); - add("IKO/Everquill Phoenix2.fullborder"); - add("IKO/Everquill Phoenix3.fullborder"); - add("IKO/Gemrazer2.fullborder"); - add("IKO/Gemrazer3.fullborder"); - add("IKO/Gyruda, Doom of Depths3.fullborder"); - add("IKO/Huntmaster Liger2.fullborder"); - add("IKO/Huntmaster Liger3.fullborder"); - add("IKO/Illuna, Apex of Wishes2.fullborder"); - add("IKO/Illuna, Apex of Wishes3.fullborder"); - add("IKO/Indatha Triome2.fullborder"); - add("IKO/Ketria Triome2.fullborder"); - add("IKO/Lukka, Coppercoat Outcast2.fullborder"); - add("IKO/Luminous Broodmoth3.fullborder"); - add("IKO/Mysterious Egg2.fullborder"); - add("IKO/Narset of the Ancient Way2.fullborder"); - add("IKO/Nethroi, Apex of Death2.fullborder"); - add("IKO/Nethroi, Apex of Death3.fullborder"); - add("IKO/Pollywog Symbiote2.fullborder"); - add("IKO/Raugrin Triome2.fullborder"); - add("IKO/Savai Triome2.fullborder"); - add("IKO/Sea-Dasher Octopus2.fullborder"); - add("IKO/Snapdax, Apex of the Hunt2.fullborder"); - add("IKO/Snapdax, Apex of the Hunt3.fullborder"); - add("IKO/Sprite Dragon3.fullborder"); - add("IKO/Titanoth Rex2.fullborder"); - add("IKO/Vadrok, Apex of Thunder2.fullborder"); - add("IKO/Vadrok, Apex of Thunder3.fullborder"); - add("IKO/Vivien, Monsters' Advocate2.fullborder"); - add("IKO/Void Beckoner2.fullborder"); - add("IKO/Yidaro, Wandering Monster3.fullborder"); - add("IKO/Zagoth Triome2.fullborder"); - add("IKO/Zilortha, Strength Incarnate.fullborder"); - add("M21/Basri Ket2.fullborder"); - add("M21/Chandra, Heart of Fire2.fullborder"); - add("M21/Containment Priest2.fullborder"); - add("M21/Cultivate2.fullborder"); - add("M21/Garruk, Unleashed2.fullborder"); - add("M21/Grim Tutor2.fullborder"); - add("M21/Liliana, Waker of the Dead2.fullborder"); - add("M21/Massacre Wurm2.fullborder"); - add("M21/Scavenging Ooze2.fullborder"); - add("M21/Solemn Simulacrum2.fullborder"); - add("M21/Teferi, Master of Time2.fullborder"); - add("M21/Ugin, the Spirit Dragon2.fullborder"); - add("M21/Ugin, the Spirit Dragon3.fullborder"); - add("PLGS/Hangarback Walker.fullborder"); - add("SLD/Acidic Slime.fullborder"); - add("SLD/Captain Sisay.fullborder"); - add("SLD/Meren of Clan Nel Toth.fullborder"); - add("SLD/Narset, Enlightened Master.fullborder"); - add("SLD/Necrotic Ooze.fullborder"); - add("SLD/Oona, Queen of the Fae.fullborder"); - add("SLD/Saskia the Unyielding.fullborder"); - add("SLD/The Mimeoplasm.fullborder"); - add("SLD/Voidslime.fullborder"); - add("THB/Ashiok, Nightmare Muse2.fullborder"); - add("THB/Calix, Destiny's Hand2.fullborder"); - add("THB/Elspeth, Sun's Nemesis2.fullborder"); - add("UST/Forest.fullborder"); - add("UST/Island.fullborder"); - add("UST/Mountain.fullborder"); - add("UST/Plains.fullborder"); - add("UST/Swamp.fullborder"); - add("ZNR/Boulderloft Pathway2.fullborder"); - add("ZNR/Branchloft Pathway2.fullborder"); - add("ZNR/Brightclimb Pathway2.fullborder"); - add("ZNR/Clearwater Pathway2.fullborder"); - add("ZNR/Cragcrown Pathway2.fullborder"); - add("ZNR/Grimclimb Pathway2.fullborder"); - add("ZNR/Jace, Mirror Mage2.fullborder"); - add("ZNR/Lavaglide Pathway2.fullborder"); - add("ZNR/Murkwater Pathway2.fullborder"); - add("ZNR/Nahiri, Heir of the Ancients2.fullborder"); - add("ZNR/Needleverge Pathway2.fullborder"); - add("ZNR/Nissa of Shadowed Boughs2.fullborder"); - add("ZNR/Pillarverge Pathway2.fullborder"); - add("ZNR/Riverglide Pathway2.fullborder"); - add("ZNR/Timbercrown Pathway2.fullborder"); - } - }; + private static List borderlessCardlistKey = FileUtil.readFile(ForgeConstants.BORDERLESS_CARD_LIST_FILE); Texture n; @Override @@ -162,7 +35,7 @@ final class ImageLoader extends CacheLoader { try { Texture t = new Texture(fh, textureFilter); //update - ImageCache.updateBorders(t, extendedArt ? false: isCloserToWhite(getpixelColor(t))); + ImageCache.updateBorders(t.toString(), extendedArt ? Pair.of(Color.valueOf("#171717").toString(), false): isCloserToWhite(getpixelColor(t))); if (textureFilter) t.setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear); if (extendedArt) @@ -240,6 +113,8 @@ final class ImageLoader extends CacheLoader { } public boolean isBorderless(String imagekey) { + if(borderlessCardlistKey.isEmpty()) + return false; if (imagekey.length() > 7) { if ((!imagekey.substring(0, 7).contains("MPS_KLD"))&&(imagekey.substring(0, 4).contains("MPS_"))) //MPS_ sets except MPD_KLD return true; @@ -248,6 +123,8 @@ final class ImageLoader extends CacheLoader { } public static boolean isBorderless(Texture t) { + if(borderlessCardlistKey.isEmpty()) + return false; //generated texture/pixmap? if (t.toString().contains("com.badlogic.gdx.graphics.Texture@")) return true; @@ -269,13 +146,13 @@ final class ImageLoader extends CacheLoader { pixmap.dispose(); return color.toString(); } - public static boolean isCloserToWhite(String c){ + public static Pair isCloserToWhite(String c){ if (c == null || c == "") - return false; + return Pair.of(Color.valueOf("#171717").toString(), false); int c_r = Integer.parseInt(c.substring(0,2),16); int c_g = Integer.parseInt(c.substring(2,4),16); int c_b = Integer.parseInt(c.substring(4,6),16); int brightness = ((c_r * 299) + (c_g * 587) + (c_b * 114)) / 1000; - return brightness > 155; + return Pair.of(c,brightness > 155); } } diff --git a/forge-gui-mobile/src/forge/assets/TextRenderer.java b/forge-gui-mobile/src/forge/assets/TextRenderer.java index d73a5b966fd..9b53bde5bac 100644 --- a/forge-gui-mobile/src/forge/assets/TextRenderer.java +++ b/forge-gui-mobile/src/forge/assets/TextRenderer.java @@ -16,7 +16,7 @@ import forge.util.TextBounds; //Encodes text for drawing with symbols and reminder text public class TextRenderer { - private static final Map symbolLookup = new HashMap<>(); + private static final Map symbolLookup = new HashMap<>(64); static { symbolLookup.put("C", FSkinImage.MANA_COLORLESS); symbolLookup.put("W", FSkinImage.MANA_W); diff --git a/forge-gui-mobile/src/forge/card/CardFaceSymbols.java b/forge-gui-mobile/src/forge/card/CardFaceSymbols.java index b82ad3aae11..86942c1c3d9 100644 --- a/forge-gui-mobile/src/forge/card/CardFaceSymbols.java +++ b/forge-gui-mobile/src/forge/card/CardFaceSymbols.java @@ -29,7 +29,7 @@ import java.util.StringTokenizer; public class CardFaceSymbols { public static final float FONT_SIZE_FACTOR = 0.85f; - private static final Map MANA_IMAGES = new HashMap<>(); + private static final Map MANA_IMAGES = new HashMap<>(128); public static void loadImages() { for (int i = 0; i <= 20; i++) { diff --git a/forge-gui-mobile/src/forge/card/CardImage.java b/forge-gui-mobile/src/forge/card/CardImage.java index a15772a51d7..70883350f1b 100644 --- a/forge-gui-mobile/src/forge/card/CardImage.java +++ b/forge-gui-mobile/src/forge/card/CardImage.java @@ -53,7 +53,7 @@ public class CardImage implements FImage { g.drawImage(image, x, y, w, h); else { float radius = (h - w)/8; - g.drawfillBorder(3, ImageCache.borderColor(card), x, y, w, h, radius); + g.drawborderImage(ImageCache.borderColor(image), x, y, w, h); g.drawImage(ImageCache.croppedBorderImage(image), x+radius/2.2f, y+radius/2, w*0.96f, h*0.96f); } } diff --git a/forge-gui-mobile/src/forge/card/CardImageRenderer.java b/forge-gui-mobile/src/forge/card/CardImageRenderer.java index 0295d1be631..209642f87f2 100644 --- a/forge-gui-mobile/src/forge/card/CardImageRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardImageRenderer.java @@ -73,9 +73,12 @@ public class CardImageRenderer { prevImageHeight = h; } - public static void drawFaceDownCard(Graphics g, float x, float y, float w, float h) { - // TODO: improve the way a face-down card back is represented so it doesn't look as ugly - drawArt(g, x, y, w, h); + public static void drawFaceDownCard(CardView card, Graphics g, float x, float y, float w, float h) { + //try to draw the card sleeves first + if (FSkin.getSleeves().get(card.getOwner()) != null) + g.drawImage(FSkin.getSleeves().get(card.getOwner()), x, y, w, h); + else + drawArt(g, x, y, w, h); } public static void drawCardImage(Graphics g, CardView card, boolean altState, float x, float y, float w, float h, CardStackPosition pos) { @@ -92,7 +95,7 @@ public class CardImageRenderer { final boolean canShow = MatchController.instance.mayView(card); if (!canShow) { - drawFaceDownCard(g, x, y, w, h); + drawFaceDownCard(card, g, x, y, w, h); return; } @@ -333,7 +336,17 @@ public class CardImageRenderer { public static void drawZoom(Graphics g, CardView card, GameView gameView, boolean altState, float x, float y, float w, float h, float dispW, float dispH, boolean isCurrentCard) { boolean canshow = MatchController.instance.mayView(card); - final Texture image = ImageCache.getImage(card.getState(altState).getImageKey(), true); + Texture image = null; + try { + image = ImageCache.getImage(card.getState(altState).getImageKey(), true); + } catch (Exception ex) { + //System.err.println(card.toString()+" : " +ex.getMessage()); + //TODO: don't know why this is needed, needs further investigation... + if (!card.hasAlternateState()) { + altState = false; + image = ImageCache.getImage(card.getState(altState).getImageKey(), true); + } + } FImage sleeves = MatchController.getPlayerSleeve(card.getOwner()); if (image == null) { //draw details if can't draw zoom drawDetails(g, card, gameView, altState, x, y, w, h); @@ -390,7 +403,7 @@ public class CardImageRenderer { if (ImageCache.isBorderlessCardArt(image)) g.drawImage(image, x, y, w, h); else { - g.drawImage(ImageCache.getBorderImage(image, canshow), x, y, w, h); + g.drawImage(ImageCache.getBorderImage(image.toString()), ImageCache.borderColor(image), x, y, w, h); g.drawImage(ImageCache.croppedBorderImage(image), x + radius / 2.4f-minusxy, y + radius / 2-minusxy, w * croppedArea, h * croppedArea); } } else { diff --git a/forge-gui-mobile/src/forge/card/CardRenderer.java b/forge-gui-mobile/src/forge/card/CardRenderer.java index 3eb6ed751e2..3f352afeedb 100644 --- a/forge-gui-mobile/src/forge/card/CardRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardRenderer.java @@ -55,6 +55,7 @@ import forge.util.TextBounds; import java.util.Arrays; import java.util.ArrayList; +import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -192,7 +193,7 @@ public class CardRenderer { return Math.round(MANA_SYMBOL_SIZE + FSkinFont.get(12).getLineHeight() + 3 * FList.PADDING + 1); } - private static final Map cardArtCache = new HashMap<>(); + private static final Map cardArtCache = new HashMap<>(1024); public static final float CARD_ART_RATIO = 1.302f; public static final float CARD_ART_HEIGHT_PERCENTAGE = 0.43f; @@ -463,7 +464,7 @@ public class CardRenderer { if (ImageCache.isBorderlessCardArt(image)) g.drawImage(image, x, y, w, h); else { - g.drawImage(ImageCache.getBorderImage(image), x, y, w, h); + g.drawImage(ImageCache.getBorderImage(image.toString()), x, y, w, h); g.drawImage(ImageCache.croppedBorderImage(image), x + radius / 2.4f-minusxy, y + radius / 2-minusxy, w * croppedArea, h * croppedArea); } } else @@ -484,8 +485,12 @@ public class CardRenderer { } } public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean rotate) { + drawCard(g, card, x, y, w, h, pos, rotate, false); + } + public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean rotate, boolean showAltState) { boolean canshow = MatchController.instance.mayView(card); - Texture image = new RendererCachedCardImage(card, false).getImage(card.getCurrentState().getImageKey()); + boolean showsleeves = card.isFaceDown() && card.isInZone(EnumSet.of(ZoneType.Exile)); //fix facedown card image ie gonti lord of luxury + Texture image = new RendererCachedCardImage(card, false).getImage( showAltState ? card.getAlternateState().getImageKey() : card.getCurrentState().getImageKey()); FImage sleeves = MatchController.getPlayerSleeve(card.getOwner()); float radius = (h - w)/8; float croppedArea = isModernFrame(card) ? CROP_MULTIPLIER : 0.97f; @@ -497,6 +502,8 @@ public class CardRenderer { if (image != null) { if (image == ImageCache.defaultImage) { CardImageRenderer.drawCardImage(g, card, false, x, y, w, h, pos); + } else if (showsleeves) { + g.drawImage(sleeves, x, y, w, h); } else { if(FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ROTATE_PLANE_OR_PHENOMENON) && (card.getCurrentState().isPhenomenon() || card.getCurrentState().isPlane()) && rotate){ @@ -515,7 +522,7 @@ public class CardRenderer { g.drawImage(image, x, y, w, h); else { boolean t = (card.getCurrentState().getOriginalColors() != card.getCurrentState().getColors()) || card.getCurrentState().hasChangeColors(); - g.drawBorderImage(ImageCache.getBorderImage(image, canshow), ImageCache.getTint(card), x, y, w, h, t); //tint check for changed colors + g.drawBorderImage(ImageCache.getBorderImage(image.toString(), canshow), ImageCache.borderColor(image), ImageCache.getTint(card), x, y, w, h, t); //tint check for changed colors g.drawImage(ImageCache.croppedBorderImage(image), x + radius / 2.4f-minusxy, y + radius / 2-minusxy, w * croppedArea, h * croppedArea); } } else { @@ -536,15 +543,15 @@ public class CardRenderer { } public static void drawCardWithOverlays(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos) { - drawCardWithOverlays(g, card, x, y, w, h, pos, false); + drawCardWithOverlays(g, card, x, y, w, h, pos, false, false); } - public static void drawCardWithOverlays(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean stackview) { + public static void drawCardWithOverlays(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean stackview, boolean showAltState) { boolean canShow = MatchController.instance.mayView(card); float oldAlpha = g.getfloatAlphaComposite(); boolean unselectable = !MatchController.instance.isSelectable(card) && MatchController.instance.isSelecting(); float cx, cy, cw, ch; cx = x; cy = y; cw = w; ch = h; - drawCard(g, card, x, y, w, h, pos, false); + drawCard(g, card, x, y, w, h, pos, false, showAltState); float padding = w * PADDING_MULTIPLIER; //adjust for card border x += padding; @@ -553,7 +560,7 @@ public class CardRenderer { h -= 2 * padding; // TODO: A hacky workaround is currently used to make the game not leak the color information for Morph cards. - final CardStateView details = card.getCurrentState(); + final CardStateView details = showAltState ? card.getAlternateState() : card.getCurrentState(); final boolean isFaceDown = card.isFaceDown(); final DetailColors borderColor = isFaceDown ? CardDetailUtil.DetailColors.FACE_DOWN : CardDetailUtil.getBorderColor(details, canShow); // canShow doesn't work here for face down Morphs Color color = FSkinColor.fromRGB(borderColor.r, borderColor.g, borderColor.b); @@ -930,7 +937,7 @@ public class CardRenderer { } } else { - drawManaCost(g, card.getCurrentState().getManaCost(), x - padding, y, w + 2 * padding, h, manaSymbolSize); + drawManaCost(g, showAltState ? card.getAlternateState().getManaCost() : card.getCurrentState().getManaCost(), x - padding, y, w + 2 * padding, h, manaSymbolSize); } } } diff --git a/forge-gui-mobile/src/forge/card/CardZoom.java b/forge-gui-mobile/src/forge/card/CardZoom.java index 2eea37d2ec6..bd77c7618f0 100644 --- a/forge-gui-mobile/src/forge/card/CardZoom.java +++ b/forge-gui-mobile/src/forge/card/CardZoom.java @@ -46,10 +46,15 @@ public class CardZoom extends FOverlay { private static String currentActivateAction; private static Rectangle flipIconBounds; private static boolean showAltState; + private static boolean showBackSide = false; public static void show(Object item) { + show(item, false); + } + public static void show(Object item, boolean showbackside) { List items0 = new ArrayList<>(); items0.add(item); + showBackSide = showbackside; //reverse the displayed zoomed card for the choice list show(items0, 0, null); } public static void show(FCollectionView items0, int currentIndex0, ActivateHandler activateHandler0) { @@ -158,10 +163,15 @@ public class CardZoom extends FOverlay { @Override public boolean tap(float x, float y, int count) { if (flipIconBounds != null && flipIconBounds.contains(x, y)) { - showAltState = !showAltState; + if (!showBackSide) + showAltState = !showAltState; + else + showBackSide = !showBackSide; return true; } hide(); + showBackSide = false; + showAltState = false; return true; } @@ -169,14 +179,20 @@ public class CardZoom extends FOverlay { public boolean fling(float velocityX, float velocityY) { if (Math.abs(velocityX) > Math.abs(velocityY)) { incrementCard(velocityX > 0 ? -1 : 1); + showBackSide = false; + showAltState = false; return true; } if (velocityY > 0) { zoomMode = !zoomMode; + showBackSide = false; + showAltState = false; return true; } if (currentActivateAction != null && activateHandler != null) { hide(); + showBackSide = false; + showAltState = false; activateHandler.activate(currentIndex); return true; } @@ -282,10 +298,9 @@ public class CardZoom extends FOverlay { float x = (w - cardWidth) / 2; y = (h - cardHeight) / 2; if (zoomMode) { - CardImageRenderer.drawZoom(g, currentCard, gameView, showAltState, x, y, cardWidth, cardHeight, getWidth(), getHeight(), true); - } - else { - CardImageRenderer.drawDetails(g, currentCard, gameView, showAltState, x, y, cardWidth, cardHeight); + CardImageRenderer.drawZoom(g, currentCard, gameView, showBackSide? showBackSide : showAltState, x, y, cardWidth, cardHeight, getWidth(), getHeight(), true); + } else { + CardImageRenderer.drawDetails(g, currentCard, gameView, showBackSide? showBackSide : showAltState, x, y, cardWidth, cardHeight); } if (flipIconBounds != null) { @@ -307,6 +322,8 @@ public class CardZoom extends FOverlay { } g.fillRect(FDialog.MSG_BACK_COLOR, 0, h - messageHeight, w, messageHeight); g.drawText(zoomMode ? Localizer.getInstance().getMessage("lblSwipeDownDetailView") : Localizer.getInstance().getMessage("lblSwipeDownPictureView"), FDialog.MSG_FONT, FDialog.MSG_FORE_COLOR, 0, h - messageHeight, w, messageHeight, false, Align.center, true); + + interrupt(false); } @Override @@ -318,4 +335,15 @@ public class CardZoom extends FOverlay { void setSelectedIndex(int index); void activate(int index); } + + public void interrupt(boolean resume) { + if (MatchController.instance.hasLocalPlayers()) + return; + if(resume && MatchController.instance.isGamePaused()) { + MatchController.instance.resumeMatch(); + return; + } + if(!MatchController.instance.isGamePaused()) + MatchController.instance.pauseMatch(); + } } diff --git a/forge-gui-mobile/src/forge/deck/FDeckChooser.java b/forge-gui-mobile/src/forge/deck/FDeckChooser.java index ccbe174bc3b..36378199774 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckChooser.java +++ b/forge-gui-mobile/src/forge/deck/FDeckChooser.java @@ -3,6 +3,7 @@ package forge.deck; import forge.FThreads; import forge.Forge; import forge.GuiBase; +import forge.assets.ImageCache; import forge.deck.FDeckEditor.EditorType; import forge.deck.io.DeckPreferences; import forge.error.BugReporter; @@ -472,6 +473,8 @@ public class FDeckChooser extends FScreen { break; } needRefreshOnActivate = true; + /*preload deck to cache*/ + ImageCache.preloadCache(deck.getDeck()); Forge.openScreen(new FDeckEditor(editorType, deck, true)); } @@ -1147,7 +1150,7 @@ public class FDeckChooser extends FScreen { }); } }); - chooser.show(null, true); + chooser.show(null, false); /*setting selectMax to true will select all available option*/ } }); } diff --git a/forge-gui-mobile/src/forge/deck/FDeckViewer.java b/forge-gui-mobile/src/forge/deck/FDeckViewer.java index c363cec6ebd..51e838b8b96 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckViewer.java +++ b/forge-gui-mobile/src/forge/deck/FDeckViewer.java @@ -5,6 +5,7 @@ import forge.assets.FImage; import forge.assets.FSkin; import forge.assets.FSkinImage; import forge.assets.FTextureRegionImage; +import forge.assets.ImageCache; import forge.item.PaperCard; import forge.itemmanager.CardManager; import forge.itemmanager.ItemManagerConfig; @@ -112,6 +113,9 @@ public class FDeckViewer extends FScreen { public static void show(final Deck deck0) { if (deck0 == null) { return; } + /*preload deck to cache*/ + ImageCache.preloadCache(deck0); + deckViewer = new FDeckViewer(deck0); deckViewer.setRotate180(MatchController.getView() != null && MatchController.getView().isTopHumanPlayerActive()); Forge.openScreen(deckViewer); diff --git a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java index 529df5cde9e..32abd93cbe5 100644 --- a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java +++ b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.List; import forge.GuiBase; +import forge.assets.ImageCache; import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckSection; @@ -625,6 +626,10 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { if (isNewPanel) { panel.setVisible(true); } + if (Forge.gameInProgress) { + /*preload deck to cache*/ + ImageCache.preloadCache(decks[i]); + } Gdx.graphics.requestRendering(); } else if (hasPanel) { diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index 6e0d269c725..ec7bf10906a 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -445,7 +445,6 @@ public class MatchController extends AbstractGuiGame { @Override public void afterGameEnd() { Forge.back(); - ImageCache.disposeTexture(); //view = null; } diff --git a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java index 5fbfa260579..1bbc9435e0a 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java @@ -355,6 +355,32 @@ public class MatchScreen extends FScreen { final GameView game = MatchController.instance.getGameView(); if (game == null) { return; } + if(gameMenu!=null) { + if(gameMenu.getChildCount()>3){ + if(viewWinLose == null) { + gameMenu.getChildAt(0).setEnabled(true); + gameMenu.getChildAt(1).setEnabled(true); + gameMenu.getChildAt(2).setEnabled(true); + gameMenu.getChildAt(3).setEnabled(true); + gameMenu.getChildAt(4).setEnabled(false); + } else { + gameMenu.getChildAt(0).setEnabled(false); + gameMenu.getChildAt(1).setEnabled(false); + gameMenu.getChildAt(2).setEnabled(false); + gameMenu.getChildAt(3).setEnabled(false); + gameMenu.getChildAt(4).setEnabled(true); + } + } + } + if(devMenu!=null) { + if(devMenu.isVisible()){ + if(viewWinLose == null) + devMenu.setEnabled(true); + else + devMenu.setEnabled(false); + } + } + //draw arrows for paired cards Set pairedCards = new HashSet<>(); for (VPlayerPanel playerPanel : playerPanels.values()) { diff --git a/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java b/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java index 5c925b70b8f..d9bbc38166d 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java @@ -92,7 +92,7 @@ public class VGameMenu extends FDropDownMenu { SettingsScreen.show(false); } })); - addItem(new FMenuItem(localizer.getMessage("lblShowWinLoseOverlay"), null, new FEventHandler() { + addItem(new FMenuItem(localizer.getMessage("lblShowWinLoseOverlay"), FSkinImage.ENDTURN, new FEventHandler() { @Override public void handleEvent(FEvent e) { MatchController.instance.showWinlose(); diff --git a/forge-gui-mobile/src/forge/screens/match/views/VStack.java b/forge-gui-mobile/src/forge/screens/match/views/VStack.java index 567665e69bd..b3ae6edd666 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VStack.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VStack.java @@ -382,7 +382,7 @@ public class VStack extends FDropDown { x += PADDING; y += PADDING; - CardRenderer.drawCardWithOverlays(g, stackInstance.getSourceCard(), x, y, CARD_WIDTH, CARD_HEIGHT, CardStackPosition.Top, true); + CardRenderer.drawCardWithOverlays(g, stackInstance.getSourceCard(), x, y, CARD_WIDTH, CARD_HEIGHT, CardStackPosition.Top, true, false); x += CARD_WIDTH + PADDING; w -= x + PADDING - BORDER_THICKNESS; diff --git a/forge-gui-mobile/src/forge/screens/match/winlose/ControlWinLose.java b/forge-gui-mobile/src/forge/screens/match/winlose/ControlWinLose.java index 2c0d0e8e413..9efa454a3d5 100644 --- a/forge-gui-mobile/src/forge/screens/match/winlose/ControlWinLose.java +++ b/forge-gui-mobile/src/forge/screens/match/winlose/ControlWinLose.java @@ -1,7 +1,6 @@ package forge.screens.match.winlose; import forge.Forge; -import forge.assets.ImageCache; import forge.game.GameView; import forge.game.player.PlayerView; import forge.screens.match.MatchController; @@ -85,7 +84,6 @@ public class ControlWinLose { view.hide(); if(humancount == 0) { Forge.back(); - ImageCache.disposeTexture(); } } diff --git a/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java index 5cee692ef29..81b113fb80d 100644 --- a/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java +++ b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java @@ -10,6 +10,7 @@ import forge.Graphics; import forge.assets.FImage; import forge.assets.FSkinColor; import forge.assets.FSkinFont; +import forge.assets.ImageCache; import forge.card.CardFaceSymbols; import forge.card.CardRenderer; import forge.card.ColorSet; @@ -76,6 +77,8 @@ public class ConquestCommandersScreen extends FScreen { public void handleEvent(FEvent e) { final ConquestCommander commander = lstCommanders.getSelectedItem(); if (commander != null) { + /*preload deck to cache*/ + ImageCache.preloadCache(commander.getDeck()); preventRefreshOnActivate = true; //refresh not needed since deck changes won't affect commander display Forge.openScreen(new ConquestDeckEditor(commander)); } diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java b/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java index 5e2a0bc3344..902bd7eafe7 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.utils.Align; import forge.FThreads; import forge.Forge; import forge.assets.FSkinFont; +import forge.assets.ImageCache; import forge.deck.DeckProxy; import forge.deck.DeckgenUtil; import forge.deck.FDeckChooser; @@ -152,6 +153,9 @@ public class QuestDecksScreen extends FScreen { final DeckProxy deck = lstDecks.getSelectedItem(); if (deck == null) { return; } + /*preload deck to cache*/ + ImageCache.preloadCache(deck.getDeck()); + needRefreshOnActivate = true; Forge.openScreen(new QuestDeckEditor(deck)); } diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java b/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java index 63e6aabc669..f267bf2fc80 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java @@ -106,6 +106,10 @@ public class QuestPrefsScreen extends FScreen { scroller.add(new PrefsOption(localizer.getMessage("lblColorBias"), QPref.STARTING_POOL_COLOR_BIAS, PrefsGroup.DIFFICULTY_ALL)); scroller.add(new PrefsOption(localizer.getMessage("lblPenaltyforLoss"), QPref.PENALTY_LOSS, PrefsGroup.DIFFICULTY_ALL)); + //wild opponents addon + scroller.add(new PrefsOption(localizer.getMessage("lblWildOpponentMultiplier"), QPref.WILD_OPPONENTS_MULTIPLIER, PrefsGroup.DIFFICULTY_ALL)); + scroller.add(new PrefsOption(localizer.getMessage("lblWildOpponentNumber"), QPref.WILD_OPPONENTS_NUMBER, PrefsGroup.DIFFICULTY_ALL)); + //Difficulty Adjustments (Easy) scroller.add(new PrefsHeader(localizer.getMessage("lblDifficultyAdjustmentsEasy"), FSkinImage.QUEST_NOTES, PrefsGroup.DIFFICULTY_EASY)); scroller.add(new PrefsOption(localizer.getMessage("lblWinsForBooster"), QPref.WINS_BOOSTER_EASY, PrefsGroup.DIFFICULTY_EASY)); diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java b/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java index c1e22b1aab5..b7a4f02e5fc 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java @@ -9,6 +9,7 @@ import forge.GuiBase; import forge.assets.FSkinColor; import forge.assets.FSkinFont; import forge.assets.FSkinImage; +import forge.assets.ImageCache; import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckGroup; @@ -25,6 +26,7 @@ import forge.quest.QuestEventDraft; import forge.quest.QuestTournamentController; import forge.quest.QuestDraftUtils.Mode; import forge.quest.data.QuestEventDraftContainer; +import forge.screens.LoadingOverlay; import forge.screens.limited.DraftingProcessScreen; import forge.toolbox.FButton; import forge.toolbox.FContainer; @@ -227,7 +229,17 @@ public class QuestTournamentsScreen extends QuestLaunchScreen implements IQuestT @Override public void startDraft(BoosterDraft draft) { - Forge.openScreen(new DraftingProcessScreen(draft, EditorType.QuestDraft, controller)); + FThreads.invokeInEdtLater(new Runnable() { + @Override + public void run() { + LoadingOverlay.show("Loading Quest Tournament", new Runnable() { + @Override + public void run() { + Forge.openScreen(new DraftingProcessScreen(draft, EditorType.QuestDraft, controller)); + } + }); + } + }); } private Deck getDeck() { @@ -241,6 +253,8 @@ public class QuestTournamentsScreen extends QuestLaunchScreen implements IQuestT public void editDeck(boolean isExistingDeck) { Deck deck = getDeck(); if (deck != null) { + /*preload deck to cache*/ + ImageCache.preloadCache(deck); if (isExistingDeck) { Forge.openScreen(new QuestDraftDeckEditor(deck.getName())); } diff --git a/forge-gui-mobile/src/forge/toolbox/FButton.java b/forge-gui-mobile/src/forge/toolbox/FButton.java index 33b64b7b4fc..ac07cfe6e43 100644 --- a/forge-gui-mobile/src/forge/toolbox/FButton.java +++ b/forge-gui-mobile/src/forge/toolbox/FButton.java @@ -60,6 +60,9 @@ public class FButton extends FDisplayObject implements IButton { } private void resetImg() { + imgL = FSkinImage.BTN_UP_LEFT; + imgM = FSkinImage.BTN_UP_CENTER; + imgR = FSkinImage.BTN_UP_RIGHT; if (hdbuttonskin()) { imgL = FSkinImage.HDBTN_UP_LEFT; @@ -95,6 +98,9 @@ public class FButton extends FDisplayObject implements IButton { resetImg(); } else { + imgL = FSkinImage.BTN_DISABLED_LEFT; + imgM = FSkinImage.BTN_DISABLED_CENTER; + imgR = FSkinImage.BTN_DISABLED_RIGHT; if (hdbuttonskin()) { imgL = FSkinImage.HDBTN_DISABLED_LEFT; @@ -108,9 +114,9 @@ public class FButton extends FDisplayObject implements IButton { } } - /** + /** * Button toggle state, for a "permanently pressed" functionality, e.g. as a tab. - * + * * @return boolean */ public boolean isToggled() { @@ -121,6 +127,9 @@ public class FButton extends FDisplayObject implements IButton { toggled = b0; if (toggled) { + imgL = FSkinImage.BTN_TOGGLE_LEFT; + imgM = FSkinImage.BTN_TOGGLE_CENTER; + imgR = FSkinImage.BTN_TOGGLE_RIGHT; if (hdbuttonskin()) { imgL = FSkinImage.HDBTN_TOGGLE_LEFT; @@ -136,6 +145,9 @@ public class FButton extends FDisplayObject implements IButton { resetImg(); } else { + imgL = FSkinImage.BTN_DISABLED_LEFT; + imgM = FSkinImage.BTN_DISABLED_CENTER; + imgR = FSkinImage.BTN_DISABLED_RIGHT; if (hdbuttonskin()) { imgL = FSkinImage.HDBTN_DISABLED_LEFT; @@ -170,6 +182,9 @@ public class FButton extends FDisplayObject implements IButton { @Override public final boolean press(float x, float y) { if (isToggled()) { return true; } + imgL = FSkinImage.BTN_DOWN_LEFT; + imgM = FSkinImage.BTN_DOWN_CENTER; + imgR = FSkinImage.BTN_DOWN_RIGHT; if (hdbuttonskin()) { @@ -227,51 +242,51 @@ public class FButton extends FDisplayObject implements IButton { else { //determine images to draw and text alignment based on which corner button is in (if any) switch (corner) { - case None: - if (w > 2 * h) { - g.drawImage(imgL, 0, 0, h, h); - g.drawImage(imgM, h, 0, w - (2 * h), h); - g.drawImage(imgR, w - h, 0, h, h); - } - else { - g.drawImage(imgL, 0, 0, cornerButtonWidth, h); - g.drawImage(imgR, cornerButtonWidth, 0, w - cornerButtonWidth, h); - } - x += PADDING; - w -= 2 * PADDING; - break; - case BottomLeft: - g.startClip(x, y, w, h); - g.drawImage(imgM, 0, 0, cornerButtonWidth, cornerButtonHeight); - g.drawImage(imgR, cornerButtonWidth, 0, cornerButtonWidth, cornerButtonHeight); - g.endClip(); - w -= cornerTextOffsetX; - y += cornerTextOffsetY; - h -= cornerTextOffsetY; - break; - case BottomRight: - g.startClip(x, y, w, h); - g.drawImage(imgL, 0, 0, cornerButtonWidth, cornerButtonHeight); - g.drawImage(imgM, cornerButtonWidth, 0, cornerButtonWidth, cornerButtonHeight); - g.endClip(); - x += cornerTextOffsetX; - w -= cornerTextOffsetX; - y += cornerTextOffsetY; - h -= cornerTextOffsetY; - break; - case BottomMiddle: - g.startClip(x, y, w, h); - cornerButtonWidth = w / 3; - cornerTextOffsetX = cornerButtonWidth / 2; - g.drawImage(imgL, 0, 0, cornerButtonWidth, cornerButtonHeight); - g.drawImage(imgM, cornerButtonWidth, 0, w - 2 * cornerButtonWidth, cornerButtonHeight); - g.drawImage(imgR, w - cornerButtonWidth, 0, cornerButtonWidth, cornerButtonHeight); - g.endClip(); - x += cornerTextOffsetX / 2; - w -= cornerTextOffsetX; - y += cornerTextOffsetY; - h -= cornerTextOffsetY; - break; + case None: + if (w > 2 * h) { + g.drawImage(imgL, 0, 0, h, h); + g.drawImage(imgM, h, 0, w - (2 * h), h); + g.drawImage(imgR, w - h, 0, h, h); + } + else { + g.drawImage(imgL, 0, 0, cornerButtonWidth, h); + g.drawImage(imgR, cornerButtonWidth, 0, w - cornerButtonWidth, h); + } + x += PADDING; + w -= 2 * PADDING; + break; + case BottomLeft: + g.startClip(x, y, w, h); + g.drawImage(imgM, 0, 0, cornerButtonWidth, cornerButtonHeight); + g.drawImage(imgR, cornerButtonWidth, 0, cornerButtonWidth, cornerButtonHeight); + g.endClip(); + w -= cornerTextOffsetX; + y += cornerTextOffsetY; + h -= cornerTextOffsetY; + break; + case BottomRight: + g.startClip(x, y, w, h); + g.drawImage(imgL, 0, 0, cornerButtonWidth, cornerButtonHeight); + g.drawImage(imgM, cornerButtonWidth, 0, cornerButtonWidth, cornerButtonHeight); + g.endClip(); + x += cornerTextOffsetX; + w -= cornerTextOffsetX; + y += cornerTextOffsetY; + h -= cornerTextOffsetY; + break; + case BottomMiddle: + g.startClip(x, y, w, h); + cornerButtonWidth = w / 3; + cornerTextOffsetX = cornerButtonWidth / 2; + g.drawImage(imgL, 0, 0, cornerButtonWidth, cornerButtonHeight); + g.drawImage(imgM, cornerButtonWidth, 0, w - 2 * cornerButtonWidth, cornerButtonHeight); + g.drawImage(imgR, w - cornerButtonWidth, 0, cornerButtonWidth, cornerButtonHeight); + g.endClip(); + x += cornerTextOffsetX / 2; + w -= cornerTextOffsetX; + y += cornerTextOffsetY; + h -= cornerTextOffsetY; + break; } } @@ -297,9 +312,9 @@ public class FButton extends FDisplayObject implements IButton { @Override public boolean keyDown(int keyCode) { switch (keyCode) { - case Keys.ENTER: - case Keys.SPACE: - return trigger(); //trigger button on Enter or Space + case Keys.ENTER: + case Keys.SPACE: + return trigger(); //trigger button on Enter or Space } return false; } @@ -333,4 +348,4 @@ public class FButton extends FDisplayObject implements IButton { public FSkinColor getForeColor() { return foreColor; } -} +} \ No newline at end of file diff --git a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java index 770736b177e..96e19487634 100644 --- a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java +++ b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java @@ -367,6 +367,24 @@ public class FChoiceList extends FList implements ActivateHandler { g.drawText(getChoiceText(value), font, foreColor, x, y, w, h, false, Align.center, true); } } + //simple check for cardview needed on some special renderer for cards + private boolean showAlternate(CardView cardView, String value){ + boolean showAlt = false; + if(cardView.hasAlternateState()){ + if(cardView.hasBackSide()) + showAlt = value.contains(cardView.getBackSideName()); + else if (cardView.isAdventureCard()) + showAlt = value.equals(cardView.getAlternateState().getAbilityText()); + else if (cardView.isSplitCard()) { + //special case if aftermath cards can be cast from graveyard like yawgmoths will, you will have choices + if (cardView.getAlternateState().getOracleText().contains("Aftermath")) + showAlt = cardView.getAlternateState().getOracleText().contains(value); + else + showAlt = value.equals(cardView.getAlternateState().getAbilityText()); + } + } + return showAlt; + } //special renderer for cards protected class PaperCardItemRenderer extends ItemRenderer { @Override @@ -464,7 +482,8 @@ public class FChoiceList extends FList implements ActivateHandler { @Override public boolean tap(Integer index, T value, float x, float y, int count) { if (x <= VStack.CARD_WIDTH + 2 * FList.PADDING) { - CardZoom.show(((IHasCardView)value).getCardView()); + CardView cv = ((IHasCardView)value).getCardView(); + CardZoom.show(cv, showAlternate(cv, value.toString())); return true; } return false; @@ -472,13 +491,16 @@ public class FChoiceList extends FList implements ActivateHandler { @Override public boolean longPress(Integer index, T value, float x, float y) { - CardZoom.show(((IHasCardView)value).getCardView()); + CardView cv = ((IHasCardView)value).getCardView(); + CardZoom.show(cv, showAlternate(cv, value.toString())); return true; } @Override public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) { - CardRenderer.drawCardWithOverlays(g, ((IHasCardView)value).getCardView(), x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top); + CardView cv = ((IHasCardView)value).getCardView(); + boolean showAlternate = showAlternate(cv, value.toString()); + CardRenderer.drawCardWithOverlays(g, cv, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate); float dx = VStack.CARD_WIDTH + FList.PADDING; x += dx; diff --git a/forge-gui/release-files/CONTRIBUTORS.txt b/forge-gui/release-files/CONTRIBUTORS.txt index adb1d4d40a5..30e87a2f66c 100644 --- a/forge-gui/release-files/CONTRIBUTORS.txt +++ b/forge-gui/release-files/CONTRIBUTORS.txt @@ -1,12 +1,14 @@ Agetian apantel Austinio7116 +CCTV-1 Churrufli DrDev Elwin excessum Flair Gos +guytrash Hanmac Indigo Dragon Jamin Collins @@ -16,7 +18,9 @@ KrazyTheFox leriomaggio Luke Marek14 +Marvel mcrawford620 +medusa Meerkov Myrd nefigah @@ -28,8 +32,11 @@ Seravy Sirspud Sloth slyfox7777777 +Snoops Sol +squee1968 Swordshine +Svaldan tjtillman tojammot torridus diff --git a/forge-gui/res/blockdata/printsheets.txt b/forge-gui/res/blockdata/printsheets.txt index 65bea9ea298..29e25bd4641 100644 --- a/forge-gui/res/blockdata/printsheets.txt +++ b/forge-gui/res/blockdata/printsheets.txt @@ -6130,3 +6130,41 @@ Bloodchief's Thirst|ZNR|2 Roil Eruption|ZNR|2 Roiling Regrowth|ZNR|2 Kargan Warleader|ZNR|2 + +[ZNRModalDoubleFaceCards] +1 Agadeem's Awakening|ZNR +1 Emeria's Call|ZNR +1 Sea Gate Restoration|ZNR +1 Shatterskull Smashing|ZNR +1 Turntimber Symbiosis|ZNR +2 Branchloft Pathway|ZNR +2 Brightclimb Pathway|ZNR +2 Clearwater Pathway|ZNR +2 Cragcrown Pathway|ZNR +2 Glasspool Mimic|ZNR +2 Hagra Mauling|ZNR +2 Kazandu Mammoth|ZNR +2 Needleverge Pathway|ZNR +2 Ondu Inversion|ZNR +2 Riverglide Pathway|ZNR +2 Valakut Awakening|ZNR +6 Akoum Warrior|ZNR +6 Bala Ged Recovery|ZNR +6 Beyeen Veil|ZNR +6 Blackbloom Rogue|ZNR +6 Jwari Disruption|ZNR +6 Kabira Takedown|ZNR +6 Kazuul's Fury|ZNR +6 Khalni Ambush|ZNR +6 Makindi Stampede|ZNR +6 Malakir Rebirth|ZNR +6 Pelakka Predation|ZNR +6 Sejiri Shelter|ZNR +6 Silundi Vision|ZNR +6 Skyclave Cleric|ZNR +6 Song-Mad Treachery|ZNR +6 Spikefield Hazard|ZNR +6 Tangled Florahedron|ZNR +6 Umara Wizard|ZNR +6 Vastwood Fortification|ZNR +6 Zof Consumption|ZNR diff --git a/forge-gui/res/cardsfolder/a/admirals_order.txt b/forge-gui/res/cardsfolder/a/admirals_order.txt index 7e1902f6f16..6b173b78066 100644 --- a/forge-gui/res/cardsfolder/a/admirals_order.txt +++ b/forge-gui/res/cardsfolder/a/admirals_order.txt @@ -1,7 +1,7 @@ Name:Admiral's Order ManaCost:1 U U Types:Instant +SVar:AltCost:Cost$ U | CheckSVar$ X | References$ X | Description$ Raid — If you attacked this turn, you may pay {U} rather than pay this spell's mana cost. A:SP$ Counter | Cost$ 1 U U | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | SpellDescription$ Counter target spell. -A:SP$ Counter | Cost$ U | CheckSVar$ X | References$ X | SVarCompare$ GE1 | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | SpellDescription$ Raid — If you attacked this turn, you may pay {U} rather than pay this spell's mana cost. Counter target spell. SVar:X:Count$AttackersDeclared Oracle:Raid — If you attacked this turn, you may pay {U} rather than pay this spell's mana cost.\nCounter target spell. diff --git a/forge-gui/res/cardsfolder/a/aegis_of_honor.txt b/forge-gui/res/cardsfolder/a/aegis_of_honor.txt index a2f719e5910..a8cb6cdc25b 100644 --- a/forge-gui/res/cardsfolder/a/aegis_of_honor.txt +++ b/forge-gui/res/cardsfolder/a/aegis_of_honor.txt @@ -2,9 +2,8 @@ Name:Aegis of Honor ManaCost:W Types:Enchantment A:AB$ Effect | Cost$ 1 | ReplacementEffects$ SelflessDamage | SVars$ SelflessDmg,ExileEffect | References$ SelflessDamage,SelflessDmg,ExileEffect | AILogic$ RedirectSpellDamageFromPlayer | Stackable$ False | SpellDescription$ The next time an instant or sorcery spell would deal damage to you this turn, that spell deals that damage to its controller instead. -SVar:SelflessDamage:Event$ DamageDone | ValidTarget$ You | ValidSource$ Instant,Sorcery | ReplaceWith$ SelflessDmg | Description$ The next time a source of your choice would deal damage this turn, that damage is dealt to that source's controller instead. +SVar:SelflessDamage:Event$ DamageDone | ValidTarget$ You | ValidSource$ Instant,Sorcery | ReplaceWith$ SelflessDmg | DamageTarget$ ReplacedSourceController | Description$ The next time a source of your choice would deal damage this turn, that damage is dealt to that source's controller instead. SVar:SelflessDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ ReplacedSourceController | VarType$ Player | SubAbility$ ExileEffect SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile SVar:NonStackingEffect:True -SVar:Picture:http://www.wizards.com/global/images/magic/general/aegis_of_honor.jpg Oracle:{1}: The next time an instant or sorcery spell would deal damage to you this turn, that spell deals that damage to its controller instead. diff --git a/forge-gui/res/cardsfolder/a/allosaurus_rider.txt b/forge-gui/res/cardsfolder/a/allosaurus_rider.txt index b7362115849..6eccb310d0e 100644 --- a/forge-gui/res/cardsfolder/a/allosaurus_rider.txt +++ b/forge-gui/res/cardsfolder/a/allosaurus_rider.txt @@ -4,6 +4,5 @@ Types:Creature Elf Warrior PT:1+*/1+* S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | SetToughness$ X | Description$ CARDNAME's power and toughness are each equal to 1 plus the number of lands you control. SVar:X:Count$Valid Land.YouCtrl/Plus.1 -SVar:AltCost:Cost$ ExileFromHand<2/Card.Green> | Description$ You may exile two green cards from your hand rather than pay CARDNAME's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/allosaurus_rider.jpg +SVar:AltCost:Cost$ ExileFromHand<2/Card.Green> | Description$ You may exile two green cards from your hand rather than pay this spell's mana cost. Oracle:You may exile two green cards from your hand rather than pay this spell's mana cost.\nAllosaurus Rider's power and toughness are each equal to 1 plus the number of lands you control. diff --git a/forge-gui/res/cardsfolder/a/angelic_favor.txt b/forge-gui/res/cardsfolder/a/angelic_favor.txt index 40f5bfbbc9b..0546c850950 100644 --- a/forge-gui/res/cardsfolder/a/angelic_favor.txt +++ b/forge-gui/res/cardsfolder/a/angelic_favor.txt @@ -1,9 +1,8 @@ Name:Angelic Favor ManaCost:3 W Types:Instant -A:SP$ Token | Cost$ 3 W | TokenScript$ w_4_4_angel_flying | LegacyImage$ w 4 4 angel flying nms | AtEOT$ Exile | ActivationPhases$ BeginCombat->EndCombat | SpellDescription$ Cast CARDNAME only during combat. Create a 4/4 white Angel creature token with flying. Exile it at the beginning of the next end step. -SVar:AltCost:Cost$ tapXType<1/Creature> | IsPresent$ Plains.YouCtrl | Description$ If you control a Plains, you may tap an untapped creature you control rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ tapXType<1/Creature> | IsPresent$ Plains.YouCtrl | Description$ If you control a Plains, you may tap an untapped creature you control rather than pay this spell's mana cost. +A:SP$ Token | Cost$ 3 W | TokenScript$ w_4_4_angel_flying | AtEOT$ Exile | ActivationPhases$ BeginCombat->EndCombat | StackDescription$ {p:You} creates a 4/4 white Angel creature token with flying. Exile it at the beginning of the next end step. | SpellDescription$ Cast this spell only during combat. Create a 4/4 white Angel creature token with flying. Exile it at the beginning of the next end step. DeckHas:Ability$Token AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/angelic_favor.jpg Oracle:If you control a Plains, you may tap an untapped creature you control rather than pay this spell's mana cost.\nCast this spell only during combat.\nCreate a 4/4 white Angel creature token with flying. Exile it at the beginning of the next end step. diff --git a/forge-gui/res/cardsfolder/a/archive_trap.txt b/forge-gui/res/cardsfolder/a/archive_trap.txt index c29ccf1c104..7f848d39d51 100644 --- a/forge-gui/res/cardsfolder/a/archive_trap.txt +++ b/forge-gui/res/cardsfolder/a/archive_trap.txt @@ -1,7 +1,7 @@ Name:Archive Trap ManaCost:3 U U Types:Instant Trap +SVar:AltCost:Cost$ 0 | CheckSVar$ TrapTrigger | References$ TrapTrigger | Description$ If an opponent searched their library this turn, you may pay {0} rather than pay this spell's mana cost. A:SP$ Mill | Cost$ 3 U U | NumCards$ 13 | ValidTgts$ Opponent | TgtPrompt$ Choose an opponent | SpellDescription$ Target opponent mills thirteen cards. -A:SP$ Mill | Cost$ 0 | CheckSVar$ TrapTrigger | NumCards$ 13 | ValidTgts$ Opponent | TgtPrompt$ Choose an opponent | CostDesc$ If an opponent searched their library this turn, you may pay {0} rather than pay CARDNAME's mana cost. | References$ TrapTrigger | SpellDescription$ SVar:TrapTrigger:Count$SearchedLibrary.Opponent Oracle:If an opponent searched their library this turn, you may pay {0} rather than pay this spell's mana cost.\nTarget opponent mills thirteen cards. diff --git a/forge-gui/res/cardsfolder/a/arrow_volley_trap.txt b/forge-gui/res/cardsfolder/a/arrow_volley_trap.txt index 0708984f932..8408d7cd746 100644 --- a/forge-gui/res/cardsfolder/a/arrow_volley_trap.txt +++ b/forge-gui/res/cardsfolder/a/arrow_volley_trap.txt @@ -1,7 +1,6 @@ Name:Arrow Volley Trap ManaCost:3 W W Types:Instant Trap +SVar:AltCost:Cost$ 1 W | IsPresent$ Creature.attacking | PresentCompare$ GE4 | Description$ If four or more creatures are attacking, you may pay {1}{W} rather than pay this spell's mana cost. A:SP$ DealDamage | Cost$ 3 W W | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature to distribute damage to | NumDmg$ 5 | TargetMin$ 1 | TargetMax$ 5 | DividedAsYouChoose$ 5 | SpellDescription$ CARDNAME deals 5 damage divided as you choose among any number of target attacking creatures. -A:SP$ DealDamage | Cost$ 1 W | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature to distribute damage to | NumDmg$ 5 | TargetMin$ 1 | TargetMax$ 5 | DividedAsYouChoose$ 5 | IsPresent$ Creature.attacking | PresentCompare$ GE4 | CostDesc$ If four or more creatures are attacking, you may pay {1}{W} rather than pay CARDNAME's mana cost. | SpellDescription$ -SVar:Picture:http://www.wizards.com/global/images/magic/general/arrow_volley_trap.jpg Oracle:If four or more creatures are attacking, you may pay {1}{W} rather than pay this spell's mana cost.\nArrow Volley Trap deals 5 damage divided as you choose among any number of target attacking creatures. diff --git a/forge-gui/res/cardsfolder/b/baloth_cage_trap.txt b/forge-gui/res/cardsfolder/b/baloth_cage_trap.txt index f27a9775f00..63ff090ea05 100644 --- a/forge-gui/res/cardsfolder/b/baloth_cage_trap.txt +++ b/forge-gui/res/cardsfolder/b/baloth_cage_trap.txt @@ -1,8 +1,7 @@ Name:Baloth Cage Trap ManaCost:3 G G Types:Instant Trap -A:SP$ Token | Cost$ 3 G G | TokenAmount$ 1 | TokenScript$ g_4_4_beast | TokenOwner$ You | LegacyImage$ g 4 4 beast zen | SpellDescription$ Create a 4/4 green Beast creature token. -A:SP$ Token | Cost$ 1 G | CheckSVar$ ArtifactsEntered | TokenAmount$ 1 | TokenScript$ g_4_4_beast | TokenOwner$ You | LegacyImage$ g 4 4 beast zen | SpellDescription$ If an opponent had an artifact enter the battlefield under their control this turn, you may pay {1}{G} rather than pay Baloth Cage Trap's mana cost. +SVar:AltCost:Cost$ 1 G | CheckSVar$ ArtifactsEntered | References$ ArtifactsEntered | Description$ If an opponent had an artifact enter the battlefield under their control this turn, you may pay {1}{G} rather than pay this spell's mana cost. +A:SP$ Token | Cost$ 3 G G | TokenAmount$ 1 | TokenScript$ g_4_4_beast | TokenOwner$ You | StackDescription$ {p:You} creates a 4/4 green Beast creature token. | SpellDescription$ Create a 4/4 green Beast creature token. SVar:ArtifactsEntered:Count$ThisTurnEntered_Battlefield_Artifact.OppCtrl -SVar:Picture:http://www.wizards.com/global/images/magic/general/baloth_cage_trap.jpg -Oracle:If an opponent had an artifact enter the battlefield under their control this turn, you may pay {1}{G} rather than pay Baloth Cage Trap's mana cost.\nCreate a 4/4 green Beast creature token. +Oracle:If an opponent had an artifact enter the battlefield under their control this turn, you may pay {1}{G} rather than pay this spell's mana cost.\nCreate a 4/4 green Beast creature token. diff --git a/forge-gui/res/cardsfolder/b/baloth_packhunter.txt b/forge-gui/res/cardsfolder/b/baloth_packhunter.txt new file mode 100644 index 00000000000..31756cd9b75 --- /dev/null +++ b/forge-gui/res/cardsfolder/b/baloth_packhunter.txt @@ -0,0 +1,10 @@ +Name:Baloth Packhunter +ManaCost:3 G +Types:Creature Beast +PT:3/3 +K:Trample +T:Mode$ ChangesZone | ValidCard$ Card.Self | Destination$ Battlefield | Execute$ TrigPutCounters | TriggerDescription$ When CARDNAME enters the battlefield, put two +1/+1 counters on each other creature you control named Baloth Packhunter. +SVar:TrigPutCounters:DB$ PutCounterAll | ValidCards$ Creature.Other+namedBaloth Packhunter | CounterType$ P1P1 | CounterNum$ 2 +DeckHints:Name$CARDNAME +DeckHas:Ability$Counters +Oracle:Trample\nWhen Baloth Packhunter enters the battlefield, put two +1/+1 counters on each other creature you control named Baloth Packhunter. diff --git a/forge-gui/res/cardsfolder/b/blazing_shoal.txt b/forge-gui/res/cardsfolder/b/blazing_shoal.txt index 1f6604f167f..edeccc760a5 100644 --- a/forge-gui/res/cardsfolder/b/blazing_shoal.txt +++ b/forge-gui/res/cardsfolder/b/blazing_shoal.txt @@ -1,10 +1,10 @@ Name:Blazing Shoal ManaCost:X R R Types:Instant Arcane -A:SP$ Pump | Cost$ X R R | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +X | References$ X | SpellDescription$ Target creature gets +X/+0 until end of turn. -A:SP$ Pump | Cost$ ExileFromHand<1/Card.Red> | CostDesc$ You may exile a red card from your hand rather than pay Blazing Shoal's mana cost. | ValidTgts$ Creature | NumAtt$ +Y | References$ Y | SpellDescription$ Target creature gets +X/+0 until end of turn, where X is the exiled card's converted mana cost. +SVar:AltCost:Cost$ ExileFromHand<1/Card.Red+Other/red card> | Description$ You may exile a red card with converted mana cost X from your hand rather than pay this spell's mana cost. +A:SP$ Pump | Cost$ X R R | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +Z | References$ X,Y,Z | SpellDescription$ Target creature gets +X/+0 until end of turn. SVar:X:Count$xPaid SVar:Y:Exiled$CardManaCost +SVar:Z:SVar$Y/Plus.X AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/blazing_shoal.jpg Oracle:You may exile a red card with converted mana cost X from your hand rather than pay this spell's mana cost.\nTarget creature gets +X/+0 until end of turn. diff --git a/forge-gui/res/cardsfolder/b/blood_of_the_martyr.txt b/forge-gui/res/cardsfolder/b/blood_of_the_martyr.txt index 6d6aca31e4e..3ea90e4b116 100644 --- a/forge-gui/res/cardsfolder/b/blood_of_the_martyr.txt +++ b/forge-gui/res/cardsfolder/b/blood_of_the_martyr.txt @@ -2,8 +2,7 @@ Name:Blood of the Martyr ManaCost:W W W Types:Instant A:SP$ Effect | Cost$ W W W | Name$ Blood of the Martyr Effect | ReplacementEffects$ MartyrDamage | SVars$ DmgYou | SpellDescription$ Until end of turn, if damage would be dealt to any creature, you may have that damage dealt to you instead. -SVar:Damage:Event$ DamageDone | ValidTarget$ Creature | Optional$ True | OptionalDecider$ You | ReplaceWith$ DmgYou | Description$ Until end of turn, if damage would be dealt to any creature, you may have that damage dealt to you instead. +SVar:Damage:Event$ DamageDone | ValidTarget$ Creature | Optional$ True | OptionalDecider$ You | DamageTarget$ You | ReplaceWith$ DmgYou | Description$ Until end of turn, if damage would be dealt to any creature, you may have that damage dealt to you instead. SVar:DmgYou:DB$ ReplaceEffect | VarName$ Affected | VarValue$ You | VarType$ Player AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/blood_of_the_martyr.jpg Oracle:Until end of turn, if damage would be dealt to any creature, you may have that damage dealt to you instead. diff --git a/forge-gui/res/cardsfolder/b/bounty_of_the_hunt.txt b/forge-gui/res/cardsfolder/b/bounty_of_the_hunt.txt index 18847d2c6eb..b3cf16d50fb 100644 --- a/forge-gui/res/cardsfolder/b/bounty_of_the_hunt.txt +++ b/forge-gui/res/cardsfolder/b/bounty_of_the_hunt.txt @@ -2,8 +2,7 @@ Name:Bounty of the Hunt ManaCost:3 G G Types:Instant A:SP$ PutCounter | Cost$ 3 G G | ValidTgts$ Creature | TgtPrompt$ Select target creature to distribute counters to | CounterType$ P1P1 | CounterNum$ 3 | TargetMin$ 1 | TargetMax$ 3 | DividedAsYouChoose$ 3 | RemovePhase$ Cleanup | SpellDescription$ Distribute three +1/+1 counters among one, two, or three target creatures. For each +1/+1 counter you put on a creature this way, remove a +1/+1 counter from that creature at the beginning of the next cleanup step. -SVar:AltCost:Cost$ExileFromHand<1/Card.Green> | Description$ You may exile a green card from your hand rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ExileFromHand<1/Card.Green+Other> | Description$ You may exile a green card from your hand rather than pay this spell's mana cost. DeckHas:Ability$Counters AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/bounty_of_the_hunt.jpg Oracle:You may exile a green card from your hand rather than pay this spell's mana cost.\nDistribute three +1/+1 counters among one, two, or three target creatures. For each +1/+1 counter you put on a creature this way, remove a +1/+1 counter from that creature at the beginning of the next cleanup step. diff --git a/forge-gui/res/cardsfolder/b/bringer_of_the_black_dawn.txt b/forge-gui/res/cardsfolder/b/bringer_of_the_black_dawn.txt index c4541358baa..a5c0e370c24 100644 --- a/forge-gui/res/cardsfolder/b/bringer_of_the_black_dawn.txt +++ b/forge-gui/res/cardsfolder/b/bringer_of_the_black_dawn.txt @@ -3,9 +3,8 @@ ManaCost:7 B B Types:Creature Bringer PT:5/5 K:Trample -SVar:AltCost:Cost$ W U B R G | Description$ You may pay {W}{U}{B}{R}{G} rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ W U B R G | Description$ You may pay {W}{U}{B}{R}{G} rather than pay this spell's mana cost. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigChange | TriggerDescription$ At the beginning of your upkeep, you may pay 2 life. If you do, search your library for a card, then shuffle your library and put that card on top of it. -SVar:TrigChange:AB$ChangeZone | Cost$ PayLife<2> | Origin$ Library | Destination$ Library | LibraryPosition$ 0 | ChangeType$ Card | ChangeNum$ 1 +SVar:TrigChange:AB$ ChangeZone | Cost$ PayLife<2> | Origin$ Library | Destination$ Library | LibraryPosition$ 0 | ChangeType$ Card | ChangeNum$ 1 AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/bringer_of_the_black_dawn.jpg Oracle:You may pay {W}{U}{B}{R}{G} rather than pay this spell's mana cost.\nTrample\nAt the beginning of your upkeep, you may pay 2 life. If you do, search your library for a card, then shuffle your library and put that card on top of it. diff --git a/forge-gui/res/cardsfolder/b/bringer_of_the_blue_dawn.txt b/forge-gui/res/cardsfolder/b/bringer_of_the_blue_dawn.txt index d2b9c030063..866c0c1ff90 100644 --- a/forge-gui/res/cardsfolder/b/bringer_of_the_blue_dawn.txt +++ b/forge-gui/res/cardsfolder/b/bringer_of_the_blue_dawn.txt @@ -3,8 +3,7 @@ ManaCost:7 U U Types:Creature Bringer PT:5/5 K:Trample +SVar:AltCost:Cost$ W U B R G | Description$ You may pay {W}{U}{B}{R}{G} rather than pay this spell's mana cost. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigDraw | TriggerDescription$ At the beginning of your upkeep, you may draw two cards. -SVar:TrigDraw:DB$Draw | Defined$ You | NumCards$ 2 -SVar:AltCost:Cost$ W U B R G | Description$ You may pay {W}{U}{B}{R}{G} rather than pay CARDNAME's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/bringer_of_the_blue_dawn.jpg +SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 2 Oracle:You may pay {W}{U}{B}{R}{G} rather than pay this spell's mana cost.\nTrample\nAt the beginning of your upkeep, you may draw two cards. diff --git a/forge-gui/res/cardsfolder/b/bringer_of_the_green_dawn.txt b/forge-gui/res/cardsfolder/b/bringer_of_the_green_dawn.txt index beab47e2fa6..9b7a4e3eefa 100644 --- a/forge-gui/res/cardsfolder/b/bringer_of_the_green_dawn.txt +++ b/forge-gui/res/cardsfolder/b/bringer_of_the_green_dawn.txt @@ -3,8 +3,8 @@ ManaCost:7 G G Types:Creature Bringer PT:5/5 K:Trample -SVar:AltCost:Cost$ W U B R G | Description$ You may pay {W}{U}{B}{R}{G} rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ W U B R G | Description$ You may pay {W}{U}{B}{R}{G} rather than pay this spell's mana cost. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigToken | TriggerDescription$ At the beginning of your upkeep, you may create a 3/3 green Beast creature token. -SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenScript$ g_3_3_beast | TokenOwner$ You | LegacyImage$ g 3 3 beast 5dn -SVar:Picture:http://www.wizards.com/global/images/magic/general/bringer_of_the_green_dawn.jpg +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ g_3_3_beast | TokenOwner$ You +DeckHas:Ability$Token Oracle:You may pay {W}{U}{B}{R}{G} rather than pay this spell's mana cost.\nTrample\nAt the beginning of your upkeep, you may create a 3/3 green Beast creature token. diff --git a/forge-gui/res/cardsfolder/b/bringer_of_the_red_dawn.txt b/forge-gui/res/cardsfolder/b/bringer_of_the_red_dawn.txt index eb6eb1dee7c..58d2c3e352e 100644 --- a/forge-gui/res/cardsfolder/b/bringer_of_the_red_dawn.txt +++ b/forge-gui/res/cardsfolder/b/bringer_of_the_red_dawn.txt @@ -3,8 +3,7 @@ ManaCost:7 R R Types:Creature Bringer PT:5/5 K:Trample -SVar:AltCost:Cost$ W U B R G | Description$ You may pay {W}{U}{B}{R}{G} rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ W U B R G | Description$ You may pay {W}{U}{B}{R}{G} rather than pay this spell's mana cost. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigChange | TriggerDescription$ At the beginning of your upkeep, you may untap target creature and gain control of it until end of turn. That creature gains haste until end of turn. -SVar:TrigChange:DB$GainControl | ValidTgts$ Creature | TgtPrompt$ Select target creature | LoseControl$ EOT | Untap$ True | AddKWs$ Haste -SVar:Picture:http://www.wizards.com/global/images/magic/general/bringer_of_the_red_dawn.jpg +SVar:TrigChange:DB$ GainControl | ValidTgts$ Creature | TgtPrompt$ Select target creature | LoseControl$ EOT | Untap$ True | AddKWs$ Haste Oracle:You may pay {W}{U}{B}{R}{G} rather than pay this spell's mana cost.\nTrample\nAt the beginning of your upkeep, you may untap target creature and gain control of it until end of turn. That creature gains haste until end of turn. diff --git a/forge-gui/res/cardsfolder/b/bringer_of_the_white_dawn.txt b/forge-gui/res/cardsfolder/b/bringer_of_the_white_dawn.txt index 5efbda3ead6..990a0791894 100644 --- a/forge-gui/res/cardsfolder/b/bringer_of_the_white_dawn.txt +++ b/forge-gui/res/cardsfolder/b/bringer_of_the_white_dawn.txt @@ -3,8 +3,9 @@ ManaCost:7 W W Types:Creature Bringer PT:5/5 K:Trample -SVar:AltCost:Cost$ W U B R G | Description$ You may pay {W}{U}{B}{R}{G} rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ W U B R G | Description$ You may pay {W}{U}{B}{R}{G} rather than pay this spell's mana cost. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigChange | TriggerDescription$ At the beginning of your upkeep, you may return target artifact card from your graveyard to the battlefield. -SVar:TrigChange:AB$ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Artifact.YouCtrl | Cost$ 0 -SVar:Picture:http://www.wizards.com/global/images/magic/general/bringer_of_the_white_dawn.jpg +SVar:TrigChange:AB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Artifact.YouCtrl | Cost$ 0 +DeckHas:Ability$Graveyard +DeckNeeds:Type$Artifact Oracle:You may pay {W}{U}{B}{R}{G} rather than pay this spell's mana cost.\nTrample\nAt the beginning of your upkeep, you may return target artifact card from your graveyard to the battlefield. diff --git a/forge-gui/res/cardsfolder/b/burn_at_the_stake.txt b/forge-gui/res/cardsfolder/b/burn_at_the_stake.txt index efe562375df..12fb105e301 100644 --- a/forge-gui/res/cardsfolder/b/burn_at_the_stake.txt +++ b/forge-gui/res/cardsfolder/b/burn_at_the_stake.txt @@ -1,9 +1,8 @@ Name:Burn at the Stake ManaCost:2 R R R Types:Sorcery -A:SP$ DealDamage | Cost$ 2 R R R tapXType | CostDesc$ As an additional cost to cast CARDNAME, tap any number of untapped creatures you control. | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ BurnAtTheStakeDmg | References$ X,BurnAtTheStakeDmg | SpellDescription$ CARDNAME deals damage to any target equal to three times the number of creatures tapped this way. +A:SP$ DealDamage | Cost$ 2 R R R tapXType | CostDesc$ As an additional cost to cast this spell, tap any number of untapped creatures you control. | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ BurnAtTheStakeDmg | References$ X,BurnAtTheStakeDmg | SpellDescription$ CARDNAME deals damage to any target equal to three times the number of creatures tapped this way. SVar:X:XChoice SVar:BurnAtTheStakeDmg:Number$3/Times.ChosenX AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/burn_at_the_stake.jpg Oracle:As an additional cost to cast this spell, tap any number of untapped creatures you control.\nBurn at the Stake deals damage to any target equal to three times the number of creatures tapped this way. diff --git a/forge-gui/res/cardsfolder/b/burning_wish.txt b/forge-gui/res/cardsfolder/b/burning_wish.txt index a6fe901792b..385441aebf9 100644 --- a/forge-gui/res/cardsfolder/b/burning_wish.txt +++ b/forge-gui/res/cardsfolder/b/burning_wish.txt @@ -1,8 +1,7 @@ Name:Burning Wish ManaCost:1 R Types:Sorcery -A:SP$ ChangeZone | Cost$ 1 R | Origin$ Sideboard | Destination$ Hand | ChangeType$ Sorcery.YouOwn | ChangeNum$ 1 | SubAbility$ DBChange | SpellDescription$ You may choose a sorcery card you own from outside the game, reveal that card, and put it into your hand. Exile CARDNAME. +A:SP$ ChangeZone | Cost$ 1 R | Reveal$ True | Origin$ Sideboard | Destination$ Hand | ChangeType$ Sorcery.YouOwn | ChangeTypeDesc$ sorcery card they own | ChangeNum$ 1 | SubAbility$ DBChange | Hidden$ True | SpellDescription$ You may reveal a sorcery card you own from outside the game and put it into your hand. Exile CARDNAME. SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/burning_wish.jpg -Oracle:You may choose a sorcery card you own from outside the game, reveal that card, and put it into your hand. Exile Burning Wish. +Oracle:You may reveal a sorcery card you own from outside the game and put it into your hand. Exile Burning Wish. diff --git a/forge-gui/res/cardsfolder/c/captive_audience.txt b/forge-gui/res/cardsfolder/c/captive_audience.txt index 3890127f79a..c13efac2b57 100644 --- a/forge-gui/res/cardsfolder/c/captive_audience.txt +++ b/forge-gui/res/cardsfolder/c/captive_audience.txt @@ -5,14 +5,11 @@ R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ SVar:DBChooseOpp:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | ChoiceTitle$ Choose an opponent to give control to: | AILogic$ Curse | SubAbility$ MoveToPlay SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard | GainControl$ True | NewController$ ChosenPlayer | SubAbility$ ClearRemembered T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigCharm | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, ABILITY -SVar:TrigCharm:DB$ Charm | Choices$ LifePact,DiscardPact,ZombiesPact | ChoiceRestriction$ NotRemembered | RememberChoice$ True | CharmNum$ 1 -SVar:LifePact:DB$ SetLife | Defined$ You | LifeAmount$ 4 | ChoiceName$ LifePact | SpellDescription$ Your life total becomes 4. -SVar:DiscardPact:DB$ Discard | Defined$ You | Mode$ Hand | ChoiceName$ DiscardPact | SpellDescription$ Discard your hand. -SVar:ZombiesPact:DB$ RepeatEach | RepeatPlayers$ Player.Opponent | RepeatSubAbility$ MakeZombies | ChoiceName$ ZombiesPact | ChangeZoneTable$ True | SpellDescription$ Each opponent creates five 2/2 black Zombie creature tokens. +SVar:TrigCharm:DB$ Charm | Choices$ LifePact,DiscardPact,ZombiesPact | ChoiceRestriction$ ThisGame | CharmNum$ 1 +SVar:LifePact:DB$ SetLife | Defined$ You | LifeAmount$ 4 | SpellDescription$ Your life total becomes 4. +SVar:DiscardPact:DB$ Discard | Defined$ You | Mode$ Hand | SpellDescription$ Discard your hand. +SVar:ZombiesPact:DB$ RepeatEach | RepeatPlayers$ Player.Opponent | RepeatSubAbility$ MakeZombies | ChangeZoneTable$ True | SpellDescription$ Each opponent creates five 2/2 black Zombie creature tokens. SVar:MakeZombies:DB$ Token | LegacyImage$ b 2 2 zombie rna | TokenAmount$ 5 | TokenScript$ b_2_2_zombie | TokenOwner$ Remembered | SpellDescription$ Each opponent creates five 2/2 black Zombie creature tokens. -# Clear RememberChoice just in case it's not getting cleared by Zone changes -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ ClearRemembered | Static$ True -SVar:ClearRemembered:DB$ Cleanup | ClearRemembered$ True | ClearChosenPlayer$ True AI:RemoveDeck:Random DeckHas:Ability$Token Oracle:Captive Audience enters the battlefield under the control of an opponent of your choice.\nAt the beginning of your upkeep, choose one that hasn't been chosen —\n• Your life total becomes 4.\n• Discard your hand.\n• Each opponent creates five 2/2 black Zombie creature tokens. diff --git a/forge-gui/res/cardsfolder/c/cathartic_reunion.txt b/forge-gui/res/cardsfolder/c/cathartic_reunion.txt index 701a869a3d2..b6d41105980 100644 --- a/forge-gui/res/cardsfolder/c/cathartic_reunion.txt +++ b/forge-gui/res/cardsfolder/c/cathartic_reunion.txt @@ -1,8 +1,7 @@ Name:Cathartic Reunion ManaCost:1 R Types:Sorcery -A:SP$ Draw | Cost$ 1 R Discard<2/Card> | CostDesc$ As an additional cost to cast CARDNAME, discard two cards. | NumCards$ 3 | Defined$ You | SpellDescription$ Draw three cards. +A:SP$ Draw | Cost$ 1 R Discard<2/Card/cards> | CostDesc$ As an additional cost to cast this spell, discard two cards. | NumCards$ 3 | Defined$ You | SpellDescription$ Draw three cards. DeckHas:Ability$Discard DeckHints:Keyword$Madness & Ability$Delirium -SVar:Picture:http://www.wizards.com/global/images/magic/general/cathartic_reunion.jpg -Oracle:As an additional cost to cast this spell, discard two cards.\nDraw three cards. \ No newline at end of file +Oracle:As an additional cost to cast this spell, discard two cards.\nDraw three cards. diff --git a/forge-gui/res/cardsfolder/c/cave_in.txt b/forge-gui/res/cardsfolder/c/cave_in.txt index 0950ec2dcec..01ee5b3d454 100644 --- a/forge-gui/res/cardsfolder/c/cave_in.txt +++ b/forge-gui/res/cardsfolder/c/cave_in.txt @@ -1,7 +1,6 @@ Name:Cave-In ManaCost:3 R R Types:Sorcery +SVar:AltCost:Cost$ ExileFromHand<1/Card.Red+Other> | Description$ You may exile a red card from your hand rather than pay this spell's mana cost. A:SP$ DamageAll | Cost$ 3 R R | NumDmg$ 2 | ValidCards$ Creature | ValidPlayers$ Player | ValidDescription$ each creature and each player. | SpellDescription$ CARDNAME deals 2 damage to each creature and each player. -SVar:AltCost:Cost$ ExileFromHand<1/Card.Red> | Description$ You may exile a red card from your hand rather than pay Cave-In's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/cave_in.jpg Oracle:You may exile a red card from your hand rather than pay this spell's mana cost.\nCave-In deals 2 damage to each creature and each player. diff --git a/forge-gui/res/cardsfolder/c/coax_from_the_blind_eternities.txt b/forge-gui/res/cardsfolder/c/coax_from_the_blind_eternities.txt index a624eab00b3..31311802bc4 100644 --- a/forge-gui/res/cardsfolder/c/coax_from_the_blind_eternities.txt +++ b/forge-gui/res/cardsfolder/c/coax_from_the_blind_eternities.txt @@ -1,7 +1,6 @@ Name:Coax from the Blind Eternities ManaCost:2 U Types:Sorcery -A:SP$ ChangeZone | Cost$ 2 U | Origin$ Sideboard,Exile | Destination$ Hand | ChangeType$ Card.Eldrazi+YouOwn | ChangeNum$ 1 | SpellDescription$ You may choose an Eldrazi card you own from outside the game or in exile, reveal that card, and put it into your hand. +A:SP$ ChangeZone | Cost$ 2 U | Origin$ Sideboard,Exile | Destination$ Hand | ChangeType$ Card.Eldrazi+YouOwn | ChangeNum$ 1 | Hidden$ True | Reveal$ True | StackDescription$ {p:You} may reveal an Eldrazi card they own from outside the game or in exile and put it into their hand. | SpellDescription$ You may reveal an Eldrazi card you own from outside the game or in exile and put it into your hand. AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/coax_from_the_blind_eternities.jpg -Oracle:You may choose an Eldrazi card you own from outside the game or in exile, reveal that card, and put it into your hand. \ No newline at end of file +Oracle:You may reveal an Eldrazi card you own from outside the game or in exile and put it into your hand. diff --git a/forge-gui/res/cardsfolder/c/cobra_trap.txt b/forge-gui/res/cardsfolder/c/cobra_trap.txt index c0109cd2a3c..71ca5b4997a 100644 --- a/forge-gui/res/cardsfolder/c/cobra_trap.txt +++ b/forge-gui/res/cardsfolder/c/cobra_trap.txt @@ -2,11 +2,10 @@ Name:Cobra Trap ManaCost:4 G G Types:Instant Trap T:Mode$ Destroyed | ValidCauser$ Player.Opponent | ValidCard$ Permanent.nonCreature+YouCtrl | Execute$ TrackValidDestroy | Static$ True -SVar:TrackValidDestroy:DB$ StoreSVar | SVar$ SetTrap | Type$ CountSVar | Expression$ SetTrap/Plus.1 | References$ SetTrap -T:Mode$ Phase | Phase$ Cleanup | Execute$ TrigReset | Static$ True -SVar:TrigReset:DB$ StoreSVar | SVar$ SetTrap | Type$ Number | Expression$ 0 | References$ SetSVar -SVar:SetTrap:Number$0 -SVar:AltCost:Cost$ G | CheckSVar$ SetTrap | SVarCompare$ GE1 | References$ SetTrap | Description$ If a noncreature permanent under your control was destroyed this turn by a spell or ability an opponent controlled, you may pay {G} rather than pay CARDNAME's mana cost. -A:SP$ Token | Cost$ 4 G G | TokenAmount$ 4 | TokenScript$ g_1_1_snake | TokenOwner$ You | LegacyImage$ g 1 1 snake zen | SpellDescription$ Create four 1/1 green Snake creature tokens. -SVar:Picture:http://www.wizards.com/global/images/magic/general/cobra_trap.jpg +SVar:TrackValidDestroy:DB$ Pump | RememberObjects$ TriggeredCard +T:Mode$ TurnBegin | Execute$ TrigReset | Static$ True +SVar:TrigReset:DB$ Cleanup | ClearRemembered$ True +SVar:SetTrap:Remembered$Amount +SVar:AltCost:Cost$ G | CheckSVar$ SetTrap | References$ SetTrap | Description$ If a noncreature permanent under your control was destroyed this turn by a spell or ability an opponent controlled, you may pay {G} rather than pay this spell's mana cost. +A:SP$ Token | Cost$ 4 G G | TokenAmount$ 4 | TokenScript$ g_1_1_snake | TokenOwner$ You | StackDescription$ {p:You} creates four 1/1 green Snake creature tokens. | SpellDescription$ Create four 1/1 green Snake creature tokens. Oracle:If a noncreature permanent under your control was destroyed this turn by a spell or ability an opponent controlled, you may pay {G} rather than pay this spell's mana cost.\nCreate four 1/1 green Snake creature tokens. diff --git a/forge-gui/res/cardsfolder/c/commandeer.txt b/forge-gui/res/cardsfolder/c/commandeer.txt index 4cf31b27537..d5d0f3f0170 100644 --- a/forge-gui/res/cardsfolder/c/commandeer.txt +++ b/forge-gui/res/cardsfolder/c/commandeer.txt @@ -1,9 +1,8 @@ Name:Commandeer ManaCost:5 U U Types:Instant +SVar:AltCost:Cost$ ExileFromHand<2/Card.Blue+Other> | Description$ You may exile two blue cards from your hand rather than pay this spell's mana cost. A:SP$ ControlSpell | Cost$ 5 U U | ValidTgts$ Card.nonCreature | TargetType$ Spell | Mode$ Gain | SubAbility$ DBChooseTargets | SpellDescription$ Gain control of target noncreature spell. You may choose new targets for it. (If that spell is an artifact, enchantment, or planeswalker, the permanent enters the battlefield under your control.) SVar:DBChooseTargets:DB$ ChangeTargets | Defined$ Targeted | Optional$ True -SVar:AltCost:Cost$ ExileFromHand<2/Card.Blue> | Description$ You may exile two blue cards from your hand rather than pay CARDNAME's mana cost. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/commandeer.jpg Oracle:You may exile two blue cards from your hand rather than pay this spell's mana cost.\nGain control of target noncreature spell. You may choose new targets for it. (If that spell is an artifact, enchantment, or planeswalker, the permanent enters the battlefield under your control.) diff --git a/forge-gui/res/cardsfolder/c/compound_fracture.txt b/forge-gui/res/cardsfolder/c/compound_fracture.txt new file mode 100644 index 00000000000..3231fff209c --- /dev/null +++ b/forge-gui/res/cardsfolder/c/compound_fracture.txt @@ -0,0 +1,7 @@ +Name:Compound Fracture +ManaCost:B +Types:Instant +A:SP$ Pump | Cost$ B | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ -1 | NumDef$ -1 | SubAbility$ DBPump | SpellDescription$ Target creature gets -1/-1 until end of turn. It gets an additional -1/-1 until end of turn for each card named Compound Fracture in your graveyard. +SVar:DBPump:DB$ Pump | Defined$ ParentTarget | NumAtt$ -X | NumDef$ -X | References$ X +SVar:X:Count$ValidGraveyard Card.namedCompound Fracture +Oracle:Target creature gets -1/-1 until end of turn. It gets an additional -1/-1 until end of turn for each card named Compound Fracture in your graveyard. diff --git a/forge-gui/res/cardsfolder/c/contagion.txt b/forge-gui/res/cardsfolder/c/contagion.txt index 53ccfec418c..6fb20dbc41c 100644 --- a/forge-gui/res/cardsfolder/c/contagion.txt +++ b/forge-gui/res/cardsfolder/c/contagion.txt @@ -1,8 +1,7 @@ Name:Contagion ManaCost:3 B B Types:Instant +SVar:AltCost:Cost$ PayLife<1> ExileFromHand<1/Card.Black+Other/black card> | Description$ You may pay 1 life and exile a black card from your hand rather than pay this spell's mana cost. A:SP$ PutCounter | Cost$ 3 B B | ValidTgts$ Creature | TgtPrompt$ Select target creature to distribute counters to | CounterType$ M2M1 | CounterNum$ 2 | TargetMin$ 1 | TargetMax$ 2 | DividedAsYouChoose$ 2 | IsCurse$ True | SpellDescription$ Distribute two -2/-1 counters among one or two target creatures. -SVar:AltCost:Cost$ PayLife<1> ExileFromHand<1/Card.Black> | Description$ You may pay 1 life and exile a black card from your hand rather than pay Contagion's mana cost. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/contagion.jpg Oracle:You may pay 1 life and exile a black card from your hand rather than pay this spell's mana cost.\nDistribute two -2/-1 counters among one or two target creatures. diff --git a/forge-gui/res/cardsfolder/c/corpse_lunge.txt b/forge-gui/res/cardsfolder/c/corpse_lunge.txt index 77c8c904d53..8f60694924b 100644 --- a/forge-gui/res/cardsfolder/c/corpse_lunge.txt +++ b/forge-gui/res/cardsfolder/c/corpse_lunge.txt @@ -1,8 +1,7 @@ Name:Corpse Lunge ManaCost:2 B Types:Instant -A:SP$ DealDamage | Cost$ 2 B ExileFromGrave<1/Creature> | NumDmg$ X | ValidTgts$ Creature | TgtPrompt$ Select target creature | CostDesc$ As an additional cost to cast CARDNAME, exile a creature card from your graveyard. | References$ X | SpellDescription$ CARDNAME deals damage equal to the exiled card's power to target creature. +A:SP$ DealDamage | Cost$ 2 B ExileFromGrave<1/Card.Creature/creature card> | NumDmg$ X | ValidTgts$ Creature | TgtPrompt$ Select target creature | CostDesc$ As an additional cost to cast this spell, exile a creature card from your graveyard. | References$ X | SpellDescription$ CARDNAME deals damage equal to the exiled card's power to target creature. SVar:X:Exiled$CardPower AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/corpse_lunge.jpg Oracle:As an additional cost to cast this spell, exile a creature card from your graveyard.\nCorpse Lunge deals damage equal to the exiled card's power to target creature. diff --git a/forge-gui/res/cardsfolder/c/crash.txt b/forge-gui/res/cardsfolder/c/crash.txt index 61d5820ebb8..53e9a838115 100644 --- a/forge-gui/res/cardsfolder/c/crash.txt +++ b/forge-gui/res/cardsfolder/c/crash.txt @@ -1,7 +1,6 @@ Name:Crash ManaCost:2 R Types:Instant +SVar:AltCost:Cost$ Sac<1/Mountain> | Description$ You may sacrifice a Mountain rather than pay this spell's mana cost. A:SP$ Destroy | Cost$ 2 R | ValidTgts$ Artifact | TgtPrompt$ Select target artifact | SpellDescription$ Destroy target artifact. -SVar:AltCost:Cost$ Sac<1/Mountain> -SVar:Picture:http://www.wizards.com/global/images/magic/general/crash.jpg Oracle:You may sacrifice a Mountain rather than pay this spell's mana cost.\nDestroy target artifact. diff --git a/forge-gui/res/cardsfolder/c/culling_the_weak.txt b/forge-gui/res/cardsfolder/c/culling_the_weak.txt index 0f4131e67b5..2aece822071 100644 --- a/forge-gui/res/cardsfolder/c/culling_the_weak.txt +++ b/forge-gui/res/cardsfolder/c/culling_the_weak.txt @@ -5,5 +5,4 @@ A:SP$ Mana | Cost$ B Sac<1/Creature> | Produced$ B | Amount$ 4 | AILogic$ ManaRi SVar:AIPreference:SacCost$Creature.cmcLE2 #TODO: Improve the mana ritual AI such that it does not "misfire" from time to time, and only then remove RemoveDeck here, because otherwise sometimes the AI will just sac the creature and not cast anything. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/culling_the_weak.jpg -Oracle:As an additional cost to cast Culling the Weak, sacrifice a creature.\nAdd {B}{B}{B}{B}. +Oracle:As an additional cost to cast this spell, sacrifice a creature.\nAdd {B}{B}{B}{B}. diff --git a/forge-gui/res/cardsfolder/c/cunning_wish.txt b/forge-gui/res/cardsfolder/c/cunning_wish.txt index 489db144b0e..be2fc159cab 100644 --- a/forge-gui/res/cardsfolder/c/cunning_wish.txt +++ b/forge-gui/res/cardsfolder/c/cunning_wish.txt @@ -1,8 +1,7 @@ Name:Cunning Wish ManaCost:2 U Types:Instant -A:SP$ ChangeZone | Cost$ 2 U | Origin$ Sideboard | Destination$ Hand | ChangeType$ Instant.YouOwn | ChangeNum$ 1 | SubAbility$ DBChange | SpellDescription$ You may choose an instant card you own from outside the game, reveal that card, and put it into your hand. Exile CARDNAME. +A:SP$ ChangeZone | Cost$ 2 U | Reveal$ True | Origin$ Sideboard | Destination$ Hand | ChangeType$ Instant.YouOwn | ChangeTypeDesc$ instant card they own | ChangeNum$ 1 | SubAbility$ DBChange | Hidden$ True | SpellDescription$ You may reveal an instant card you own from outside the game and put it into your hand. Exile CARDNAME. SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/cunning_wish.jpg -Oracle:You may choose an instant card you own from outside the game, reveal that card, and put it into your hand. Exile Cunning Wish. +Oracle:You may reveal an instant card you own from outside the game and put it into your hand. Exile Cunning Wish. diff --git a/forge-gui/res/cardsfolder/d/daring_buccaneer.txt b/forge-gui/res/cardsfolder/d/daring_buccaneer.txt index 6a4fedfc4d5..383c967cd59 100644 --- a/forge-gui/res/cardsfolder/d/daring_buccaneer.txt +++ b/forge-gui/res/cardsfolder/d/daring_buccaneer.txt @@ -3,5 +3,4 @@ ManaCost:R Types:Creature Human Pirate PT:2/2 K:AlternateAdditionalCost:Reveal<1/Pirate>:2 -SVar:Picture:http://www.wizards.com/global/images/magic/general/daring_buccaneer.jpg -Oracle:As an additional cost to cast Daring Buccaneer, reveal a Pirate card from your hand or pay {2}. +Oracle:As an additional cost to cast this spell, reveal a Pirate card from your hand or pay {2}. diff --git a/forge-gui/res/cardsfolder/d/dark_triumph.txt b/forge-gui/res/cardsfolder/d/dark_triumph.txt index aaf60999cc8..3060f21f9e2 100644 --- a/forge-gui/res/cardsfolder/d/dark_triumph.txt +++ b/forge-gui/res/cardsfolder/d/dark_triumph.txt @@ -1,8 +1,7 @@ Name:Dark Triumph ManaCost:4 B Types:Instant +SVar:AltCost:Cost$ Sac<1/Creature/creature> | IsPresent$ Swamp.YouCtrl | Description$ If you control a Swamp, you may sacrifice a creature rather than pay this spell's mana cost. A:SP$ PumpAll | Cost$ 4 B | ValidCards$ Creature.YouCtrl | NumAtt$ +2 | SpellDescription$ Creatures you control get +2/+0 until end of turn. -A:SP$ PumpAll | Cost$ Sac<1/Creature> | ValidCards$ Creature.YouCtrl | NumAtt$ +2 | IsPresent$ Swamp.YouCtrl | CostDesc$ If you control a Swamp, you may sacrifice a creature | SpellDescription$ rather than pay CARDNAME's mana cost. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/dark_triumph.jpg -Oracle:If you control a Swamp, you may sacrifice a creature rather than pay Dark Triumph's mana cost.\nCreatures you control get +2/+0 until end of turn. +Oracle:If you control a Swamp, you may sacrifice a creature rather than pay this spell's mana cost.\nCreatures you control get +2/+0 until end of turn. diff --git a/forge-gui/res/cardsfolder/d/daze.txt b/forge-gui/res/cardsfolder/d/daze.txt index 0c32616d97a..16f8ef8000e 100644 --- a/forge-gui/res/cardsfolder/d/daze.txt +++ b/forge-gui/res/cardsfolder/d/daze.txt @@ -1,7 +1,6 @@ Name:Daze ManaCost:1 U Types:Instant +SVar:AltCost:Cost$ Return<1/Island> | AILogic$ MinCMC.4 | Description$ You may return an Island you control to its owner's hand rather than pay this spell's mana cost. A:SP$ Counter | Cost$ 1 U | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | UnlessCost$ 1 | SpellDescription$ Counter target spell unless its controller pays {1}. -A:SP$ Counter | Cost$ Return<1/Island> | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | UnlessCost$ 1 | AILogic$ MinCMC.4 | CostDesc$ You may return an Island you control to its owner's hand | SpellDescription$ rather than pay CARDNAME's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/daze.jpg -Oracle:You may return an Island you control to its owner's hand rather than pay Daze's mana cost.\nCounter target spell unless its controller pays {1}. +Oracle:You may return an Island you control to its owner's hand rather than pay this spell's mana cost.\nCounter target spell unless its controller pays {1}. diff --git a/forge-gui/res/cardsfolder/d/death_bomb.txt b/forge-gui/res/cardsfolder/d/death_bomb.txt index 0b6a0196ea2..ecbe22abdef 100644 --- a/forge-gui/res/cardsfolder/d/death_bomb.txt +++ b/forge-gui/res/cardsfolder/d/death_bomb.txt @@ -1,8 +1,7 @@ Name:Death Bomb ManaCost:3 B Types:Instant -A:SP$ Destroy | Cost$ 3 B Sac<1/Creature> | ValidTgts$ Creature.nonBlack | NoRegen$ True | TgtPrompt$ Select target nonblack creature | SubAbility$ DBDrain | SpellDescription$ Destroy target nonblack creature. It can't be regenerated. Its controller loses 2 life. -SVar:DBDrain:DB$LoseLife | Defined$ TargetedController | LifeAmount$ 2 +A:SP$ Destroy | Cost$ 3 B Sac<1/Creature/creature> | ValidTgts$ Creature.nonBlack | NoRegen$ True | TgtPrompt$ Select target nonblack creature | SubAbility$ DBDrain | SpellDescription$ Destroy target nonblack creature. It can't be regenerated. Its controller loses 2 life. +SVar:DBDrain:DB$ LoseLife | Defined$ TargetedController | LifeAmount$ 2 AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/death_bomb.jpg -Oracle:As an additional cost to cast Death Bomb, sacrifice a creature.\nDestroy target nonblack creature. It can't be regenerated. Its controller loses 2 life. +Oracle:As an additional cost to cast this spell, sacrifice a creature.\nDestroy target nonblack creature. It can't be regenerated. Its controller loses 2 life. diff --git a/forge-gui/res/cardsfolder/d/death_wish.txt b/forge-gui/res/cardsfolder/d/death_wish.txt index 3cae9ac46a4..c6399d065df 100644 --- a/forge-gui/res/cardsfolder/d/death_wish.txt +++ b/forge-gui/res/cardsfolder/d/death_wish.txt @@ -1,10 +1,9 @@ Name:Death Wish ManaCost:1 B B Types:Sorcery -A:SP$ ChangeZone | Cost$ 1 B B | Origin$ Sideboard | Destination$ Hand | ChangeType$ Card.YouOwn | ChangeNum$ 1 | SubAbility$ DBLoseLife | SpellDescription$ You may choose a card you own from outside the game and put it into your hand. You lose half your life, rounded up. Exile CARDNAME. +A:SP$ ChangeZone | Cost$ 1 B B | Origin$ Sideboard | Destination$ Hand | ChangeType$ Card.YouOwn | ChangeTypeDesc$ card they own | ChangeNum$ 1 | SubAbility$ DBLoseLife | Hidden$ True | SpellDescription$ You may put a card you own from outside the game into your hand. You lose half your life, rounded up. Exile CARDNAME. SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ X | References$ X | SubAbility$ DBChange SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile SVar:X:Count$YourLifeTotal/HalfUp AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/death_wish.jpg -Oracle:You may choose a card you own from outside the game and put it into your hand. You lose half your life, rounded up. Exile Death Wish. +Oracle:You may put a card you own from outside the game into your hand. You lose half your life, rounded up. Exile Death Wish. diff --git a/forge-gui/res/cardsfolder/d/delraich.txt b/forge-gui/res/cardsfolder/d/delraich.txt index e8770d7f108..271d1aec054 100644 --- a/forge-gui/res/cardsfolder/d/delraich.txt +++ b/forge-gui/res/cardsfolder/d/delraich.txt @@ -3,6 +3,5 @@ ManaCost:6 B Types:Creature Horror PT:6/6 K:Trample -SVar:AltCost:Cost$ Sac<3/Creature.Black> | Description$ You may sacrifice three black creatures rather than pay Delraich's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/delraich.jpg -Oracle:Trample\nYou may sacrifice three black creatures rather than pay Delraich's mana cost. +SVar:AltCost:Cost$ Sac<3/Creature.Black> | Description$ You may sacrifice three black creatures rather than pay this spell's mana cost. +Oracle:Trample\nYou may sacrifice three black creatures rather than pay this spell's mana cost. diff --git a/forge-gui/res/cardsfolder/d/demon_of_deaths_gate.txt b/forge-gui/res/cardsfolder/d/demon_of_deaths_gate.txt index 9f09e01633d..cc9fbb8f613 100644 --- a/forge-gui/res/cardsfolder/d/demon_of_deaths_gate.txt +++ b/forge-gui/res/cardsfolder/d/demon_of_deaths_gate.txt @@ -4,6 +4,5 @@ Types:Creature Demon PT:9/9 K:Trample K:Flying -SVar:AltCost:Cost$ PayLife<6> Sac<3/Creature.Black> | Description$ You may pay 6 life and sacrifice three black creatures rather than pay Demon of Death's Gate's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/demon_of_deaths_gate.jpg -Oracle:You may pay 6 life and sacrifice three black creatures rather than pay Demon of Death's Gate's mana cost.\nFlying, trample +SVar:AltCost:Cost$ PayLife<6> Sac<3/Creature.Black> | Description$ You may pay 6 life and sacrifice three black creatures rather than pay this spell's mana cost. +Oracle:You may pay 6 life and sacrifice three black creatures rather than pay this spell's mana cost.\nFlying, trample diff --git a/forge-gui/res/cardsfolder/d/demonic_pact.txt b/forge-gui/res/cardsfolder/d/demonic_pact.txt index b240b246ee4..aff9a33cf7a 100644 --- a/forge-gui/res/cardsfolder/d/demonic_pact.txt +++ b/forge-gui/res/cardsfolder/d/demonic_pact.txt @@ -2,15 +2,11 @@ Name:Demonic Pact ManaCost:2 B B Types:Enchantment T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigCharm | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, ABILITY -SVar:TrigCharm:DB$ Charm | Choices$ DrainPact,DiscardPact,DrawPact,DeathPact | ChoiceRestriction$ NotRemembered | RememberChoice$ True | CharmNum$ 1 -SVar:DrainPact:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 4 | SubAbility$ DBGainLife | ChoiceName$ DrainPact | SpellDescription$ CARDNAME deals 4 damage to any target and you gain 4 life. +SVar:TrigCharm:DB$ Charm | Choices$ DrainPact,DiscardPact,DrawPact,DeathPact | ChoiceRestriction$ ThisGame | CharmNum$ 1 +SVar:DrainPact:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 4 | SubAbility$ DBGainLife | SpellDescription$ CARDNAME deals 4 damage to any target and you gain 4 life. SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 4 -SVar:DiscardPact:DB$ Discard | ValidTgts$ Player | NumCards$ 2 | Mode$ TgtChoose | ChoiceName$ DiscardPact | SpellDescription$ Target player discards two cards. -SVar:DrawPact:DB$ Draw | NumCards$ 2 | ChoiceName$ DrawPact | SpellDescription$ Draw two cards. -SVar:DeathPact:DB$ LosesGame | Defined$ You | ChoiceName$ DeathPact | SpellDescription$ You lose the game. -# Clear RememberChoice just in case it's not getting cleared by Zone changes -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ ClearRemembered | Static$ True -SVar:ClearRemembered:DB$ Cleanup | ClearRemembered$ True +SVar:DiscardPact:DB$ Discard | ValidTgts$ Player | NumCards$ 2 | Mode$ TgtChoose | SpellDescription$ Target player discards two cards. +SVar:DrawPact:DB$ Draw | NumCards$ 2 | SpellDescription$ Draw two cards. +SVar:DeathPact:DB$ LosesGame | Defined$ You | SpellDescription$ You lose the game. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/demonic_pact.jpg Oracle:At the beginning of your upkeep, choose one that hasn't been chosen —\n• Demonic Pact deals 4 damage to any target and you gain 4 life.\n• Target opponent discards two cards.\n• Draw two cards.\n• You lose the game. diff --git a/forge-gui/res/cardsfolder/d/discovery_dispersal.txt b/forge-gui/res/cardsfolder/d/discovery_dispersal.txt index bcf7d315b13..31779afc749 100644 --- a/forge-gui/res/cardsfolder/d/discovery_dispersal.txt +++ b/forge-gui/res/cardsfolder/d/discovery_dispersal.txt @@ -13,7 +13,7 @@ Name:Dispersal ManaCost:3 U B Types:Instant A:SP$ RepeatEach | Cost$ 3 U B | RepeatPlayers$ Player.Opponent | RepeatSubAbility$ TrigChooseReturn | SubAbility$ DBReturn | SpellDescription$ Each opponent returns a nonland permanent they control with the highest converted mana cost among permanents they control to its owner's hand, then discards a card. -SVar:TrigChooseReturn:DB$ ChooseCard | Defined$ Remembered | Choices$ Permanent.greatestCMC_NonLandPermanentControlledByRemembered | ChoiceTitle$ Chhose a nonland permanent with the highest converted mana cost | Mandatory$ True | RememberChosen$ True +SVar:TrigChooseReturn:DB$ ChooseCard | Defined$ Remembered | Choices$ Permanent.greatestCMC_NonLandPermanentControlledByRemembered | ChoiceTitle$ Choose a nonland permanent with the highest converted mana cost | Mandatory$ True | RememberChosen$ True SVar:DBReturn:DB$ ChangeZone | Origin$ Battlefield | Destination$ Hand | Defined$ Remembered | SubAbility$ DBDiscard SVar:DBDiscard:DB$ Discard | Defined$ Player.Opponent | NumCards$ 1 | Mode$ TgtChoose | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/cardsfolder/d/disrupting_shoal.txt b/forge-gui/res/cardsfolder/d/disrupting_shoal.txt index 7c5a6481a83..c6a6f945dfb 100644 --- a/forge-gui/res/cardsfolder/d/disrupting_shoal.txt +++ b/forge-gui/res/cardsfolder/d/disrupting_shoal.txt @@ -1,11 +1,12 @@ Name:Disrupting Shoal ManaCost:X U U Types:Instant Arcane -A:SP$ Counter | Cost$ X U U | TargetType$ Spell | ValidTgts$ Card | ConditionCheckSVar$ TargetCMC | ConditionSVarCompare$ EQX | References$ X,TargetCMC | SpellDescription$ Counter target spell if its converted mana cost is X. -A:SP$ Counter | Cost$ ExileFromHand<1/Card.Blue> | CostDesc$ You may exile a blue card with converted mana cost X from your hand. | TargetType$ Spell | ValidTgts$ Card | ConditionCheckSVar$ TargetCMC | ConditionSVarCompare$ EQY | References$ TargetCMC,Y | SpellDescription$ Counter target spell if its converted mana cost is X. +SVar:AltCost:Cost$ ExileFromHand<1/Card.Blue+Other/blue card> | Description$ You may exile a blue card with converted mana cost X from your hand rather than pay this spell's mana cost. +A:SP$ Pump | Cost$ X U U | IsCurse$ True | TargetType$ Spell | TgtZone$ Stack | TgtPrompt$ Select target spell | ValidTgts$ Card | SubAbility$ DBCounter +SVar:DBCounter:DB$ Counter | Defined$ Targeted | ConditionCheckSVar$ T | ConditionSVarCompare$ EQZ | References$ X,Y,Z,T | SpellDescription$ Counter target spell if its converted mana cost is X. SVar:X:Count$xPaid -SVar:TargetCMC:Targeted$CardManaCost SVar:Y:Exiled$CardManaCost +SVar:Z:SVar$Y/Plus.X +SVar:T:Targeted$CardManaCost AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/disrupting_shoal.jpg -Oracle:You may exile a blue card with converted mana cost X from your hand rather than pay Disrupting Shoal's mana cost.\nCounter target spell if its converted mana cost is X. +Oracle:You may exile a blue card with converted mana cost X from your hand rather than pay this spell's mana cost.\nCounter target spell if its converted mana cost is X. diff --git a/forge-gui/res/cardsfolder/d/downhill_charge.txt b/forge-gui/res/cardsfolder/d/downhill_charge.txt index df044bd88ee..69f1b0f5198 100644 --- a/forge-gui/res/cardsfolder/d/downhill_charge.txt +++ b/forge-gui/res/cardsfolder/d/downhill_charge.txt @@ -1,8 +1,7 @@ Name:Downhill Charge ManaCost:2 R Types:Instant +SVar:AltCost:Cost$ Sac<1/Mountain> | Description$ You may sacrifice a Mountain rather than pay this spell's mana cost. A:SP$ Pump | Cost$ 2 R | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +X | References$ X | SpellDescription$ Target creature gets +X/+0 until end of turn, where X is the number of Mountains you control. -SVar:AltCost:Cost$ Sac<1/Mountain> | Description$ You may sacrifice a Mountain rather than pay CARDNAME's mana cost. SVar:X:Count$TypeYouCtrl.Mountain -SVar:Picture:http://www.wizards.com/global/images/magic/general/downhill_charge.jpg -Oracle:You may sacrifice a Mountain rather than pay Downhill Charge's mana cost.\nTarget creature gets +X/+0 until end of turn, where X is the number of Mountains you control. +Oracle:You may sacrifice a Mountain rather than pay this spell's mana cost.\nTarget creature gets +X/+0 until end of turn, where X is the number of Mountains you control. diff --git a/forge-gui/res/cardsfolder/e/empyrial_archangel.txt b/forge-gui/res/cardsfolder/e/empyrial_archangel.txt index 819363c9de1..614ddbe80b9 100644 --- a/forge-gui/res/cardsfolder/e/empyrial_archangel.txt +++ b/forge-gui/res/cardsfolder/e/empyrial_archangel.txt @@ -4,7 +4,6 @@ Types:Creature Angel PT:5/8 K:Flying K:Shroud -R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ You | ReplaceWith$ DmgSelf | Description$ All damage that would be dealt to you is dealt to CARDNAME instead. +R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ You | ReplaceWith$ DmgSelf | DamageTarget$ Self | Description$ All damage that would be dealt to you is dealt to CARDNAME instead. SVar:DmgSelf:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Self | VarType$ Card -SVar:Picture:http://www.wizards.com/global/images/magic/general/empyrial_archangel.jpg Oracle:Flying\nShroud (This creature can't be the target of spells or abilities.)\nAll damage that would be dealt to you is dealt to Empyrial Archangel instead. diff --git a/forge-gui/res/cardsfolder/e/ensnare.txt b/forge-gui/res/cardsfolder/e/ensnare.txt index 2feaba3a804..64b144dc6e8 100644 --- a/forge-gui/res/cardsfolder/e/ensnare.txt +++ b/forge-gui/res/cardsfolder/e/ensnare.txt @@ -1,8 +1,7 @@ Name:Ensnare ManaCost:3 U Types:Instant +SVar:AltCost:Cost$ Return<2/Island> | Description$ You may return two Islands you control to their owner's hand rather than pay this spell's mana cost. A:SP$ TapAll | Cost$ 3 U | ValidCards$ Creature | SpellDescription$ Tap all creatures. -SVar:AltCost:Cost$ Return<2/Island> AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/ensnare.jpg -Oracle:You may return two Islands you control to their owner's hand rather than pay Ensnare's mana cost.\nTap all creatures. +Oracle:You may return two Islands you control to their owner's hand rather than pay this spell's mana cost.\nTap all creatures. diff --git a/forge-gui/res/cardsfolder/f/fae_of_wishes_granted.txt b/forge-gui/res/cardsfolder/f/fae_of_wishes_granted.txt index 9745ecee112..a51df6109d5 100644 --- a/forge-gui/res/cardsfolder/f/fae_of_wishes_granted.txt +++ b/forge-gui/res/cardsfolder/f/fae_of_wishes_granted.txt @@ -12,5 +12,5 @@ ALTERNATE Name:Granted ManaCost:3 U Types:Sorcery Adventure -A:SP$ ChangeZone | Cost$ 3 U | Origin$ Sideboard | Destination$ Hand | ChangeType$ Card.nonCreature+YouOwn | ChangeNum$ 1 | SpellDescription$ You may choose a noncreature card you own from outside the game, reveal it, and put it into your hand. -Oracle:You may choose a noncreature card you own from outside the game, reveal it, and put it into your hand. +A:SP$ ChangeZone | Cost$ 3 U | Origin$ Sideboard | Destination$ Hand | ChangeType$ Card.nonCreature+YouOwn | ChangeTypeDesc$ noncreature card they own | ChangeNum$ 1 | Reveal$ True | Hidden$ True | SpellDescription$ You may reveal a noncreature card you own from outside the game and put it into your hand. +Oracle:You may reveal a noncreature card you own from outside the game and put it into your hand. diff --git a/forge-gui/res/cardsfolder/f/fairgrounds_trumpeter.txt b/forge-gui/res/cardsfolder/f/fairgrounds_trumpeter.txt index b555b2fd221..d2c27378cd3 100644 --- a/forge-gui/res/cardsfolder/f/fairgrounds_trumpeter.txt +++ b/forge-gui/res/cardsfolder/f/fairgrounds_trumpeter.txt @@ -5,6 +5,6 @@ PT:2/2 T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | CheckSVar$ X | Execute$ TrigPutCounter | TriggerDescription$ At the beginning of each end step, if a +1/+1 counter was put on a permanent under your control this turn, put a +1/+1 counter on CARDNAME. SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 DeckHints:Ability$Counters -SVar:X:Count$CountersAddedToPermYouCtrl P1P1 -SVar:Picture:http://www.wizards.com/global/images/magic/general/fairgrounds_trumpeter.jpg +DeckHas:Ability$Counters +SVar:X:Count$CountersAddedThisTurn P1P1 Player Permanent.YouCtrl Oracle:At the beginning of each end step, if a +1/+1 counter was put on a permanent under your control this turn, put a +1/+1 counter on Fairgrounds Trumpeter. diff --git a/forge-gui/res/cardsfolder/f/fieldmist_borderpost.txt b/forge-gui/res/cardsfolder/f/fieldmist_borderpost.txt index cd08bb7eabf..387cdc45cf8 100644 --- a/forge-gui/res/cardsfolder/f/fieldmist_borderpost.txt +++ b/forge-gui/res/cardsfolder/f/fieldmist_borderpost.txt @@ -1,9 +1,8 @@ Name:Fieldmist Borderpost ManaCost:1 W U Types:Artifact +SVar:AltCost:Cost$ 1 Return<1/Land.Basic> | Description$ You may pay {1} and return a basic land you control to its owner's hand rather than pay this spell's mana cost. K:CARDNAME enters the battlefield tapped. A:AB$ Mana | Cost$ T | Produced$ W | SpellDescription$ Add {W}. A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {U}. -SVar:AltCost:Cost$ 1 Return<1/Land.Basic> | Description$ You may pay {1} and return a basic land you control to its owner's hand rather than pay Fieldmist Borderpost's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/fieldmist_borderpost.jpg -Oracle:You may pay {1} and return a basic land you control to its owner's hand rather than pay Fieldmist Borderpost's mana cost.\nFieldmist Borderpost enters the battlefield tapped.\n{T}: Add {W} or {U}. +Oracle:You may pay {1} and return a basic land you control to its owner's hand rather than pay this spell's mana cost.\nFieldmist Borderpost enters the battlefield tapped.\n{T}: Add {W} or {U}. diff --git a/forge-gui/res/cardsfolder/f/fireblast.txt b/forge-gui/res/cardsfolder/f/fireblast.txt index 551dff6eaca..b828037f5a9 100644 --- a/forge-gui/res/cardsfolder/f/fireblast.txt +++ b/forge-gui/res/cardsfolder/f/fireblast.txt @@ -1,7 +1,6 @@ Name:Fireblast ManaCost:4 R R Types:Instant +SVar:AltCost:Cost$ Sac<2/Mountain> | Description$ You may sacrifice two Mountains rather than pay this spell's mana cost. A:SP$ DealDamage | Cost$ 4 R R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 4 | SpellDescription$ CARDNAME deals 4 damage to any target. -SVar:AltCost:Cost$ Sac<2/Mountain> -SVar:Picture:http://www.wizards.com/global/images/magic/general/fireblast.jpg -Oracle:You may sacrifice two Mountains rather than pay Fireblast's mana cost.\nFireblast deals 4 damage to any target. +Oracle:You may sacrifice two Mountains rather than pay this spell's mana cost.\nFireblast deals 4 damage to any target. diff --git a/forge-gui/res/cardsfolder/f/firespout.txt b/forge-gui/res/cardsfolder/f/firespout.txt index 618bb26236d..9a65e6464f7 100644 --- a/forge-gui/res/cardsfolder/f/firespout.txt +++ b/forge-gui/res/cardsfolder/f/firespout.txt @@ -1,8 +1,7 @@ Name:Firespout ManaCost:2 RG Types:Sorcery -A:SP$ DamageAll | Cost$ 2 RG | ValidCards$ Creature.withoutFlying | NumDmg$ 3 | ConditionManaSpent$ R | SubAbility$ GPaid | SpellDescription$ CARDNAME deals 3 damage to each creature without flying if {R} was spent to cast CARDNAME and 3 damage to each creature with flying if {G} was spent to cast it. (Do both if {R}{G} was spent.) -SVar:GPaid:DB$ DamageAll | ValidCards$ Creature.withFlying | NumDmg$ 3 | ConditionManaSpent$ G +A:SP$ DamageAll | Cost$ 2 RG | ValidCards$ Creature.withoutFlying | ValidDescription$ each creature without flying if {R} was spent to cast it. | NumDmg$ 3 | ConditionManaSpent$ R | SubAbility$ GPaid | SpellDescription$ CARDNAME deals 3 damage to each creature without flying if {R} was spent to cast CARDNAME and 3 damage to each creature with flying if {G} was spent to cast it. (Do both if {R}{G} was spent.) +SVar:GPaid:DB$ DamageAll | ValidCards$ Creature.withFlying | ValidDescription$ each creature with flying if {R} was spent to cast it. (Do both if {R}{G} was spent. | NumDmg$ 3 | ConditionManaSpent$ G AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/firespout.jpg Oracle:Firespout deals 3 damage to each creature without flying if {R} was spent to cast Firespout and 3 damage to each creature with flying if {G} was spent to cast it. (Do both if {R}{G} was spent.) diff --git a/forge-gui/res/cardsfolder/f/firewild_borderpost.txt b/forge-gui/res/cardsfolder/f/firewild_borderpost.txt index b5870f9282f..18b81ba4af9 100644 --- a/forge-gui/res/cardsfolder/f/firewild_borderpost.txt +++ b/forge-gui/res/cardsfolder/f/firewild_borderpost.txt @@ -1,9 +1,8 @@ Name:Firewild Borderpost ManaCost:1 R G Types:Artifact +SVar:AltCost:Cost$ 1 Return<1/Land.Basic> | Description$ You may pay {1} and return a basic land you control to its owner's hand rather than pay this spell's mana cost. K:CARDNAME enters the battlefield tapped. A:AB$ Mana | Cost$ T | Produced$ R | SpellDescription$ Add {R}. A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G}. -SVar:AltCost:Cost$ 1 Return<1/Land.Basic> | Description$ You may pay {1} and return a basic land you control to its owner's hand rather than pay Firewild Borderpost's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/firewild_borderpost.jpg -Oracle:You may pay {1} and return a basic land you control to its owner's hand rather than pay Firewild Borderpost's mana cost.\nFirewild Borderpost enters the battlefield tapped.\n{T}: Add {R} or {G}. +Oracle:You may pay {1} and return a basic land you control to its owner's hand rather than pay this spell's mana cost.\nFirewild Borderpost enters the battlefield tapped.\n{T}: Add {R} or {G}. diff --git a/forge-gui/res/cardsfolder/f/flameshot.txt b/forge-gui/res/cardsfolder/f/flameshot.txt index 233d3ea7849..8d6c00e83c0 100644 --- a/forge-gui/res/cardsfolder/f/flameshot.txt +++ b/forge-gui/res/cardsfolder/f/flameshot.txt @@ -1,8 +1,7 @@ Name:Flameshot ManaCost:3 R Types:Sorcery -A:SP$ DealDamage | Cost$ 3 R | ValidTgts$ Creature | TgtPrompt$ Select target creature to distribute damage to | NumDmg$ 3 | TargetMin$ 1 | TargetMax$ 3 | DividedAsYouChoose$ 3 | SpellDescription$ CARDNAME deals 3 damage divided as you choose among any number of target creatures. -SVar:AltCost:Cost$ Discard<1/Mountain> +SVar:AltCost:Cost$ Discard<1/Mountain> | Description$ You may discard a Mountain card rather than pay this spell's mana cost. +A:SP$ DealDamage | Cost$ 3 R | ValidTgts$ Creature | TgtPrompt$ Select target creature to distribute damage to | NumDmg$ 3 | TargetMin$ 1 | TargetMax$ 3 | DividedAsYouChoose$ 3 | SpellDescription$ CARDNAME deals 3 damage divided as you choose among one, two, or three target creatures. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/flameshot.jpg -Oracle:You may discard a Mountain card rather than pay Flameshot's mana cost.\nFlameshot deals 3 damage divided as you choose among one, two, or three target creatures. +Oracle:You may discard a Mountain card rather than pay this spell's mana cost.\nFlameshot deals 3 damage divided as you choose among one, two, or three target creatures. diff --git a/forge-gui/res/cardsfolder/f/foil.txt b/forge-gui/res/cardsfolder/f/foil.txt index 949fb5dba11..21fb929baaf 100644 --- a/forge-gui/res/cardsfolder/f/foil.txt +++ b/forge-gui/res/cardsfolder/f/foil.txt @@ -1,7 +1,6 @@ Name:Foil ManaCost:2 U U Types:Instant +SVar:AltCost:Cost$ Discard<1/Island> Discard<1/Card.Other> | Description$ You may discard an Island card and another card rather than pay this spell's mana cost. A:SP$ Counter | Cost$ 2 U U | TargetType$ Spell | ValidTgts$ Card | SpellDescription$ Counter target spell. -SVar:AltCost:Cost$ Discard<1/Island> Discard<1/Card> | Description$ You may discard an Island card and another card rather than pay Foil's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/foil.jpg -Oracle:You may discard an Island card and another card rather than pay Foil's mana cost.\nCounter target spell. +Oracle:You may discard an Island card and another card rather than pay this spell's mana cost.\nCounter target spell. diff --git a/forge-gui/res/cardsfolder/f/force_of_despair.txt b/forge-gui/res/cardsfolder/f/force_of_despair.txt index 5b8fe787724..6f90288a4de 100644 --- a/forge-gui/res/cardsfolder/f/force_of_despair.txt +++ b/forge-gui/res/cardsfolder/f/force_of_despair.txt @@ -1,6 +1,6 @@ Name:Force of Despair ManaCost:1 B B Types:Instant -SVar:AltCost:Cost$ ExileFromHand<1/Card.Black> | OpponentTurn$ True | Description$ If it's not your turn, you may exile a black card from your hand rather than pay this spell's mana cost. +SVar:AltCost:Cost$ ExileFromHand<1/Card.Black+Other> | OpponentTurn$ True | Description$ If it's not your turn, you may exile a black card from your hand rather than pay this spell's mana cost. A:SP$ DestroyAll | Cost$ 1 B B | ValidCards$ Creature.enteredBattlefieldThisTurn | SpellDescription$ Destroy all creatures that entered the battlefield this turn. Oracle:If it's not your turn, you may exile a black card from your hand rather than pay this spell's mana cost.\nDestroy all creatures that entered the battlefield this turn. diff --git a/forge-gui/res/cardsfolder/f/force_of_negation.txt b/forge-gui/res/cardsfolder/f/force_of_negation.txt index 5c84d3dc9e6..10986e2073c 100644 --- a/forge-gui/res/cardsfolder/f/force_of_negation.txt +++ b/forge-gui/res/cardsfolder/f/force_of_negation.txt @@ -1,6 +1,6 @@ Name:Force of Negation ManaCost:1 U U Types:Instant -A:SP$ Counter | Cost$ 1 U U | TargetType$ Spell | TgtPrompt$ Select target nonCreature Spell | ValidTgts$ Card.nonCreature | Destination$ Exile | SpellDescription$ Counter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyayrd. -SVar:AltCost:Cost$ ExileFromHand<1/Card.Blue> | OpponentTurn$ True | Description$ If it's not your turn, you may exile a blue card from your hand rather than pay this spell's mana cost. -Oracle:If it's not your turn, you may exile a blue card from your hand rather than pay this spell's mana cost.\nCounter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyayrd. \ No newline at end of file +SVar:AltCost:Cost$ ExileFromHand<1/Card.Blue+Other> | OpponentTurn$ True | Description$ If it's not your turn, you may exile a blue card from your hand rather than pay this spell's mana cost. +A:SP$ Counter | Cost$ 1 U U | TargetType$ Spell | TgtPrompt$ Select target noncreature spell | ValidTgts$ Card.nonCreature | Destination$ Exile | SpellDescription$ Counter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyayrd. +Oracle:If it's not your turn, you may exile a blue card from your hand rather than pay this spell's mana cost.\nCounter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. diff --git a/forge-gui/res/cardsfolder/f/force_of_rage.txt b/forge-gui/res/cardsfolder/f/force_of_rage.txt index a7421490081..8559d0ed0e3 100644 --- a/forge-gui/res/cardsfolder/f/force_of_rage.txt +++ b/forge-gui/res/cardsfolder/f/force_of_rage.txt @@ -1,7 +1,7 @@ Name:Force of Rage ManaCost:1 R R Types:Instant -SVar:AltCost:Cost$ ExileFromHand<1/Card.Red> | OpponentTurn$ True | Description$ If it's not your turn, you may exile a red card from your hand rather than pay this spell's mana cost. +SVar:AltCost:Cost$ ExileFromHand<1/Card.Red+Other> | OpponentTurn$ True | Description$ If it's not your turn, you may exile a red card from your hand rather than pay this spell's mana cost. A:SP$ Token | Cost$ 1 R R | TokenAmount$ 2 | TokenScript$ r_3_1_elemental_trample_haste | TokenOwner$ You | LegacyImage$ r 3 1 elemental trample haste mh1 | SubAbility$ DelayedSac | RememberTokens$ True | SpellDescription$ Create two 3/1 red Elemental creature tokens with trample and haste. Sacrifice those tokens at the beginning of your next upkeep. SVar:DelayedSac:DB$ DelayedTrigger | Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ DBSacToken | RememberObjects$ Remembered | SubAbility$ DBCleanup | TriggerDescription$ Sacrifice those tokens at the beginning of your next upkeep. SVar:DBSacToken:DB$ SacrificeAll | Defined$ DelayTriggerRemembered | Controller$ You diff --git a/forge-gui/res/cardsfolder/f/force_of_vigor.txt b/forge-gui/res/cardsfolder/f/force_of_vigor.txt index cbf697bb3a6..7cd85fef1a1 100644 --- a/forge-gui/res/cardsfolder/f/force_of_vigor.txt +++ b/forge-gui/res/cardsfolder/f/force_of_vigor.txt @@ -1,6 +1,6 @@ Name:Force of Vigor ManaCost:2 G G Types:Instant +SVar:AltCost:Cost$ ExileFromHand<1/Card.Green+Other> | OpponentTurn$ True | Description$ If it's not your turn, you may exile a green card from your hand rather than pay this spell's mana cost. A:SP$ Destroy | Cost$ 2 G G | TargetMin$ 0 | TargetMax$ 2 | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | SpellDescription$ Destroy up to two target artifacts and/or enchantments. -SVar:AltCost:Cost$ ExileFromHand<1/Card.Green> | OpponentTurn$ True | Description$ If it's not your turn, you may exile a green card from your hand rather than pay this spell's mana cost. Oracle:If it's not your turn, you may exile a green card from your hand rather than pay this spell's mana cost.\nDestroy up to two target artifacts and/or enchantments. diff --git a/forge-gui/res/cardsfolder/f/force_of_virtue.txt b/forge-gui/res/cardsfolder/f/force_of_virtue.txt index a242487a575..27b71601bd9 100644 --- a/forge-gui/res/cardsfolder/f/force_of_virtue.txt +++ b/forge-gui/res/cardsfolder/f/force_of_virtue.txt @@ -2,8 +2,8 @@ Name:Force of Virtue ManaCost:2 W W Types:Enchantment K:Flash +SVar:AltCost:Cost$ ExileFromHand<1/Card.White+Other> | OpponentTurn$ True | Description$ If it's not your turn, you may exile a white card from your hand rather than pay this spell's mana cost. S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddPower$ 1 | AddToughness$ 1 | Description$ Creatures you control get +1/+1. -SVar:AltCost:Cost$ ExileFromHand<1/Card.White> | OpponentTurn$ True | Description$ If it's not your turn, you may exile a white card from your hand rather than pay this spell's mana cost. SVar:BuffedBy:Creature AI:RemoveDeck:All Oracle:If it's not your turn, you may exile a white card from your hand rather than pay this spell's mana cost.\nFlash\nCreatures you control get +1/+1. diff --git a/forge-gui/res/cardsfolder/f/force_of_will.txt b/forge-gui/res/cardsfolder/f/force_of_will.txt index 5ea97cf4c80..6c08653694b 100644 --- a/forge-gui/res/cardsfolder/f/force_of_will.txt +++ b/forge-gui/res/cardsfolder/f/force_of_will.txt @@ -1,7 +1,6 @@ Name:Force of Will ManaCost:3 U U Types:Instant +SVar:AltCost:Cost$ PayLife<1> ExileFromHand<1/Card.Blue+Other> | Description$ You may pay 1 life and exile a blue card from your hand rather than pay CARDNAME's mana cost. A:SP$ Counter | Cost$ 3 U U | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | Destination$ Graveyard | AILogic$ MinCMC.3 | SpellDescription$ Counter target spell. -SVar:AltCost:Cost$ PayLife<1> ExileFromHand<1/Card.Blue> | Description$ You may pay 1 life and exile a blue card from your hand rather than pay CARDNAME's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/force_of_will.jpg Oracle:You may pay 1 life and exile a blue card from your hand rather than pay Force of Will's mana cost.\nCounter target spell. diff --git a/forge-gui/res/cardsfolder/f/forsaken_monument.txt b/forge-gui/res/cardsfolder/f/forsaken_monument.txt index c1e2c929667..5282f5a0ce1 100644 --- a/forge-gui/res/cardsfolder/f/forsaken_monument.txt +++ b/forge-gui/res/cardsfolder/f/forsaken_monument.txt @@ -4,9 +4,9 @@ Types:Legendary Artifact S:Mode$ Continuous | Affected$ Creature.Colorless+YouCtrl | AddPower$ 2 | AddToughness$ 2 | Description$ Colorless creatures you control get +2/+2. T:Mode$ TapsForMana | ValidCard$ Permanent.YouCtrl | Produced$ C | Execute$ TrigMana | TriggerZones$ Battlefield | Static$ True | TriggerDescription$ Whenever you tap a permanent for {C}, add an additional {C}. SVar:TrigMana:DB$ Mana | Produced$ C -T:Mode$ SpellCast | ValidCard$ Card.Colorless | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigGainLife | TriggerDescription$ Whenever you cast a colorless spell, you gain 1 life. -SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1 +T:Mode$ SpellCast | ValidCard$ Card.Colorless | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigGainLife | TriggerDescription$ Whenever you cast a colorless spell, you gain 2 life. +SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 2 SVar:PlayMain1:TRUE DeckHints:Color$Colorless DeckHas:Ability$LifeGain -Oracle:Colorless creatures you control get +2/+2.\nWhenever you tap a permanent for {C}, add an additional {C}.\nWhenever you cast a colorless spell, you gain 1 life. +Oracle:Colorless creatures you control get +2/+2.\nWhenever you tap a permanent for {C}, add an additional {C}.\nWhenever you cast a colorless spell, you gain 2 life. diff --git a/forge-gui/res/cardsfolder/f/fury_of_the_horde.txt b/forge-gui/res/cardsfolder/f/fury_of_the_horde.txt index c3c248d87fa..18b6b3a4848 100644 --- a/forge-gui/res/cardsfolder/f/fury_of_the_horde.txt +++ b/forge-gui/res/cardsfolder/f/fury_of_the_horde.txt @@ -1,8 +1,7 @@ Name:Fury of the Horde ManaCost:5 R R Types:Sorcery -SVar:AltCost:Cost$ ExileFromHand<2/Card.Red> | Description$ You may exile two red cards from your hand rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ ExileFromHand<2/Card.Red+Other> | Description$ You may exile two red cards from your hand rather than pay this spell's mana cost. A:SP$ UntapAll | Cost$ 5 R R | ValidCards$ Creature.attackedThisTurn | SubAbility$ DBAddCombat | SpellDescription$ Untap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase. SVar:DBAddCombat:DB$ AddPhase | ExtraPhase$ BeginCombat | FollowedBy$ ThisPhase | ConditionPhases$ Main1,Main2 -SVar:Picture:http://www.wizards.com/global/images/magic/general/fury_of_the_horde.jpg -Oracle:You may exile two red cards from your hand rather than pay Fury of the Horde's mana cost.\nUntap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase. +Oracle:You may exile two red cards from your hand rather than pay this spell's mana cost.\nUntap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase. diff --git a/forge-gui/res/cardsfolder/g/gaze_of_justice.txt b/forge-gui/res/cardsfolder/g/gaze_of_justice.txt index 7414210628b..c31a3c9d15e 100644 --- a/forge-gui/res/cardsfolder/g/gaze_of_justice.txt +++ b/forge-gui/res/cardsfolder/g/gaze_of_justice.txt @@ -2,6 +2,5 @@ Name:Gaze of Justice ManaCost:W Types:Sorcery K:Flashback:5 W tapXType<3/Creature.White/white creature> -A:SP$ ChangeZone | Cost$ W tapXType<3/Creature.White> | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Exile | CostDesc$ As an additional cost to cast CARDNAME, tap three untapped white creatures you control. | SpellDescription$ Exile target creature. -SVar:Picture:http://www.wizards.com/global/images/magic/general/gaze_of_justice.jpg -Oracle:As an additional cost to cast Gaze of Justice, tap three untapped white creatures you control.\nExile target creature.\nFlashback {5}{W} (You may cast this card from your graveyard for its flashback cost and any additional costs. Then exile it.) +A:SP$ ChangeZone | Cost$ W tapXType<3/Creature.White> | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Exile | CostDesc$ As an additional cost to cast this spell, tap three untapped white creatures you control. | SpellDescription$ Exile target creature. +Oracle:As an additional cost to cast this spell, tap three untapped white creatures you control.\nExile target creature.\nFlashback {5}{W} (You may cast this card from your graveyard for its flashback cost and any additional costs. Then exile it.) diff --git a/forge-gui/res/cardsfolder/g/gideons_sacrifice.txt b/forge-gui/res/cardsfolder/g/gideons_sacrifice.txt index d76910c2231..b26c4afb055 100644 --- a/forge-gui/res/cardsfolder/g/gideons_sacrifice.txt +++ b/forge-gui/res/cardsfolder/g/gideons_sacrifice.txt @@ -3,7 +3,7 @@ ManaCost:W Types:Instant A:SP$ ChooseCard | Cost$ W | Choices$ Creature.YouCtrl,Planeswalker.YouCtrl | SubAbility$ DBEffect | SpellDescription$ Choose a creature or planeswalker you control. All damage that would be dealt this turn to you and permanents you control is dealt to the chosen permanent instead (if it's still on the battlefield). SVar:DBEffect:DB$ Effect | ReplacementEffects$ DamageEvent | SVars$ GideonSac | References$ DamageEvent,GideonSac | ExileOnMoved$ True | RememberObjects$ ChosenCard -SVar:DamageEvent:Event$ DamageDone | ActiveZones$ Command | ValidTarget$ You,Permanent.YouCtrl | ReplaceWith$ GideonSac | Description$ All damage that would be dealt this turn to you and permanents you control is dealt to the chosen permanent instead (if it's still on the battlefield). +SVar:DamageEvent:Event$ DamageDone | ActiveZones$ Command | ValidTarget$ You,Permanent.YouCtrl | ReplaceWith$ GideonSac | DamageTarget$ Remembered | Description$ All damage that would be dealt this turn to you and permanents you control is dealt to the chosen permanent instead (if it's still on the battlefield). SVar:GideonSac:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Remembered | VarType$ Card SVar:NeedsToPlayVar:Z GE1 SVar:Z:SVar$Z1/Plus.Z2 diff --git a/forge-gui/res/cardsfolder/g/glittering_wish.txt b/forge-gui/res/cardsfolder/g/glittering_wish.txt index 15fa5e5aa3d..fc47efc83d9 100644 --- a/forge-gui/res/cardsfolder/g/glittering_wish.txt +++ b/forge-gui/res/cardsfolder/g/glittering_wish.txt @@ -1,8 +1,7 @@ Name:Glittering Wish ManaCost:G W Types:Sorcery -A:SP$ ChangeZone | Cost$ G W | Origin$ Sideboard | Destination$ Hand | ChangeType$ Card.MultiColor+YouOwn | ChangeNum$ 1 | SubAbility$ DBChange | SpellDescription$ You may choose a multicolored card you own from outside the game, reveal that card, and put it into your hand. Exile CARDNAME. +A:SP$ ChangeZone | Cost$ G W | Origin$ Sideboard | Destination$ Hand | ChangeType$ Card.MultiColor+YouOwn | ChangeTypeDesc$ multicolored card they own | ChangeNum$ 1 | Hidden$ True | Reveal$ True | SubAbility$ DBChange | SpellDescription$ You may reveal a multicolored card you own from outside the game and put it into your hand. Exile CARDNAME. SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/glittering_wish.jpg -Oracle:You may choose a multicolored card you own from outside the game, reveal that card, and put it into your hand. Exile Glittering Wish. +Oracle:You may reveal a multicolored card you own from outside the game and put it into your hand. Exile Glittering Wish. diff --git a/forge-gui/res/cardsfolder/g/golden_wish.txt b/forge-gui/res/cardsfolder/g/golden_wish.txt index 0452d57d10f..1cdfcb22f6d 100644 --- a/forge-gui/res/cardsfolder/g/golden_wish.txt +++ b/forge-gui/res/cardsfolder/g/golden_wish.txt @@ -1,8 +1,7 @@ Name:Golden Wish ManaCost:3 W W Types:Sorcery -A:SP$ ChangeZone | Cost$ 3 W W | Origin$ Sideboard | Destination$ Hand | ChangeType$ Artifact.YouOwn,Enchantment.YouOwn | ChangeNum$ 1 | SubAbility$ DBChange | SpellDescription$ You may choose an artifact or enchantment card you own from outside the game, reveal that card, and put it into your hand. Exile CARDNAME. +A:SP$ ChangeZone | Cost$ 3 W W | Origin$ Sideboard | Destination$ Hand | ChangeType$ Artifact.YouOwn,Enchantment.YouOwn | ChangeTypeDesc$ artifact or enchantment they own | ChangeNum$ 1 | SubAbility$ DBChange | Hidden$ True | Reveal$ True | SpellDescription$ You may reveal an artifact or enchantment card you own from outside the game and put it into your hand. Exile CARDNAME. SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/golden_wish.jpg -Oracle:You may choose an artifact or enchantment card you own from outside the game, reveal that card, and put it into your hand. Exile Golden Wish. +Oracle:You may reveal an artifact or enchantment card you own from outside the game and put it into your hand. Exile Golden Wish. diff --git a/forge-gui/res/cardsfolder/g/gush.txt b/forge-gui/res/cardsfolder/g/gush.txt index 7d67c25d7a3..965db4f6c4f 100644 --- a/forge-gui/res/cardsfolder/g/gush.txt +++ b/forge-gui/res/cardsfolder/g/gush.txt @@ -1,7 +1,6 @@ Name:Gush ManaCost:4 U Types:Instant +SVar:AltCost:Cost$ Return<2/Island> | Description$ You may return two Islands you control to their owner's hand rather than pay this spell's mana cost. A:SP$ Draw | Cost$ 4 U | NumCards$ 2 | SpellDescription$ Draw two cards. -SVar:AltCost:Cost$ Return<2/Island> -SVar:Picture:http://www.wizards.com/global/images/magic/general/gush.jpg -Oracle:You may return two Islands you control to their owner's hand rather than pay Gush's mana cost.\nDraw two cards. +Oracle:You may return two Islands you control to their owner's hand rather than pay this spell's mana cost.\nDraw two cards. diff --git a/forge-gui/res/cardsfolder/h/hallowed_priest.txt b/forge-gui/res/cardsfolder/h/hallowed_priest.txt new file mode 100644 index 00000000000..9add5863d35 --- /dev/null +++ b/forge-gui/res/cardsfolder/h/hallowed_priest.txt @@ -0,0 +1,9 @@ +Name:Hallowed Priest +ManaCost:1 W +Types:Creature Human Cleric +PT:1/1 +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:Whenever you gain life, put a +1/+1 counter on Hallowed Priest. diff --git a/forge-gui/res/cardsfolder/h/hand_of_emrakul.txt b/forge-gui/res/cardsfolder/h/hand_of_emrakul.txt index 828fe609fe0..cc09ac64bb5 100644 --- a/forge-gui/res/cardsfolder/h/hand_of_emrakul.txt +++ b/forge-gui/res/cardsfolder/h/hand_of_emrakul.txt @@ -3,6 +3,5 @@ ManaCost:9 Types:Creature Eldrazi PT:7/7 K:Annihilator:1 -SVar:AltCost:Cost$ Sac<4/Eldrazi.Spawn> | Description$ You may sacrifice four Eldrazi Spawn rather than pay Hand of Emrakul's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/hand_of_emrakul.jpg -Oracle:You may sacrifice four Eldrazi Spawn rather than pay Hand of Emrakul's mana cost.\nAnnihilator 1 (Whenever this creature attacks, defending player sacrifices a permanent.) +SVar:AltCost:Cost$ Sac<4/Eldrazi.Spawn> | Description$ You may sacrifice four Eldrazi Spawn rather than pay this spell's mana cost. +Oracle:You may sacrifice four Eldrazi Spawn rather than pay this spell's mana cost.\nAnnihilator 1 (Whenever this creature attacks, defending player sacrifices a permanent.) diff --git a/forge-gui/res/cardsfolder/h/honor_the_god_pharaoh.txt b/forge-gui/res/cardsfolder/h/honor_the_god_pharaoh.txt index 6d234fb5523..1ea722b5234 100644 --- a/forge-gui/res/cardsfolder/h/honor_the_god_pharaoh.txt +++ b/forge-gui/res/cardsfolder/h/honor_the_god_pharaoh.txt @@ -1,7 +1,7 @@ Name:Honor the God-Pharaoh ManaCost:2 R Types:Sorcery -A:SP$ Draw | Cost$ 2 R Discard<1/Card> | CostDesc$ As an additional cost to cast CARDNAME, discard a card. | NumCards$ 2 | Defined$ You | SubAbility$ DBAmass | SpellDescription$ Draw two cards. Amass 1. (Put a +1/+1 counter on an Army you control. If you don't control one, create a 0/0 black Zombie Army creature token first.) +A:SP$ Draw | Cost$ 2 R Discard<1/Card> | CostDesc$ As an additional cost to cast this spell, discard a card. | NumCards$ 2 | Defined$ You | SubAbility$ DBAmass | SpellDescription$ Draw two cards. Amass 1. (Put a +1/+1 counter on an Army you control. If you don't control one, create a 0/0 black Zombie Army creature token first.) SVar:DBAmass:DB$ Amass | Num$ 1 DeckHas:Ability$Discard & Ability$Amass & Ability$Counters & Ability$Token DeckHints:Keyword$Madness & Ability$Delirium & Ability$Amass & Type$Zombie diff --git a/forge-gui/res/cardsfolder/i/infernal_harvest.txt b/forge-gui/res/cardsfolder/i/infernal_harvest.txt index 5341fa462d2..4ca7c61da28 100644 --- a/forge-gui/res/cardsfolder/i/infernal_harvest.txt +++ b/forge-gui/res/cardsfolder/i/infernal_harvest.txt @@ -6,5 +6,4 @@ SVar:MaxTgts:Count$Valid Creature SVar:X:Count$XChoice #X Will get overwritten by Announce AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/infernal_harvest.jpg -Oracle:As an additional cost to cast Infernal Harvest, return X Swamps you control to their owner's hand.\nInfernal Harvest deals X damage divided as you choose among any number of target creatures. +Oracle:As an additional cost to cast this spell, return X Swamps you control to their owner's hand.\nInfernal Harvest deals X damage divided as you choose among any number of target creatures. diff --git a/forge-gui/res/cardsfolder/i/inferno_trap.txt b/forge-gui/res/cardsfolder/i/inferno_trap.txt index a3e7db4e746..4e51a0b3380 100644 --- a/forge-gui/res/cardsfolder/i/inferno_trap.txt +++ b/forge-gui/res/cardsfolder/i/inferno_trap.txt @@ -1,9 +1,8 @@ Name:Inferno Trap ManaCost:3 R Types:Instant Trap +SVar:AltCost:Cost$ R | CheckSVar$ CreaturesAttacked | References$ CreaturesAttacked | SVarCompare$ GE2 | Description$ If you've been dealt damage by two or more creatures this turn, you may pay {R} rather than pay this spell's mana cost. A:SP$ DealDamage | Cost$ 3 R | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 4 | SpellDescription$ CARDNAME deals 4 damage to target creature. -A:SP$ DealDamage | Cost$ R | CheckSVar$ CreaturesAttacked | SVarCompare$ GE2 | ValidTgts$ Creature | References$ CreaturesAttacked | TgtPrompt$ Select target creature | NumDmg$ 4 | SpellDescription$ If you've been dealt damage by two or more creatures this turn, you may pay {R} rather than pay CARDNAME's mana cost. SVar:CreaturesAttacked:Count$YourDamageSourcesThisTurn Creature AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/inferno_trap.jpg -Oracle:If you've been dealt damage by two or more creatures this turn, you may pay {R} rather than pay Inferno Trap's mana cost.\nInferno Trap deals 4 damage to target creature. +Oracle:If you've been dealt damage by two or more creatures this turn, you may pay {R} rather than pay this spell's mana cost.\nInferno Trap deals 4 damage to target creature. diff --git a/forge-gui/res/cardsfolder/i/inscription_of_abundance.txt b/forge-gui/res/cardsfolder/i/inscription_of_abundance.txt new file mode 100644 index 00000000000..e022e047e90 --- /dev/null +++ b/forge-gui/res/cardsfolder/i/inscription_of_abundance.txt @@ -0,0 +1,14 @@ +Name:Inscription of Abundance +ManaCost:1 G +Types:Instant +K:Kicker:2 G +A:SP$ Charm | Cost$ 1 G | MinCharmNum$ X | CharmNum$ Y | References$ X,Y | Choices$ DBPutCounter,DBGainLife,DBPump | AdditionalDescription$ If this spell was kicked, choose any number instead. +SVar:DBPutCounter:DB$ PutCounter | ValidTgts$ Creature | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ 2 | SpellDescription$ Put two +1/+1 counters on target creature. +SVar:DBGainLife:DB$ GainLife | ValidTgts$ Player | TgtPrompt$ Select target player | LifeAmount$ Z | References$ Z | SpellDescription$ Target player gains X life, where X is the greatest power among creatures they control. +SVar:DBPump:DB$ Pump | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | AILogic$ Fight | SubAbility$ DBFight | SpellDescription$ Target creature you control fights target creature you don't control. +SVar:DBFight:DB$ Fight | Defined$ ParentTarget | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Select target creature you don't control +SVar:X:Count$Kicked.0.1 +SVar:Y:Count$Kicked.3.1 +SVar:Z:Count$GreatestPower_Creature.TargetedPlayerCtrl +Oracle:Kicker {2}{G}\nChoose one. If this spell was kicked, choose any number instead.\n• Put two +1/+1 counters on target creature.\n• Target player gains X life, where X is the greatest power among creatures they control.\n• Target creature you control fights target creature you don't control. + diff --git a/forge-gui/res/cardsfolder/i/inscription_of_insight.txt b/forge-gui/res/cardsfolder/i/inscription_of_insight.txt new file mode 100644 index 00000000000..4752572a7eb --- /dev/null +++ b/forge-gui/res/cardsfolder/i/inscription_of_insight.txt @@ -0,0 +1,14 @@ +Name:Inscription of Insight +ManaCost:3 U +Types:Sorcery +K:Kicker:2 U U +A:SP$ Charm | Cost$ 3 U | MinCharmNum$ X | CharmNum$ Y | References$ X,Y | Choices$ DBReturn,DBScry,DBToken | AdditionalDescription$ If this spell was kicked, choose any number instead. +SVar:DBReturn:DB$ ChangeZone | TargetMin$ 0 | TargetMax$ 2 | ValidTgts$ Creature | TgtPrompt$ Select up to two target creatures | Origin$ Battlefield | Destination$ Hand | SpellDescription$ Return up to two target creatures to their owners' hands. +SVar:DBScry:DB$ Scry | ScryNum$ 2 | SubAbility$ DBDraw | SpellDescription$ Scry 2, then draw two cards. +SVar:DBDraw:DB$ Draw | NumCards$ 2 +SVar:DBToken:DB$ Token | ValidTgts$ Player | TgtPrompt$ Select target player | TokenAmount$ 1 | TokenScript$ u_x_x_illusion | TokenOwner$ TargetedPlayer | TokenPower$ Z | TokenToughness$ Z | References$ Z | SpellDescription$ Target player creates an X/X blue Illusion creature token, where X is the number of cards in their hand. +SVar:X:Count$Kicked.0.1 +SVar:Y:Count$Kicked.3.1 +SVar:Z:TargetedPlayer$CardsInHand +Oracle:Kicker {2}{U}{U}\nChoose one. If this spell was kicked, choose any number instead.\n• Return up to two target creatures to their owners’ hands.\n• Scry 2, then draw two cards.\n• Target player creates an X/X blue Illusion creature token, where X is the number of cards in their hand. + diff --git a/forge-gui/res/cardsfolder/i/inscription_of_ruin.txt b/forge-gui/res/cardsfolder/i/inscription_of_ruin.txt new file mode 100644 index 00000000000..8674495dcaf --- /dev/null +++ b/forge-gui/res/cardsfolder/i/inscription_of_ruin.txt @@ -0,0 +1,12 @@ +Name:Inscription of Ruin +ManaCost:2 B +Types:Sorcery +K:Kicker:2 B B +A:SP$ Charm | Cost$ 2 B | MinCharmNum$ X | CharmNum$ Y | References$ X,Y | Choices$ DBDiscard,DBReturn,DBDestroy | AdditionalDescription$ If this spell was kicked, choose any number instead. +SVar:DBDiscard:DB$ Discard | ValidTgts$ Opponent | NumCards$ 2 | Mode$ TgtChoose | SpellDescription$ Target opponent discards two cards. +SVar:DBReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Card.Creature+cmcLE2+YouOwn | TgtPrompt$ Select target creature card with converted mana cost 2 or less | SpellDescription$ Return target creature card with converted mana cost 2 or less from your graveyard to the battlefield. +SVar:DBDestroy:DB$ Destroy | ValidTgts$ Creature.cmcLE3 | TgtPrompt$ Select target creature with converted mana cost 3 or less | SpellDescription$ Destroy target creature with converted mana cost 3 or less. +SVar:X:Count$Kicked.0.1 +SVar:Y:Count$Kicked.3.1 +Oracle:Kicker {2}{B}{B}\nChoose one. If this spell was kicked, choose any number instead.\n• Target opponent discards two cards.\n• Return target creature card with converted mana cost 2 or less from your graveyard to the battlefield.\n• Destroy target creature with converted mana cost 3 or less. + diff --git a/forge-gui/res/cardsfolder/i/invigorate.txt b/forge-gui/res/cardsfolder/i/invigorate.txt index 419a5dbf53b..058809edeb2 100644 --- a/forge-gui/res/cardsfolder/i/invigorate.txt +++ b/forge-gui/res/cardsfolder/i/invigorate.txt @@ -1,7 +1,6 @@ Name:Invigorate ManaCost:2 G Types:Instant +SVar:AltCost:Cost$ GainLife<3/Player.Opponent> | IsPresent$ Forest.YouCtrl | Description$ If you control a Forest, rather than pay this spell's mana cost, you may have an opponent gain 3 life. A:SP$ Pump | Cost$ 2 G | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +4 | NumDef$ +4 | SpellDescription$ Target creature gets +4/+4 until end of turn. -A:SP$ Pump | Cost$ GainLife<3/Player.Opponent> | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +4 | NumDef$ +4 | IsPresent$ Forest.YouCtrl | PrecostDesc$ If you control a Forest, rather than pay CARDNAME's mana cost, | CostDesc$ you may have an opponent gain 3 life | SpellDescription$ . -SVar:Picture:http://www.wizards.com/global/images/magic/general/invigorate.jpg -Oracle:If you control a Forest, rather than pay Invigorate's mana cost, you may have an opponent gain 3 life.\nTarget creature gets +4/+4 until end of turn. +Oracle:If you control a Forest, rather than pay this spell's mana cost, you may have an opponent gain 3 life.\nTarget creature gets +4/+4 until end of turn. diff --git a/forge-gui/res/cardsfolder/i/iridescent_hornbeetle.txt b/forge-gui/res/cardsfolder/i/iridescent_hornbeetle.txt new file mode 100644 index 00000000000..9f93bfe7635 --- /dev/null +++ b/forge-gui/res/cardsfolder/i/iridescent_hornbeetle.txt @@ -0,0 +1,11 @@ +Name:Iridescent Hornbeetle +ManaCost:4 G +Types:Creature Insect +PT:3/4 +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ At the beginning of your end step, create a 1/1 green Insect creature token for each +1/+1 counter you've put on creatures under your control this turn. +SVar:TrigToken:DB$ Token | TokenAmount$ X | References$ X | TokenOwner$ You | TokenScript$ g_1_1_insect +SVar:X:Count$CountersAddedThisTurn P1P1 You Creature.YouCtrl +DeckNeeds:Ability$Counters +DeckHas:Ability$Counters +Oracle:At the beginning of your end step, create a 1/1 green Insect creature token for each +1/+1 counter you've put on creatures under your control this turn. + diff --git a/forge-gui/res/cardsfolder/j/jade_monolith.txt b/forge-gui/res/cardsfolder/j/jade_monolith.txt index 699614bd74f..694ae7992ae 100644 --- a/forge-gui/res/cardsfolder/j/jade_monolith.txt +++ b/forge-gui/res/cardsfolder/j/jade_monolith.txt @@ -3,12 +3,11 @@ ManaCost:4 Types:Artifact A:AB$ ChooseSource | Cost$ 1 | Choices$ Card,Emblem | AILogic$ NeedsPrevention | SubAbility$ DBEffect | SpellDescription$ The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to you instead. SVar:DBEffect:DB$ Effect | ValidTgts$ Creature | TgtPrompt$ Select target creature to redirect the damage from | ReplacementEffects$ SelflessDamage | Triggers$ OutOfSight | SVars$ SelflessDamage,OutOfSight,SelflessDmg,ExileEffect | Duration$ HostLeavesOrEOT | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | SubAbility$ DBCleanup | ConditionDefined$ ChosenCard | ConditionPresent$ Card,Emblem | ConditionCompare$ GE1 -SVar:SelflessDamage:Event$ DamageDone | ValidTarget$ Creature.IsRemembered | ValidSource$ Card.ChosenCard,Emblem.ChosenCard | ReplaceWith$ SelflessDmg | Description$ The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to you instead. +SVar:SelflessDamage:Event$ DamageDone | ValidTarget$ Creature.IsRemembered | ValidSource$ Card.ChosenCard,Emblem.ChosenCard | ReplaceWith$ SelflessDmg | DamageTarget$ You | Description$ The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to you instead. SVar:SelflessDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ You | VarType$ Player | SubAbility$ ExileEffect #Zone Change for the source of your choice SVar:OutOfSight:Mode$ ChangesZone | Origin$ Any | Destination$ Any | Defined$ ChosenCard | Execute$ ExileEffect | Static$ True SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile | Static$ True SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/jade_monolith.jpg Oracle:{1}: The next time a source of your choice would deal damage to target creature this turn, that source deals that damage to you instead. diff --git a/forge-gui/res/cardsfolder/k/kargan_intimidator.txt b/forge-gui/res/cardsfolder/k/kargan_intimidator.txt index f26e3246a31..44838f413c7 100755 --- a/forge-gui/res/cardsfolder/k/kargan_intimidator.txt +++ b/forge-gui/res/cardsfolder/k/kargan_intimidator.txt @@ -4,9 +4,7 @@ Types:Creature Human Warrior PT:3/1 S:Mode$ Continuous | Affected$ Creature.Coward | AddHiddenKeyword$ CantBlock Creature.Warrior:Warriors | Description$ Cowards can't block Warriors. SVar:PlayMain1:TRUE -T:Mode$ TurnBegin | ValidPlayer$ Player | Static$ True | TriggerZones$ Battlefield | Execute$ CharmReset -SVar:CharmReset:DB$ Cleanup | ClearRemembered$ True -A:AB$ Charm | Cost$ 1 | Choices$ Pump,Coward,Trample | ChoiceRestriction$ NotRemembered | RememberChoice$ True | CharmNum$ 1 +A:AB$ Charm | Cost$ 1 | Choices$ Pump,Coward,Trample | ChoiceRestriction$ ThisTurn | CharmNum$ 1 SVar:Pump:DB$ Pump | Defined$ Self | NumAtt$ 1 | NumDef$ 1 | SpellDescription$ CARDNAME gets +1/+1 until end of turn. SVar:Coward:DB$ Animate | ValidTgts$ Creature | TgtPrompt$ Select target creature | Types$ Coward | RemoveCreatureTypes$ True | SpellDescription$ Target creature becomes a Coward until end of turn. SVar:Trample:DB$ Pump | ValidTgts$ Warrior | TgtPrompt$ Select target Warrior | KW$ Trample | SpellDescription$ Target Warrior gains trample until end of turn. diff --git a/forge-gui/res/cardsfolder/k/karn_the_great_creator.txt b/forge-gui/res/cardsfolder/k/karn_the_great_creator.txt index ecfa34f2385..a265961052c 100644 --- a/forge-gui/res/cardsfolder/k/karn_the_great_creator.txt +++ b/forge-gui/res/cardsfolder/k/karn_the_great_creator.txt @@ -6,6 +6,6 @@ S:Mode$ Continuous | Affected$ Artifact.OppCtrl | AddHiddenKeyword$ CARDNAME's a SVar:NonStackingEffect:True A:AB$ Animate | Cost$ AddCounter<1/LOYALTY> | TargetMin$ 0 | TargetMax$ 1 | Planeswalker$ True | ValidTgts$ Artifact.nonCreature | TgtPrompt$ Select target noncreature artifact | Power$ X | Toughness$ X | Types$ Artifact,Creature | References$ X | UntilYourNextTurn$ True | AILogic$ PTByCMC | SpellDescription$ Until your next turn, up to one target noncreature artifact becomes an artifact creature with power and toughness equal to its converted mana cost. SVar:X:Targeted$CardManaCost -A:AB$ ChangeZone | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | Origin$ Sideboard,Exile | Destination$ Hand | ChangeType$ Artifact.YouOwn | ChangeNum$ 1 | SpellDescription$ You may choose an artifact card you own from outside the game or in exile, reveal that card, and put it into your hand. +A:AB$ ChangeZone | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | Origin$ Sideboard,Exile | Destination$ Hand | ChangeType$ Artifact.YouOwn | ChangeTypeDesc$ artifact they own | ChangeNum$ 1 | Hidden$ True | Reveal$ True | StackDescription$ {p:You} may reveal an artifact card they own from outside the game or in exile and put it into their hand. | SpellDescription$ You may reveal an artifact card you own from outside the game or in exile and put it into your hand. AI:RemoveDeck:Random -Oracle:Activated abilities of artifacts your opponents control can't be activated.\n[+1]: Until your next turn, up to one target noncreature artifact becomes an artifact creature with power and toughness equal to its converted mana cost.\n[-2]: You may choose an artifact card you own from outside the game or in exile, reveal that card, and put it into your hand. +Oracle:Activated abilities of artifacts your opponents control can't be activated.\n[+1]: Until your next turn, up to one target noncreature artifact becomes an artifact creature with power and toughness equal to its converted mana cost.\n[-2]: You may reveal an artifact card you own from outside the game or in exile and put it into your hand. diff --git a/forge-gui/res/cardsfolder/k/kinnan_bonder_prodigy.txt b/forge-gui/res/cardsfolder/k/kinnan_bonder_prodigy.txt index 69077cc3d6a..e73a35fff33 100755 --- a/forge-gui/res/cardsfolder/k/kinnan_bonder_prodigy.txt +++ b/forge-gui/res/cardsfolder/k/kinnan_bonder_prodigy.txt @@ -4,5 +4,5 @@ Types:Legendary Creature Human Druid PT:2/2 T:Mode$ TapsForMana | ValidCard$ Permanent.nonLand+YouCtrl | Execute$ TrigMana | TriggerZones$ Battlefield | Static$ True | TriggerDescription$ Whenever you tap a nonland permanent for mana, add one mana of any type that permanent produced. SVar:TrigMana:DB$ ManaReflected | ColorOrType$ Type | Valid$ Defined.Triggered | ReflectProperty$ Produced | Defined$ TriggeredPlayer -A:AB$ Dig | Cost$ 5 G U | DigNum$ 5 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Creature.nonHuman | DestinationZone$ Battlefield | RestRandomOrder$ True | SpellDescription$ Look at the top five cards of your library. You may put a non-Human creature card from among them onto the battlefield. Put the rest on the bottom of your library in a random order. +A:AB$ Dig | Cost$ 5 G U | ForceRevealToController$ True | DigNum$ 5 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Creature.nonHuman | DestinationZone$ Battlefield | RestRandomOrder$ True | SpellDescription$ Look at the top five cards of your library. You may put a non-Human creature card from among them onto the battlefield. Put the rest on the bottom of your library in a random order. Oracle:Whenever you tap a nonland permanent for mana, add one mana of any type that permanent produced.\n{5}{G}{U}: Look at the top five cards of your library. You may put a non-Human creature card from among them onto the battlefield. Put the rest on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/k/kytheon_hero_of_akros.txt b/forge-gui/res/cardsfolder/k/kytheon_hero_of_akros.txt index 583b68ad5d2..c231d378422 100644 --- a/forge-gui/res/cardsfolder/k/kytheon_hero_of_akros.txt +++ b/forge-gui/res/cardsfolder/k/kytheon_hero_of_akros.txt @@ -2,17 +2,14 @@ Name:Kytheon, Hero of Akros ManaCost:W Types:Legendary Creature Human Soldier PT:2/1 -T:Mode$ Phase | Phase$ EndCombat | ValidPlayer$ Player | CheckSVar$ CanFlip | SVarCompare$ GE3 | TriggerZones$ Battlefield | Execute$ TrigExile | TriggerDescription$ At end of combat, if CARDNAME and at least two other creatures attacked this combat, exile CARDNAME, then return him to the battlefield transformed under his owner's control. +T:Mode$ Phase | Mode$ Phase | Phase$ EndCombat | CheckSVar$ X | SVarCompare$ GE3 | Execute$ TrigExile | TriggerDescription$ At end of combat, if CARDNAME and at least two other creatures attacked this combat, exile CARDNAME, then return him to the battlefield transformed under his owner's control. SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DBReturn SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | Transformed$ True | ForgetOtherRemembered$ True | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -# Fix for Kytheon except for Manifested corner case -T:Mode$ Attacks | ValidCard$ Card.YouCtrl | Execute$ KytheonReset | Static$ True -SVar:KytheonReset:DB$ StoreSVar | SVar$ CanFlip | Type$ Number | Expression$ 0 | SubAbility$ KytheonsFriends -SVar:KytheonsFriends:DB$ StoreSVar | SVar$ CanFlip | Type$ Count | Expression$ Valid Card.attackedThisCombat | ConditionPresent$ Card.attackedThisCombat+Self +SVar:X:SVar$Y/Plus.Z +SVar:Y:Count$Valid Card.Self+attackedThisCombat +SVar:Z:Count$Valid Creature.Other+attackedThisCombat/LimitMax.2 A:AB$ Pump | Cost$ 2 W | Defined$ Self | KW$ Indestructible | SpellDescription$ CARDNAME gains indestructible until end of turn. -SVar:CanFlip:Number$0 -SVar:Picture:http://www.wizards.com/global/images/magic/general/kytheon_hero_of_akros.jpg AlternateMode:DoubleFaced Oracle:At end of combat, if Kytheon, Hero of Akros and at least two other creatures attacked this combat, exile Kytheon, then return him to the battlefield transformed under his owner's control.\n{2}{W}: Kytheon gains indestructible until end of turn. @@ -28,5 +25,4 @@ A:AB$ Pump | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Creat SVar:DBUntap:DB$ Untap | Defined$ Targeted A:AB$ Animate | Cost$ AddCounter<0/LOYALTY> | Defined$ Self | Power$ 4 | Toughness$ 4 | Types$ Creature,Human,Soldier | Keywords$ Indestructible | SubAbility$ DBPrevent | Planeswalker$ True | Ultimate$ True | SpellDescription$ Until end of turn, CARDNAME becomes a 4/4 Human Soldier creature with indestructible that's still a planeswalker. Prevent all damage that would be dealt to him this turn. SVar:DBPrevent:DB$ Pump | Defined$ Self | KW$ Prevent all damage that would be dealt to CARDNAME. -SVar:Picture:http://www.wizards.com/global/images/magic/general/gideon_battle_forged.jpg Oracle:[+2]: Up to one target creature an opponent controls attacks Gideon, Battle-Forged during its controller's next turn if able.\n[+1]: Until your next turn, target creature gains indestructible. Untap that creature.\n[0]: Until end of turn, Gideon, Battle-Forged becomes a 4/4 Human Soldier creature with indestructible that's still a planeswalker. Prevent all damage that would be dealt to him this turn. diff --git a/forge-gui/res/cardsfolder/l/land_grant.txt b/forge-gui/res/cardsfolder/l/land_grant.txt index 68879b78d06..b1c4fdd234f 100644 --- a/forge-gui/res/cardsfolder/l/land_grant.txt +++ b/forge-gui/res/cardsfolder/l/land_grant.txt @@ -4,5 +4,4 @@ Types:Sorcery S:Mode$ Continuous | Affected$ Card.Self | EffectZone$ All | AddKeyword$ Alternative Cost:Reveal<1/Hand> | CheckSVar$ X | SVarCompare$ EQ0 | Description$ If you have no land cards in hand, you may reveal your hand rather than pay Land Grant's mana cost. SVar:X:Count$TypeInYourHand.Land A:SP$ ChangeZone | Cost$ 1 G | Origin$ Library | Destination$ Hand | ChangeType$ Forest | ChangeNum$ 1 | SpellDescription$ Search your library for a Forest card, reveal that card, and put it into your hand. Then shuffle your library. -SVar:Picture:http://www.wizards.com/global/images/magic/general/land_grant.jpg -Oracle:If you have no land cards in hand, you may reveal your hand rather than pay Land Grant's mana cost.\nSearch your library for a Forest card, reveal that card, and put it into your hand. Then shuffle your library. +Oracle:If you have no land cards in hand, you may reveal your hand rather than pay this spell's mana cost.\nSearch your library for a Forest card, reveal that card, and put it into your hand. Then shuffle your library. diff --git a/forge-gui/res/cardsfolder/l/lashknife.txt b/forge-gui/res/cardsfolder/l/lashknife.txt index 209763bc792..37d95cab8a9 100644 --- a/forge-gui/res/cardsfolder/l/lashknife.txt +++ b/forge-gui/res/cardsfolder/l/lashknife.txt @@ -2,8 +2,7 @@ Name:Lashknife ManaCost:1 W Types:Enchantment Aura K:Enchant creature +SVar:AltCost:Cost$ tapXType<1/Creature> | IsPresent$ Plains.YouCtrl | Description$ If you control a Plains, you may tap an untapped creature you control rather than pay this spell's mana cost. A:SP$ Attach | Cost$ 1 W | ValidTgts$ Creature | AILogic$ Pump S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddKeyword$ First Strike | Description$ Enchanted creature has first strike. -SVar:AltCost:Cost$ tapXType<1/Creature> | IsPresent$ Plains.YouCtrl | Description$ If you control a Plains, you may tap an untapped creature you control rather than pay Lashknife's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/lashknife.jpg -Oracle:If you control a Plains, you may tap an untapped creature you control rather than pay Lashknife's mana cost.\nEnchant creature\nEnchanted creature has first strike. +Oracle:If you control a Plains, you may tap an untapped creature you control rather than pay this spell's mana cost.\nEnchant creature\nEnchanted creature has first strike. diff --git a/forge-gui/res/cardsfolder/l/lava_burst.txt b/forge-gui/res/cardsfolder/l/lava_burst.txt new file mode 100644 index 00000000000..7c743e849e4 --- /dev/null +++ b/forge-gui/res/cardsfolder/l/lava_burst.txt @@ -0,0 +1,7 @@ +Name:Lava Burst +ManaCost:X R +Types:Sorcery +A:SP$ DealDamage | Cost$ X R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | ConditionDefined$ Targeted | ConditionPresent$ Creature | ConditionCompare$ EQ0 | References$ X | SubAbility$ CreatureDmg | SpellDescription$ CARDNAME deals X damage to any target. If CARDNAME would deal damage to a creature, that damage can’t be prevented or dealt instead to another permanent or player. +SVar:CreatureDmg:DB$ DealDamage | Defined$ Targeted | NumDmg$ X | NoPrevention$ True | NoRedirection$ True | ConditionDefined$ Targeted | ConditionPresent$ Creature | ConditionCompare$ EQ1 | References$ X | StackDescription$ If CARDNAME would deal damage to a creature, that damage can’t be prevented or dealt instead to another permanent or player. +SVar:X:Count$xPaid +Oracle:Lava Burst deals X damage to any target. If Lava Burst would deal damage to a creature, that damage can’t be prevented or dealt instead to another permanent or player. diff --git a/forge-gui/res/cardsfolder/l/lavaball_trap.txt b/forge-gui/res/cardsfolder/l/lavaball_trap.txt index d995119f495..fe68ee7f3f5 100644 --- a/forge-gui/res/cardsfolder/l/lavaball_trap.txt +++ b/forge-gui/res/cardsfolder/l/lavaball_trap.txt @@ -1,9 +1,8 @@ Name:Lavaball Trap ManaCost:6 R R Types:Instant Trap -A:SP$Destroy | Cost$ 6 R R | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Land | TgtPrompt$ Select target land. | SubAbility$ DBDamageAll | SpellDescription$ Destroy two target lands. CARDNAME deals 4 damage to each creature. -A:SP$Destroy | Cost$ 3 R R | CheckSVar$ LandsEntered | SVarCompare$ GE2 | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Land | TgtPrompt$ Select target land. | SubAbility$ DBDamageAll | References$ LandsEntered | SpellDescription$ If an opponent had two or more lands enter the battlefield under their control this turn, you may pay {3}{R}{R} rather than pay CARDNAME's mana cost. -SVar:DBDamageAll:DB$DamageAll | ValidCards$ Creature | NumDmg$ 4 | ValidDescription$ each creature. +SVar:AltCost:Cost$ 3 R R | CheckSVar$ LandsEntered | SVarCompare$ GE2 | References$ LandsEntered | Description$ If an opponent had two or more lands enter the battlefield under their control this turn, you may pay {3}{R}{R} rather than pay this spell's mana cost. +A:SP$ Destroy | Cost$ 6 R R | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Land | TgtPrompt$ Select two target lands | SubAbility$ DBDamageAll | SpellDescription$ Destroy two target lands. CARDNAME deals 4 damage to each creature. +SVar:DBDamageAll:DB$ DamageAll | ValidCards$ Creature | NumDmg$ 4 | ValidDescription$ each creature. SVar:LandsEntered:PlayerCountOpponents$HighestValid Card.ThisTurnEntered_Battlefield_Land.YouCtrl -SVar:Picture:http://www.wizards.com/global/images/magic/general/lavaball_trap.jpg -Oracle:If an opponent had two or more lands enter the battlefield under their control this turn, you may pay {3}{R}{R} rather than pay Lavaball Trap's mana cost.\nDestroy two target lands. Lavaball Trap deals 4 damage to each creature. +Oracle:If an opponent had two or more lands enter the battlefield under their control this turn, you may pay {3}{R}{R} rather than pay this spell's mana cost.\nDestroy two target lands. Lavaball Trap deals 4 damage to each creature. diff --git a/forge-gui/res/cardsfolder/l/lethargy_trap.txt b/forge-gui/res/cardsfolder/l/lethargy_trap.txt index f5b65ffc438..2497f252de4 100644 --- a/forge-gui/res/cardsfolder/l/lethargy_trap.txt +++ b/forge-gui/res/cardsfolder/l/lethargy_trap.txt @@ -1,7 +1,6 @@ Name:Lethargy Trap ManaCost:3 U Types:Instant Trap +SVar:AltCost:Cost$ U | IsPresent$ Creature.attacking | PresentCompare$ GE3 | Description$ If three or more creatures are attacking, you may pay {U} rather than pay this spell's mana cost. A:SP$ PumpAll | Cost$ 3 U | ValidCards$ Creature.attacking | NumAtt$ -3 | IsCurse$ True | SpellDescription$ Attacking creatures get -3/-0 until end of turn. -A:SP$ PumpAll | Cost$ U | ValidCards$ Creature.attacking | NumAtt$ -3 | IsCurse$ True | IsPresent$ Creature.attacking | PresentCompare$ GE3 | NonBasicSpell$ True | SpellDescription$ If three or more creatures are attacking, you may pay {U} rather than pay CARDNAME mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/lethargy_trap.jpg -Oracle:If three or more creatures are attacking, you may pay {U} rather than pay Lethargy Trap's mana cost.\nAttacking creatures get -3/-0 until end of turn. +Oracle:If three or more creatures are attacking, you may pay {U} rather than pay this spell's mana cost.\nAttacking creatures get -3/-0 until end of turn. diff --git a/forge-gui/res/cardsfolder/l/liquid_fire.txt b/forge-gui/res/cardsfolder/l/liquid_fire.txt index 66a7ea5a2e6..f4d602329a1 100644 --- a/forge-gui/res/cardsfolder/l/liquid_fire.txt +++ b/forge-gui/res/cardsfolder/l/liquid_fire.txt @@ -1,11 +1,9 @@ Name:Liquid Fire ManaCost:4 R R Types:Sorcery -Text:As an additional cost to cast CARDNAME, choose a number between 0 and 5. -A:SP$ DealDamage | Cost$ 4 R R | AnnounceType$ ChooseNumber | Min$ 0 | Max$ 5 | ValidTgts$ Creature | NumDmg$ X | References$ X | SubAbility$ DBDmg | SpellDescription$ CARDNAME deals X damage to target creature and 5 minus X damage to that creature's controller, where X is the chosen number. +A:SP$ DealDamage | Cost$ 4 R R | CostDesc$ As an additional cost to cast this spell, choose a number between 0 and 5. | AnnounceType$ ChooseNumber | Min$ 0 | Max$ 5 | ValidTgts$ Creature | NumDmg$ X | References$ X | SubAbility$ DBDmg | SpellDescription$ CARDNAME deals X damage to target creature and 5 minus X damage to that creature's controller, where X is the chosen number. SVar:DBDmg:DB$ DealDamage | Defined$ TargetedController | NumDmg$ Y | References$ Y SVar:X:Count$ChosenNumber SVar:Y:SVar$X/NMinus.5 AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/liquid_fire.jpg -Oracle:As an additional cost to cast Liquid Fire, choose a number between 0 and 5.\nLiquid Fire deals X damage to target creature and 5 minus X damage to that creature's controller, where X is the chosen number. +Oracle:As an additional cost to cast this spell, choose a number between 0 and 5.\nLiquid Fire deals X damage to target creature and 5 minus X damage to that creature's controller, where X is the chosen number. diff --git a/forge-gui/res/cardsfolder/l/living_wish.txt b/forge-gui/res/cardsfolder/l/living_wish.txt index 729a86aa84e..2344e43c060 100644 --- a/forge-gui/res/cardsfolder/l/living_wish.txt +++ b/forge-gui/res/cardsfolder/l/living_wish.txt @@ -1,8 +1,7 @@ Name:Living Wish ManaCost:1 G Types:Sorcery -A:SP$ ChangeZone | Cost$ 1 G | Origin$ Sideboard | Destination$ Hand | ChangeType$ Creature.YouOwn,Land.YouOwn | ChangeNum$ 1 | SubAbility$ DBChange | SpellDescription$ You may choose a creature or land card you own from outside the game, reveal that card, and put it into your hand. Exile CARDNAME. +A:SP$ ChangeZone | Cost$ 1 G | Origin$ Sideboard | Destination$ Hand | ChangeType$ Creature.YouOwn,Land.YouOwn | ChangeTypeDesc$ creature or land card they own | ChangeNum$ 1 | Reveal$ True | Hidden$ True | SubAbility$ DBChange | SpellDescription$ You may reveal a creature or land card you own from outside the game and put it into your hand. Exile CARDNAME. SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/living_wish.jpg -Oracle:You may choose a creature or land card you own from outside the game, reveal that card, and put it into your hand. Exile Living Wish. +Oracle:You may reveal a creature or land card you own from outside the game and put it into your hand. Exile Living Wish. diff --git a/forge-gui/res/cardsfolder/m/magma_rift.txt b/forge-gui/res/cardsfolder/m/magma_rift.txt index b0384a7ebe1..e61be675487 100644 --- a/forge-gui/res/cardsfolder/m/magma_rift.txt +++ b/forge-gui/res/cardsfolder/m/magma_rift.txt @@ -1,6 +1,5 @@ Name:Magma Rift ManaCost:2 R Types:Sorcery -A:SP$ DealDamage | Cost$ 2 R Sac<1/Land> | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 5 | SpellDescription$ CARDNAME deals 5 damage to target creature. -SVar:Picture:http://www.wizards.com/global/images/magic/general/magma_rift.jpg -Oracle:As an additional cost to cast Magma Rift, sacrifice a land.\nMagma Rift deals 5 damage to target creature. +A:SP$ DealDamage | Cost$ 2 R Sac<1/Land/land> | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 5 | SpellDescription$ CARDNAME deals 5 damage to target creature. +Oracle:As an additional cost to cast this spell, sacrifice a land.\nMagma Rift deals 5 damage to target creature. diff --git a/forge-gui/res/cardsfolder/m/magmatic_insight.txt b/forge-gui/res/cardsfolder/m/magmatic_insight.txt index 2f85c216fe2..820294dc9e8 100644 --- a/forge-gui/res/cardsfolder/m/magmatic_insight.txt +++ b/forge-gui/res/cardsfolder/m/magmatic_insight.txt @@ -1,7 +1,6 @@ Name:Magmatic Insight ManaCost:R Types:Sorcery -A:SP$ Draw | Cost$ R Discard<1/Land> | CostDesc$ As an additional cost to cast CARDNAME, discard a land card. | NumCards$ 2 | Defined$ You | SpellDescription$ Draw two cards. +A:SP$ Draw | Cost$ R Discard<1/Land/land card> | CostDesc$ As an additional cost to cast this spell, discard a land card. | NumCards$ 2 | Defined$ You | SpellDescription$ Draw two cards. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/magmatic_insight.jpg -Oracle:As an additional cost to cast Magmatic Insight, discard a land card.\nDraw two cards. +Oracle:As an additional cost to cast this spell, discard a land card.\nDraw two cards. diff --git a/forge-gui/res/cardsfolder/m/mardu_outrider.txt b/forge-gui/res/cardsfolder/m/mardu_outrider.txt new file mode 100644 index 00000000000..c903a11114c --- /dev/null +++ b/forge-gui/res/cardsfolder/m/mardu_outrider.txt @@ -0,0 +1,6 @@ +Name:Mardu Outrider +ManaCost:1 B B +Types:Creature Orc Warrior +PT:5/5 +A:SP$ PermanentCreature | Cost$ 1 B B Discard<1/Card> +Oracle:As an additional cost to cast this spell, discard a card. diff --git a/forge-gui/res/cardsfolder/m/martyrdom.txt b/forge-gui/res/cardsfolder/m/martyrdom.txt new file mode 100644 index 00000000000..18dd0a1d31f --- /dev/null +++ b/forge-gui/res/cardsfolder/m/martyrdom.txt @@ -0,0 +1,8 @@ +Name:Martyrdom +ManaCost:1 W W +Types:Instant +A:SP$ Animate | Cost$ 1 W W | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | Abilities$ Martyr | sVars$ DamageEvent,DamageEventDmg,IsCreature | StackDescription$ Until end of turn, {c:Targeted} gains "{0}: The next 1 damage that would be dealt to target creature, planeswalker, or player this turn is dealt to this creature instead." | SpellDescription$ Until end of turn, target creature you control gains "{0}: The next 1 damage that would be dealt to target creature, planeswalker, or player this turn is dealt to this creature instead." Only you may activate this ability. +SVar:Martyr:AB$ Effect | Name$ Martyrdom Effect | Cost$ 0 | Activator$ Player.IsRemembered | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target to redirect damage from | Amount$ 1 | ReplacementEffects$ DamageEvent | SVars$ DamageEventDmg,IsCreature | References$ DamageEvent,DamageEventDmg,IsCreature | Duration$ HostLeavesOrEOT | RememberObjects$ You,Targeted | ImprintCards$ Self | ExileOnMoved$ Battlefield | StackDescription$ The next 1 damage that would be dealt to {c:Targeted}{p:Targeted} this turn is dealt to {c:Self} instead. | SpellDescription$ The next 1 damage that would be dealt to target creature, planeswalker, or player this turn is dealt to CARDNAME instead. +SVar:DamageEvent:Event$ DamageDone | IsPresent$ Card.IsImprinted+Creature | ValidTarget$ Player.IsRemembered,Card.IsRemembered | ReplaceWith$ DamageEventDmg | DamageTarget$ Imprinted | Description$ The next 1 damage that would be dealt to this target this turn is dealt to EFFECTSOURCE instead. +SVar:DamageEventDmg:DB$ ReplaceSplitDamage | DamageTarget$ Imprinted +Oracle:Until end of turn, target creature you control gains "{0}: The next 1 damage that would be dealt to target creature, planeswalker, or player this turn is dealt to this creature instead." Only you may activate this ability. diff --git a/forge-gui/res/cardsfolder/m/martyrs_of_korlis.txt b/forge-gui/res/cardsfolder/m/martyrs_of_korlis.txt index d25ce4f61d8..ad806e5088f 100644 --- a/forge-gui/res/cardsfolder/m/martyrs_of_korlis.txt +++ b/forge-gui/res/cardsfolder/m/martyrs_of_korlis.txt @@ -2,7 +2,6 @@ Name:Martyrs of Korlis ManaCost:3 W W Types:Creature Human PT:1/6 -R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Artifact | ValidTarget$ You | ReplaceWith$ DmgMe | IsPresent$ Card.Self+untapped | Description$ As long as CARDNAME is untapped, all damage that would be dealt to you by artifacts is dealt to CARDNAME instead. +R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Artifact | ValidTarget$ You | ReplaceWith$ DmgMe | IsPresent$ Card.Self+untapped | DamageTarget$ Self | Description$ As long as CARDNAME is untapped, all damage that would be dealt to you by artifacts is dealt to CARDNAME instead. SVar:DmgMe:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Self | VarType$ Card -SVar:Picture:http://www.wizards.com/global/images/magic/general/martyrs_of_korlis.jpg Oracle:As long as Martyrs of Korlis is untapped, all damage that would be dealt to you by artifacts is dealt to Martyrs of Korlis instead. diff --git a/forge-gui/res/cardsfolder/m/mask_of_the_mimic.txt b/forge-gui/res/cardsfolder/m/mask_of_the_mimic.txt index 259f64277df..885e508e08d 100644 --- a/forge-gui/res/cardsfolder/m/mask_of_the_mimic.txt +++ b/forge-gui/res/cardsfolder/m/mask_of_the_mimic.txt @@ -1,8 +1,7 @@ Name:Mask of the Mimic ManaCost:U Types:Instant -A:SP$ Pump | Cost$ U Sac<1/Creature> | ValidTgts$ Creature.nonToken | TgtPrompt$ Select target nontoken creature | StackDescription$ None | SubAbility$ DBChangeZone -SVar:DBChangeZone:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Targeted.sameName | ChangeNum$ 1 | Hidden$ True | StackDescription$ Search your library for a card with the same name as target nontoken creature and put that card onto the battlefield. | SpellDescription$ As an additional cost to cast CARDNAME, sacrifice a creature. Search your library for a card with the same name as target nontoken creature and put that card onto the battlefield. Then shuffle your library. +A:SP$ Pump | Cost$ U Sac<1/Creature/creature> | ValidTgts$ Creature.nonToken | TgtPrompt$ Select target nontoken creature | StackDescription$ None | SubAbility$ DBChangeZone +SVar:DBChangeZone:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Targeted.sameName | ChangeNum$ 1 | Hidden$ True | StackDescription$ Search your library for a card with the same name as target nontoken creature and put that card onto the battlefield. | SpellDescription$ As an additional cost to cast this spell, sacrifice a creature. Search your library for a card with the same name as target nontoken creature and put that card onto the battlefield. Then shuffle your library. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/mask_of_the_mimic.jpg -Oracle:As an additional cost to cast Mask of the Mimic, sacrifice a creature.\nSearch your library for a card with the same name as target nontoken creature and put that card onto the battlefield. Then shuffle your library. +Oracle:As an additional cost to cast this spell, sacrifice a creature.\nSearch your library for a card with the same name as target nontoken creature and put that card onto the battlefield. Then shuffle your library. diff --git a/forge-gui/res/cardsfolder/m/masterminds_acquisition.txt b/forge-gui/res/cardsfolder/m/masterminds_acquisition.txt index e65089aff08..7b52ff4a5e6 100644 --- a/forge-gui/res/cardsfolder/m/masterminds_acquisition.txt +++ b/forge-gui/res/cardsfolder/m/masterminds_acquisition.txt @@ -3,6 +3,5 @@ ManaCost:2 B B Types:Sorcery A:SP$ Charm | Cost$ 2 B B | Choices$ DBSearch,DBWish SVar:DBSearch:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Card | ChangeNum$ 1 | Mandatory$ True | SpellDescription$ Search your library for a card, put it into your hand, then shuffle your library. -SVar:DBWish:DB$ ChangeZone | Origin$ Sideboard | Destination$ Hand | ChangeType$ Card.YouOwn | ChangeNum$ 1 | Mandatory$ True | SpellDescription$ Choose a card you own from outside the game and put it into your hand. -SVar:Picture:http://www.wizards.com/global/images/magic/general/masterminds_acquisition.jpg -Oracle:Choose one —\n• Search your library for a card, put it into your hand, then shuffle your library.\n• Choose a card you own from outside the game and put it into your hand. +SVar:DBWish:DB$ ChangeZone | Origin$ Sideboard | Destination$ Hand | ChangeType$ Card.YouOwn | ChangeNum$ 1 | Mandatory$ True | Hidden$ True | SpellDescription$ Put a card you own from outside the game into your hand. +Oracle:Choose one —\n• Search your library for a card, put it into your hand, then shuffle your library.\n• Put a card you own from outside the game into your hand. diff --git a/forge-gui/res/cardsfolder/m/mind_swords.txt b/forge-gui/res/cardsfolder/m/mind_swords.txt index 59bb7a2252c..ab9edc8f0c0 100644 --- a/forge-gui/res/cardsfolder/m/mind_swords.txt +++ b/forge-gui/res/cardsfolder/m/mind_swords.txt @@ -1,9 +1,8 @@ Name:Mind Swords ManaCost:1 B Types:Sorcery -A:SP$ ChangeZone | Cost$ 1 B | Origin$ Hand | Destination$ Exile | ChangeType$ Card | ChangeNum$ 2 | Hidden$ True | Mandatory$ True | SubAbility$ DBExileOpp | SpellDescription$ Each player exiles two cards from their hand. -A:SP$ ChangeZone | Cost$ Sac<1/Creature> | IsPresent$ Swamp.YouCtrl | Origin$ Hand | Destination$ Exile | ChangeType$ Card | ChangeNum$ 2 | Hidden$ True | Mandatory$ True | SubAbility$ DBExileOpp | CostDesc$ If you control a Swamp, you may sacrifice a creature | SpellDescription$ rather than pay CARDNAME's mana cost. -SVar:DBExileOpp:DB$ ChangeZone | DefinedPlayer$ Opponent | Origin$ Hand | Destination$ Exile | ChangeType$ Card | ChangeNum$ 2 | Mandatory$ True | Hidden$ True +SVar:AltCost:Cost$ Sac<1/Creature/creature> | IsPresent$ Swamp.YouCtrl | Description$ If you control a Swamp, you may sacrifice a creature rather than pay this spell's mana cost. +A:SP$ RepeatEach | Cost$ 1 B | RepeatPlayers$ Player | RepeatSubAbility$ DBExile | StackDescription$ SpellDescription | SpellDescription$ Each player exiles two cards from their hand. +SVar:DBExile:DB$ ChangeZone | DefinedPlayer$ Player.IsRemembered | Chooser$ Player.IsRemembered | Origin$ Hand | Destination$ Exile | ChangeType$ Card | ChangeNum$ 2 | Hidden$ True | Mandatory$ True | SpellDescription$ exiles two cards from their hand. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/mind_swords.jpg -Oracle:If you control a Swamp, you may sacrifice a creature rather than pay Mind Swords's mana cost.\nEach player exiles two cards from their hand. +Oracle:If you control a Swamp, you may sacrifice a creature rather than pay this spell's mana cost.\nEach player exiles two cards from their hand. diff --git a/forge-gui/res/cardsfolder/m/mindbreak_trap.txt b/forge-gui/res/cardsfolder/m/mindbreak_trap.txt index 555879b29c4..76e493ac3f5 100644 --- a/forge-gui/res/cardsfolder/m/mindbreak_trap.txt +++ b/forge-gui/res/cardsfolder/m/mindbreak_trap.txt @@ -1,10 +1,9 @@ Name:Mindbreak Trap ManaCost:2 U U Types:Instant Trap -A:SP$ ChangeZone | Cost$ 2 U U | TargetType$ Spell | ValidTgts$ Card | TgtZone$ Stack | Origin$ Stack | Destination$ Exile | TargetMin$ 0 | TargetMax$ MaxTgts | References$ MaxTgts | Fizzle$ True | SpellDescription$ Exile any number of target spells. -A:SP$ ChangeZone | Cost$ 0 | CheckSVar$ OppCastThisTurn | SVarCompare$ GE3 | TargetType$ Spell | ValidTgts$ Card | TgtZone$ Stack | Origin$ Stack | Destination$ Exile | TargetMin$ 0 | TargetMax$ MaxTgts | References$ OppCastThisTurn,MaxTgts | Fizzle$ True | SpellDescription$ If an opponent cast three or more spells this turn, you may pay {0} rather than pay CARDNAME's mana cost. -SVar:OppCastThisTurn:Count$ThisTurnCast_Card.YouDontCtrl +SVar:AltCost:Cost$ 0 | CheckSVar$ OppCastThisTurn | SVarCompare$ GE3 | References$ OppCastThisTurn | Description$ If an opponent cast three or more spells this turn, you may pay {0} rather than pay this spell's mana cost. +A:SP$ ChangeZone | Cost$ 2 U U | TargetType$ Spell | ValidTgts$ Card | TgtZone$ Stack | Origin$ Stack | Destination$ Exile | TargetMin$ 0 | TargetMax$ MaxTgts | References$ MaxTgts | Fizzle$ True | StackDescription$ SpellDescription | SpellDescription$ Exile any number of target spells. +SVar:OppCastThisTurn:Count$ThisTurnCast_Card.OppCtrl SVar:MaxTgts:Count$SpellsOnStack AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/mindbreak_trap.jpg -Oracle:If an opponent cast three or more spells this turn, you may pay {0} rather than pay Mindbreak Trap's mana cost.\nExile any number of target spells. +Oracle:If an opponent cast three or more spells this turn, you may pay {0} rather than pay this spell's mana cost.\nExile any number of target spells. diff --git a/forge-gui/res/cardsfolder/m/mirror_strike.txt b/forge-gui/res/cardsfolder/m/mirror_strike.txt index b9029d0b991..81671624b4a 100644 --- a/forge-gui/res/cardsfolder/m/mirror_strike.txt +++ b/forge-gui/res/cardsfolder/m/mirror_strike.txt @@ -2,8 +2,7 @@ Name:Mirror Strike ManaCost:3 W Types:Instant A:SP$ Effect | Cost$ 3 W | Name$ Mirror Strike Effect | ReplacementEffects$ DamageEvent | SVars$ MirrorStrikeDmg | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | ValidTgts$ Creature.attacking+unblocked | TgtPrompt$ Select target unblocked creature | IsCurse$ True | SpellDescription$ All combat damage that would be dealt to you this turn by target unblocked creature is dealt to its controller instead. -SVar:DamageEvent:Event$ DamageDone | ValidSource$ Creature.IsRemembered | ValidTarget$ You | ReplaceWith$ MirrorStrikeDmg | IsCombat$ True | Description$ All combat damage that would be dealt to you this turn by target unblocked creature is dealt to its controller instead. +SVar:DamageEvent:Event$ DamageDone | ValidSource$ Creature.IsRemembered | ValidTarget$ You | ReplaceWith$ MirrorStrikeDmg | IsCombat$ True | DamageTarget$ ReplacedSourceController | Description$ All combat damage that would be dealt to you this turn by target unblocked creature is dealt to its controller instead. SVar:MirrorStrikeDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ ReplacedSourceController | VarType$ Player AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/mirror_strike.jpg Oracle:All combat damage that would be dealt to you this turn by target unblocked creature is dealt to its controller instead. diff --git a/forge-gui/res/cardsfolder/m/misdirection.txt b/forge-gui/res/cardsfolder/m/misdirection.txt index 81acda228bf..4344682116c 100644 --- a/forge-gui/res/cardsfolder/m/misdirection.txt +++ b/forge-gui/res/cardsfolder/m/misdirection.txt @@ -1,8 +1,7 @@ Name:Misdirection ManaCost:3 U U Types:Instant -SVar:AltCost:Cost$ ExileFromHand<1/Card.Blue> | Description$ You may exile a blue card from your hand rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ ExileFromHand<1/Card.Blue+Other> | Description$ You may exile a blue card from your hand rather than pay this spell's mana cost. A:SP$ ChangeTargets | Cost$ 3 U U | TargetType$ Spell | ValidTgts$ Card | TargetsSingleTarget$ True | SpellDescription$ Change the target of target spell with a single target. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/misdirection.jpg -Oracle:You may exile a blue card from your hand rather than pay Misdirection's mana cost.\nChange the target of target spell with a single target. +Oracle:You may exile a blue card from your hand rather than pay this spell's mana cost.\nChange the target of target spell with a single target. diff --git a/forge-gui/res/cardsfolder/m/mistvein_borderpost.txt b/forge-gui/res/cardsfolder/m/mistvein_borderpost.txt index 7afd37d6b84..a13ffb4372c 100644 --- a/forge-gui/res/cardsfolder/m/mistvein_borderpost.txt +++ b/forge-gui/res/cardsfolder/m/mistvein_borderpost.txt @@ -1,9 +1,8 @@ Name:Mistvein Borderpost ManaCost:1 U B Types:Artifact +SVar:AltCost:Cost$ 1 Return<1/Land.Basic> | Description$ You may pay {1} and return a basic land you control to its owner's hand rather than pay this spell's mana cost. K:CARDNAME enters the battlefield tapped. A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {U}. A:AB$ Mana | Cost$ T | Produced$ B | SpellDescription$ Add {B}. -SVar:AltCost:Cost$ 1 Return<1/Land.Basic> | Description$ You may pay {1} and return a basic land you control to its owner's hand rather than pay Mistvein Borderpost's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/mistvein_borderpost.jpg -Oracle:You may pay {1} and return a basic land you control to its owner's hand rather than pay Mistvein Borderpost's mana cost.\nMistvein Borderpost enters the battlefield tapped.\n{T}: Add {U} or {B}. +Oracle:You may pay {1} and return a basic land you control to its owner's hand rather than pay this spell's mana cost.\nMistvein Borderpost enters the battlefield tapped.\n{T}: Add {U} or {B}. diff --git a/forge-gui/res/cardsfolder/m/mogg_alarm.txt b/forge-gui/res/cardsfolder/m/mogg_alarm.txt index 2d8f8fbde31..ab944dd59ea 100644 --- a/forge-gui/res/cardsfolder/m/mogg_alarm.txt +++ b/forge-gui/res/cardsfolder/m/mogg_alarm.txt @@ -1,7 +1,6 @@ Name:Mogg Alarm ManaCost:1 R R Types:Sorcery -A:SP$ Token | Cost$ 1 R R | TokenAmount$ 2 | TokenScript$ r_1_1_goblin | TokenOwner$ You | SpellDescription$ Create two 1/1 red Goblin creature tokens. -A:SP$ Token | Cost$ Sac<2/Mountain> | TokenAmount$ 2 | TokenScript$ r_1_1_goblin | LegacyImage$ r 1 1 goblin nms | TokenOwner$ You | CostDesc$ You may sacrifice two Mountains | SpellDescription$ rather than pay CARDNAME's mana cost -SVar:Picture:http://www.wizards.com/global/images/magic/general/mogg_alarm.jpg -Oracle:You may sacrifice two Mountains rather than pay Mogg Alarm's mana cost.\nCreate two 1/1 red Goblin creature tokens. \ No newline at end of file +SVar:AltCost:Cost$ Sac<2/Mountain> | Description$ You may sacrifice two Mountains rather than pay this spell's mana cost. +A:SP$ Token | Cost$ 1 R R | TokenAmount$ 2 | TokenScript$ r_1_1_goblin | TokenOwner$ You | StackDescription$ {p:You} creates two 1/1 red Goblin creature tokens. | SpellDescription$ Create two 1/1 red Goblin creature tokens. +Oracle:You may sacrifice two Mountains rather than pay this spell's mana cost.\nCreate two 1/1 red Goblin creature tokens. diff --git a/forge-gui/res/cardsfolder/m/morbid_curiosity.txt b/forge-gui/res/cardsfolder/m/morbid_curiosity.txt index a5c0b6ae149..2de9077c126 100644 --- a/forge-gui/res/cardsfolder/m/morbid_curiosity.txt +++ b/forge-gui/res/cardsfolder/m/morbid_curiosity.txt @@ -3,5 +3,4 @@ ManaCost:1 B B Types:Sorcery A:SP$ Draw | Cost$ 1 B B Sac<1/Artifact;Creature/artifact or creature> | NumCards$ X | References$ X | SpellDescription$ Draw cards equal to the converted mana cost of the sacrificed permanent. SVar:X:Sacrificed$CardManaCost -SVar:Picture:http://www.wizards.com/global/images/magic/general/morbid_curiosity.jpg -Oracle:As an additional cost to cast Morbid Curiosity, sacrifice an artifact or creature.\nDraw cards equal to the converted mana cost of the sacrificed permanent. +Oracle:As an additional cost to cast this spell, sacrifice an artifact or creature.\nDraw cards equal to the converted mana cost of the sacrificed permanent. diff --git a/forge-gui/res/cardsfolder/m/muldrotha_the_gravetide.txt b/forge-gui/res/cardsfolder/m/muldrotha_the_gravetide.txt index 8f6f434bd20..15d41f3c2ff 100644 --- a/forge-gui/res/cardsfolder/m/muldrotha_the_gravetide.txt +++ b/forge-gui/res/cardsfolder/m/muldrotha_the_gravetide.txt @@ -1,10 +1,10 @@ Name:Muldrotha, the Gravetide -ManaCost: 3 B G U +ManaCost:3 B G U Types:Legendary Creature Elemental Avatar PT:6/6 -S:Mode$ Continuous | Affected$ Land.YouCtrl | Condition$ PlayerTurn | MayPlay$ True | MayPlayLimit$ 1 | MayPlayText$ Land | EffectZone$ Battlefield | AffectedZone$ Graveyard | Description$ During each of your turns, you may play up to one permanent card of each permanent type from your graveyard. (If a card has multiple permanent types, choose one as you play it.) -S:Mode$ Continuous | Affected$ Creature.YouCtrl | Condition$ PlayerTurn | MayPlay$ True | MayPlayLimit$ 1 | MayPlayText$ Creature | EffectZone$ Battlefield | AffectedZone$ Graveyard -S:Mode$ Continuous | Affected$ Planeswalker.YouCtrl | Condition$ PlayerTurn | MayPlay$ True | MayPlayLimit$ 1 | MayPlayText$ Planeswalker | EffectZone$ Battlefield | AffectedZone$ Graveyard -S:Mode$ Continuous | Affected$ Artifact.YouCtrl | Condition$ PlayerTurn | MayPlay$ True | MayPlayLimit$ 1 | MayPlayText$ Artifact | EffectZone$ Battlefield | AffectedZone$ Graveyard -S:Mode$ Continuous | Affected$ Enchantment.YouCtrl | Condition$ PlayerTurn | MayPlay$ True | MayPlayLimit$ 1 | MayPlayText$ Enchantment | EffectZone$ Battlefield | AffectedZone$ Graveyard -Oracle:During each of your turns, you may play up to one permanent card of each permanent type from your graveyard. (If a card has multiple permanent types, choose one as you play it.) +S:Mode$ Continuous | Affected$ Land.YouOwn | Condition$ PlayerTurn | MayPlay$ True | MayPlayLimit$ 1 | MayPlayText$ Land | EffectZone$ Battlefield | AffectedZone$ Graveyard | Description$ During each of your turns, you may play a land and cast a permanent spell of each permanent type from your graveyard. (If a card has multiple permanent types, choose one as you play it.) +S:Mode$ Continuous | Affected$ Creature.YouOwn+nonLand | Condition$ PlayerTurn | MayPlay$ True | MayPlayLimit$ 1 | MayPlayText$ Creature | EffectZone$ Battlefield | AffectedZone$ Graveyard +S:Mode$ Continuous | Affected$ Planeswalker.YouOwn+nonLand | Condition$ PlayerTurn | MayPlay$ True | MayPlayLimit$ 1 | MayPlayText$ Planeswalker | EffectZone$ Battlefield | AffectedZone$ Graveyard +S:Mode$ Continuous | Affected$ Artifact.YouOwn+nonLand | Condition$ PlayerTurn | MayPlay$ True | MayPlayLimit$ 1 | MayPlayText$ Artifact | EffectZone$ Battlefield | AffectedZone$ Graveyard +S:Mode$ Continuous | Affected$ Enchantment.YouOwn+nonLand | Condition$ PlayerTurn | MayPlay$ True | MayPlayLimit$ 1 | MayPlayText$ Enchantment | EffectZone$ Battlefield | AffectedZone$ Graveyard +Oracle:During each of your turns, you may play a land and cast a permanent spell of each permanent type from your graveyard. (If a card has multiple permanent types, choose one as you play it.) diff --git a/forge-gui/res/cardsfolder/n/needlebite_trap.txt b/forge-gui/res/cardsfolder/n/needlebite_trap.txt index a30b64e97b9..38d091405b3 100644 --- a/forge-gui/res/cardsfolder/n/needlebite_trap.txt +++ b/forge-gui/res/cardsfolder/n/needlebite_trap.txt @@ -1,9 +1,8 @@ Name:Needlebite Trap ManaCost:5 B B Types:Instant Trap -SVar:AltCost:Cost$ B | CheckSVar$ OppLifeGained | References$ OppLifeGained | Description$ If an opponent gained life this turn, you may pay {B} rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ B | CheckSVar$ OppLifeGained | References$ OppLifeGained | Description$ If an opponent gained life this turn, you may pay {B} rather than pay this spell's mana cost. SVar:OppLifeGained:PlayerCountOpponents$LifeGainedThisTurn A:SP$ LoseLife | Cost$ 5 B B | ValidTgts$ Player | TgtPrompt$ Select target player | LifeAmount$ 5 | SubAbility$ DBGainLife | SpellDescription$ Target player loses 5 life and you gain 5 life. SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 5 -SVar:Picture:http://www.wizards.com/global/images/magic/general/needlebite_trap.jpg -Oracle:If an opponent gained life this turn, you may pay {B} rather than pay Needlebite Trap's mana cost.\nTarget player loses 5 life and you gain 5 life. +Oracle:If an opponent gained life this turn, you may pay {B} rather than pay this spell's mana cost.\nTarget player loses 5 life and you gain 5 life. diff --git a/forge-gui/res/cardsfolder/n/nemesis_trap.txt b/forge-gui/res/cardsfolder/n/nemesis_trap.txt index 93758109cba..501b2e150d8 100644 --- a/forge-gui/res/cardsfolder/n/nemesis_trap.txt +++ b/forge-gui/res/cardsfolder/n/nemesis_trap.txt @@ -1,8 +1,7 @@ Name:Nemesis Trap ManaCost:4 B B Types:Instant Trap +SVar:AltCost:Cost$ B B | IsPresent$ Creature.White+attacking | Description$ If a white creature is attacking, you may pay {B}{B} rather than pay this spell's mana cost. A:SP$ ChangeZone | Cost$ 4 B B | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature | Origin$ Battlefield | Destination$ Exile | SubAbility$ NemesisToken | SpellDescription$ Exile target attacking creature. Create a token that's a copy of that creature. Exile it at the beginning of the next end step. -A:SP$ ChangeZone | Cost$ B B | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature | Origin$ Battlefield | Destination$ Exile | SubAbility$ NemesisToken | IsPresent$ Creature.White+attacking | SpellDescription$ If a white creature is attacking, you may pay {B}{B} rather than pay CARDNAME's mana cost. SVar:NemesisToken:DB$ CopyPermanent | Defined$ Targeted | AtEOT$ Exile -SVar:Picture:http://www.wizards.com/global/images/magic/general/nemesis_trap.jpg -Oracle:If a white creature is attacking, you may pay {B}{B} rather than pay Nemesis Trap's mana cost.\nExile target attacking creature. Create a token that's a copy of that creature. Exile it at the beginning of the next end step. +Oracle:If a white creature is attacking, you may pay {B}{B} rather than pay this spell's mana cost.\nExile target attacking creature. Create a token that's a copy of that creature. Exile it at the beginning of the next end step. diff --git a/forge-gui/res/cardsfolder/n/nourishing_shoal.txt b/forge-gui/res/cardsfolder/n/nourishing_shoal.txt index e239157a3eb..5dcb8c063a3 100644 --- a/forge-gui/res/cardsfolder/n/nourishing_shoal.txt +++ b/forge-gui/res/cardsfolder/n/nourishing_shoal.txt @@ -1,10 +1,10 @@ Name:Nourishing Shoal ManaCost:X G G Types:Instant Arcane -A:SP$ GainLife | Cost$ X G G | LifeAmount$ X | References$ X | SpellDescription$ You gain X life. -A:SP$ GainLife | Cost$ ExileFromHand<1/Card.Green> | CostDesc$ You may exile a green card from your hand rather than pay CARDNAME's mana cost. | LifeAmount$ Y | References$ Y | SpellDescription$ You gain X life, where X is the exiled card's converted mana cost. +SVar:AltCost:Cost$ ExileFromHand<1/Card.Green+Other/green card> | Description$ You may exile a green card with converted mana cost X from your hand rather than pay this spell's mana cost. +A:SP$ GainLife | Cost$ X G G | LifeAmount$ Z | References$ X,Y,Z | SpellDescription$ You gain X life. SVar:X:Count$xPaid SVar:Y:Exiled$CardManaCost +SVar:Z:SVar$Y/Plus.X AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/nourishing_shoal.jpg -Oracle:You may exile a green card with converted mana cost X from your hand rather than pay Nourishing Shoal's mana cost.\nYou gain X life. +Oracle:You may exile a green card with converted mana cost X from your hand rather than pay this spell's mana cost.\nYou gain X life. diff --git a/forge-gui/res/cardsfolder/n/nova_pentacle.txt b/forge-gui/res/cardsfolder/n/nova_pentacle.txt index 2e5c6e88787..306cd4257c3 100644 --- a/forge-gui/res/cardsfolder/n/nova_pentacle.txt +++ b/forge-gui/res/cardsfolder/n/nova_pentacle.txt @@ -3,7 +3,7 @@ ManaCost: 4 Types:Artifact A:AB$ ChooseSource | Cost$ 3 T | Choices$ Card,Emblem | AILogic$ NeedsPrevention | SubAbility$ DBEffect | SpellDescription$ The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead. SVar:DBEffect:DB$ Effect | TargetingPlayer$ Player.Opponent | ValidTgts$ Creature | TgtPrompt$ Select target creature to redirect the damage to | ReplacementEffects$ SelflessDamage | Triggers$ OutOfSight | SVars$ SelflessDamage,SelflessDmg,ExileEffect | References$ SelflessDamage,OutOfSight,SelflessDmg,ExileEffect | Duration$ HostLeavesOrEOT | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | SubAbility$ DBCleanup | ConditionDefined$ ChosenCard | ConditionPresent$ Card,Emblem | ConditionCompare$ GE1 | AILogic$ RedirectFromOppToCreature -SVar:SelflessDamage:Event$ DamageDone | ValidTarget$ You | ValidSource$ Card.ChosenCard,Emblem.ChosenCard | ReplaceWith$ SelflessDmg | Description$ The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead. +SVar:SelflessDamage:Event$ DamageDone | ValidTarget$ You | ValidSource$ Card.ChosenCard,Emblem.ChosenCard | ReplaceWith$ SelflessDmg | DamageTarget$ Remembered | Description$ The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead. SVar:SelflessDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Remembered | VarType$ Card | SubAbility$ ExileEffect #Zone Change for the source of your choice SVar:OutOfSight:Mode$ ChangesZone | Origin$ Any | Destination$ Any | Defined$ ChosenCard | Execute$ ExileEffect | Static$ True @@ -11,5 +11,4 @@ SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True AI:RemoveDeck:All AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/nova_pentacle.jpg Oracle:{3}, {T}: The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead. diff --git a/forge-gui/res/cardsfolder/o/orims_cure.txt b/forge-gui/res/cardsfolder/o/orims_cure.txt index d9ae9004d8b..130537f7f74 100644 --- a/forge-gui/res/cardsfolder/o/orims_cure.txt +++ b/forge-gui/res/cardsfolder/o/orims_cure.txt @@ -1,7 +1,6 @@ Name:Orim's Cure ManaCost:1 W Types:Instant -A:SP$ PreventDamage | Cost$ tapXType<1/Creature> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | Amount$ 4 | IsPresent$ Plains.YouCtrl | CostDesc$ Tap an untapped creature you control | SpellDescription$ Prevent the next 4 damage that would be dealt to any target this turn. +SVar:AltCost:Cost$ tapXType<1/Creature/creature> | IsPresent$ Plains.YouCtrl | Description$ If you control a Plains, you may tap an untapped creature you control rather than pay this spells's mana cost. A:SP$ PreventDamage | Cost$ 1 W | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | Amount$ 4 | SpellDescription$ Prevent the next 4 damage that would be dealt to any target this turn. -SVar:Picture:http://www.wizards.com/global/images/magic/general/orims_cure.jpg -Oracle:If you control a Plains, you may tap an untapped creature you control rather than pay Orim's Cure's mana cost.\nPrevent the next 4 damage that would be dealt to any target this turn. +Oracle:If you control a Plains, you may tap an untapped creature you control rather than pay this spells's mana cost.\nPrevent the next 4 damage that would be dealt to any target this turn. diff --git a/forge-gui/res/cardsfolder/o/outbreak.txt b/forge-gui/res/cardsfolder/o/outbreak.txt index 5525fa6395c..bad38638483 100644 --- a/forge-gui/res/cardsfolder/o/outbreak.txt +++ b/forge-gui/res/cardsfolder/o/outbreak.txt @@ -1,8 +1,8 @@ Name:Outbreak ManaCost:3 B Types:Sorcery +SVar:AltCost:Cost$ Discard<1/Swamp/Swamp card> | Description$ You may discard a Swamp card rather than pay this spell's mana cost. A:SP$ ChooseType | Cost$ 3 B | Defined$ You | Type$ Creature | SubAbility$ DBPumpAll | SpellDescription$ Choose a creature type. All creatures of that type get -1/-1 until end of turn. SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Creature.ChosenType | IsCurse$ True | NumAtt$ -1 | NumDef$ -1 | SpellDescription$ All creatures of that type get -1/-1 until end of turn. -SVar:AltCost:Cost$ Discard<1/Swamp> AI:RemoveDeck:All -Oracle:You may discard a Swamp card rather than pay Outbreak's mana cost.\nChoose a creature type. All creatures of that type get -1/-1 until end of turn. +Oracle:You may discard a Swamp card rather than pay this spell's mana cost.\nChoose a creature type. All creatures of that type get -1/-1 until end of turn. diff --git a/forge-gui/res/cardsfolder/p/palisade_giant.txt b/forge-gui/res/cardsfolder/p/palisade_giant.txt index aa5524e7448..40ca99fd820 100644 --- a/forge-gui/res/cardsfolder/p/palisade_giant.txt +++ b/forge-gui/res/cardsfolder/p/palisade_giant.txt @@ -2,7 +2,6 @@ Name:Palisade Giant ManaCost:4 W W Types:Creature Giant Soldier PT:2/7 -R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ You,Permanent.Other+YouCtrl | ReplaceWith$ DmgMe | Description$ All damage that would be dealt to you and other permanents you control is dealt to CARDNAME instead. +R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ You,Permanent.Other+YouCtrl | DamageTarget$ Self | ReplaceWith$ DmgMe | Description$ All damage that would be dealt to you and other permanents you control is dealt to CARDNAME instead. SVar:DmgMe:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Self | VarType$ Card -SVar:Picture:http://www.wizards.com/global/images/magic/general/palisade_giant.jpg Oracle:All damage that would be dealt to you and other permanents you control is dealt to Palisade Giant instead. diff --git a/forge-gui/res/cardsfolder/p/pariah.txt b/forge-gui/res/cardsfolder/p/pariah.txt index 605c5523775..74b0ae4d255 100644 --- a/forge-gui/res/cardsfolder/p/pariah.txt +++ b/forge-gui/res/cardsfolder/p/pariah.txt @@ -3,8 +3,7 @@ ManaCost:2 W Types:Enchantment Aura K:Enchant creature A:SP$ Attach | Cost$ 2 W | ValidTgts$ Creature | TgtPrompt$ Select target creature | AILogic$ Curse -R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ You | ReplaceWith$ DmgEnchanted | Description$ All damage that would be dealt to you is dealt to enchanted creature instead. +R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ You | ReplaceWith$ DmgEnchanted | DamageTarget$ Enchanted | Description$ All damage that would be dealt to you is dealt to enchanted creature instead. SVar:DmgEnchanted:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Enchanted | VarType$ Card SVar:NonStackingAttachEffect:True -SVar:Picture:http://www.wizards.com/global/images/magic/general/pariah.jpg Oracle:Enchant creature\nAll damage that would be dealt to you is dealt to enchanted creature instead. diff --git a/forge-gui/res/cardsfolder/p/pariahs_shield.txt b/forge-gui/res/cardsfolder/p/pariahs_shield.txt index 0fc9ff4697b..1166af2a770 100644 --- a/forge-gui/res/cardsfolder/p/pariahs_shield.txt +++ b/forge-gui/res/cardsfolder/p/pariahs_shield.txt @@ -2,7 +2,6 @@ Name:Pariah's Shield ManaCost:5 Types:Artifact Equipment K:Equip:3 -R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ You | ReplaceWith$ DmgEquipped | IsEquipping$ True | Description$ All damage that would be dealt to you is dealt to equipped creature instead. +R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ You | ReplaceWith$ DmgEquipped | IsEquipping$ True | DamageTarget$ Equipped | Description$ All damage that would be dealt to you is dealt to equipped creature instead. SVar:DmgEquipped:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Equipped | VarType$ Card -SVar:Picture:http://www.wizards.com/global/images/magic/general/pariahs_shield.jpg Oracle:All damage that would be dealt to you is dealt to equipped creature instead.\nEquip {3} diff --git a/forge-gui/res/cardsfolder/p/path_to_exile.txt b/forge-gui/res/cardsfolder/p/path_to_exile.txt index db81241db34..5b0c706c44b 100644 --- a/forge-gui/res/cardsfolder/p/path_to_exile.txt +++ b/forge-gui/res/cardsfolder/p/path_to_exile.txt @@ -1,8 +1,7 @@ Name:Path to Exile ManaCost:W Types:Instant -A:SP$ ChangeZone | Cost$ W | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Creature | SubAbility$ DBChange | RememberLKI$ True | SpellDescription$ Exile target creature. Its controller may search their library for a basic land card, put that card onto the battlefield tapped, then shuffle their library. -SVar:DBChange:DB$ ChangeZone | Optional$ True | Origin$ Library | Destination$ Battlefield | Tapped$ True | ChangeType$ Land.Basic | ChangeNum$ 1 | DefinedPlayer$ RememberedController | ShuffleNonMandatory$ True | SubAbility$ DBCleanup +A:SP$ ChangeZone | Cost$ W | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Creature | SubAbility$ DBChange | RememberLKI$ True | StackDescription$ Exile {c:Targeted}. {p:TargetedController} may search their library for a basic land card, put that card onto the battlefield tapped, then shuffle their library. | SpellDescription$ Exile target creature. Its controller may search their library for a basic land card, put that card onto the battlefield tapped, then shuffle their library. +SVar:DBChange:DB$ ChangeZone | Optional$ True | Origin$ Library | Destination$ Battlefield | Tapped$ True | ChangeType$ Land.Basic | ChangeNum$ 1 | DefinedPlayer$ RememberedController | ShuffleNonMandatory$ True | SubAbility$ DBCleanup | StackDescription$ None SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:Picture:http://www.wizards.com/global/images/magic/general/path_to_exile.jpg Oracle:Exile target creature. Its controller may search their library for a basic land card, put that card onto the battlefield tapped, then shuffle their library. diff --git a/forge-gui/res/cardsfolder/p/permafrost_trap.txt b/forge-gui/res/cardsfolder/p/permafrost_trap.txt index 4dfe4872ce6..d8261af4156 100644 --- a/forge-gui/res/cardsfolder/p/permafrost_trap.txt +++ b/forge-gui/res/cardsfolder/p/permafrost_trap.txt @@ -1,8 +1,8 @@ Name:Permafrost Trap ManaCost:2 U U Types:Instant Trap +SVar:AltCost:Cost$ U | CheckSVar$ GreenCreats | References$ GreenCreats | Description$ If an opponent had a green creature enter the battlefield under their control this turn, you may pay {U} rather than pay this spell's mana cost. A:SP$ Tap | Cost$ 2 U U | TargetMin$ 0 | TargetMax$ 2 | ValidTgts$ Creature | TgtPrompt$ Select target creature | SubAbility$ DBPump | SpellDescription$ Tap up to two target creatures. Those creatures don't untap during their controller's next untap step. -A:SP$ Tap | Cost$ U | CheckSVar$ GreenCreats | References$ GreenCreats | TargetMin$ 0 | TargetMax$ 2 | ValidTgts$ Creature | TgtPrompt$ Select target creature | SubAbility$ DBPump | SpellDescription$ If an opponent had a green creature enter the battlefield under their control this turn, you may pay {U} rather than pay CARDNAME's mana cost. -SVar:DBPump:DB$ Pump | Defined$ Targeted | KW$ HIDDEN This card doesn't untap during your next untap step. | Permanent$ True +SVar:DBPump:DB$ Pump | Defined$ Targeted | KW$ HIDDEN This card doesn't untap during your next untap step. | Permanent$ True | StackDescription$ {c:Targeted} don't untap during {p:TargetedController}'s next untap step. SVar:GreenCreats:Count$ThisTurnEntered_Battlefield_Creature.Green+OppCtrl -Oracle:If an opponent had a green creature enter the battlefield under their control this turn, you may pay {U} rather than pay Permafrost Trap's mana cost.\nTap up to two target creatures. Those creatures don't untap during their controller's next untap step. +Oracle:If an opponent had a green creature enter the battlefield under their control this turn, you may pay {U} rather than pay this spell's mana cost.\nTap up to two target creatures. Those creatures don't untap during their controller's next untap step. diff --git a/forge-gui/res/cardsfolder/p/pirates_pillage.txt b/forge-gui/res/cardsfolder/p/pirates_pillage.txt index 1e60d59a37c..da01c96d974 100644 --- a/forge-gui/res/cardsfolder/p/pirates_pillage.txt +++ b/forge-gui/res/cardsfolder/p/pirates_pillage.txt @@ -1,9 +1,8 @@ Name:Pirate's Pillage ManaCost:3 R Types:Sorcery -A:SP$ Draw | Cost$ 3 R Discard<1/Card> | CostDesc$ As an additional cost to cast CARDNAME, discard a card. | NumCards$ 2 | Defined$ You | SubAbility$ DBToken | SpellDescription$ Draw two cards and create two colorless Treasure artifacts with "{T}, Sacrifice this artifact: Add one mana of any color." -SVar:DBToken:DB$ Token | TokenAmount$ 2 | TokenScript$ c_a_treasure_sac | TokenOwner$ You | LegacyImage$ c a treasure sac rix +A:SP$ Draw | Cost$ 3 R Discard<1/Card/card> | CostDesc$ As an additional cost to cast this spell, discard a card. | NumCards$ 2 | Defined$ You | SubAbility$ DBToken | SpellDescription$ Draw two cards and create two colorless Treasure artifacts with "{T}, Sacrifice this artifact: Add one mana of any color." +SVar:DBToken:DB$ Token | TokenAmount$ 2 | TokenScript$ c_a_treasure_sac | TokenOwner$ You DeckHas:Ability$Discard DeckHints:Keyword$Madness & Ability$Delirium -SVar:Picture:http://www.wizards.com/global/images/magic/general/pirates_pillage.jpg -Oracle:As an additional cost to cast Pirate's Pillage, discard a card.\nDraw two cards and create two colorless Treasure artifacts with "{T}, Sacrifice this artifact: Add one mana of any color." +Oracle:As an additional cost to cast this spell, discard a card.\nDraw two cards and create two colorless Treasure artifacts with "{T}, Sacrifice this artifact: Add one mana of any color." diff --git a/forge-gui/res/cardsfolder/p/pitfall_trap.txt b/forge-gui/res/cardsfolder/p/pitfall_trap.txt index 5a8c5af9b1c..0af88ac77b7 100644 --- a/forge-gui/res/cardsfolder/p/pitfall_trap.txt +++ b/forge-gui/res/cardsfolder/p/pitfall_trap.txt @@ -1,7 +1,6 @@ Name:Pitfall Trap ManaCost:2 W Types:Instant Trap -A:SP$ Destroy | Cost$ W | ValidTgts$ Creature.attacking+withoutFlying | IsPresent$ Creature.attacking | PresentCompare$ EQ1 | TgtPrompt$ Select target attacking creature without flying | SpellDescription$ If exactly one creature is attacking, you may pay {W} rather than pay CARDNAME mana cost. +SVar:AltCost:Cost$ W | IsPresent$ Creature.attacking | PresentCompare$ EQ1 | Description$ If exactly one creature is attacking, you may pay {W} rather than pay this spell's mana cost. A:SP$ Destroy | Cost$ 2 W | ValidTgts$ Creature.attacking+withoutFlying | TgtPrompt$ Select target attacking creature without flying | SpellDescription$ Destroy target attacking creature without flying. -SVar:Picture:http://www.wizards.com/global/images/magic/general/pitfall_trap.jpg -Oracle:If exactly one creature is attacking, you may pay {W} rather than pay Pitfall Trap's mana cost.\nDestroy target attacking creature without flying. +Oracle:If exactly one creature is attacking, you may pay {W} rather than pay this spell's mana cost.\nDestroy target attacking creature without flying. diff --git a/forge-gui/res/cardsfolder/p/protector_of_the_crown.txt b/forge-gui/res/cardsfolder/p/protector_of_the_crown.txt index 9c0c4648e05..44b9a2875ab 100644 --- a/forge-gui/res/cardsfolder/p/protector_of_the_crown.txt +++ b/forge-gui/res/cardsfolder/p/protector_of_the_crown.txt @@ -4,7 +4,6 @@ Types:Creature Giant Soldier PT:2/5 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigMonarch | TriggerDescription$ When CARDNAME enters the battlefield, you become the monarch. SVar:TrigMonarch:DB$ BecomeMonarch | Defined$ You -R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ You | ReplaceWith$ DmgSelf | Description$ All damage that would be dealt to you is dealt to CARDNAME instead. +R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ You | ReplaceWith$ DmgSelf | DamageTarget$ Self | Description$ All damage that would be dealt to you is dealt to CARDNAME instead. SVar:DmgSelf:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Self | VarType$ Card -SVar:Picture:http://www.wizards.com/global/images/magic/general/protector_of_the_crown.jpg Oracle:When Protector of the Crown enters the battlefield, you become the monarch.\nAll damage that would be dealt to you is dealt to Protector of the Crown instead. diff --git a/forge-gui/res/cardsfolder/p/pulverize.txt b/forge-gui/res/cardsfolder/p/pulverize.txt index 228d806098a..1ca1d558c32 100644 --- a/forge-gui/res/cardsfolder/p/pulverize.txt +++ b/forge-gui/res/cardsfolder/p/pulverize.txt @@ -1,7 +1,6 @@ Name:Pulverize ManaCost:4 R R Types:Sorcery +SVar:AltCost:Cost$ Sac<2/Mountain> | Description$ You may sacrifice two Mountains rather than pay this spell's mana cost. A:SP$ DestroyAll | Cost$ 4 R R | ValidCards$ Artifact | SpellDescription$ Destroy all artifacts. -SVar:AltCost:Cost$ Sac<2/Mountain> | Description$ You may sacrifice two Mountains rather than pay Pulverize's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/pulverize.jpg -Oracle:You may sacrifice two Mountains rather than pay Pulverize's mana cost.\nDestroy all artifacts. +Oracle:You may sacrifice two Mountains rather than pay this spell's mana cost.\nDestroy all artifacts. diff --git a/forge-gui/res/cardsfolder/p/pyrokinesis.txt b/forge-gui/res/cardsfolder/p/pyrokinesis.txt index cc74f7667a2..49abfb6c0ae 100644 --- a/forge-gui/res/cardsfolder/p/pyrokinesis.txt +++ b/forge-gui/res/cardsfolder/p/pyrokinesis.txt @@ -1,7 +1,6 @@ Name:Pyrokinesis ManaCost:4 R R Types:Instant +SVar:AltCost:Cost$ ExileFromHand<1/Card.Red+Other> | Description$ You may exile a red card from your hand rather than pay this spell's mana cost. A:SP$ DealDamage | Cost$ 4 R R | ValidTgts$ Creature | TgtPrompt$ Select target creature to distribute damage to | NumDmg$ 4 | TargetMin$ 1 | TargetMax$ 4 | DividedAsYouChoose$ 4 | SpellDescription$ CARDNAME deals 4 damage divided as you choose among any number of target creatures. -SVar:AltCost:Cost$ ExileFromHand<1/Card.Red> | Description$ You may exile a red card from your hand rather than pay CARDNAME 's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/pyrokinesis.jpg -Oracle:You may exile a red card from your hand rather than pay Pyrokinesis's mana cost.\nPyrokinesis deals 4 damage divided as you choose among any number of target creatures. +Oracle:You may exile a red card from your hand rather than pay this spell's mana cost.\nPyrokinesis deals 4 damage divided as you choose among any number of target creatures. diff --git a/forge-gui/res/cardsfolder/r/ramosian_rally.txt b/forge-gui/res/cardsfolder/r/ramosian_rally.txt index cac901e9d77..92c55cc2c19 100644 --- a/forge-gui/res/cardsfolder/r/ramosian_rally.txt +++ b/forge-gui/res/cardsfolder/r/ramosian_rally.txt @@ -1,8 +1,7 @@ Name:Ramosian Rally ManaCost:3 W Types:Instant +SVar:AltCost:Cost$ tapXType<1/Creature/creature> | IsPresent$ Plains.YouCtrl | Description$ If you control a Plains, you may tap an untapped creature you control rather than pay this spell's mana cost. A:SP$ PumpAll | Cost$ 3 W | ValidCards$ Creature.YouCtrl | NumAtt$ +1 | NumDef$ +1 | SpellDescription$ Creatures you control get +1/+1 until end of turn. -A:SP$ PumpAll | Cost$ tapXType<1/Creature> | ValidCards$ Creature.YouCtrl | NumAtt$ +1 | NumDef$ +1 | IsPresent$ Plains.YouCtrl | SpellDescription$ If you control a Plains, you may tap an untapped creature you control rather than pay CARDNAME's mana cost. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/ramosian_rally.jpg -Oracle:If you control a Plains, you may tap an untapped creature you control rather than pay Ramosian Rally's mana cost.\nCreatures you control get +1/+1 until end of turn. +Oracle:If you control a Plains, you may tap an untapped creature you control rather than pay this spell's mana cost.\nCreatures you control get +1/+1 until end of turn. diff --git a/forge-gui/res/cardsfolder/r/ravenous_trap.txt b/forge-gui/res/cardsfolder/r/ravenous_trap.txt index adff251928e..f9a0bcb5f6b 100644 --- a/forge-gui/res/cardsfolder/r/ravenous_trap.txt +++ b/forge-gui/res/cardsfolder/r/ravenous_trap.txt @@ -1,9 +1,8 @@ Name:Ravenous Trap ManaCost:2 B B Types:Instant Trap -A:SP$ ChangeZoneAll | Cost$ 2 B B | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Player | TgtPrompt$ Select target player | ChangeType$ Card | SpellDescription$ Exile all cards from target player's graveyard. -A:SP$ ChangeZoneAll | Cost$ 0 | CheckSVar$ CardsToGraveyard | SVarCompare$ GE3 | References$ CardsToGraveyard |Origin$ Graveyard | Destination$ Exile | ValidTgts$ Player | TgtPrompt$ Select target player | ChangeType$ Card | SpellDescription$ If an opponent had three or more cards put into their graveyard from anywhere this turn, you may pay {0} rather than pay CARDNAME's mana cost. -SVar:CardsToGraveyard:Count$ThisTurnEntered_Graveyard_Card.YouDontCtrl +SVar:AltCost:Cost$ 0 | CheckSVar$ CardsToGraveyard | SVarCompare$ GE3 | References$ CardsToGraveyard | Description$ If an opponent had three or more cards put into their graveyard from anywhere this turn, you may pay {0} rather than pay this spell's mana cost. +A:SP$ ChangeZoneAll | Cost$ 2 B B | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Player | TgtPrompt$ Select target player | ChangeType$ Card | StackDescription$ Exile all cards from {p:Targeted}'s graveyard. | SpellDescription$ Exile all cards from target player's graveyard. +SVar:CardsToGraveyard:Count$ThisTurnEntered_Graveyard_Card.OppCtrl AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/ravenous_trap.jpg -Oracle:If an opponent had three or more cards put into their graveyard from anywhere this turn, you may pay {0} rather than pay Ravenous Trap's mana cost.\nExile all cards from target player's graveyard. +Oracle:If an opponent had three or more cards put into their graveyard from anywhere this turn, you may pay {0} rather than pay this spell's mana cost.\nExile all cards from target player's graveyard. diff --git a/forge-gui/res/cardsfolder/r/reflect_damage.txt b/forge-gui/res/cardsfolder/r/reflect_damage.txt index c6c59f31d15..f1d5196889c 100644 --- a/forge-gui/res/cardsfolder/r/reflect_damage.txt +++ b/forge-gui/res/cardsfolder/r/reflect_damage.txt @@ -3,10 +3,9 @@ ManaCost:3 R W Types:Instant A:SP$ ChooseSource | Cost$ 3 W R | Choices$ Card,Emblem | SubAbility$ DBEffect | StackDescription$ SpellDescription | SpellDescription$ The next time a source of your choice would deal damage this turn, that damage is dealt to that source's controller instead. SVar:DBEffect:DB$ Effect | ReplacementEffects$ SelflessDamage | SVars$ SelflessDmg,ExileEffect | References$ SelflessDamage,SelflessDmg,ExileEffect | SubAbility$ DBCleanup -SVar:SelflessDamage:Event$ DamageDone | ValidSource$ Card.ChosenCard,Emblem.ChosenCard | ReplaceWith$ SelflessDmg | Description$ The next time a source of your choice would deal damage this turn, that damage is dealt to that source's controller instead. +SVar:SelflessDamage:Event$ DamageDone | ValidSource$ Card.ChosenCard,Emblem.ChosenCard | ReplaceWith$ SelflessDmg | DamageTarget$ ReplacedSourceController | Description$ The next time a source of your choice would deal damage this turn, that damage is dealt to that source's controller instead. SVar:SelflessDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ ReplacedSourceController | VarType$ Player | SubAbility$ ExileEffect SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile | Static$ True SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/reflect_damage.jpg Oracle:The next time a source of your choice would deal damage this turn, that damage is dealt to that source's controller instead. diff --git a/forge-gui/res/cardsfolder/r/research_development.txt b/forge-gui/res/cardsfolder/r/research_development.txt index d08db5cd8b8..58e5fd69ca8 100644 --- a/forge-gui/res/cardsfolder/r/research_development.txt +++ b/forge-gui/res/cardsfolder/r/research_development.txt @@ -2,10 +2,9 @@ Name:Research ManaCost:G U AlternateMode: Split Types:Instant -A:SP$ ChangeZone | Cost$ G U | Origin$ Sideboard | Destination$ Library | Shuffle$ True | ChangeType$ Card.YouOwn | ChangeNum$ 4 | SpellDescription$ Choose up to four cards you own from outside the game and shuffle them into your library. +A:SP$ ChangeZone | Cost$ G U | Origin$ Sideboard | Destination$ Library | Shuffle$ True | ChangeType$ Card.YouOwn | ChangeNum$ 4 | Hidden$ True | StackDescription$ {p:You} shuffles up to four cards they own from outside the game into their library. | SpellDescription$ Shuffle up to four cards you own from outside the game into your library. AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/researchdevelopment.jpg -Oracle:Choose up to four cards you own from outside the game and shuffle them into your library. +Oracle:Shuffle up to four cards you own from outside the game into your library. ALTERNATE diff --git a/forge-gui/res/cardsfolder/r/reverberation.txt b/forge-gui/res/cardsfolder/r/reverberation.txt index 0347b4755fb..a6bc39d1436 100644 --- a/forge-gui/res/cardsfolder/r/reverberation.txt +++ b/forge-gui/res/cardsfolder/r/reverberation.txt @@ -3,8 +3,7 @@ ManaCost:2 U U Types:Instant # The target lists a second zone to a Card is returned instead of a SA A:SP$ Effect | Cost$ 2 U U | ValidTgts$ Sorcery | AILogic$ Prevent | TgtZone$ Stack,Battlefield | TgtPrompt$ Select target sorcery spell to redirect damage from | RememberObjects$ Targeted | ExileOnMoved$ Stack | ReplacementEffects$ SelflessDamage | SVars$ SelflessDmg | References$ SelflessDamage,SelflessDmg | StackDescription$ SpellDescription | SpellDescription$ All damage that would be dealt this turn by target sorcery spell is dealt to that spell's controller instead. -SVar:SelflessDamage:Event$ DamageDone | ValidSource$ Card.IsRemembered | ReplaceWith$ SelflessDmg | Description$ The next time a source of your choice would deal damage this turn, that damage is dealt to that source's controller instead. +SVar:SelflessDamage:Event$ DamageDone | ValidSource$ Card.IsRemembered | ReplaceWith$ SelflessDmg | DamageTarget$ ReplacedSourceController | Description$ The next time a source of your choice would deal damage this turn, that damage is dealt to that source's controller instead. SVar:SelflessDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ ReplacedSourceController | VarType$ Player AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/reverberation.jpg Oracle:All damage that would be dealt this turn by target sorcery spell is dealt to that spell's controller instead. diff --git a/forge-gui/res/cardsfolder/r/reverent_mantra.txt b/forge-gui/res/cardsfolder/r/reverent_mantra.txt index fb1ea07d49f..56dad5048ea 100644 --- a/forge-gui/res/cardsfolder/r/reverent_mantra.txt +++ b/forge-gui/res/cardsfolder/r/reverent_mantra.txt @@ -1,9 +1,8 @@ Name:Reverent Mantra ManaCost:3 W Types:Instant -SVar:AltCost:Cost$ ExileFromHand<1/Card.White> | Description$ You may exile a white card from your hand rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ ExileFromHand<1/Card.White+Other> | Description$ You may exile a white card from your hand rather than pay this spell's mana cost. A:SP$ ChooseColor | Cost$ 3 W | Defined$ You | SubAbility$ DBProtection | AILogic$ MostProminentHumanControls | StackDescription$ SpellDescription | SpellDescription$ Choose a color. All creatures gain protection from the chosen color until end of turn. SVar:DBProtection:DB$ ProtectionAll | ValidCards$ Creature | Gains$ ChosenColor AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/reverent_mantra.jpg -Oracle:You may exile a white card from your hand rather than pay Reverent Mantra's mana cost.\nChoose a color. All creatures gain protection from the chosen color until end of turn. +Oracle:You may exile a white card from your hand rather than pay this spell's mana cost.\nChoose a color. All creatures gain protection from the chosen color until end of turn. diff --git a/forge-gui/res/cardsfolder/r/reverent_silence.txt b/forge-gui/res/cardsfolder/r/reverent_silence.txt index e9b3c98f1c2..240f224fec0 100644 --- a/forge-gui/res/cardsfolder/r/reverent_silence.txt +++ b/forge-gui/res/cardsfolder/r/reverent_silence.txt @@ -1,7 +1,6 @@ Name:Reverent Silence ManaCost:3 G Types:Sorcery +SVar:AltCost:Cost$ GainLife<6/Player.Other/*> | IsPresent$ Forest.YouCtrl | Description$ If you control a Forest, rather than pay this spell's mana cost, you may have each other player gain 6 life. A:SP$ DestroyAll | Cost$ 3 G | ValidCards$ Enchantment | SpellDescription$ Destroy all enchantments. -A:SP$ DestroyAll | Cost$ GainLife<6/Player.Other/*> | ValidCards$ Enchantment | IsPresent$ Forest.YouCtrl | StackDescription$ Destroy all enchantments. | PrecostDesc$ If you control a Forest, rather than pay CARDNAME's mana cost, | CostDesc$ you may have each other player gain 6 life | SpellDescription$ . -SVar:Picture:http://www.wizards.com/global/images/magic/general/reverent_silence.jpg -Oracle:If you control a Forest, rather than pay Reverent Silence's mana cost, you may have each other player gain 6 life.\nDestroy all enchantments. +Oracle:If you control a Forest, rather than pay this spell's mana cost, you may have each other player gain 6 life.\nDestroy all enchantments. diff --git a/forge-gui/res/cardsfolder/r/ricochet_trap.txt b/forge-gui/res/cardsfolder/r/ricochet_trap.txt index fe124f48b1b..daa0b0af4c1 100644 --- a/forge-gui/res/cardsfolder/r/ricochet_trap.txt +++ b/forge-gui/res/cardsfolder/r/ricochet_trap.txt @@ -1,8 +1,7 @@ Name:Ricochet Trap ManaCost:3 R Types:Instant Trap -A:SP$ ChangeTargets | Cost$ 3 R | TargetType$ Spell | ValidTgts$ Card | TargetsSingleTarget$ True | SpellDescription$ Change the target of target spell with a single target. -A:SP$ ChangeTargets | Cost$ R | TargetType$ Spell | ValidTgts$ Card | TargetsSingleTarget$ True | CheckSVar$ X | SVarCompare$ GE1 | SpellDescription$ If an opponent cast a blue spell this turn, you may pay {R} rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ R | CheckSVar$ X | References$ X | SVarCompare$ GE1 | StackDescription$ Description | Description$ If an opponent cast a blue spell this turn, you may pay {R} rather than pay this spell's mana cost. +A:SP$ ChangeTargets | Cost$ 3 R | TargetType$ Spell | ValidTgts$ Card | TgtPrompt$ Select target spell with a single target | TargetsSingleTarget$ True | StackDescription$ SpellDescription | SpellDescription$ Change the target of target spell with a single target. SVar:X:Count$ThisTurnCast_Card.Blue+OppCtrl -SVar:Picture:http://www.wizards.com/global/images/magic/general/ricochet_trap.jpg -Oracle:If an opponent cast a blue spell this turn, you may pay {R} rather than pay Ricochet Trap's mana cost.\nChange the target of target spell with a single target. +Oracle:If an opponent cast a blue spell this turn, you may pay {R} rather than pay this spell's mana cost.\nChange the target of target spell with a single target. diff --git a/forge-gui/res/cardsfolder/r/ring_of_maruf.txt b/forge-gui/res/cardsfolder/r/ring_of_maruf.txt index baef9a0593c..25d7fb2d790 100644 --- a/forge-gui/res/cardsfolder/r/ring_of_maruf.txt +++ b/forge-gui/res/cardsfolder/r/ring_of_maruf.txt @@ -1,11 +1,10 @@ Name:Ring of Ma'ruf ManaCost:5 Types:Artifact -A:AB$ Effect | Cost$ 5 T Exile<1/CARDNAME> | Name$ Ring of Ma'ruf Effect | ReplacementEffects$ DrawReplace | SVars$ ExileEffect,TutorSideboard | SpellDescription$ The next time you would draw a card this turn, instead choose a card you own from outside the game and put it into your hand. -SVar:DrawReplace:Event$ Draw | ValidPlayer$ You | ReplaceWith$ TutorSideboard | Description$ The next time you would draw a card this turn, instead choose a card you own from outside the game and put it into your hand. -SVar:TutorSideboard:DB$ ChangeZone | Origin$ Sideboard | Destination$ Hand | ChangeType$ Card.YouOwn | ChangeNum$ 1 | Hidden$ True | SubAbility$ ExileEffect +A:AB$ Effect | Cost$ 5 T Exile<1/CARDNAME> | Name$ Ring of Ma'ruf Effect | ReplacementEffects$ DrawReplace | SVars$ ExileEffect,TutorSideboard | SpellDescription$ The next time you would draw a card this turn, instead put a card you own from outside the game into your hand. +SVar:DrawReplace:Event$ Draw | ValidPlayer$ You | ReplaceWith$ TutorSideboard | Description$ The next time you would draw a card this turn, instead put a card you own from outside the game into your hand. +SVar:TutorSideboard:DB$ ChangeZone | Origin$ Sideboard | Destination$ Hand | ChangeType$ Card.YouOwn | ChangeNum$ 1 | Hidden$ True | Mandatory$ True | SubAbility$ ExileEffect SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile AI:RemoveDeck:All AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/ring_of_maruf.jpg -Oracle:{5}, {T}, Exile Ring of Ma'ruf: The next time you would draw a card this turn, instead choose a card you own from outside the game and put it into your hand. +Oracle:{5}, {T}, Exile Ring of Ma'ruf: The next time you would draw a card this turn, instead put a card you own from outside the game into your hand. diff --git a/forge-gui/res/cardsfolder/r/rouse.txt b/forge-gui/res/cardsfolder/r/rouse.txt index 223a9a747df..edc91a47e52 100644 --- a/forge-gui/res/cardsfolder/r/rouse.txt +++ b/forge-gui/res/cardsfolder/r/rouse.txt @@ -1,8 +1,7 @@ Name:Rouse ManaCost:1 B Types:Instant +SVar:AltCost:Cost$ PayLife<2> | IsPresent$ Swamp.YouCtrl | Description$ If you control a Swamp, you may pay 2 life rather than pay this spell's mana cost. A:SP$ Pump | Cost$ 1 B | ValidTgts$ Creature | NumAtt$ +2 | TgtPrompt$ Select target creature | SpellDescription$ Target creature gets +2/+0 until end of turn. -A:SP$ Pump | Cost$ PayLife<2> | ValidTgts$ Creature | NumAtt$ +2 | TgtPrompt$ Select target creature | isPresent$ Swamp.YouCtrl | SpellDescription$ If you control a Swamp, you may pay 2 life rather than pay Rouse's mana cost. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/rouse.jpg -Oracle:If you control a Swamp, you may pay 2 life rather than pay Rouse's mana cost.\nTarget creature gets +2/+0 until end of turn. +Oracle:If you control a Swamp, you may pay 2 life rather than pay this spell's mana cost.\nTarget creature gets +2/+0 until end of turn. diff --git a/forge-gui/res/cardsfolder/r/runeflare_trap.txt b/forge-gui/res/cardsfolder/r/runeflare_trap.txt index 1d6c80907b0..7c49bb2f91b 100644 --- a/forge-gui/res/cardsfolder/r/runeflare_trap.txt +++ b/forge-gui/res/cardsfolder/r/runeflare_trap.txt @@ -1,9 +1,8 @@ Name:Runeflare Trap ManaCost:4 R R Types:Instant Trap -A:SP$DealDamage | Cost$ R | ValidTgts$ Player | NumDmg$ X | CheckSVar$ Y | SVarCompare$ GE3 | References$ X,Y | SpellDescription$ If an opponent drew three or more cards this turn, you may pay {R} rather than pay CARDNAME's mana cost. -A:SP$DealDamage | Cost$ 4 R R | ValidTgts$ Player | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals damage to target player equal to the number of cards in that player's hand. +SVar:AltCost:Cost$ R | CheckSVar$ Y | SVarCompare$ GE3 | References$ Y | Description$ If an opponent drew three or more cards this turn, you may pay {R} rather than pay this spell's mana cost. +A:SP$ DealDamage | Cost$ 4 R R | ValidTgts$ Player | TgtPrompt$ Select target player | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals damage to target player equal to the number of cards in that player's hand. SVar:X:TargetedPlayer$CardsInHand SVar:Y:PlayerCountOpponents$HighestCardsDrawn -SVar:Picture:http://www.wizards.com/global/images/magic/general/runeflare_trap.jpg -Oracle:If an opponent drew three or more cards this turn, you may pay {R} rather than pay Runeflare Trap's mana cost.\nRuneflare Trap deals damage to target player equal to the number of cards in that player's hand. +Oracle:If an opponent drew three or more cards this turn, you may pay {R} rather than pay this spell's mana cost.\nRuneflare Trap deals damage to target player equal to the number of cards in that player's hand. diff --git a/forge-gui/res/cardsfolder/s/salvage_titan.txt b/forge-gui/res/cardsfolder/s/salvage_titan.txt index 12990e2b036..de7d3c9f0a8 100644 --- a/forge-gui/res/cardsfolder/s/salvage_titan.txt +++ b/forge-gui/res/cardsfolder/s/salvage_titan.txt @@ -2,7 +2,6 @@ Name:Salvage Titan ManaCost:4 B B Types:Artifact Creature Golem PT:6/4 -SVar:AltCost:Cost$ Sac<3/Artifact> | Description$ You may sacrifice three artifacts creatures rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ Sac<3/Artifact> | Description$ You may sacrifice three artifacts rather than pay this spell's mana cost. A:AB$ ChangeZone | Cost$ ExileFromGrave<3/Artifact> | Origin$ Graveyard | Destination$ Hand | Defined$ Self | ActivationZone$ Graveyard | SpellDescription$ Return CARDNAME from your graveyard to your hand. -SVar:Picture:http://www.wizards.com/global/images/magic/general/salvage_titan.jpg -Oracle:You may sacrifice three artifacts rather than pay Salvage Titan's mana cost.\nExile three artifact cards from your graveyard: Return Salvage Titan from your graveyard to your hand. +Oracle:You may sacrifice three artifacts rather than pay this spell's mana cost.\nExile three artifact cards from your graveyard: Return Salvage Titan from your graveyard to your hand. diff --git a/forge-gui/res/cardsfolder/s/scapegoat.txt b/forge-gui/res/cardsfolder/s/scapegoat.txt index 77ce42f083c..cf9ea53ffe4 100644 --- a/forge-gui/res/cardsfolder/s/scapegoat.txt +++ b/forge-gui/res/cardsfolder/s/scapegoat.txt @@ -1,8 +1,7 @@ Name:Scapegoat ManaCost:W Types:Instant -A:SP$ ChangeZone | Cost$ W Sac<1/Creature> | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature | TargetMin$ 0 | TargetMax$ X | Origin$ Battlefield | Destination$ Hand | CostDesc$ As an additional cost to cast CARDNAME, sacrifice a creature. | References$ X | SpellDescription$ Return any number of target creatures you control to their owner's hand. +A:SP$ ChangeZone | Cost$ W Sac<1/Creature/creature> | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature | TargetMin$ 0 | TargetMax$ X | Origin$ Battlefield | Destination$ Hand | CostDesc$ As an additional cost to cast this spell, sacrifice a creature. | References$ X | SpellDescription$ Return any number of target creatures you control to their owner's hand. SVar:X:Count$Valid Creature.YouCtrl AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/scapegoat.jpg -Oracle:As an additional cost to cast Scapegoat, sacrifice a creature.\nReturn any number of target creatures you control to their owner's hand. +Oracle:As an additional cost to cast this spell, sacrifice a creature.\nReturn any number of target creatures you control to their owner's hand. diff --git a/forge-gui/res/cardsfolder/s/scars_of_the_veteran.txt b/forge-gui/res/cardsfolder/s/scars_of_the_veteran.txt index 72a6e87235b..c053a35c582 100644 --- a/forge-gui/res/cardsfolder/s/scars_of_the_veteran.txt +++ b/forge-gui/res/cardsfolder/s/scars_of_the_veteran.txt @@ -1,7 +1,7 @@ Name:Scars of the Veteran ManaCost:4 W Types:Instant -SVar:AltCost:Cost$ ExileFromHand<1/Card.White> | Description$ You may exile a white card from your hand rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ ExileFromHand<1/Card.White+Other> | Description$ You may exile a white card from your hand rather than pay this spell's mana cost. A:SP$ PreventDamage | Cost$ 4 W | ValidTgts$ Creature,Player,Planeswalker | Amount$ 7 | PreventionSubAbility$ ScarEffect | ShieldEffectTarget$ Targeted | TgtPrompt$ Select any target | SpellDescription$ Prevent the next 7 damage that would be dealt to any target this turn. If it's a creature, put a +0/+1 counter on it for each 1 damage prevented this way at the beginning of the next end step. SVar:ScarEffect:DB$ Effect | RememberObjects$ ShieldEffectTarget | Triggers$ DelTrig,OutOfSight,NoCreatTgt | SVars$ DelayedScars,ExileEffect | SpellDescription$ If it's a creature, put a +0/+1 counter on it for each 1 damage prevented this way at the beginning of the next end step. SVar:DelTrig:Mode$ Phase | Phase$ End of Turn | Execute$ DelayedScars | TriggerDescription$ If it's a creature, put a +0/+1 counter on it for each 1 damage prevented this way at the beginning of the next end step. @@ -9,5 +9,4 @@ SVar:DelayedScars:DB$ PutCounter | Defined$ Remembered | CounterType$ P0P1 | Cou SVar:OutOfSight:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Permanent.IsRemembered | Execute$ ExileEffect | Static$ True SVar:NoCreatTgt:Mode$ Always | IsPresent$ Permanent.IsRemembered | PresentCompare$ EQ0 | Execute$ ExileEffect | Static$ True SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile | Static$ True -SVar:Picture:http://www.wizards.com/global/images/magic/general/scars_of_the_veteran.jpg -Oracle:You may exile a white card from your hand rather than pay Scars of the Veteran's mana cost.\nPrevent the next 7 damage that would be dealt to any target this turn. If it's a creature, put a +0/+1 counter on it for each 1 damage prevented this way at the beginning of the next end step. +Oracle:You may exile a white card from your hand rather than pay this spell's mana cost.\nPrevent the next 7 damage that would be dealt to any target this turn. If it's a creature, put a +0/+1 counter on it for each 1 damage prevented this way at the beginning of the next end step. diff --git a/forge-gui/res/cardsfolder/s/shimian_night_stalker.txt b/forge-gui/res/cardsfolder/s/shimian_night_stalker.txt index 6b8d399dfd4..4cce10a7faf 100644 --- a/forge-gui/res/cardsfolder/s/shimian_night_stalker.txt +++ b/forge-gui/res/cardsfolder/s/shimian_night_stalker.txt @@ -3,7 +3,6 @@ ManaCost:3 B B Types:Creature Nightstalker PT:4/4 A:AB$ Effect | Cost$ B T | Name$ Shimian Night Stalker Effect | ReplacementEffects$ DamageEvent | SVars$ MirrorStrikeDmg | References$ MirrorStrikeDmg | ImprintCards$ Targeted | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature | AILogic$ Fog | SpellDescription$ All damage that would be dealt to you this turn by target attacking creature is dealt to CARDNAME instead. -SVar:DamageEvent:Event$ DamageDone | ValidSource$ Creature.IsImprinted | ValidTarget$ You | ReplaceWith$ MirrorStrikeDmg | Description$ All damage that would be dealt to you this turn by the attacking creature is dealt to Shimian Night Stalker instead. +SVar:DamageEvent:Event$ DamageDone | ValidSource$ Creature.IsImprinted | ValidTarget$ You | ReplaceWith$ MirrorStrikeDmg | DamageTarget$ EffectSource | Description$ All damage that would be dealt to you this turn by the attacking creature is dealt to EFFECTSOURCE instead. SVar:MirrorStrikeDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ EffectSource | VarType$ Card -SVar:Picture:http://www.wizards.com/global/images/magic/general/shimian_night_stalker.jpg Oracle:{B}, {T}: All damage that would be dealt to you this turn by target attacking creature is dealt to Shimian Night Stalker instead. diff --git a/forge-gui/res/cardsfolder/s/sickening_shoal.txt b/forge-gui/res/cardsfolder/s/sickening_shoal.txt index ed50a626476..7bb399a2cbd 100644 --- a/forge-gui/res/cardsfolder/s/sickening_shoal.txt +++ b/forge-gui/res/cardsfolder/s/sickening_shoal.txt @@ -1,10 +1,10 @@ Name:Sickening Shoal ManaCost:X B B Types:Instant Arcane -A:SP$ Pump | Cost$ X B B | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ -X | NumDef$ -X | IsCurse$ True | References$ X | SpellDescription$ Target creature gets -X/-X until end of turn. -A:SP$ Pump | Cost$ ExileFromHand<1/Card.Black> | CostDesc$ You may exile a black card from your hand rather than pay Sickening Shoal's mana cost. | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ -Y | NumDef$ -Y | IsCurse$ True | References$ Y | SpellDescription$ Target creature gets -X/-X until end of turn, where X is the exiled card's converted mana cost. +SVar:AltCost:Cost$ ExileFromHand<1/Card.Black+Other> | Description$ You may exile a black card with converted mana cost X from your hand rather than pay this spell's mana cost. +A:SP$ Pump | Cost$ X B B | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ -Z | NumDef$ -Z | IsCurse$ True | References$ X,Y,Z | SpellDescription$ Target creature gets -X/-X until end of turn. SVar:X:Count$xPaid SVar:Y:Exiled$CardManaCost +SVar:Z:SVar$Y/Plus.X AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/sickening_shoal.jpg -Oracle:You may exile a black card with converted mana cost X from your hand rather than pay Sickening Shoal's mana cost.\nTarget creature gets -X/-X until end of turn. +Oracle:You may exile a black card with converted mana cost X from your hand rather than pay this spell's mana cost.\nTarget creature gets -X/-X until end of turn. diff --git a/forge-gui/res/cardsfolder/s/sivvis_valor.txt b/forge-gui/res/cardsfolder/s/sivvis_valor.txt index a939d504722..c7799ceaa3d 100644 --- a/forge-gui/res/cardsfolder/s/sivvis_valor.txt +++ b/forge-gui/res/cardsfolder/s/sivvis_valor.txt @@ -1,12 +1,11 @@ Name:Sivvi's Valor ManaCost:2 W Types:Instant -A:SP$ Effect | Name$ Sivvi's Effect | Cost$ tapXType<1/Creature> | ValidTgts$ Creature | TgtPrompt$ Select target creature to redirect damage from | ReplacementEffects$ SelflessDamage | Triggers$ OutOfSight | SVars$ SelflessDmg,ExileEffect | References$ SelflessDamage,OutOfSight,SelflessDmg,ExileEffect | RememberObjects$ Targeted | IsPresent$ Plains.YouCtrl | CostDesc$ If you control a Plains, | SpellDescription$ you may tap an untapped creature you control rather than pay CARDNAME's mana cost. -A:SP$ Effect | Name$ Sivvi's Effect | Cost$ 2 W | ValidTgts$ Creature | TgtPrompt$ Select target creature to redirect damage from | ReplacementEffects$ SelflessDamage | Triggers$ OutOfSight | SVars$ SelflessDmg,ExileEffect | References$ SelflessDamage,OutOfSight,SelflessDmg,ExileEffect | RememberObjects$ Targeted | SpellDescription$ All damage that would be dealt to target creature this turn is dealt to you instead. -SVar:SelflessDamage:Event$ DamageDone | ValidTarget$ Card.IsRemembered | ReplaceWith$ SelflessDmg | Description$ All damage that would be dealt to target creature this turn is dealt to you instead. +SVar:AltCost:Cost$ tapXType<1/Creature/creature> | IsPresent$ Plains.YouCtrl | Description$ If you control a Plains, you may tap an untapped creature you control rather than pay this spell's mana cost. +A:SP$ Effect | Cost$ 2 W | ValidTgts$ Creature | TgtPrompt$ Select target creature to redirect damage from | ReplacementEffects$ SelflessDamage | Triggers$ OutOfSight | SVars$ SelflessDmg,ExileEffect | References$ SelflessDamage,OutOfSight,SelflessDmg,ExileEffect | RememberObjects$ Targeted | StackDescription$ All damage that would be dealt to {c:Targeted} this turn is dealt to {p:You} instead. | SpellDescription$ All damage that would be dealt to target creature this turn is dealt to you instead. +SVar:SelflessDamage:Event$ DamageDone | ValidTarget$ Card.IsRemembered | ReplaceWith$ SelflessDmg | DamageTarget$ You | Description$ All damage that would be dealt to target creature this turn is dealt to you instead. SVar:SelflessDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ You | VarType$ Player SVar:OutOfSight:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Creature.IsRemembered | Execute$ ExileEffect | Static$ True SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile | Static$ True AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/sivvis_valor.jpg -Oracle:If you control a Plains, you may tap an untapped creature you control rather than pay Sivvi's Valor's mana cost.\nAll damage that would be dealt to target creature this turn is dealt to you instead. +Oracle:If you control a Plains, you may tap an untapped creature you control rather than pay this spell's mana cost.\nAll damage that would be dealt to target creature this turn is dealt to you instead. diff --git a/forge-gui/res/cardsfolder/s/skyshroud_cutter.txt b/forge-gui/res/cardsfolder/s/skyshroud_cutter.txt index 53e972daac3..6ec3b21a09a 100644 --- a/forge-gui/res/cardsfolder/s/skyshroud_cutter.txt +++ b/forge-gui/res/cardsfolder/s/skyshroud_cutter.txt @@ -2,6 +2,5 @@ Name:Skyshroud Cutter ManaCost:3 G Types:Creature Beast PT:2/2 -SVar:AltCost:Cost$ GainLife<5/Player.Other/*> | IsPresent$ Forest.YouCtrl | Description$ If you control a Forest, rather than pay Skyshroud Cutter's mana cost, you may have each other player gain 5 life. -SVar:Picture:http://www.wizards.com/global/images/magic/general/skyshroud_cutter.jpg -Oracle:If you control a Forest, rather than pay Skyshroud Cutter's mana cost, you may have each other player gain 5 life. +SVar:AltCost:Cost$ GainLife<5/Player.Other/*> | IsPresent$ Forest.YouCtrl | Description$ If you control a Forest, rather than pay this spell's mana cost, you may have each other player gain 5 life. +Oracle:If you control a Forest, rather than pay this spell's mana cost, you may have each other player gain 5 life. diff --git a/forge-gui/res/cardsfolder/s/slingbow_trap.txt b/forge-gui/res/cardsfolder/s/slingbow_trap.txt index 5962fcf3b0a..96cd647e83f 100644 --- a/forge-gui/res/cardsfolder/s/slingbow_trap.txt +++ b/forge-gui/res/cardsfolder/s/slingbow_trap.txt @@ -1,8 +1,7 @@ Name:Slingbow Trap ManaCost:3 G Types:Instant Trap -A:SP$ Destroy | Cost$ G | ValidTgts$ Creature.attacking+withFlying | IsPresent$ Creature.attacking+Black+withFlying | OptionalDecider$ You | TgtPrompt$ Select target attacking creature with flying. | SpellDescription$ If a black creature with flying is attacking, you may pay {G} rather than pay CARDNAME's mana cost. -A:SP$ Destroy | Cost$ 3 G | ValidTgts$ Creature.attacking+withFlying | TgtPrompt$ Select target attacking creature with flying. | SpellDescription$ Destroy target attacking creature with flying. +SVar:AltCost:Cost$ G | IsPresent$ Creature.attacking+Black+withFlying | Description$ If a black creature with flying is attacking, you may pay {G} rather than pay this spell's mana cost. +A:SP$ Destroy | Cost$ 3 G | ValidTgts$ Creature.attacking+withFlying | TgtPrompt$ Select target attacking creature with flying | SpellDescription$ Destroy target attacking creature with flying. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/Slingbow_Trap.jpg -Oracle:If a black creature with flying is attacking, you may pay {G} rather than pay Slingbow Trap's mana cost.\nDestroy target attacking creature with flying. +Oracle:If a black creature with flying is attacking, you may pay {G} rather than pay this spell's mana cost.\nDestroy target attacking creature with flying. diff --git a/forge-gui/res/cardsfolder/s/snag.txt b/forge-gui/res/cardsfolder/s/snag.txt index 47386a3806f..86a6e4ffccc 100644 --- a/forge-gui/res/cardsfolder/s/snag.txt +++ b/forge-gui/res/cardsfolder/s/snag.txt @@ -1,8 +1,7 @@ Name:Snag ManaCost:3 G Types:Instant -SVar:AltCost:Cost$ Discard<1/Forest> +SVar:AltCost:Cost$ Discard<1/Forest> | Description$ You may discard a Forest card rather than pay this spell's mana cost. A:SP$ Effect | Cost$ 3 G | Name$ Snag Effect | ReplacementEffects$ RPrevent | AILogic$ Fog | SpellDescription$ Prevent all combat damage that would be dealt by unblocked creatures this turn. SVar:RPrevent:Event$ DamageDone | Prevent$ True | IsCombat$ True | ActiveZones$ Command | ValidSource$ Creature.unblocked | Description$ Prevent all combat damage that would be dealt by unblocked creatures this turn. -SVar:Picture:http://www.wizards.com/global/images/magic/general/snag.jpg -Oracle:You may discard a Forest card rather than pay Snag's mana cost.\nPrevent all combat damage that would be dealt by unblocked creatures this turn. +Oracle:You may discard a Forest card rather than pay this spell's mana cost.\nPrevent all combat damage that would be dealt by unblocked creatures this turn. diff --git a/forge-gui/res/cardsfolder/s/snapback.txt b/forge-gui/res/cardsfolder/s/snapback.txt index 68a494e66ca..f0a9e77a40e 100644 --- a/forge-gui/res/cardsfolder/s/snapback.txt +++ b/forge-gui/res/cardsfolder/s/snapback.txt @@ -1,7 +1,6 @@ Name:Snapback ManaCost:1 U Types:Instant +SVar:AltCost:Cost$ ExileFromHand<1/Card.Blue+Other> | Description$ You may exile a blue card from your hand rather than pay this spell's mana cost. A:SP$ ChangeZone | Cost$ 1 U | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Hand | SpellDescription$ Return target creature to its owner's hand. -A:SP$ ChangeZone | Cost$ ExileFromHand<1/Card.Blue> | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Hand | CostDesc$ You may exile a blue card from your hand | SpellDescription$ rather than pay CARDNAME's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/snapback.jpg -Oracle:You may exile a blue card from your hand rather than pay Snapback's mana cost.\nReturn target creature to its owner's hand. +Oracle:You may exile a blue card from your hand rather than pay this spell's mana cost.\nReturn target creature to its owner's hand. diff --git a/forge-gui/res/cardsfolder/s/snuff_out.txt b/forge-gui/res/cardsfolder/s/snuff_out.txt index 175789ab98e..1283cd5790e 100644 --- a/forge-gui/res/cardsfolder/s/snuff_out.txt +++ b/forge-gui/res/cardsfolder/s/snuff_out.txt @@ -1,7 +1,6 @@ Name:Snuff Out ManaCost:3 B Types:Instant +SVar:AltCost:Cost$ PayLife<4> | IsPresent$ Swamp.YouCtrl | Description$ If you control a Swamp, you may pay 4 life rather than pay this spell's mana cost. A:SP$ Destroy | Cost$ 3 B | ValidTgts$ Creature.nonBlack | TgtPrompt$ Select target nonblack creature | NoRegen$ True | SpellDescription$ Destroy target nonblack creature. It can't be regenerated. -A:SP$ Destroy | Cost$ PayLife<4> | ValidTgts$ Creature.nonBlack | TgtPrompt$ Select target nonblack creature | NoRegen$ True | IsPresent$ Swamp.YouCtrl | CostDesc$ If you control a Swamp, you may pay 4 life rather than pay CARDNAME's mana cost. | SpellDescription$ -SVar:Picture:http://www.wizards.com/global/images/magic/general/snuff_out.jpg -Oracle:If you control a Swamp, you may pay 4 life rather than pay Snuff Out's mana cost.\nDestroy target nonblack creature. It can't be regenerated. +Oracle:If you control a Swamp, you may pay 4 life rather than pay this spell's mana cost.\nDestroy target nonblack creature. It can't be regenerated. diff --git a/forge-gui/res/cardsfolder/s/soul_spike.txt b/forge-gui/res/cardsfolder/s/soul_spike.txt index 61c6774c7f0..fd499f51e6c 100644 --- a/forge-gui/res/cardsfolder/s/soul_spike.txt +++ b/forge-gui/res/cardsfolder/s/soul_spike.txt @@ -1,8 +1,7 @@ Name:Soul Spike ManaCost:5 B B Types:Instant +SVar:AltCost:Cost$ ExileFromHand<2/Card.Black+Other> | Description$ You may exile two black cards from your hand rather than pay this spell's mana cost. A:SP$ DealDamage | Cost$ 5 B B | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 4 | SubAbility$ DBGainLife | SpellDescription$ CARDNAME deals 4 damage to any target and you gain 4 life. -A:SP$ DealDamage | Cost$ ExileFromHand<2/Card.Black> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 4 | SubAbility$ DBGainLife | CostDesc$ You may exile two black cards from your hand | SpellDescription$ rather than pay CARDNAME's mana cost. -SVar:DBGainLife:DB$GainLife | LifeAmount$ 4 -SVar:Picture:http://www.wizards.com/global/images/magic/general/soul_spike.jpg -Oracle:You may exile two black cards from your hand rather than pay Soul Spike's mana cost.\nSoul Spike deals 4 damage to any target and you gain 4 life. +SVar:DBGainLife:DB$ GainLife | LifeAmount$ 4 +Oracle:You may exile two black cards from your hand rather than pay this spell's mana cost.\nSoul Spike deals 4 damage to any target and you gain 4 life. diff --git a/forge-gui/res/cardsfolder/s/soulblast.txt b/forge-gui/res/cardsfolder/s/soulblast.txt index 10d135107d8..9965441b046 100644 --- a/forge-gui/res/cardsfolder/s/soulblast.txt +++ b/forge-gui/res/cardsfolder/s/soulblast.txt @@ -1,8 +1,7 @@ Name:Soulblast ManaCost:3 R R R Types:Instant -A:SP$ DealDamage | Cost$ 3 R R R Sac | NumDmg$ X | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | CostDesc$ As an additional cost to cast CARDNAME, sacrifice all creatures you control. | SpellDescription$ CARDNAME deals damage to any target equal to the total power of the sacrificed creatures. +A:SP$ DealDamage | Cost$ 3 R R R Sac | NumDmg$ X | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | CostDesc$ As an additional cost to cast this spell, sacrifice all creatures you control. | SpellDescription$ CARDNAME deals damage to any target equal to the total power of the sacrificed creatures. SVar:X:Sacrificed$CardPower AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/soulblast.jpg -Oracle:As an additional cost to cast Soulblast, sacrifice all creatures you control.\nSoulblast deals damage to any target equal to the total power of the sacrificed creatures. +Oracle:As an additional cost to cast this spell, sacrifice all creatures you control.\nSoulblast deals damage to any target equal to the total power of the sacrificed creatures. diff --git a/forge-gui/res/cardsfolder/s/spawnsire_of_ulamog.txt b/forge-gui/res/cardsfolder/s/spawnsire_of_ulamog.txt index 55b16fb43b5..d06aa0b16d6 100644 --- a/forge-gui/res/cardsfolder/s/spawnsire_of_ulamog.txt +++ b/forge-gui/res/cardsfolder/s/spawnsire_of_ulamog.txt @@ -3,10 +3,9 @@ ManaCost:10 Types:Creature Eldrazi PT:7/11 K:Annihilator:1 -A:AB$ Token | Cost$ 4 | TokenAmount$ 2 | TokenScript$ c_0_1_eldrazi_spawn_sac | TokenOwner$ You | LegacyImage$ c 0 1 eldrazi spawn sac roe | SpellDescription$ Create two 0/1 colorless Eldrazi Spawn creature tokens. They have "Sacrifice this creature: Add {C}." -A:AB$ Play | Cost$ 20 | Valid$ Card.Eldrazi+YouOwn | ValidZone$ Sideboard | WithoutManaCost$ True | Amount$ SpawnsireX | Controller$ You | Optional$ True | References$ SpawnsireX | SpellDescription$ Cast any number of Eldrazi cards you own from outside the game without paying their mana costs. +A:AB$ Token | Cost$ 4 | TokenAmount$ 2 | TokenScript$ c_0_1_eldrazi_spawn_sac | TokenOwner$ You | SpellDescription$ Create two 0/1 colorless Eldrazi Spawn creature tokens. They have "Sacrifice this creature: Add {C}." +A:AB$ Play | Cost$ 20 | Valid$ Card.Eldrazi+YouOwn | ValidZone$ Sideboard | WithoutManaCost$ True | Amount$ SpawnsireX | Controller$ You | Optional$ True | References$ SpawnsireX | SpellDescription$ Cast any number of Eldrazi spells you own from outside the game without paying their mana costs. SVar:SpawnsireX:Count$TypeInYourSideboard.Eldrazi DeckHints:Type$Eldrazi DeckHas:Ability$Mana.Colorless & Ability$Token -SVar:Picture:http://www.wizards.com/global/images/magic/general/spawnsire_of_ulamog.jpg -Oracle:Annihilator 1 (Whenever this creature attacks, defending player sacrifices a permanent.)\n{4}: Create two 0/1 colorless Eldrazi Spawn creature tokens. They have "Sacrifice this creature: Add {C}."\n{20}: Cast any number of Eldrazi cards you own from outside the game without paying their mana costs. +Oracle:Annihilator 1 (Whenever this creature attacks, defending player sacrifices a permanent.)\n{4}: Create two 0/1 colorless Eldrazi Spawn creature tokens. They have "Sacrifice this creature: Add {C}."\n{20}: Cast any number of Eldrazi spells you own from outside the game without paying their mana costs. diff --git a/forge-gui/res/cardsfolder/s/spinning_darkness.txt b/forge-gui/res/cardsfolder/s/spinning_darkness.txt index 3058e4b2bee..aa96a605771 100644 --- a/forge-gui/res/cardsfolder/s/spinning_darkness.txt +++ b/forge-gui/res/cardsfolder/s/spinning_darkness.txt @@ -1,10 +1,9 @@ Name:Spinning Darkness ManaCost:4 B B Types:Instant -SVar:AltCost:Cost$ ExileFromGrave<3/Card.Black+FromTopGrave> | Description$ You may exile the top three black cards of your graveyard rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ ExileFromGrave<3/Card.Black+FromTopGrave> | Description$ You may exile the top three black cards of your graveyard rather than pay this spell's mana cost. A:SP$ DealDamage | Cost$ 4 B B | ValidTgts$ Creature.nonBlack | TgtPrompt$ Select target nonblack creature | NumDmg$ 3 | SubAbility$ DBGainLife | SpellDescription$ CARDNAME deals 3 damage to target nonblack creature. You gain 3 life. SVar:DBGainLife:DB$ GainLife | LifeAmount$ 3 AI:RemoveDeck:All SVar:NeedsOrderedGraveyard:TRUE -SVar:Picture:http://www.wizards.com/global/images/magic/general/spinning_darkness.jpg -Oracle:You may exile the top three black cards of your graveyard rather than pay Spinning Darkness's mana cost.\nSpinning Darkness deals 3 damage to target nonblack creature. You gain 3 life. +Oracle:You may exile the top three black cards of your graveyard rather than pay this spell's mana cost.\nSpinning Darkness deals 3 damage to target nonblack creature. You gain 3 life. diff --git a/forge-gui/res/cardsfolder/s/statecraft.txt b/forge-gui/res/cardsfolder/s/statecraft.txt index 9bc5ae8aefc..f2ab9f65db5 100644 --- a/forge-gui/res/cardsfolder/s/statecraft.txt +++ b/forge-gui/res/cardsfolder/s/statecraft.txt @@ -1,9 +1,8 @@ Name:Statecraft ManaCost:3 U Types:Enchantment -R:Event$ DamageDone | Prevent$ True | IsCombat$ True | ValidTarget$ Creature.EnchantedBy | Description$ Prevent all combat damage that would be dealt to and dealt by enchanted creature. -R:Event$ DamageDone | Prevent$ True | IsCombat$ True | ValidSource$ Creature.EnchantedBy | Secondary$ True | Description$ Prevent all combat damage that would be dealt to and dealt by enchanted creature. +R:Event$ DamageDone | Prevent$ True | IsCombat$ True | ValidTarget$ Creature.YouCtrl | Description$ Prevent all combat damage that would be dealt to and dealt by creatures you control. +R:Event$ DamageDone | Prevent$ True | IsCombat$ True | ValidSource$ Creature.YouCtrl | Secondary$ True | Description$ Prevent all combat damage that would be dealt to and dealt by creatures you control. SVar:NonStackingEffect:True AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/statecraft.jpg Oracle:Prevent all combat damage that would be dealt to and dealt by creatures you control. diff --git a/forge-gui/res/cardsfolder/s/summoning_trap.txt b/forge-gui/res/cardsfolder/s/summoning_trap.txt index edbbb4db17f..f957bd4e780 100644 --- a/forge-gui/res/cardsfolder/s/summoning_trap.txt +++ b/forge-gui/res/cardsfolder/s/summoning_trap.txt @@ -8,7 +8,6 @@ T:Mode$ Phase | Phase$ Cleanup | Execute$ TrigReset | Static$ True SVar:TrigReset:DB$ StoreSVar | SVar$ SetTrap | Type$ Number | Expression$ 0 SVar:SetTrap:Number$0 #Set up main abilities -SVar:AltCost:Cost$ 0 | CheckSVar$ SetTrap | SVarCompare$ GE1 | Description$ If a creature spell you cast this turn was countered by a spell or ability an opponent controlled, you may pay {0} rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ 0 | CheckSVar$ SetTrap | SVarCompare$ GE1 | Description$ If a creature spell you cast this turn was countered by a spell or ability an opponent controlled, you may pay {0} rather than pay this spell's mana cost. A:SP$ Dig | Cost$ 4 G G | DigNum$ 7 | ChangeNum$ 1 | ChangeValid$ Creature | DestinationZone$ Battlefield | SpellDescription$ Look at the top seven cards of your library. You may put a creature card from among them onto the battlefield. Put the rest on the bottom of your library in any order. -SVar:Picture:http://www.wizards.com/global/images/magic/general/summoning_trap.jpg -Oracle:If a creature spell you cast this turn was countered by a spell or ability an opponent controlled, you may pay {0} rather than pay Summoning Trap's mana cost.\nLook at the top seven cards of your library. You may put a creature card from among them onto the battlefield. Put the rest on the bottom of your library in any order. +Oracle:If a creature spell you cast this turn was countered by a spell or ability an opponent controlled, you may pay {0} rather than pay this spell's mana cost.\nLook at the top seven cards of your library. You may put a creature card from among them onto the battlefield. Put the rest on the bottom of your library in any order. diff --git a/forge-gui/res/cardsfolder/s/sunscour.txt b/forge-gui/res/cardsfolder/s/sunscour.txt index e8fd80d6e43..5c1e76c3dfa 100644 --- a/forge-gui/res/cardsfolder/s/sunscour.txt +++ b/forge-gui/res/cardsfolder/s/sunscour.txt @@ -1,8 +1,7 @@ Name:Sunscour ManaCost:5 W W Types:Sorcery +SVar:AltCost:Cost$ ExileFromHand<2/Card.White+Other> | Description$ You may exile two white cards from your hand rather than pay this spell's mana cost. A:SP$ DestroyAll | Cost$ 5 W W | ValidCards$ Creature | SpellDescription$ Destroy all creatures. -A:SP$ DestroyAll | Cost$ ExileFromHand<2/Card.White> | ValidCards$ Creature | CostDesc$ You may exile two white cards from your hand | SpellDescription$ rather than pay CARDNAME's mana cost. AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/sunscour.jpg -Oracle:You may exile two white cards from your hand rather than pay Sunscour's mana cost.\nDestroy all creatures. +Oracle:You may exile two white cards from your hand rather than pay this spell's mana cost.\nDestroy all creatures. diff --git a/forge-gui/res/cardsfolder/t/tezzeret_cruel_machinist.txt b/forge-gui/res/cardsfolder/t/tezzeret_cruel_machinist.txt index 8334739ca06..cd8dd60919a 100644 --- a/forge-gui/res/cardsfolder/t/tezzeret_cruel_machinist.txt +++ b/forge-gui/res/cardsfolder/t/tezzeret_cruel_machinist.txt @@ -4,6 +4,6 @@ Loyalty:4 Types:Legendary Planeswalker Tezzeret A:AB$ Draw | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | NumCards$ 1 | Defined$ You | SpellDescription$ Draw a card. A:AB$ Animate | Cost$ AddCounter<0/LOYALTY> | Planeswalker$ True | ValidTgts$ Artifact.YouCtrl | TgtPrompt$ Select target artifact you control | Power$ 5 | Toughness$ 5 | Types$ Creature | UntilYourNextTurn$ True | SpellDescription$ Until your next turn, target artifact you control becomes a 5/5 creature in addition to its other types. -A:AB$ ChangeZone | Cost$ SubCounter<7/LOYALTY> | Planeswalker$ True | Ultimate$ True | Origin$ Hand | Destination$ Battlefield | ChangeType$ Card | ChangeNum$ X | References$ X | FaceDown$ True | FaceDownPower$ 5 | FaceDownToughness$ 5 | FaceDownAddType$ Artifact,Creature | StackDescription$ SpellDescription | SpellDescription$ Put any number of cards from your hand onto the battlefield face down. They're 5/5 artifact creatures. +A:AB$ ChangeZone | Cost$ SubCounter<7/LOYALTY> | Planeswalker$ True | Ultimate$ True | Origin$ Hand | Destination$ Battlefield | ChangeType$ Card | ChangeNum$ X | References$ X | FaceDown$ True | FaceDownPower$ 5 | FaceDownToughness$ 5 | FaceDownAddType$ Artifact & Creature | StackDescription$ SpellDescription | SpellDescription$ Put any number of cards from your hand onto the battlefield face down. They're 5/5 artifact creatures. SVar:X:Count$InYourHand Oracle:[+1]: Draw a card.\n[0]: Until your next turn, target artifact you control becomes a 5/5 creature in addition to its other types.\n[-7]: Put any number of cards from your hand onto the battlefield face down. They're 5/5 artifact creatures. diff --git a/forge-gui/res/cardsfolder/t/thunderclap.txt b/forge-gui/res/cardsfolder/t/thunderclap.txt index bcca37312cd..6329c754a8d 100644 --- a/forge-gui/res/cardsfolder/t/thunderclap.txt +++ b/forge-gui/res/cardsfolder/t/thunderclap.txt @@ -1,7 +1,6 @@ Name:Thunderclap ManaCost:2 R Types:Instant +SVar:AltCost:Cost$ Sac<1/Mountain> | Description$ You may sacrifice a Mountain rather than pay this spell's mana cost. A:SP$ DealDamage | Cost$ 2 R | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 3 | SpellDescription$ CARDNAME deals 3 damage to target creature. -SVar:AltCost:Cost$ Sac<1/Mountain> -SVar:Picture:http://www.wizards.com/global/images/magic/general/thunderclap.jpg -Oracle:You may sacrifice a Mountain rather than pay Thunderclap's mana cost.\nThunderclap deals 3 damage to target creature. +Oracle:You may sacrifice a Mountain rather than pay this spell's mana cost.\nThunderclap deals 3 damage to target creature. diff --git a/forge-gui/res/cardsfolder/t/thwart.txt b/forge-gui/res/cardsfolder/t/thwart.txt index bdb4cfdfdea..7c0e1e81225 100644 --- a/forge-gui/res/cardsfolder/t/thwart.txt +++ b/forge-gui/res/cardsfolder/t/thwart.txt @@ -1,8 +1,7 @@ Name:Thwart ManaCost:2 U U Types:Instant +SVar:AltCost:Cost$ Return<3/Island> | Description$ You may return three Islands you control to their owner's hand rather than pay this spell's mana cost. A:SP$ Counter | Cost$ 2 U U | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | SpellDescription$ Counter target spell. -SVar:AltCost:Cost$ Return<3/Island> AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/thwart.jpg -Oracle:You may return three Islands you control to their owner's hand rather than pay Thwart's mana cost.\nCounter target spell. +Oracle:You may return three Islands you control to their owner's hand rather than pay this spell's mana cost.\nCounter target spell. diff --git a/forge-gui/res/cardsfolder/t/tidal_bore.txt b/forge-gui/res/cardsfolder/t/tidal_bore.txt index 99ca8ee980a..3c4ec047ab1 100644 --- a/forge-gui/res/cardsfolder/t/tidal_bore.txt +++ b/forge-gui/res/cardsfolder/t/tidal_bore.txt @@ -1,8 +1,7 @@ Name:Tidal Bore ManaCost:1 U Types:Instant +SVar:AltCost:Cost$ Return<1/Island> | Description$ You may return an Island you control to its owner's hand rather than pay this spell's mana cost. A:SP$ TapOrUntap | Cost$ 1 U | ValidTgts$ Creature | TgtPrompt$ Select target creature | SpellDescription$ You may tap or untap target creature. -SVar:AltCost:Cost$ Return<1/Island> AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/tidal_bore.jpg -Oracle:You may return an Island you control to its owner's hand rather than pay Tidal Bore's mana cost.\nYou may tap or untap target creature. +Oracle:You may return an Island you control to its owner's hand rather than pay this spell's mana cost.\nYou may tap or untap target creature. diff --git a/forge-gui/res/cardsfolder/t/tin_street_cadet.txt b/forge-gui/res/cardsfolder/t/tin_street_cadet.txt new file mode 100644 index 00000000000..6a2c9881b25 --- /dev/null +++ b/forge-gui/res/cardsfolder/t/tin_street_cadet.txt @@ -0,0 +1,7 @@ +Name:Tin Street Cadet +ManaCost:R +Types:Creature Goblin +PT:1/1 +T:Mode$ AttackerBlocked | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME becomes blocked, create a 1/1 red Goblin creature token. +SVar:TrigToken:DB$ Token | TokenScript$ r_1_1_goblin | TokenAmount$ 1 +Oracle:Whenever Tin Street Cadet becomes blocked, create a 1/1 red Goblin creature token. diff --git a/forge-gui/res/cardsfolder/t/tormenting_voice.txt b/forge-gui/res/cardsfolder/t/tormenting_voice.txt index 9be8e90a2ef..a2855813af8 100644 --- a/forge-gui/res/cardsfolder/t/tormenting_voice.txt +++ b/forge-gui/res/cardsfolder/t/tormenting_voice.txt @@ -1,8 +1,7 @@ Name:Tormenting Voice ManaCost:1 R Types:Sorcery -A:SP$ Draw | Cost$ 1 R Discard<1/Card> | CostDesc$ As an additional cost to cast CARDNAME, discard a card. | NumCards$ 2 | Defined$ You | SpellDescription$ Draw two cards. +A:SP$ Draw | Cost$ 1 R Discard<1/Card> | CostDesc$ As an additional cost to cast this spell, discard a card. | NumCards$ 2 | Defined$ You | SpellDescription$ Draw two cards. DeckHas:Ability$Discard DeckHints:Keyword$Madness & Ability$Delirium -SVar:Picture:http://www.wizards.com/global/images/magic/general/tormenting_voice.jpg -Oracle:As an additional cost to cast Tormenting Voice, discard a card.\nDraw two cards. +Oracle:As an additional cost to cast this spell, discard a card.\nDraw two cards. diff --git a/forge-gui/res/cardsfolder/t/treacherous_link.txt b/forge-gui/res/cardsfolder/t/treacherous_link.txt index c5e8829163a..059c896bbfd 100644 --- a/forge-gui/res/cardsfolder/t/treacherous_link.txt +++ b/forge-gui/res/cardsfolder/t/treacherous_link.txt @@ -3,8 +3,7 @@ ManaCost:1 B Types:Enchantment Aura K:Enchant creature A:SP$ Attach | Cost$ 1 B | ValidTgts$ Creature | AILogic$ Curse -R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Card.EnchantedBy | ReplaceWith$ DmgEnchanted | Description$ All damage that would be dealt to enchanted creature is dealt to its controller instead. +R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Card.EnchantedBy | ReplaceWith$ DmgEnchanted | DamageTarget$ ReplacedTargetController | Description$ All damage that would be dealt to enchanted creature is dealt to its controller instead. SVar:DmgEnchanted:DB$ ReplaceEffect | VarName$ Affected | VarValue$ ReplacedTargetController | VarType$ Player AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/treacherous_link.jpg Oracle:Enchant creature\nAll damage that would be dealt to enchanted creature is dealt to its controller instead. diff --git a/forge-gui/res/cardsfolder/t/turn_the_tables.txt b/forge-gui/res/cardsfolder/t/turn_the_tables.txt index 35f4baf5ddf..2f870aa3778 100644 --- a/forge-gui/res/cardsfolder/t/turn_the_tables.txt +++ b/forge-gui/res/cardsfolder/t/turn_the_tables.txt @@ -2,7 +2,6 @@ Name:Turn the Tables ManaCost:3 W W Types:Instant A:SP$ Effect | Cost$ 3 W W | Name$ Turn the Tables Effect | ReplacementEffects$ DamageEvent | SVars$ TurnTheTables | References$ TurnTheTables | RememberObjects$ Targeted | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature | IsCurse$ True | AILogic$ Fog | SpellDescription$ All combat damage that would be dealt to you this turn is dealt to target attacking creature instead. -SVar:DamageEvent:Event$ DamageDone | ValidSource$ Creature | ValidTarget$ You | ReplaceWith$ TurnTheTables | IsCombat$ True | Description$ All combat damage that would be dealt to you this turn is dealt to target attacking creature instead. +SVar:DamageEvent:Event$ DamageDone | ValidSource$ Creature | ValidTarget$ You | ReplaceWith$ TurnTheTables | IsCombat$ True | DamageTarget$ Remembered | Description$ All combat damage that would be dealt to you this turn is dealt to target attacking creature instead. SVar:TurnTheTables:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Remembered | VarType$ Card -SVar:Picture:http://www.wizards.com/global/images/magic/general/turn_the_tables.jpg Oracle:All combat damage that would be dealt to you this turn is dealt to target attacking creature instead. diff --git a/forge-gui/res/cardsfolder/u/undergrowth.txt b/forge-gui/res/cardsfolder/u/undergrowth.txt index ed45fa0aff2..c58f677aaff 100644 --- a/forge-gui/res/cardsfolder/u/undergrowth.txt +++ b/forge-gui/res/cardsfolder/u/undergrowth.txt @@ -1,12 +1,10 @@ Name:Undergrowth ManaCost:G Types:Instant -Text:As an additional cost to cast CARDNAME, you may pay {2}{R}. K:Kicker:2 R:Generic -A:SP$ Fog | Cost$ G | Condition$ OptionalCost | ConditionOptionalPaid$ False | SubAbility$ DBEffect | SpellDescription$ Prevent all combat damage that would be dealt this turn. If its additional cost was paid, CARDNAME doesn't affect combat damage that would be dealt by red creatures. | StackDescription$ SpellDescription +A:SP$ Fog | Cost$ G | CostDesc$ As an additional cost to cast this spell, you may pay {2}{R}. | Condition$ OptionalCost | ConditionOptionalPaid$ False | SubAbility$ DBEffect | SpellDescription$ Prevent all combat damage that would be dealt this turn. If its additional cost was paid, CARDNAME doesn't affect combat damage that would be dealt by red creatures. | StackDescription$ SpellDescription SVar:DBEffect:DB$ Effect | Condition$ OptionalCost | ConditionOptionalPaid$ True | Name$ Undergrowth Effect | StaticAbilities$ KWPump SVar:KWPump:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature.nonRed | AddKeyword$ Prevent all combat damage that would be dealt by CARDNAME. | Description$ Prevent all combat damage this turn except that from red creatures. AI:RemoveDeck:All DeckHints:Color$Red -SVar:Picture:http://www.wizards.com/global/images/magic/general/undergrowth.jpg -Oracle:As an additional cost to cast Undergrowth, you may pay {2}{R}.\nPrevent all combat damage that would be dealt this turn. If its additional cost was paid, Undergrowth doesn't affect combat damage that would be dealt by red creatures. +Oracle:As an additional cost to cast this spell, you may pay {2}{R}.\nPrevent all combat damage that would be dealt this turn. If its additional cost was paid, Undergrowth doesn't affect combat damage that would be dealt by red creatures. diff --git a/forge-gui/res/cardsfolder/u/unmask.txt b/forge-gui/res/cardsfolder/u/unmask.txt index ca53e91df7c..08ddece100f 100644 --- a/forge-gui/res/cardsfolder/u/unmask.txt +++ b/forge-gui/res/cardsfolder/u/unmask.txt @@ -1,8 +1,7 @@ Name:Unmask ManaCost:3 B Types:Sorcery +SVar:AltCost:Cost$ ExileFromHand<1/Card.Black+Other> | Description$ You may exile one black card from your hand rather than pay this spell's mana cost. A:SP$ Discard | Cost$ 3 B | ValidTgts$ Player | Mode$ RevealYouChoose | DiscardValid$ Card.nonLand | NumCards$ 1 | SpellDescription$ Target player reveals their hand. You choose a nonland card from it. That player discards that card. -SVar:AltCost:Cost$ ExileFromHand<1/Card.Black> | Description$ You may exile one black card from your hand rather than pay CARDNAME's mana cost. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/unmask.jpg -Oracle:You may exile a black card from your hand rather than pay Unmask's mana cost.\nTarget player reveals their hand. You choose a nonland card from it. That player discards that card. +Oracle:You may exile a black card from your hand rather than pay this spell's mana cost.\nTarget player reveals their hand. You choose a nonland card from it. That player discards that card. diff --git a/forge-gui/res/cardsfolder/upcoming/SLD/daryl_hunter_of_walkers.txt b/forge-gui/res/cardsfolder/upcoming/SLD/daryl_hunter_of_walkers.txt new file mode 100644 index 00000000000..e060d72c6af --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/SLD/daryl_hunter_of_walkers.txt @@ -0,0 +1,10 @@ +Name:Daryl, Hunter of Walkers +ManaCost:2 R G +Types:Legendary Creature Human Archer +PT:4/4 +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, target opponent creates three Walker tokens. +SVar:TrigToken:DB$ Token | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | TokenAmount$ 3 | TokenScript$ walker | TokenOwner$ TargetedPlayer +A:AB$ DealDamage | Cost$ T | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 2 | SpellDescription$ NICKNAME deals 2 damage to target creature. +T:Mode$ ChangesZone | ValidCard$ Zombie.OppCtrl | Origin$ Battlefield | Destination$ Graveyard | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever a Zombie an opponent controls dies, draw a card. +SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 +Oracle:At the beginning of your upkeep, target opponent creates three Walker tokens.\n{T}: Daryl deals 2 damage to target creature.\nWhenever a Zombie an opponent controls dies, draw a card. diff --git a/forge-gui/res/cardsfolder/upcoming/SLD/glenn_the_voice_of_calm.txt b/forge-gui/res/cardsfolder/upcoming/SLD/glenn_the_voice_of_calm.txt new file mode 100644 index 00000000000..36135af97e3 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/SLD/glenn_the_voice_of_calm.txt @@ -0,0 +1,9 @@ +Name:Glenn, the Voice of Calm +ManaCost:1 W U +Types:Legendary Creature Human Advisor +PT:1/3 +K:Skulk +T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigDraw | TriggerDescription$ Whenever NICKNAME deals combat damage to a player, draw cards equal to his power. +SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ X | References$ X +SVar:X:Count$CardPower +Oracle:Skulk (This creature can’t be blocked by creatures with greater power.)\nWhenever Glenn deals combat damage to a player, draw cards equal to his power. diff --git a/forge-gui/res/cardsfolder/upcoming/SLD/lucille.txt b/forge-gui/res/cardsfolder/upcoming/SLD/lucille.txt new file mode 100644 index 00000000000..7dfc795a1e4 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/SLD/lucille.txt @@ -0,0 +1,9 @@ +Name:Lucille +ManaCost:1 B +Types:Legendary Artifact Equipment +S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 2 | AddKeyword$ Menace | Description$ Equipped creature gets +2/+0 and has menace. +T:Mode$ Attacks | ValidCard$ Card.EquippedBy | Execute$ TrigSac | TriggerDescription$ Whenever equipped creature attacks, defending player sacrifices a creature. If they do, you create a Walker token. +SVar:TrigSac:DB$ Sacrifice | Defined$ TriggeredDefendingPlayer | SacValid$ Creature | Amount$ 1 | RememberSacrificed$ True | SubAbility$ DBToken +SVar:DBToken:DB$ Token | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | TokenAmount$ 1 | TokenScript$ walker | TokenOwner$ You | SubAbility$ DBCleanup +K:Equip:4 +Oracle:Equipped creature gets +2/+0 and has menace.\nWhenever equipped creature attacks, defending player sacrifices a creature. If they do, you create a Walker token.\nEquip {4} diff --git a/forge-gui/res/cardsfolder/upcoming/SLD/michonne_ruthless_survivor.txt b/forge-gui/res/cardsfolder/upcoming/SLD/michonne_ruthless_survivor.txt new file mode 100644 index 00000000000..2dd17b385a2 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/SLD/michonne_ruthless_survivor.txt @@ -0,0 +1,14 @@ +Name:Michonne, Ruthless Survivor +Nickname:Michonne +ManaCost:3 B G +Types:Legendary Creature Human Warrior +PT:3/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When NICKNAME enters the battlefield, create two Walker tokens. +SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ walker | TokenOwner$ You +S:Mode$ Continuous | Affected$ Card.Self | CheckSVar$ Equipped | SVarCompare$ EQ1 | References$ Equipped | AddHiddenKeyword$ CARDNAME must be blocked if able. | Description$ As long as NICKNAME is equipped, she must be blocked if able. +SVar:Equipped:Count$Valid Card.Self+equipped +SVar:EquipMe:Once +T:Mode$ Attacks | ValidCard$ Card.Self | TriggerZones$ Battlefield | CheckSVar$ Zombies | NoResolvingCheck$ True | SVarCompare$ GE2 | Execute$ TrigPump | TriggerDescription$ Whenever NICKNAME and at least two Zombies attack, she gains indestructible until end of turn. +SVar:TrigPump:DB$ Pump | Defined$ Self | KW$ Indestructible +SVar:Zombies:Count$Valid Zombie.attacking +Oracle:When Michonne enters the battlefield, create two Walker tokens.\nAs long as Michonne is equipped, she must be blocked if able.\nWhenever Michonne and at least two Zombies attack, she gains indestructible until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/SLD/negan_the_cold_blooded.txt b/forge-gui/res/cardsfolder/upcoming/SLD/negan_the_cold_blooded.txt new file mode 100644 index 00000000000..af6db4225b8 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/SLD/negan_the_cold_blooded.txt @@ -0,0 +1,16 @@ +Name:Negan, the Cold-Blooded +ManaCost:2 R W B +Types:Legendary Creature Human Rogue +PT:4/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigTgtOpp | TriggerDescription$ When NICKNAME enters the battlefield, you and target opponent each secretly choose a creature that player controls. Then those choices are revealed, and that player sacrifices those creatures. +SVar:TrigTgtOpp:DB$ Pump | ValidTgts$ Player | TgtPrompt$ Select target opponent | IsCurse$ True | RememberTargets$ True | SubAbility$ DBYouChoose +SVar:DBYouChoose:DB$ ChooseCard | Defined$ You | Amount$ 1 | Mandatory$ True | Choices$ Creature.RememberedPlayerCtrl | RememberChosen$ True | SubAbility$ DBOppChoose +SVar:DBOppChoose:DB$ ChooseCard | Defined$ Remembered | Amount$ 1 | Mandatory$ True | Choices$ Creature.RememberedPlayerCtrl | SubAbility$ DBReveal +SVar:DBReveal:DB$ Reveal | Defined$ You | RevealDefined$ Remembered | RememberRevealed$ True | SubAbility$ DBRevealOpp +SVar:DBRevealOpp:DB$ Reveal | Defined$ Remembered | RevealDefined$ ChosenCard | RememberRevealed$ True | SubAbility$ DBSacrificeAll +SVar:DBSacrificeAll:DB$ SacrificeAll | ValidCards$ Creature.IsRemembered | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearChosen$ True +T:Mode$ Sacrificed | ValidCard$ Creature.OppCtrl | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever an opponent sacrifices a creature, you create a Treasure token. +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_treasure_sac | TokenOwner$ You +DeckHas:Ability$Token +Oracle:When Negan enters the battlefield, you and target opponent each secretly choose a creature that player controls. Then those choices are revealed, and that player sacrifices those creatures.\nWhenever an opponent sacrifices a creature, you create a Treasure token. diff --git a/forge-gui/res/cardsfolder/upcoming/SLD/rick_steadfast_leader.txt b/forge-gui/res/cardsfolder/upcoming/SLD/rick_steadfast_leader.txt new file mode 100644 index 00000000000..8858b25c33a --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/SLD/rick_steadfast_leader.txt @@ -0,0 +1,23 @@ +Name:Rick, Steadfast Leader +ManaCost:2 W W +Types:Legendary Creature Human Soldier +PT:3/4 +K:ETBReplacement:Other:ChooseAbilities +SVar:ChooseAbilities:DB$ GenericChoice | Choices$ FSVig,VigLif,FSLif | SpellDescription$ As NICKNAME enters the battlefield, choose two abilities from among first strike, vigilance, and lifelink. +SVar:FSVig:DB$ StoreSVar | SVar$ VarFSVig | Type$ Number | Expression$ 1 | SpellDescription$ First strike, vigilance +SVar:VigLif:DB$ StoreSVar | SVar$ VarVigLif | Type$ Number | Expression$ 1 | SpellDescription$ Vigilance, lifelink +SVar:FSLif:DB$ StoreSVar | SVar$ VarFSLif | Type$ Number | Expression$ 1 | SpellDescription$ First strike, lifelink +S:Mode$ Continuous | Affected$ Human.YouCtrl | AddKeyword$ First Strike & Vigilance | CheckSVar$ VarFSVig | SVarCompare$ EQ1 | Description$ Humans you control have each of the chosen abilities. +S:Mode$ Continuous | Affected$ Human.YouCtrl | AddKeyword$ Vigilance & Lifelink | CheckSVar$ VarVigLif | SVarCompare$ EQ1 | Secondary$ True +S:Mode$ Continuous | Affected$ Human.YouCtrl | AddKeyword$ First Strike & Lifelink | CheckSVar$ VarFSLif | SVarCompare$ EQ1 | Secondary$ True +S:Mode$ Continuous | Affected$ Human.YouCtrl | AddPower$ 2 | AddToughness$ 2 | IsPresent$ Human.YouCtrl | PresentCompare$ GE4 | Description$ As long as you control four or more Humans, Humans you control get +2/+2. +T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Any | Execute$ ResetSVars | Static$ True +SVar:ResetSVars:DB$ StoreSVar | SVar$ VarFSVig | Type$ Number | Expression$ 0 | SubAbility$ ResetSVars2 +SVar:ResetSVars2:DB$ StoreSVar | SVar$ VarVigLif | Type$ Number | Expression$ 0 | SubAbility$ ResetSVars3 +SVar:ResetSVars3:DB$ StoreSVar | SVar$ VarFSLif | Type$ Number | Expression$ 0 +SVar:VarFSVig:Number$0 +SVar:VarVigLif:Number$0 +SVar:VarFSLif:Number$0 +SVar:PlayMain1:TRUE +DeckHints:Type$Human +Oracle:As Rick enters the battlefield, choose two abilities from among first strike, vigilance, and lifelink.\nHumans you control have each of the chosen abilities.\nAs long as you control four or more Humans, Humans you control get +2/+2. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/v/vassals_duty.txt b/forge-gui/res/cardsfolder/v/vassals_duty.txt index c147e695547..acf5afdc63e 100644 --- a/forge-gui/res/cardsfolder/v/vassals_duty.txt +++ b/forge-gui/res/cardsfolder/v/vassals_duty.txt @@ -2,8 +2,7 @@ Name:Vassal's Duty ManaCost:3 W Types:Enchantment A:AB$ Effect | Cost$ 1 | ValidTgts$ Creature.Legendary+YouCtrl | TgtPrompt$ Select target legendary creature to redirect damage from | ReplacementEffects$ DamageEvent | SVars$ DamageEventDmg | References$ DamageEvent,DamageEventDmg | Duration$ HostLeavesOrEOT | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | SpellDescription$ The next 1 damage that would be dealt to target legendary creature you control is dealt to you instead. -SVar:DamageEvent:Event$ DamageDone | ValidTarget$ Creature.IsRemembered | ReplaceWith$ DamageEventDmg | Description$ The next 1 damage that would be dealt to target legendary creature you control is dealt to you instead. +SVar:DamageEvent:Event$ DamageDone | ValidTarget$ Creature.IsRemembered | ReplaceWith$ DamageEventDmg | DamageTarget$ You | Description$ The next 1 damage that would be dealt to target legendary creature you control is dealt to you instead. SVar:DamageEventDmg:DB$ ReplaceSplitDamage | DamageTarget$ You AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/vassals_duty.jpg Oracle:{1}: The next 1 damage that would be dealt to target legendary creature you control this turn is dealt to you instead. diff --git a/forge-gui/res/cardsfolder/v/veinfire_borderpost.txt b/forge-gui/res/cardsfolder/v/veinfire_borderpost.txt index 41666bcd323..f958c02be2b 100644 --- a/forge-gui/res/cardsfolder/v/veinfire_borderpost.txt +++ b/forge-gui/res/cardsfolder/v/veinfire_borderpost.txt @@ -1,9 +1,8 @@ Name:Veinfire Borderpost ManaCost:1 B R Types:Artifact +SVar:AltCost:Cost$ 1 Return<1/Land.Basic> | Description$ You may pay {1} and return a basic land you control to its owner's hand rather than pay this spell's mana cost. K:CARDNAME enters the battlefield tapped. A:AB$ Mana | Cost$ T | Produced$ B | SpellDescription$ Add {B}. A:AB$ Mana | Cost$ T | Produced$ R | SpellDescription$ Add {R}. -SVar:AltCost:Cost$ 1 Return<1/Land.Basic> | Description$ You may pay {1} and return a basic land you control to its owner's hand rather than pay Veinfire Borderpost's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/veinfire_borderpost.jpg -Oracle:You may pay {1} and return a basic land you control to its owner's hand rather than pay Veinfire Borderpost's mana cost.\nVeinfire Borderpost enters the battlefield tapped.\n{T}: Add {B} or {R}. +Oracle:You may pay {1} and return a basic land you control to its owner's hand rather than pay this spell's mana cost.\nVeinfire Borderpost enters the battlefield tapped.\n{T}: Add {B} or {R}. diff --git a/forge-gui/res/cardsfolder/v/vindictive_lich.txt b/forge-gui/res/cardsfolder/v/vindictive_lich.txt index 8c94811a0f7..e8c91bbf45c 100644 --- a/forge-gui/res/cardsfolder/v/vindictive_lich.txt +++ b/forge-gui/res/cardsfolder/v/vindictive_lich.txt @@ -3,11 +3,9 @@ ManaCost:3 B Types:Creature Zombie Wizard PT:4/1 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigCharm | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, ABILITY -SVar:TrigCharm:DB$ Charm | MinCharmNum$ 1 | CharmNum$ 3 | CharmNumOnResolve$ MaxUniqueOpponents | Choices$ SacCreature,DiscardCards,LoseLife | References$ MaxUniqueOpponents | AdditionalDescription$ Each mode must target a different player. +SVar:TrigCharm:DB$ Charm | MinCharmNum$ 1 | CharmNum$ MaxUniqueOpponents | Choices$ SacCreature,DiscardCards,LoseLife | References$ MaxUniqueOpponents | AdditionalDescription$ Each mode must target a different player. SVar:SacCreature:DB$ Sacrifice | ValidTgts$ Opponent | TargetUnique$ True | SacValid$ Creature | SacMessage$ Creature | SpellDescription$ Target opponent sacrifices a creature. SVar:DiscardCards:DB$ Discard | ValidTgts$ Opponent | TargetUnique$ True | NumCards$ 2 | Mode$ TgtChoose | SpellDescription$ Target opponent discards two cards. SVar:LoseLife:DB$ LoseLife | ValidTgts$ Opponent | TargetUnique$ True | LifeAmount$ 5 | SpellDescription$ Target opponent loses 5 life. SVar:MaxUniqueOpponents:PlayerCountOpponents$Amount -#TODO: The AI is able to target the same player with multiple modes, usually all three. This should not happen. -AI:RemoveDeck:All Oracle:When Vindictive Lich dies, choose one or more. Each mode must target a different player.\n• Target opponent sacrifices a creature.\n• Target opponent discards two cards.\n• Target opponent loses 5 life. diff --git a/forge-gui/res/cardsfolder/v/vine_dryad.txt b/forge-gui/res/cardsfolder/v/vine_dryad.txt index a984cebe661..de498f2ac1b 100644 --- a/forge-gui/res/cardsfolder/v/vine_dryad.txt +++ b/forge-gui/res/cardsfolder/v/vine_dryad.txt @@ -4,6 +4,5 @@ Types:Creature Dryad PT:1/3 K:Flash K:Forestwalk -SVar:AltCost:Cost$ ExileFromHand<1/Card.Green> | Description$ You may exile one green card from your hand rather than pay CARDNAME's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/vine_dryad.jpg -Oracle:Flash\nForestwalk\nYou may exile a green card from your hand rather than pay Vine Dryad's mana cost. +SVar:AltCost:Cost$ ExileFromHand<1/Card.Green+Other> | Description$ You may exile one green card from your hand rather than pay this spell's mana cost. +Oracle:Flash\nForestwalk\nYou may exile a green card from your hand rather than pay this spell's mana cost. diff --git a/forge-gui/res/cardsfolder/v/vivien_arkbow_ranger.txt b/forge-gui/res/cardsfolder/v/vivien_arkbow_ranger.txt index 950bc622fe7..a581e010550 100644 --- a/forge-gui/res/cardsfolder/v/vivien_arkbow_ranger.txt +++ b/forge-gui/res/cardsfolder/v/vivien_arkbow_ranger.txt @@ -7,6 +7,6 @@ SVar:DBPumpAll:DB$ Pump | KW$ Trample | Defined$ Targeted A:AB$ Pump | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SubAbility$ SoulsDamage | AILogic$ Fight | StackDescription$ None | SpellDescription$ Target creature you control deals damage equal to its power to target creature or planeswalker. 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 | Ultimate$ 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. +A:AB$ ChangeZone | Cost$ SubCounter<5/LOYALTY> | Planeswalker$ True | Ultimate$ True | Origin$ Sideboard | Destination$ Hand | ChangeType$ Creature.YouOwn | ChangeTypeDesc$ creature card they own | ChangeNum$ 1 | Reveal$ True | Hidden$ True | SpellDescription$ You may reveal a creature card you own from outside the game and put it into your hand. 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. +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 reveal a creature card you own from outside the game and put it into your hand. diff --git a/forge-gui/res/cardsfolder/w/weathered_bodyguards.txt b/forge-gui/res/cardsfolder/w/weathered_bodyguards.txt index 09a7330d06f..b7f53d31fed 100644 --- a/forge-gui/res/cardsfolder/w/weathered_bodyguards.txt +++ b/forge-gui/res/cardsfolder/w/weathered_bodyguards.txt @@ -3,7 +3,6 @@ ManaCost:5 W Types:Creature Human Soldier PT:2/5 K:Morph:3 W -R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Creature.unblocked | ValidTarget$ You | ReplaceWith$ DmgSelf | IsCombat$ True | IsPresent$ Card.Self+untapped | DamageTarget$ Remembered | Description$ As long as CARDNAME is untapped, all combat damage that would be dealt to you by unblocked creatures is dealt to CARDNAME instead. +R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Creature.unblocked | ValidTarget$ You | ReplaceWith$ DmgSelf | IsCombat$ True | IsPresent$ Card.Self+untapped | DamageTarget$ Self | Description$ As long as CARDNAME is untapped, all combat damage that would be dealt to you by unblocked creatures is dealt to CARDNAME instead. SVar:DmgSelf:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Self | VarType$ Card -SVar:Picture:http://www.wizards.com/global/images/magic/general/weathered_bodyguards.jpg Oracle:As long as Weathered Bodyguards is untapped, all combat damage that would be dealt to you by unblocked creatures is dealt to Weathered Bodyguards instead.\nMorph {3}{W} (You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.) diff --git a/forge-gui/res/cardsfolder/w/whiplash_trap.txt b/forge-gui/res/cardsfolder/w/whiplash_trap.txt index bc9fbb76448..f8195e95d85 100644 --- a/forge-gui/res/cardsfolder/w/whiplash_trap.txt +++ b/forge-gui/res/cardsfolder/w/whiplash_trap.txt @@ -1,8 +1,7 @@ Name:Whiplash Trap ManaCost:3 U U Types:Instant Trap -A:SP$ ChangeZone | Cost$ 3 U U | Origin$ Battlefield | Destination$ Hand | TgtPrompt$ Choose target creatures. | ValidTgts$ Creature | TargetMin$ 2 | TargetMax$ 2 | SpellDescription$ Return two target creatures to their owners' hands. -A:SP$ ChangeZone | Cost$ U | CheckSVar$ CreaturesEntered | SVarCompare$ GE2 | Origin$ Battlefield | Destination$ Hand | TgtPrompt$ Choose target creatures. | ValidTgts$ Creature | TargetMin$ 2 | TargetMax$ 2 | References$ CreaturesEntered | SpellDescription$ If an opponent had two or more creatures enter the battlefield under their control this turn, you may pay {U} rather than pay CARDNAME's mana cost. +SVar:AltCost:Cost$ U | CheckSVar$ CreaturesEntered | SVarCompare$ GE2 | References$ CreaturesEntered | Description$ If an opponent had two or more creatures enter the battlefield under their control this turn, you may pay {U} rather than pay this spell's mana cost. +A:SP$ ChangeZone | Cost$ 3 U U | Origin$ Battlefield | Destination$ Hand | TgtPrompt$ Choose two target creatures | ValidTgts$ Creature | TargetMin$ 2 | TargetMax$ 2 | SpellDescription$ Return two target creatures to their owners' hands. SVar:CreaturesEntered:Count$ThisTurnEntered_Battlefield_Creature.YouDontCtrl -SVar:Picture:http://www.wizards.com/global/images/magic/general/whiplash_trap.jpg -Oracle:If an opponent had two or more creatures enter the battlefield under their control this turn, you may pay {U} rather than pay Whiplash Trap's mana cost.\nReturn two target creatures to their owners' hands. +Oracle:If an opponent had two or more creatures enter the battlefield under their control this turn, you may pay {U} rather than pay this spell's mana cost.\nReturn two target creatures to their owners' hands. diff --git a/forge-gui/res/cardsfolder/w/whippoorwill.txt b/forge-gui/res/cardsfolder/w/whippoorwill.txt new file mode 100644 index 00000000000..91a344338de --- /dev/null +++ b/forge-gui/res/cardsfolder/w/whippoorwill.txt @@ -0,0 +1,11 @@ +Name:Whippoorwill +ManaCost:G +Types:Creature Bird +PT:1/1 +A:AB$ Pump | Cost$ G G T | ValidTgts$ Creature | TgtPrompt$ Select target creature | AILogic$ Curse | KW$ HIDDEN CARDNAME can't be regenerated. & HIDDEN Damage that would be dealt to CARDNAME can't be redirected. | SubAbility$ DBEffect | StackDescription$ {c:Targeted} can’t be regenerated this turn. Damage that would be dealt to {c:Targeted} this turn can’t be prevented or dealt instead to another permanent or player. When {c:Targeted} dies this turn, exile {c:Targeted}. | SpellDescription$ Target creature can’t be regenerated this turn. Damage that would be dealt to that creature this turn can’t be prevented or dealt instead to another permanent or player. When the creature dies this turn, exile the creature. +SVar:DBEffect:DB$ Effect | Name$ Whippoorwill Effect | EffectOwner$ TargetedOwner | RememberObjects$ Targeted | StaticAbilities$ NoPrevent | ReplacementEffects$ ReplaceGraveyard | SVars$ MoveExile,ExileEffect +SVar:NoPrevent:Mode$ CantPreventDamage | Affected$ Creature.IsRemembered | EffectZone$ Command | Description$ Damage that would be dealt to that creature this turn can’t be prevented. +SVar:ReplaceGraveyard:Event$ Moved | ValidCard$ Card.IsRemembered | Origin$ Battlefield | Destination$ Graveyard | ReplaceWith$ MoveExile | Description$ When the creature dies this turn, exile the creature. +SVar:MoveExile:DB$ ChangeZone | Defined$ ReplacedCard | Origin$ Battlefield | Destination$ Exile | SubAbility$ ExileEffect +SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile +Oracle:{G}{G}, {T}: Target creature can’t be regenerated this turn. Damage that would be dealt to that creature this turn can’t be prevented or dealt instead to another permanent or player. When the creature dies this turn, exile the creature. diff --git a/forge-gui/res/cardsfolder/w/wild_guess.txt b/forge-gui/res/cardsfolder/w/wild_guess.txt index de72eed689a..7f09d4d871b 100644 --- a/forge-gui/res/cardsfolder/w/wild_guess.txt +++ b/forge-gui/res/cardsfolder/w/wild_guess.txt @@ -1,7 +1,6 @@ Name:Wild Guess ManaCost:R R Types:Sorcery -A:SP$ Draw | Cost$ R R Discard<1/Card> | CostDesc$ As an additional cost to cast CARDNAME, discard a card. | NumCards$ 2 | Defined$ You | SpellDescription$ Draw two cards. +A:SP$ Draw | Cost$ R R Discard<1/Card/card> | CostDesc$ As an additional cost to cast this spell, discard a card. | NumCards$ 2 | Defined$ You | SpellDescription$ Draw two cards. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/wild_guess.jpg -Oracle:As an additional cost to cast Wild Guess, discard a card.\nDraw two cards. +Oracle:As an additional cost to cast this spell, discard a card.\nDraw two cards. diff --git a/forge-gui/res/cardsfolder/w/wildfield_borderpost.txt b/forge-gui/res/cardsfolder/w/wildfield_borderpost.txt index bf0d0593dc0..e5cc6cc1a6e 100644 --- a/forge-gui/res/cardsfolder/w/wildfield_borderpost.txt +++ b/forge-gui/res/cardsfolder/w/wildfield_borderpost.txt @@ -1,9 +1,8 @@ Name:Wildfield Borderpost ManaCost:1 G W Types:Artifact +SVar:AltCost:Cost$ 1 Return<1/Land.Basic> | Description$ You may pay {1} and return a basic land you control to its owner's hand rather than pay this spell's mana cost. K:CARDNAME enters the battlefield tapped. A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G}. A:AB$ Mana | Cost$ T | Produced$ W | SpellDescription$ Add {W}. -SVar:AltCost:Cost$ 1 Return<1/Land.Basic> | Description$ You may pay {1} and return a basic land you control to its owner's hand rather than pay Wildfield Borderpost's mana cost. -SVar:Picture:http://www.wizards.com/global/images/magic/general/wildfield_borderpost.jpg -Oracle:You may pay {1} and return a basic land you control to its owner's hand rather than pay Wildfield Borderpost's mana cost.\nWildfield Borderpost enters the battlefield tapped.\n{T}: Add {G} or {W}. +Oracle:You may pay {1} and return a basic land you control to its owner's hand rather than pay this spell's mana cost.\nWildfield Borderpost enters the battlefield tapped.\n{T}: Add {G} or {W}. diff --git a/forge-gui/res/cardsfolder/w/wildfire_cerberus.txt b/forge-gui/res/cardsfolder/w/wildfire_cerberus.txt index 994005e62b5..764d0ab654c 100644 --- a/forge-gui/res/cardsfolder/w/wildfire_cerberus.txt +++ b/forge-gui/res/cardsfolder/w/wildfire_cerberus.txt @@ -3,8 +3,7 @@ ManaCost:4 R Types:Creature Dog PT:4/3 K:Monstrosity:1:5 R R -T:Mode$ BecomeMonstrous | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigDamageAll | TriggerDescription$ When CARDNAME becomes monstrous, it deals 2 damage to each opponent and each creature your opponents control. -SVar:TrigDamageAll:DB$ DamageAll | ValidCards$ Creature.OppCtrl | ValidPlayers$ Player.Opponent | NumDmg$ 2 | ValidDescription$ each opponent and each creature your opponents control. +T:Mode$ BecomeMonstrous | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigDamageAll | TriggerDescription$ When CARDNAME becomes monstrous, it deals 2 damage to each opponent and each creature they control. +SVar:TrigDamageAll:DB$ DamageAll | ValidCards$ Creature.OppCtrl | ValidPlayers$ Player.Opponent | NumDmg$ 2 | ValidDescription$ each opponent and each creature they control. DeckHas:Ability$Counters -SVar:Picture:http://www.wizards.com/global/images/magic/general/wildfire_cerberus.jpg -Oracle:{5}{R}{R}: Monstrosity 1. (If this creature isn't monstrous, put a +1/+1 counter on it and it becomes monstrous.)\nWhen Wildfire Cerberus becomes monstrous, it deals 2 damage to each opponent and each creature your opponents control. +Oracle:{5}{R}{R}: Monstrosity 1. (If this creature isn't monstrous, put a +1/+1 counter on it and it becomes monstrous.)\nWhen Wildfire Cerberus becomes monstrous, it deals 2 damage to each opponent and each creature they control. diff --git a/forge-gui/res/cardsfolder/w/witchs_vengeance.txt b/forge-gui/res/cardsfolder/w/witchs_vengeance.txt index 25aae772654..f5f4cec1534 100644 --- a/forge-gui/res/cardsfolder/w/witchs_vengeance.txt +++ b/forge-gui/res/cardsfolder/w/witchs_vengeance.txt @@ -1,6 +1,6 @@ Name:Witch's Vengeance ManaCost:1 B B Types:Sorcery -A:SP$ ChooseType | Cost$ 1 B B | Defined$ You | Type$ Creature | AILogic$ MostProminentHumanControls | SubAbility$ DBPumpAll | SpellDescription$ Creatures of the creature type of your choice get -3/-3 until end of turn. +A:SP$ ChooseType | Cost$ 1 B B | Defined$ You | Type$ Creature | AILogic$ MostProminentOppControls | SubAbility$ DBPumpAll | SpellDescription$ Creatures of the creature type of your choice get -3/-3 until end of turn. SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Creature.ChosenType | NumAtt$ -3 | NumDef$ -3 | IsCurse$ True Oracle:Creatures of the creature type of your choice get -3/-3 until end of turn. diff --git a/forge-gui/res/cardsfolder/y/yasharn_implacable_earth.txt b/forge-gui/res/cardsfolder/y/yasharn_implacable_earth.txt new file mode 100755 index 00000000000..d18d74752a8 --- /dev/null +++ b/forge-gui/res/cardsfolder/y/yasharn_implacable_earth.txt @@ -0,0 +1,10 @@ +Name:Yasharn, Implacable Earth +ManaCost:2 G W +Types:Legendary Creature Elemental Boar +PT:4/4 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Self | Execute$ TrigForest | TriggerDescription$ When CARDNAME enters the battlefield, search your library for a basic Forest card and a basic Plains card, reveal those cards, put them into your hand, then shuffle your library. +SVar:TrigForest:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Forest.Basic | ChangeNum$ 1 | SubAbility$ DBPlains +SVar:DBPlains:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Plains.Basic | ChangeNum$ 1 +S:Mode$ Continuous | Affected$ Player | AddKeyword$ You can't pay life to cast spells or activate abilities. & You can't sacrifice nonland permanents to cast spells or activate abilities. | Description$ Players can't pay life or sacrifice nonland permanents to cast spells or activate abilities. +AI:RemoveDeck:Random +Oracle:When Yasharn, Implacable Earth enters the battlefield, search your library for a basic Forest card and a basic Plains card, reveal those cards, put them into your hand, then shuffle your library.\nPlayers can't pay life or sacrifice nonland permanents to cast spells or activate abilities. diff --git a/forge-gui/res/draft/rankings.txt b/forge-gui/res/draft/rankings.txt index 7c83a19ba14..56e6f55395b 100644 --- a/forge-gui/res/draft/rankings.txt +++ b/forge-gui/res/draft/rankings.txt @@ -1,4 +1,233 @@ //Rank|Name|Rarity|Set +#1|Phylath, World Sculptor|R|ZNR +#2|Zagras, Thief of Heartbeats|R|ZNR +#3|Drana, the Last Bloodchief|M|ZNR +#4|Zareth San, the Trickster|R|ZNR +#5|Ashaya, Soul of the Wild|M|ZNR +#6|Nahiri, Heir of the Ancients|M|ZNR +#7|Nullpriest of Oblivion|R|ZNR +#8|Ancient Greenwarden|M|ZNR +#9|Leyline Tyrant|M|ZNR +#10|Inscription of Abundance|R|ZNR +#11|Maul of the Skyclaves|R|ZNR +#12|Nighthawk Scavenger|R|ZNR +#13|Omnath, Locus of Creation|M|ZNR +#14|Akiri, Fearless Voyager|R|ZNR +#15|Felidar Retreat|R|ZNR +#16|Verazol, the Split Current|R|ZNR +#17|Master of Winds|R|ZNR +#18|Angel of Destiny|M|ZNR +#19|Jace, Mirror Mage|M|ZNR +#20|Moraug, Fury of Akoum|M|ZNR +#21|Grakmaw, Skyclave Ravager|R|ZNR +#22|Shatterskull Charger|R|ZNR +#23|Yasharn, Implacable Earth|R|ZNR +#24|Taborax, Hope's Demise|R|ZNR +#25|Inscription of Ruin|R|ZNR +#26|Tajuru Paragon|R|ZNR +#27|Swarm Shambler|R|ZNR +#28|Bloodchief's Thirst|U|ZNR +#29|Nissa of Shadowed Boughs|M|ZNR +#30|Orah, Skyclave Hierophant|R|ZNR +#31|Tazri, Beacon of Unity|M|ZNR +#32|Skyclave Shade|R|ZNR +#33|Luminarch Aspirant|R|ZNR +#34|Kargan Intimidator|R|ZNR +#35|Lotus Cobra|R|ZNR +#36|Lithoform Engine|M|ZNR +#37|Scute Swarm|R|ZNR +#38|Squad Commander|R|ZNR +#39|Magmatic Channeler|R|ZNR +#40|Inscription of Insight|R|ZNR +#41|Thundering Rebuke|U|ZNR +#42|Oran-Rief Ooze|R|ZNR +#43|Charix, the Raging Isle|R|ZNR +#44|Roost of Drakes|U|ZNR +#45|Cragplate Baloth|R|ZNR +#46|Soul Shatter|R|ZNR +#47|Legion Angel|R|ZNR +#48|Journey to Oblivion|U|ZNR +#49|Murasa Sproutling|U|ZNR +#50|Fearless Fledgling|U|ZNR +#51|Sea Gate Stormcaller|M|ZNR +#52|Crawling Barrens|R|ZNR +#53|Coralhelm Chronicler|R|ZNR +#54|Vine Gecko|U|ZNR +#55|Spoils of Adventure|U|ZNR +#56|Into the Roil|C|ZNR +#57|Lullmage's Familiar|U|ZNR +#58|Thieving Skydiver|R|ZNR +#59|Merfolk Falconer|U|ZNR +#60|Roil Eruption|C|ZNR +#61|Umara Mystic|U|ZNR +#62|Deadly Alliance|C|ZNR +#63|Skyclave Apparition|R|ZNR +#64|Archpriest of Iona|R|ZNR +#65|Cleric of Life's Bond|U|ZNR +#66|Linvala, Shield of Sea Gate|R|ZNR +#67|Murasa Rootgrazer|U|ZNR +#68|Myriad Construct|R|ZNR +#69|Kargan Warleader|U|ZNR +#70|Soaring Thought-Thief|U|ZNR +#71|Ravager's Mace|U|ZNR +#72|Thundering Sparkmage|U|ZNR +#73|Vanquish the Weak|C|ZNR +#74|Brushfire Elemental|U|ZNR +#75|Rabid Bite|C|ZNR +#76|Nahiri's Binding|C|ZNR +#77|Moss-Pit Skeleton|U|ZNR +#78|Shadows' Verdict|R|ZNR +#79|Nimble Trapfinder|R|ZNR +#80|Relic Robber|R|ZNR +#81|Iridescent Hornbeetle|U|ZNR +#82|Rockslide Sorcerer|U|ZNR +#83|Bubble Snare|C|ZNR +#84|Skyclave Geopede|U|ZNR +#85|Valakut Exploration|R|ZNR +#86|Thwart the Grave|U|ZNR +#87|Kor Blademaster|U|ZNR +#88|Synchronized Spellcraft|C|ZNR +#89|Emeria Captain|U|ZNR +#90|Skyclave Pick-Axe|U|ZNR +#91|Canyon Jerboa|U|ZNR +#92|Relic Amulet|U|ZNR +#93|Scion of the Swarm|U|ZNR +#94|Cunning Geysermage|C|ZNR +#95|Attended Healer|U|ZNR +#96|Paired Tactician|U|ZNR +#97|Feed the Swarm|C|ZNR +#98|Goma Fada Vanguard|U|ZNR +#99|Taunting Arbormage|U|ZNR +#100|Windrider Wizard|U|ZNR +#101|Gnarlid Colony|C|ZNR +#102|Veteran Adventurer|U|ZNR +#103|Scourge of the Skyclaves|M|ZNR +#104|Relic Axe|U|ZNR +#105|Tazeem Roilmage|C|ZNR +#106|Shatterskull Minotaur|U|ZNR +#107|Shadow Stinger|U|ZNR +#108|Skyclave Plunder|U|ZNR +#109|Malakir Blood-Priest|C|ZNR +#110|Roiling Regrowth|U|ZNR +#111|Vastwood Surge|U|ZNR +#112|Fissure Wizard|C|ZNR +#113|Sure-Footed Infiltrator|U|ZNR +#114|Mind Carver|U|ZNR +#115|Demon's Disciple|U|ZNR +#116|Acquisitions Expert|U|ZNR +#117|Shepherd of Heroes|C|ZNR +#118|Ruin Crab|U|ZNR +#119|Maddening Cacophony|R|ZNR +#120|Reclaim the Wastes|C|ZNR +#121|Skyclave Shadowcat|U|ZNR +#122|Relic Vial|U|ZNR +#123|Risen Riptide|C|ZNR +#124|Cinderclasm|U|ZNR +#125|Archon of Emeria|R|ZNR +#126|Joraga Visionary|C|ZNR +#127|Lullmage's Domination|U|ZNR +#128|Practiced Tactics|C|ZNR +#129|Coveted Prize|R|ZNR +#130|Grotag Bug-Catcher|C|ZNR +#131|Expedition Diviner|C|ZNR +#132|Grotag Night-Runner|U|ZNR +#133|Merfolk Windrobber|U|ZNR +#134|Tazeem Raptor|C|ZNR +#135|Field Research|C|ZNR +#136|Stonework Packbeast|C|ZNR +#137|Kazandu Stomper|C|ZNR +#138|Kor Celebrant|C|ZNR +#139|Allied Assault|U|ZNR +#140|Marauding Blight-Priest|C|ZNR +#141|Springmantle Cleric|U|ZNR +#142|Canopy Baloth|C|ZNR +#143|Scale the Heights|C|ZNR +#144|Kaza, Roil Chaser|R|ZNR +#145|Subtle Strike|C|ZNR +#146|Blood Beckoning|C|ZNR +#147|Expedition Champion|C|ZNR +#148|Sea Gate Colossus|C|ZNR +#149|Expedition Skulker|C|ZNR +#150|Dauntless Survivor|C|ZNR +#151|Akoum Hellhound|C|ZNR +#152|Kitesail Cleric|U|ZNR +#153|Seafloor Stalker|C|ZNR +#154|Ardent Electromancer|C|ZNR +#155|Tajuru Blightblade|C|ZNR +#156|Skyclave Relic|R|ZNR +#157|Molten Blast|C|ZNR +#158|Drana's Silencer|C|ZNR +#159|Ghastly Gloomhunter|C|ZNR +#160|Territorial Scythecat|C|ZNR +#161|Nimana Skydancer|C|ZNR +#162|Fireblade Charger|U|ZNR +#163|Relic Golem|U|ZNR +#164|Pyroclastic Hellion|C|ZNR +#165|Expedition Healer|C|ZNR +#166|Scorch Rider|C|ZNR +#167|Dreadwurm|C|ZNR +#168|Hagra Constrictor|C|ZNR +#169|Resolute Strike|C|ZNR +#170|Lithoform Blight|U|ZNR +#171|Murasa Brute|C|ZNR +#172|Angelheart Protector|C|ZNR +#173|Prowling Felidar|C|ZNR +#174|Spitfire Lagac|C|ZNR +#175|Farsight Adept|C|ZNR +#176|Might of Murasa|C|ZNR +#177|Scavenged Blade|C|ZNR +#178|Guul Draz Mucklord|C|ZNR +#179|Skyclave Squid|C|ZNR +#180|Deliberate|C|ZNR +#181|Turntimber Ascetic|C|ZNR +#182|Kazandu Nectarpot|C|ZNR +#183|Makindi Ox|C|ZNR +#184|Nissa's Zendikon|C|ZNR +#185|Oblivion's Hunger|C|ZNR +#186|Nimana Skitter-Sneak|C|ZNR +#187|Sea Gate Banneret|C|ZNR +#188|Cascade Seer|C|ZNR +#189|Zulaport Duelist|C|ZNR +#190|Anticognition|C|ZNR +#191|Cliffhaven Sell-Sword|C|ZNR +#192|Kabira Outrider|C|ZNR +#193|Shell Shield|C|ZNR +#194|Mind Drain|C|ZNR +#195|Glacial Grasp|C|ZNR +#196|Teeterpeak Ambusher|C|ZNR +#197|Living Tempest|C|ZNR +#198|Sizzling Barrage|C|ZNR +#199|Strength of Solidarity|C|ZNR +#200|Tormenting Voice|C|ZNR +#201|Blood Price|C|ZNR +#202|Chilling Trap|C|ZNR +#203|Throne of Makindi|R|ZNR +#204|Inordinate Rage|C|ZNR +#205|Utility Knife|C|ZNR +#206|Spare Supplies|C|ZNR +#207|Adventure Awaits|C|ZNR +#208|Highborn Vampire|C|ZNR +#209|Cleansing Wildfire|C|ZNR +#210|Sneaking Guide|C|ZNR +#211|Tajuru Snarecaster|C|ZNR +#212|Dauntless Unity|C|ZNR +#213|Mesa Lynx|C|ZNR +#214|Tuktuk Rubblefort|C|ZNR +#215|Base Camp|U|ZNR +#216|Skyclave Sentinel|C|ZNR +#217|Cliffhaven Kitesail|C|ZNR +#218|Pressure Point|C|ZNR +#219|Disenchant|C|ZNR +#220|Broken Wings|C|ZNR +#221|Cleric of Chill Depths|C|ZNR +#222|Confounding Conundrum|R|ZNR +#223|Nahiri's Lithoforming|R|ZNR +#224|Negate|C|ZNR +#225|Smite the Monstrous|C|ZNR +#226|Concerted Defense|U|ZNR +#227|Forsaken Monument|M|ZNR +#228|Wayward Guide-Beast|R|ZNR +#229|Roiling Vortex|R|ZNR #1|Angel of Sanctions|M|AKR #2|Liliana, Death's Majesty|M|AKR #3|Glorybringer|R|AKR diff --git a/forge-gui/res/editions/Amonkhet.txt b/forge-gui/res/editions/Amonkhet.txt index ed341a2e32f..96365a69612 100644 --- a/forge-gui/res/editions/Amonkhet.txt +++ b/forge-gui/res/editions/Amonkhet.txt @@ -308,4 +308,21 @@ b_2_2_zombie g_4_2_beast g_3_3_hippo g_1_1_snake_deathtouch -g_5_5_wurm \ No newline at end of file +g_5_5_wurm + +[other] +embalm_angel_of_sanctions +embalm_anointer_priest +embalm_aven_initiate +embalm_aven_wind_guide +embalm_glyph_keeper +embalm_heart-piercer_manticore +embalm_honored_hydra +embalm_labyrinth_guardian +embalm_oketra's_attendant +embalm_sacred_cat +embalm_tah-crop_skirmisher +embalm_temmet_vizier_of_naktamun +embalm_trueheart_duelist +embalm_unwavering_initiate +embalm_vizier_of_many_faces diff --git a/forge-gui/res/editions/Arena Beginner Set.txt b/forge-gui/res/editions/Arena Beginner Set.txt new file mode 100644 index 00000000000..1bd64799513 --- /dev/null +++ b/forge-gui/res/editions/Arena Beginner Set.txt @@ -0,0 +1,123 @@ +[metadata] +Code=ANB +Date=2020-08-13 +Name=Arena Beginner Set +Type=Other + +[cards] +U Affectionate Indrik +U Air Elemental +R Angelic Guardian +U Angelic Reward +U Angel of Vitality +C Armored Whirl Turtle +U Bad Deal +C Baloth Packhunter +C Bombard +U Bond of Discipline +C Burn Bright +C Charging Badger +C Charmed Stray +C Cloudkin Seer +U Colossal Majesty +C Compound Fracture +U Confront the Assault +C Coral Merfolk +C Cruel Cut +R Demon of Loathing +R Epic Proportions +U Eternal Thirst +C Evolving Wilds +C Fearless Halberdier +C Fencing Ace +C Feral Roar +C Forest +C Frilled Sea Serpent +C Generous Stray +R Gigantosaurus +C Glint +U Goblin Gang Leader +C Goblin Gathering +R Goblin Trashmaster +C Goblin Tunneler +R Goring Ceratops +C Greenwood Sentinel +U Hallowed Priest +C Hurloon Minotaur +C Ilysian Caryatid +R Immortal Phoenix +C Impassioned Orator +U Inescapable Blaze +R Inspiring Commander +C Island +C Jungle Delver +C Knight's Pledge +C Krovikan Scoundrel +R Leonin Warleader +C Loxodon Line Breaker +U Malakir Cullblade +C Maniacal Rage +R Mardu Outrider +C Molten Ravager +C Moorland Inquisitor +C Mountain +U Murder +C Nest Robber +R Nightmare +C Nimble Pilferer +C Octoprophet +R Ogre Battledriver +R Overflowing Insight +C Pacifism +C Plains +U Prized Unicorn +C Rabid Bite +C Raging Goblin +U Raid Bombardment +C Raise Dead +R Rampaging Brontodon +C Reduce to Ashes +R Riddlemaster Sphinx +C River's Favor +C Rumbling Baloth +C Sanctuary Cat +C Sanitarium Skeleton +C Savage Gorger +C Scathe Zombies +U Sengir Vampire +U Sentinel Spider +U Serra Angel +C Shock +C Shrine Keeper +R Siege Dragon +C Skeleton Archer +U Sleep +R Soulblade Djinn +R Soulhunter Rakshasa +C Soulmender +C Spiritual Guardian +C Stony Strength +C Storm Strike +C Swamp +C Sworn Guardian +C Tactical Advantage +C Tin Street Cadet +C Titanic Growth +C Treetop Warden +C Typhoid Rats +C Unlikely Aid +C Unsummon +C Vampire Opportunist +U Volcanic Dragon +C Wall of Runes +U Warden of Evos Isle +C Waterkin Shaman +C Waterknot +C Wildwood Patrol +R Windreader Sphinx +U Windstorm Drake +C Winged Words +C Witch's Familiar +C Woodland Mystic +R World Shaper +C Zephyr Gull diff --git a/forge-gui/res/editions/Commander 2019.txt b/forge-gui/res/editions/Commander 2019.txt index fd8fe031d31..7c06a4355a8 100644 --- a/forge-gui/res/editions/Commander 2019.txt +++ b/forge-gui/res/editions/Commander 2019.txt @@ -335,3 +335,6 @@ w_3_3_bird_flying w_3_4_bird_flying u_2_2_drake_flying +[other] +embalm_angel_of_sanctions +embalm_heart-piercer_manticore diff --git a/forge-gui/res/editions/Commander's Arsenal.txt b/forge-gui/res/editions/Commander's Arsenal.txt index 993b2af1d38..397502591b8 100644 --- a/forge-gui/res/editions/Commander's Arsenal.txt +++ b/forge-gui/res/editions/Commander's Arsenal.txt @@ -1,6 +1,6 @@ [metadata] Code=CM1 -MciCode=cma +MciCode=CM1 Date=2012-11-02 Name=Commander's Arsenal @@ -16,12 +16,12 @@ Name=Commander's Arsenal 9 M Kaalia of the Vast 10 U Loyal Retainers 11 M Maelstrom Wanderer +12 M The Mimeoplasm 13 R Mind's Eye 14 R Mirari's Wake 15 C Rhystic Study 16 R Scroll Rack 17 R Sylvan Library -12 M The Mimeoplasm 18 M Vela the Night-Clad [tokens] diff --git a/forge-gui/res/editions/Hour of Devastation.txt b/forge-gui/res/editions/Hour of Devastation.txt index 87346a0180b..71192b7c2b8 100644 --- a/forge-gui/res/editions/Hour of Devastation.txt +++ b/forge-gui/res/editions/Hour of Devastation.txt @@ -228,4 +228,15 @@ w_5_5_horse w_1_1_warrior_vigilance b_2_2_zombie g_5_4_snake -ur_1_1_insect_flying_haste \ No newline at end of file +ur_1_1_insect_flying_haste + +[other] +eternalize_adorned_pouncer +eternalize_champion_of_wits +eternalize_dreamstealer +eternalize_earthshaker_khenra +eternalize_proven_combatant +eternalize_resilient_khenra +eternalize_sinuous_striker +eternalize_steadfast_sentinel +eternalize_sunscourge_champion diff --git a/forge-gui/res/editions/Jumpstart Arena Exclusives.txt b/forge-gui/res/editions/Jumpstart Arena Exclusives.txt new file mode 100644 index 00000000000..2f72216cd6b --- /dev/null +++ b/forge-gui/res/editions/Jumpstart Arena Exclusives.txt @@ -0,0 +1,25 @@ +[metadata] +Code=AJMP +Date=2020-07-17 +Name=Jumpstart Arena Exclusives +Type=Other + +[cards] +R Archon of Sun's Grace +C Audacious Thief +U Banishing Light +U Bond of Revival +R Carnifex Demon +R Doomed Necromancer +U Dryad Greenseeker +U Fanatic of Mogis +R Gadwick, the Wizened +U Goblin Oriflamme +R Lightning Serpent +U Lightning Strike +C Pollenbright Druid +C Prey Upon +C Scorching Dragonfire +R Serra's Guardian +U Weight of Memory +R Woe Strider diff --git a/forge-gui/res/editions/Secret Lair Drop Series.txt b/forge-gui/res/editions/Secret Lair Drop Series.txt index 83ab05fc6de..08974c079ef 100644 --- a/forge-gui/res/editions/Secret Lair Drop Series.txt +++ b/forge-gui/res/editions/Secret Lair Drop Series.txt @@ -104,15 +104,65 @@ Type=Other 135 R Scavenging Ooze 136 M The Mimeoplasm 137 R Voidslime +143 M Rick, Steadfast Leader +144 M Daryl, Hunter of Walkers +145 M Glenn, the Voice of Calm +146 M Michonne, Ruthless Survivor +147 M Negan, the Cold-Blooded 154 M Admonition Angel 155 R Roil Elemental 156 R Zulaport Cutthroat 157 M Warren Instigator 158 M Avenger of Zendikar +501 R Karn, the Great Creator +502 R Ugin, the Ineffable +503 M Gideon Blackblade +504 U Teyo, the Shieldmage +505 U The Wanderer +506 R Jace, Wielder of Mysteries +507 U Kasmina, Enigmatic Mentor +508 U Narset, Parter of Veils +509 U Davriel, Rogue Shadowmage +510 M Liliana, Dreadhorde General +511 U Ob Nixilis, the Hate-Twisted +512 R Chandra, Fire Artisan +513 U Jaya, Venerated Firemage +514 R Sarkhan the Masterless +515 U Tibalt, Rakish Instigator +516 U Arlinn, Voice of the Pack +517 U Jiang Yanggu, Wildcrafter +518 R Nissa, Who Shakes the World +519 R Vivien, Champion of the Wilds +520 R Ajani, the Greathearted +521 R Domri, Anarch of Bolas +522 M Nicol Bolas, Dragon-God +523 R Ral, Storm Conduit +524 R Sorin, Vengeful Bloodlord +525 R Tamiyo, Collector of Tales +526 R Teferi, Time Raveler +527 U Angrath, Captain of Chaos +528 U Ashiok, Dream Render +529 U Dovin, Hand of Control +530 U Huatli, the Sun's Heart +531 U Kaya, Bane of the Dead +532 U Kiora, Behemoth Beckoner +533 U Nahiri, Storm of Stone +534 U Saheeli, Sublime Artificer +535 U Samut, Tyrant Smasher +536 U Vraska, Swarm's Eminence +537 M Tibalt, the Fiend-Blooded +581 M Lucille + [tokens] b_1_1_faerie_rogue_flying b_1_1_faerie_rogue_flying b_1_1_faerie_rogue_flying b_1_1_faerie_rogue_flying w_1_1_cat_lifelink -w_1_1_cat_lifelink \ No newline at end of file +w_1_1_cat_lifelink +walker +walker +walker +walker +walker +c_a_treasure diff --git a/forge-gui/res/editions/Secret Lair Promos.txt b/forge-gui/res/editions/Secret Lair Promos.txt deleted file mode 100644 index 3532703b675..00000000000 --- a/forge-gui/res/editions/Secret Lair Promos.txt +++ /dev/null @@ -1,45 +0,0 @@ -[metadata] -Code=PSLD -Date=2019-12-02 -Name=Secret Lair Promos -MciCode=sld -Type=Other - -[cards] -501 R Karn, the Great Creator -502 R Ugin, the Ineffable -503 M Gideon Blackblade -504 U Teyo, the Shieldmage -505 U The Wanderer -506 R Jace, Wielder of Mysteries -507 U Kasmina, Enigmatic Mentor -508 U Narset, Parter of Veils -509 U Davriel, Rogue Shadowmage -510 M Liliana, Dreadhorde General -511 U Ob Nixilis, the Hate-Twisted -512 R Chandra, Fire Artisan -513 U Jaya, Venerated Firemage -514 R Sarkhan the Masterless -515 U Tibalt, Rakish Instigator -516 U Arlinn, Voice of the Pack -517 U Jiang Yanggu, Wildcrafter -518 R Nissa, Who Shakes the World -519 R Vivien, Champion of the Wilds -520 R Ajani, the Greathearted -521 R Domri, Anarch of Bolas -522 M Nicol Bolas, Dragon-God -523 R Ral, Storm Conduit -524 R Sorin, Vengeful Bloodlord -525 R Tamiyo, Collector of Tales -526 R Teferi, Time Raveler -527 U Angrath, Captain of Chaos -528 U Ashiok, Dream Render -529 U Dovin, Hand of Control -530 U Huatli, the Sun's Heart -531 U Kaya, Bane of the Dead -532 U Kiora, Behemoth Beckoner -533 U Nahiri, Storm of Stone -534 U Saheeli, Sublime Artificer -535 U Samut, Tyrant Smasher -536 U Vraska, Swarm's Eminence -537 M Tibalt, the Fiend-Blooded diff --git a/forge-gui/res/editions/The List.txt b/forge-gui/res/editions/The List.txt new file mode 100644 index 00000000000..c1d1364ed37 --- /dev/null +++ b/forge-gui/res/editions/The List.txt @@ -0,0 +1,307 @@ +[metadata] +Code=PLIST +Date=2020-09-26 +Name=The List +Type=Reprint + +[cards] +1 U Iterative Analysis +2 M Emrakul, the Aeons Torn +3 U Lashweed Lurker +4 R Thought-Knot Seer +5 R Ancestor's Prophet +6 R Angel's Grace +7 C Anointer Priest +8 C Aven Riftwatcher +9 U Belfry Spirit +10 U Calming Licid +11 U Cloudgoat Ranger +12 R Council's Judgment +13 R Disenchant +14 R Eldrazi Displacer +15 R Emeria Angel +16 U Enlightened Tutor +17 M Entreat the Angels +18 M Gideon, Ally of Zendikar +19 C Goldenglow Moth +20 M History of Benalia +21 R Hundred-Handed One +22 U Kazandu Blademaster +23 M Land Tax +24 U Loyal Unicorn +25 M Monastery Mentor +26 M Nahiri, the Lithomancer +27 R Parallax Wave +28 U Pegasus Stampede +29 R Regal Caracal +30 R Rest in Peace +31 R Reveillark +32 R Sensei Golden-Tail +33 C Snubhorn Sentry +34 U Soltari Monk +35 U Splicer's Skill +36 U Springjack Shepherd +37 U Sunscape Battlemage +38 C Triplicate Spirits +39 C Trokin High Guard +40 U Vanguard of Brimaz +41 R Winds of Abandon +42 U Wizened Cenn +43 R Wrath of God +44 C Amoeboid Changeling +45 R Battle of Wits +46 U Brain Freeze +47 R Brainstorm +48 M Brazen Borrower // Petty Theft +49 R Broodstar +50 U Chemister's Insight +51 U Coveted Peacock +52 R Cryptic Command +53 C Drift of Phantasms +54 U Enclave Cryptologist +55 R Eternal Dominion +56 U Evermind +57 R Eye of the Storm +58 U Fabricate +59 R Forced Fruition +60 R Ixidor, Reality Sculptor +61 R Jwari Shapeshifter +62 R Keeper of the Nine Gales +63 C Latchkey Faerie +64 M Lorthos, the Tidemaker +65 C Man-o'-War +66 R Mischievous Quanar +67 U Moon-Eating Dog +68 R Negate +69 U Noble Benefactor +70 R Octopus Umbra +71 R Pact of Negation +72 R Patron Wizard +73 U Pouncing Shoreshark +74 U Pteramander +75 U Reality Shift +76 U Retreat to Coralhelm +77 U Ruination Guide +78 C Spined Thopter +79 C Stonybrook Banneret +80 M Temporal Manipulation +81 R Training Grounds +82 U Vodalian Illusionist +83 R Ancient Craving +84 U Beseech the Queen +85 R Bloodghast +86 M Bloodlord of Vaasgoth +87 R Body Snatcher +88 R Bogbrew Witch +89 R Brink of Madness +90 C Cadaverous Knight +91 R Cruel Tutor +92 R Doom Blade +93 R Doomwake Giant +94 R Endling +95 R Extinction +96 U Gatekeeper of Malakir +97 C Gempalm Polluter +98 U Golgari Thug +99 R Grim Haruspex +100 C Grim Harvest +101 R Kalastria Highborn +102 R Korlash, Heir to Blackblade +103 R Living Death +104 R Lord of the Undead +105 U Murderous Cut +106 R Necravolver +107 U Necromancy +108 U Nezumi Graverobber // Nighteyes the Desecrator +109 U Oubliette +110 M Phyrexian Obliterator +111 R Promise of Power +112 U Relentless Rats +113 M Skithiryx, the Blight Dragon +114 R Tombstalker +115 C Tortured Existence +116 U Unburial Rites +117 C Urborg Panther +118 U Vampire Nighthawk +119 M Vampire Nocturnus +120 U Victimize +121 R Virtus the Veiled +122 U Abrade +123 U Anax, Hardened in the Forge +124 C Boggart Arsonists +125 U Brothers Yamazaki +126 R Burst Lightning +127 R Decree of Annihilation +128 R Fall of the Titans +129 U The Flame of Keld +130 C Fomori Nomad +131 R Goblin Chieftain +132 U Goblin Grenade +133 U Goblin Lore +134 U Hammer Mage +135 R Hammer of Purphoros +136 R Hell's Thunder +137 R Hidetsugu's Second Rite +138 R Hunted Dragon +139 R Jaya's Immolating Inferno +140 R Kilnmouth Dragon +141 C Lash Out +142 R Lightning Bolt +143 R Lightning Crafter +144 U Light Up the Stage +145 R Marauding Raptor +146 R Moggcatcher +147 R Patron of the Akki +148 C Plated Geopede +149 R Puppet's Verdict +150 R Pyromancer Ascension +151 M Scourge of the Throne +152 R Sedge Sliver +153 U Shivan Meteor +154 C Simian Spirit Guide +155 C Skred +156 C Stone Rain +157 R Tuktuk the Explorer +158 R Voracious Dragon +159 R Warp World +160 R Wild Research +161 U Alpha Kavu +162 R Awakening +163 U Cradle Guard +164 C Curious Pair // Treats to Share +165 R Elvish Archdruid +166 U Eternal Witness +167 R Food Chain +168 R Gaea's Anthem +169 R Genesis Hydra +170 R Gigantosaurus +171 R Gorm the Great +172 U Grizzly Fate +173 R Groundbreaker +174 R Harmonize +175 R Helix Pinnacle +176 R Hua Tuo, Honored Physician +177 R Imperious Perfect +178 M Ishkanah, Grafwidow +179 R Jadelight Ranger +180 M Kalonian Hydra +181 M Khalni Hydra +182 C Moonmist +183 C Muscle Sliver +184 C Nightshade Peddler +185 M Nissa Revane +186 M Nylea, God of the Hunt +187 R Parallel Evolution +188 R Primal Vigor +189 U Rootrunner +190 U Saber Ants +191 R Skyshroud Behemoth +192 R Song of the Dryads +193 M Soul of Zendikar +194 R Spike Weaver +195 R Squirrel Mob +196 U Ulvenwald Mysteries +197 C Willow Dryad +198 C Yavimaya Scion +199 R Zendikar Resurgent +200 U Army Ants +201 U Boros Challenger +202 M Chromanticore +203 M Chulane, Teller of Tales +204 U Crystalline Sliver +205 U Diregraf Captain +206 R Doran, the Siege Tower +207 R Dromar, the Banisher +208 R Dune-Brood Nephilim +209 R Etherium-Horn Sorcerer +210 M Ezuri, Claw of Progress +211 R Fathom Mage +212 R Fiery Justice +213 M Godsire +214 R Ith, High Arcanist +215 C Kingpin's Pet +216 M Lazav, the Multifarious +217 R Lightning Angel +218 M Maelstrom Nexus +219 U Merfolk Mistbinder +220 M Muldrotha, the Gravetide +221 U Necrotic Sliver +222 R Nicol Bolas +223 M Oloro, Ageless Ascetic +224 M Omnath, Locus of Rage +225 R Phyrexian Tyranny +226 M Progenitus +227 C Shambling Shell +228 U Sky Hussar +229 U Slimefoot, the Stowaway +230 R Terminate +231 U Vitu-Ghazi Guildmage +232 M Wrenn and Six +233 U Zendikar Incarnate +234 U Angrath, Captain of Chaos +235 R Djinn Illuminatus +236 U Murderous Redcap +237 U Noggle Hedge-Mage +238 R Beck // Call +239 R Cut // Ribbons +240 R Odds // Ends +241 R Acorn Catapult +242 R Akroma's Memorial +243 U Arcbound Slith +244 C Arcum's Astrolabe +245 C Blight Sickle +246 R Bonehoard +247 M The Chain Veil +248 R Clearwater Goblet +249 R Contagion Engine +250 U Crown of Empires +251 R Door to Nothingness +252 R Electrostatic Pummeler +253 R Erratic Portal +254 U Everflowing Chalice +255 U Fellwar Stone +256 U Fodder Cannon +257 C Fractured Powerstone +258 R Helm of Kaldra +259 U Isochron Scepter +260 R Krark's Thumb +261 R Lotus Bloom +262 U Memnite +263 R Mycosynth Golem +264 R Panharmonicon +265 M Platinum Angel +266 R Prismatic Geoscope +267 R Scarecrone +268 R Scroll Rack +269 U Shuriken +270 U Skullclamp +271 U Swiftfoot Boots +272 R Tamiyo's Journal +273 R Tek +274 C Thought Vessel +275 R Thrumming Stone +276 U Trusty Machete +277 R Urza's Blueprints +278 C Wayfarer's Bauble +279 M Weatherlight +280 R Workhorse +281 U Worn Powerstone +282 C Bojuka Bog +283 R Cathedral of War +284 R Command Beacon +285 U Dryad Arbor +286 U Eldrazi Temple +287 R Emeria, the Sky Ruin +288 R Gemstone Mine +289 U Hashep Oasis +290 R Inventors' Fair +291 R Kher Keep +292 U Llanowar Reborn +293 R Nykthos, Shrine to Nyx +294 R Phyrexian Tower +295 R Riptide Laboratory +296 R Shelldock Isle +297 C Tree of Tales +298 R Vesuva +299 L Wastes +300 L Plains diff --git a/forge-gui/res/editions/Zendikar Rising Commander.txt b/forge-gui/res/editions/Zendikar Rising Commander.txt index 555e14d0cf8..c968d4dd6d2 100644 --- a/forge-gui/res/editions/Zendikar Rising Commander.txt +++ b/forge-gui/res/editions/Zendikar Rising Commander.txt @@ -11,3 +11,140 @@ Type=Other 4 R Enigma Thief 5 R Whispersteel Dagger 6 R Geode Rager +7 M Anowon, the Ruin Thief +8 M Obuun, Mul Daya Ancestor +9 U Abzan Falconer +10 M Admonition Angel +11 U Banishing Light +12 U Condemn +13 U Crush Contraband +14 U Elite Scaleguard +15 R Emeria Angel +16 R Emeria Shepherd +17 R Hour of Revelation +18 C Kor Cartographer +19 R Planar Outburst +20 U Retreat to Emeria +21 M Sun Titan +22 R Together Forever +23 U Aetherize +24 C Distant Melody +25 U Fact or Fiction +26 U Faerie Vandal +27 U Invisible Stalker +28 C Latchkey Faerie +29 U Marang River Prowler +30 U Master Thief +31 U Military Intelligence +32 U Nightveil Sprite +33 R Notorious Throng +34 U Open into Wonder +35 R Scourge of Fleets +36 C Slither Blade +37 R Stolen Identity +38 C Triton Shorestalker +39 U Whirler Rogue +40 C Changeling Outcast +41 U Endless Obedience +42 R Fated Return +43 C Frogtosser Banneret +44 R Gonti, Lord of Luxury +45 R In Garruk's Wake +46 U Marsh Flitter +47 C Murder +48 R Necromantic Selection +49 R Nighthowler +50 R Ogre Slumlord +51 U Oona's Blackguard +52 U Price of Fame +53 U Rise from the Grave +54 R Sepulchral Primordial +55 U Stinkdrinker Bandit +56 U Syr Konrad, the Grim +57 U Zulaport Cutthroat +58 R Abundance +59 U Acidic Slime +60 U Armorcraft Judge +61 U Beanstalk Giant +62 U Circuitous Route +63 C Elvish Rejuvenator +64 U Embodiment of Insight +65 U Evolution Sage +66 C Far Wanderings +67 C Fertilid +68 U Harmonize +69 C Harrow +70 U Inspiring Call +71 U Keeper of Fables +72 C Khalni Heart Expedition +73 C Kodama's Reach +74 R The Mending of Dominaria +75 M Multani, Yavimaya's Avatar +76 R Nissa's Renewal +77 R Rampaging Baloths +78 U Retreat to Kazandu +79 R Return of the Wildspeaker +80 R Rites of Flourishing +81 C Satyr Wayfinder +82 C Sporemound +83 C Springbloom Druid +84 R Sylvan Advocate +85 U Tuskguard Captain +86 R Waker of the Wilds +87 C Yavimaya Elder +88 U Zendikar's Roil +89 R Consuming Aberration +90 U Extract from Darkness +91 U Ground Assault +92 M Lazav, Dimir Mastermind +93 R Living Twister +94 R Mina and Denn, Wildborn +95 U Naya Charm +96 R Notion Thief +97 M Omnath, Locus of Rage +98 R Oona, Queen of the Fae +99 R Silumgar's Command +100 U Soul Manipulation +101 R Spinal Embrace +102 U Struggle // Survive +103 R Sygg, River Cutthroat +104 U Sylvan Reclamation +105 U Treacherous Terrain +106 C Arcane Signet +107 R Blackblade Reforged +108 R Bonehoard +109 C Commander's Sphere +110 U Dimir Keyrune +111 C Dimir Locket +112 U Dimir Signet +113 U Heirloom Blade +114 C Mind Stone +115 R Obelisk of Urd +116 U Sandstone Oracle +117 C Scaretiller +118 R Scytheclaw +119 R Seer's Sundial +120 U Sol Ring +121 U Blighted Woodland +122 C Boros Garrison +123 C Boros Guildgate +124 C Command Tower +125 U Cryptic Caves +126 U Dimir Aqueduct +127 C Dimir Guildgate +128 C Dismal Backwater +129 C Evolving Wilds +130 C Gruul Guildgate +131 U Gruul Turf +132 U Jungle Shrine +133 U Jwar Isle Refuge +134 U Krosan Verge +135 U Myriad Landscape +136 C Naya Panorama +137 R Needle Spires +138 U Rogue's Passage +139 C Selesnya Guildgate +140 C Selesnya Sanctuary +141 U Submerged Boneyard +142 C Terramorphic Expanse + diff --git a/forge-gui/res/editions/Zendikar Rising.txt b/forge-gui/res/editions/Zendikar Rising.txt index eed596679df..be26549a4c0 100644 --- a/forge-gui/res/editions/Zendikar Rising.txt +++ b/forge-gui/res/editions/Zendikar Rising.txt @@ -6,7 +6,8 @@ Code2=ZNR MciCode=znr Type=Expansion BoosterCovers=3 -Booster=9 Common:!dfc:!fromSheet("ZNR Secret Cards"), 3 Uncommon:!dfc:!fromSheet("ZNR Secret Cards"), 1 RareMythic:!dfc:!fromSheet("ZNR Secret Cards"), 1 dfc:!fromSheet("ZNR Secret Cards"), 1 BasicLand +Booster=10 Common:!dfc:!fromSheet("ZNR Secret Cards"), 3 Uncommon:!dfc:!fromSheet("ZNR Secret Cards"), 1 RareMythic:!dfc:!fromSheet("ZNR Secret Cards"), 1 BasicLand +BoosterReplaceSlotFromPrintSheet=ZNRModalDoubleFaceCards Prerelease=6 Boosters, 1 RareMythic+ [cards] @@ -419,4 +420,3 @@ g_0_1_plant bg_x_x_hydra c_1_1_a_construct c_0_1_a_goblin_construct_noblock_ping -copy diff --git a/forge-gui/res/formats/Sanctioned/Standard.txt b/forge-gui/res/formats/Sanctioned/Standard.txt index 496a3967104..f9eb4b75357 100644 --- a/forge-gui/res/formats/Sanctioned/Standard.txt +++ b/forge-gui/res/formats/Sanctioned/Standard.txt @@ -4,4 +4,4 @@ Order:101 Subtype:Standard Type:Sanctioned Sets:ELD, THB, IKO, M21, ZNR -Banned:Cauldron Familiar; Fires of Invention; Oko, Thief of Crowns; Once Upon a Time; Veil of Summer +Banned:Cauldron Familiar; Fires of Invention; Oko, Thief of Crowns; Once Upon a Time; Uro, Titan of Nature's Wrath; Veil of Summer diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index e5e3e3dbdd1..9e8ed4c548c 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -981,7 +981,7 @@ nlVibrateWhenLosingLife=Aktiviert Vibration bei Lebenspunktverlust. lblEnableRoundBorder=Aktiviere Maske mit runden Ränder nlEnableRoundBorder=Wenn aktiviert, werden Kartenecken abgerundet. Vorzugsweise bei Karten mit vollem Rand. lblPreloadExtendedArtCards=Erw. Kartenbilder bei Start laden -nlPreloadExtendedArtCards=Wenn aktiviert, werden erweiterte Kartenbilder bereits beim Start in den Speicher geladen. +nlPreloadExtendedArtCards=Wenn aktiviert, werden erweiterte Kartenbilder bereits beim Start in den Speicher geladen (Hohe RAM-Auslastung). lblShowFPSDisplay=FPS-Anzeige nlShowFPSDisplay=Aktiviert die Frames-per-second-Anzeige (Experimentell). lblEnableUnknownCards=Erlaube unbekannte Karten @@ -2587,3 +2587,7 @@ lblEnterMessageToSend=Nachricht zum Senden eingeben lblDetectedInvalidHostAddress=Ungültige Host-Adresse ({0}) wurde festgestellt. #Player.java lblChooseACompanion=Wähle einen Gefährten +lblWildOpponentMultiplier=Wild-Multiplikator +lblEnteraDecimal=Eine Zahl eingeben +lblWildOpponentNumber=Anzahl der Wild-Gegner +lblWildOpponentNumberError=Anzahl der Wild-Gegner kann nur 0 bis 3 sein diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index e2fe483c927..458070f8a55 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -981,7 +981,7 @@ nlVibrateWhenLosingLife=Enable vibration when your player loses life or takes da lblEnableRoundBorder=Enable Round Border Mask nlEnableRoundBorder=When enabled, the card corners are rounded (Preferably Card with Full Borders). lblPreloadExtendedArtCards=Preload Extended Art Cards -nlPreloadExtendedArtCards=When enabled, Preloads Extended Art Cards to Cache on Startup. +nlPreloadExtendedArtCards=When enabled, Preloads Extended Art Cards to Cache on Startup (High RAM usage). lblShowFPSDisplay=Show FPS Display nlShowFPSDisplay=When enabled, show the FPS Display (Experimental). lblEnableUnknownCards=Enable Unknown Cards @@ -2587,3 +2587,7 @@ lblEnterMessageToSend=Enter message to send lblDetectedInvalidHostAddress=Invalid host address ({0}) was detected. #Player.java lblChooseACompanion=Choose a companion +lblWildOpponentMultiplier=Wild Multiplier +lblEnteraDecimal=Enter a decimal +lblWildOpponentNumber=Number of Wild Opponents +lblWildOpponentNumberError=Wild Opponents can only be 0 to 3 diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 296284bf716..05f2462797f 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -981,7 +981,7 @@ nlVibrateWhenLosingLife=Habilita la vibración cuando tu jugador pierde vida o s lblEnableRoundBorder=Habilitar máscara de bordes redondeados nlEnableRoundBorder=Cuando está habilitado, las esquinas de las cartas se redondean (Preferiblemente Cartas con bordes completos). lblPreloadExtendedArtCards=Precargar Cartas de Arte Extendido -nlPreloadExtendedArtCards=Cuando está habilitado, carga previamente las cartas de arte ampliadas en la caché al iniciar el programa. +nlPreloadExtendedArtCards=Cuando está habilitado, carga previamente las cartas de arte ampliadas en la caché al iniciar el programa (Alto uso de RAM). lblShowFPSDisplay=Mostrar FPS nlShowFPSDisplay=Cuando está habilitado, muestra los FPS (Experimental). lblEnableUnknownCards=Enable Unknown Cards diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 3f1e61e6639..f4d2e2f1a89 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -981,7 +981,7 @@ nlVibrateWhenLosingLife=Attiva le vibrazioni quando il giocatore perde punti vit lblEnableRoundBorder=Abilita maschera bordo arrotondato nlEnableRoundBorder=Se abilitato, gli angoli delle carte sono arrotondati (preferibilmente Carta con bordi pieni). lblPreloadExtendedArtCards=Carte d''arte estese precaricate -nlPreloadExtendedArtCards=Se abilitato, precarica le carte artistiche estese nella cache all''avvio. +nlPreloadExtendedArtCards=Se abilitato, precarica le carte artistiche estese nella cache all''avvio (Utilizzo elevato della RAM). lblShowFPSDisplay=Mostra display FPS nlShowFPSDisplay=Se abilitato, mostra il display FPS (sperimentale). lblEnableUnknownCards=Enable Unknown Cards diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index 40339a9f4ce..9f3f3203536 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -981,7 +981,7 @@ nlVibrateWhenLosingLife=启用当玩家在游戏中失去生命或收到伤害 lblEnableRoundBorder=启用圆角边框掩码 nlEnableRoundBorder=启用后,卡牌边框会变成圆角(带有完整边框的卡牌图片效果最好)。 lblPreloadExtendedArtCards=预加载拉伸卡图 -nlPreloadExtendedArtCards=启用后,拉伸卡图将在启动时加载到缓存。 +nlPreloadExtendedArtCards=启用后,拉伸卡图将在启动时加载到缓存(使用高内存)。 lblShowFPSDisplay=显示当前的FPS值 nlShowFPSDisplay=启用后,将在画面左上角显示当前Forge的FPS(实验性特性)。 lblEnableUnknownCards=启用未知卡牌 diff --git a/forge-gui/res/lists/borderlessCardList.txt b/forge-gui/res/lists/borderlessCardList.txt new file mode 100644 index 00000000000..c2b3cbba747 --- /dev/null +++ b/forge-gui/res/lists/borderlessCardList.txt @@ -0,0 +1,127 @@ +2XM/Academy Ruins2.fullborder +2XM/Atraxa, Praetors' Voice2.fullborder +2XM/Avacyn, Angel of Hope2.fullborder +2XM/Batterskull2.fullborder +2XM/Blightsteel Colossus2.fullborder +2XM/Blood Moon2.fullborder +2XM/Brainstorm2.fullborder +2XM/Chrome Mox2.fullborder +2XM/Council's Judgment2.fullborder +2XM/Crop Rotation2.fullborder +2XM/Cyclonic Rift2.fullborder +2XM/Dark Confidant2.fullborder +2XM/Doubling Season2.fullborder +2XM/Expedition Map2.fullborder +2XM/Exploration2.fullborder +2XM/Fatal Push2.fullborder +2XM/Force of Will2.fullborder +2XM/Goblin Guide2.fullborder +2XM/Jace, the Mind Sculptor2.fullborder +2XM/Kaalia of the Vast2.fullborder +2XM/Karn Liberated2.fullborder +2XM/Lightning Greaves2.fullborder +2XM/Mana Crypt2.fullborder +2XM/Meddling Mage2.fullborder +2XM/Mox Opal2.fullborder +2XM/Noble Hierarch2.fullborder +2XM/Phyrexian Metamorph2.fullborder +2XM/Sneak Attack2.fullborder +2XM/Stoneforge Mystic2.fullborder +2XM/Sword of Body and Mind2.fullborder +2XM/Sword of Feast and Famine2.fullborder +2XM/Sword of Fire and Ice2.fullborder +2XM/Sword of Light and Shadow2.fullborder +2XM/Sword of War and Peace2.fullborder +2XM/Thoughtseize2.fullborder +2XM/Toxic Deluge2.fullborder +2XM/Urza's Mine2.fullborder +2XM/Urza's Power Plant2.fullborder +2XM/Urza's Tower2.fullborder +2XM/Wurmcoil Engine2.fullborder +ELD/Garruk, Cursed Huntsman2.fullborder +ELD/Oko, Thief of Crowns2.fullborder +ELD/The Royal Scions2.fullborder +IKO/Brokkos, Apex of Forever2.fullborder +IKO/Brokkos, Apex of Forever3.fullborder +IKO/Crystalline Giant3.fullborder +IKO/Cubwarden2.fullborder +IKO/Dirge Bat2.fullborder +IKO/Dirge Bat3.fullborder +IKO/Everquill Phoenix2.fullborder +IKO/Everquill Phoenix3.fullborder +IKO/Gemrazer2.fullborder +IKO/Gemrazer3.fullborder +IKO/Gyruda, Doom of Depths3.fullborder +IKO/Huntmaster Liger2.fullborder +IKO/Huntmaster Liger3.fullborder +IKO/Illuna, Apex of Wishes2.fullborder +IKO/Illuna, Apex of Wishes3.fullborder +IKO/Indatha Triome2.fullborder +IKO/Ketria Triome2.fullborder +IKO/Lukka, Coppercoat Outcast2.fullborder +IKO/Luminous Broodmoth3.fullborder +IKO/Mysterious Egg2.fullborder +IKO/Narset of the Ancient Way2.fullborder +IKO/Nethroi, Apex of Death2.fullborder +IKO/Nethroi, Apex of Death3.fullborder +IKO/Pollywog Symbiote2.fullborder +IKO/Raugrin Triome2.fullborder +IKO/Savai Triome2.fullborder +IKO/Sea-Dasher Octopus2.fullborder +IKO/Snapdax, Apex of the Hunt2.fullborder +IKO/Snapdax, Apex of the Hunt3.fullborder +IKO/Sprite Dragon3.fullborder +IKO/Titanoth Rex2.fullborder +IKO/Vadrok, Apex of Thunder2.fullborder +IKO/Vadrok, Apex of Thunder3.fullborder +IKO/Vivien, Monsters' Advocate2.fullborder +IKO/Void Beckoner2.fullborder +IKO/Yidaro, Wandering Monster3.fullborder +IKO/Zagoth Triome2.fullborder +IKO/Zilortha, Strength Incarnate.fullborder +M21/Basri Ket2.fullborder +M21/Chandra, Heart of Fire2.fullborder +M21/Containment Priest2.fullborder +M21/Cultivate2.fullborder +M21/Garruk, Unleashed2.fullborder +M21/Grim Tutor2.fullborder +M21/Liliana, Waker of the Dead2.fullborder +M21/Massacre Wurm2.fullborder +M21/Scavenging Ooze2.fullborder +M21/Solemn Simulacrum2.fullborder +M21/Teferi, Master of Time2.fullborder +M21/Ugin, the Spirit Dragon2.fullborder +M21/Ugin, the Spirit Dragon3.fullborder +PLGS/Hangarback Walker.fullborder +SLD/Acidic Slime.fullborder +SLD/Captain Sisay.fullborder +SLD/Meren of Clan Nel Toth.fullborder +SLD/Narset, Enlightened Master.fullborder +SLD/Necrotic Ooze.fullborder +SLD/Oona, Queen of the Fae.fullborder +SLD/Saskia the Unyielding.fullborder +SLD/The Mimeoplasm.fullborder +SLD/Voidslime.fullborder +THB/Ashiok, Nightmare Muse2.fullborder +THB/Calix, Destiny's Hand2.fullborder +THB/Elspeth, Sun's Nemesis2.fullborder +UST/Forest.fullborder +UST/Island.fullborder +UST/Mountain.fullborder +UST/Plains.fullborder +UST/Swamp.fullborder +ZNR/Boulderloft Pathway2.fullborder +ZNR/Branchloft Pathway2.fullborder +ZNR/Brightclimb Pathway2.fullborder +ZNR/Clearwater Pathway2.fullborder +ZNR/Cragcrown Pathway2.fullborder +ZNR/Grimclimb Pathway2.fullborder +ZNR/Jace, Mirror Mage2.fullborder +ZNR/Lavaglide Pathway2.fullborder +ZNR/Murkwater Pathway2.fullborder +ZNR/Nahiri, Heir of the Ancients2.fullborder +ZNR/Needleverge Pathway2.fullborder +ZNR/Nissa of Shadowed Boughs2.fullborder +ZNR/Pillarverge Pathway2.fullborder +ZNR/Riverglide Pathway2.fullborder +ZNR/Timbercrown Pathway2.fullborder \ No newline at end of file diff --git a/forge-gui/res/lists/precon-images.txt b/forge-gui/res/lists/precon-images.txt index d21eb0ea12e..b7aeae89e8b 100644 --- a/forge-gui/res/lists/precon-images.txt +++ b/forge-gui/res/lists/precon-images.txt @@ -85,6 +85,7 @@ https://downloads.cardforge.org/images/products/precons/elementals_path.jpg https://downloads.cardforge.org/images/products/precons/elspeth_undaunted_hero.jpg https://downloads.cardforge.org/images/products/precons/elvish_predation.jpg https://downloads.cardforge.org/images/products/precons/elvish_rage.jpg +https://downloads.cardforge.org/images/products/precons/endless_march.jpg https://downloads.cardforge.org/images/products/precons/enlightened_mastery.jpg https://downloads.cardforge.org/images/products/precons/entangling_webs.jpg https://downloads.cardforge.org/images/products/precons/esper_air_assault.jpg @@ -107,6 +108,7 @@ https://downloads.cardforge.org/images/products/precons/flames_of_the_dragon.jpg https://downloads.cardforge.org/images/products/precons/flash_of_ferocity.jpg https://downloads.cardforge.org/images/products/precons/flyover.jpg https://downloads.cardforge.org/images/products/precons/forged_in_battle.jpg +https://downloads.cardforge.org/images/products/precons/fun_with_fungus.jpg https://downloads.cardforge.org/images/products/precons/furious_forces.jpg https://downloads.cardforge.org/images/products/precons/ghostly_tide.jpg https://downloads.cardforge.org/images/products/precons/gideon_martial_paragon.jpg @@ -130,6 +132,7 @@ https://downloads.cardforge.org/images/products/precons/hazoret_aggro.jpg https://downloads.cardforge.org/images/products/precons/heavy_hitters.jpg https://downloads.cardforge.org/images/products/precons/hit_the_ground_running.jpg https://downloads.cardforge.org/images/products/precons/hold_the_line.jpg +https://downloads.cardforge.org/images/products/precons/hopes_crusaders.jpg https://downloads.cardforge.org/images/products/precons/horrific_visions.jpg https://downloads.cardforge.org/images/products/precons/huatli_dinosaur_knight.jpg https://downloads.cardforge.org/images/products/precons/hunting_pack.jpg @@ -139,6 +142,7 @@ https://downloads.cardforge.org/images/products/precons/infestation.jpg https://downloads.cardforge.org/images/products/precons/inspiration-struck.jpg https://downloads.cardforge.org/images/products/precons/into_the_breach.jpg https://downloads.cardforge.org/images/products/precons/invading_spawn.jpg +https://downloads.cardforge.org/images/products/precons/ixidors_legacy.jpg https://downloads.cardforge.org/images/products/precons/izzet_gizmometry.jpg https://downloads.cardforge.org/images/products/precons/izzet_ingenuity.jpg https://downloads.cardforge.org/images/products/precons/jace_ingenious_mind_mage.jpg @@ -184,6 +188,7 @@ https://downloads.cardforge.org/images/products/precons/nicol_bolas_the_deceiver https://downloads.cardforge.org/images/products/precons/ninjutsu.jpg https://downloads.cardforge.org/images/products/precons/nissa_natures_artisan.jpg https://downloads.cardforge.org/images/products/precons/nissa_genesis_mage.jpg +https://downloads.cardforge.org/images/products/precons/nuts_and_bolts.jpg https://downloads.cardforge.org/images/products/precons/orzhov_oppression.jpg https://downloads.cardforge.org/images/products/precons/orzhov_power.jpg https://downloads.cardforge.org/images/products/precons/overkill.jpg @@ -206,6 +211,7 @@ https://downloads.cardforge.org/images/products/precons/rallying_cry.jpg https://downloads.cardforge.org/images/products/precons/rapid_fire.jpg https://downloads.cardforge.org/images/products/precons/rats_nest.jpg https://downloads.cardforge.org/images/products/precons/ravaging_swarm.jpg +https://downloads.cardforge.org/images/products/precons/reality_fracture.jpg https://downloads.cardforge.org/images/products/precons/rebels_unite.jpg https://downloads.cardforge.org/images/products/precons/reign_of_vampirism.jpg https://downloads.cardforge.org/images/products/precons/relentless_dead.jpg @@ -230,15 +236,20 @@ https://downloads.cardforge.org/images/products/precons/simic_synthesis.jpg https://downloads.cardforge.org/images/products/precons/sky_slam.jpg https://downloads.cardforge.org/images/products/precons/slaughterhouse.jpg https://downloads.cardforge.org/images/products/precons/sleeper.jpg +https://downloads.cardforge.org/images/products/precons/sliver_evolution.jpg https://downloads.cardforge.org/images/products/precons/sliver_shivers.jpg +https://downloads.cardforge.org/images/products/precons/snakes_path.jpg https://downloads.cardforge.org/images/products/precons/snowscape.jpg https://downloads.cardforge.org/images/products/precons/sole_domination.jpg https://downloads.cardforge.org/images/products/precons/solitary_fiends.jpg +https://downloads.cardforge.org/images/products/precons/soratamis_wisdom.jpg https://downloads.cardforge.org/images/products/precons/spectral_legions.jpg https://downloads.cardforge.org/images/products/precons/spectral_slam.jpg +https://downloads.cardforge.org/images/products/precons/special_forces.jpg https://downloads.cardforge.org/images/products/precons/speed_scorch.jpg https://downloads.cardforge.org/images/products/precons/spiraling_doom.jpg https://downloads.cardforge.org/images/products/precons/spirit_flames.jpg +https://downloads.cardforge.org/images/products/precons/spiritbane.jpg https://downloads.cardforge.org/images/products/precons/spiritcraft.jpg https://downloads.cardforge.org/images/products/precons/stampede.jpg https://downloads.cardforge.org/images/products/precons/stampede_of_beasts.jpg @@ -277,6 +288,7 @@ https://downloads.cardforge.org/images/products/precons/united_assault.jpg https://downloads.cardforge.org/images/products/precons/unlikely_alliances.jpg https://downloads.cardforge.org/images/products/precons/unnatural_schemes.jpg https://downloads.cardforge.org/images/products/precons/unstable_terrain.jpg +https://downloads.cardforge.org/images/products/precons/unraveling_mind.jpg https://downloads.cardforge.org/images/products/precons/untamed_wild.jpg https://downloads.cardforge.org/images/products/precons/vampire_onslaught.jpg https://downloads.cardforge.org/images/products/precons/vampiric_thirst.jpg @@ -286,6 +298,7 @@ https://downloads.cardforge.org/images/products/precons/voracious_rage.jpg https://downloads.cardforge.org/images/products/precons/vraska_scheming_gorgon.jpg https://downloads.cardforge.org/images/products/precons/war_of_attrition.jpg https://downloads.cardforge.org/images/products/precons/warriors_code.jpg +https://downloads.cardforge.org/images/products/precons/way_of_the_warrior.jpg https://downloads.cardforge.org/images/products/precons/way_wild.jpg https://downloads.cardforge.org/images/products/precons/weapons_and_wards.jpg https://downloads.cardforge.org/images/products/precons/wicked_big.jpg diff --git a/forge-gui/res/quest/precons/Dead Again.dck b/forge-gui/res/quest/precons/Dead Again.dck new file mode 100644 index 00000000000..90620e9ca02 --- /dev/null +++ b/forge-gui/res/quest/precons/Dead Again.dck @@ -0,0 +1,34 @@ +[shop] +WinsToUnlock=0 +Credits=3000 +MinDifficulty=0 +MaxDifficulty=5 +[metadata] +Name=Dead Again +Description=In the "Dead Again" deck, life begins at death. The deck uses your life total and your graveyard as extra resources. It even uses your opponent's life total as a resource! +Deck Type=constructed +Set=9ED +Image=dead_again.jpg + +[Main] +1 Consume Spirit|9ED +1 Contaminated Bond|9ED +1 Dark Banishing|9ED +1 Deathgazer|9ED +1 Demon's Horn|9ED +1 Drudge Skeletons|9ED +2 Foul Imp|9ED +2 Gravedigger|9ED +2 Highway Robber|9ED +2 Hollow Dogs|9ED +1 Nekrataal|9ED +1 Nightmare|9ED +1 Phyrexian Gargantua|9ED +1 Raise Dead|9ED +2 Serpent Warrior|9ED +17 Swamp|9ED|1 +1 Tanglebloom|9ED +1 Underworld Dreams|9ED +1 Unholy Strength|9ED +[Sideboard] + diff --git a/forge-gui/res/quest/precons/Endless March.dck b/forge-gui/res/quest/precons/Endless March.dck new file mode 100644 index 00000000000..2af36849ee5 --- /dev/null +++ b/forge-gui/res/quest/precons/Endless March.dck @@ -0,0 +1,40 @@ +[shop] +WinsToUnlock=0 +Credits=1200 +MinDifficulty=0 +MaxDifficulty=5 + +[metadata] +Name=Endless March +Description=For the creatures in the Endless March deck, the battle never ends—and they wouldn't have it any other way. This deck revolves around the interaction of vanishing and “rescue.” It's an ideal match: When a vanishing creature gets low on time counters, play a rescue creature and return it to your hand. You can replay it fully restocked with time counters! +Deck Type=constructed +Set=PLC +Image=endless_march.jpg + +[Main] +1 Avalanche Riders|TSB +3 Aven Riftwatcher|PLC +2 Brute Force|PLC +2 Calciderm|PLC +1 Children of Korlis|TSP +1 Dawn Charm|PLC +1 Dead // Gone|PLC +1 Dust Elemental|PLC +2 Errant Doomsayers|TSP +1 Fatal Frenzy|PLC +2 Icatian Javelineers|TSB +2 Jhoira's Timebug|TSP +1 Keldon Marauders|PLC +2 Lavacore Elemental|PLC +2 Mogg War Marshal|TSP +10 Mountain|TSP|1 +11 Plains|TSP|1 +1 Riftmarked Knight|PLC +1 Soltari Priest|TSB +2 Stonecloaker|PLC +2 Stormfront Riders|PLC +1 Sunlance|PLC +3 Terramorphic Expanse|TSP +2 Timecrafting|PLC +3 Whitemane Lion|PLC +[Sideboard] \ No newline at end of file diff --git a/forge-gui/res/quest/precons/Fun with Fungus.dck b/forge-gui/res/quest/precons/Fun with Fungus.dck new file mode 100644 index 00000000000..0180ae6492f --- /dev/null +++ b/forge-gui/res/quest/precons/Fun with Fungus.dck @@ -0,0 +1,39 @@ +[shop] +WinsToUnlock=0 +Credits=1200 +MinDifficulty=0 +MaxDifficulty=5 + +[metadata] +Name=Fun with Fungus +Description=Fungus doesn’t think or sleep—it just spreads and devours. The Fun with Fungus deck lets you take the reins of a post-apocalyptic rampage of Thallids, and these freaky fungus fiends won’t take “Eeeeewww!” for an answer. +Deck Type=constructed +Set=TSP +Image=fun_with_fungus.jpg + +[Main] +1 Assassinate|TSP +1 Claws of Gix|TSB +3 Deathspore Thallid|TSP +1 Dread Return|TSP +2 Fallen Ideal|TSP +1 Feebleness|TSP +13 Forest|TSP|1 +2 Herd Gnarr|TSP +1 Krosan Grip|TSP +1 Might of Old Krosa|TSP +1 Pendelhaven|TSB +2 Pendelhaven Elder|TSP +2 Savage Thallid|TSP +2 Sporesower Thallid|TSP +2 Sprout|TSP +2 Strength in Numbers|TSP +2 Sudden Death|TSP +10 Swamp|TSP|1 +2 Thallid|TSB +3 Thallid Germinator|TSP +3 Thallid Shell-Dweller|TSP +1 Thelon of Havenwood|TSP +1 Verdant Embrace|TSP +1 Wormwood Dryad|TSP +[Sideboard] \ No newline at end of file diff --git a/forge-gui/res/quest/precons/Hopes Crusaders.dck b/forge-gui/res/quest/precons/Hopes Crusaders.dck new file mode 100644 index 00000000000..79b7e4de877 --- /dev/null +++ b/forge-gui/res/quest/precons/Hopes Crusaders.dck @@ -0,0 +1,37 @@ +[shop] +WinsToUnlock=0 +Credits=1200 +MinDifficulty=0 +MaxDifficulty=5 + +[metadata] +Name=Hope's Crusaders +Description=Nothing—not even an apocalypse—can keep a noble fighter down, and the “Hope’s Crusaders” deck is proof of that. Lead your troops onto the battlefield and give them the one command they want to hear: “Charge!” This deck gives your opponent no good blocking options: Either your creatures will get through, or your opponent’s blockers will be overmatched in combat. +Deck Type=constructed +Set=TSP +Image=hopes_crusaders.jpg + +[Main] +3 Benalish Cavalry|TSP +2 Brass Gnat|TSP +2 Cavalry Master|TSP +1 Celestial Crusader|TSP +1 Cloudchaser Kestrel|TSP +2 D'Avenant Healer|TSP +1 Divine Congregation|TSP +2 Errant Doomsayers|TSP +2 Foriysian Interceptor|TSP +1 Fortify|TSP +3 Gaze of Justice|TSP +1 Gustcloak Cavalier|TSP +1 Icatian Crier|TSP +3 Icatian Javelineers|TSB +1 Ivory Giant|TSP +3 Knight of the Holy Nimbus|TSP +2 Outrider en-Kor|TSP +1 Pentarch Paladin|TSP +23 Plains|LRW|1 +1 Sarpadian Empires, Vol. VII|TSP +2 Thunder Totem|TSP +2 Zhalfirin Commander|TSB +[Sideboard] \ No newline at end of file diff --git a/forge-gui/res/quest/precons/Ixidors Legacy.dck b/forge-gui/res/quest/precons/Ixidors Legacy.dck new file mode 100644 index 00000000000..812b8d2367c --- /dev/null +++ b/forge-gui/res/quest/precons/Ixidors Legacy.dck @@ -0,0 +1,42 @@ +[shop] +WinsToUnlock=0 +Credits=1200 +MinDifficulty=0 +MaxDifficulty=5 + +[metadata] +Name=Ixidor's Legacy +Description=Ixidor was the master illusionist who created morph magic, and his legacy is one of trickery and deceit. While playing the Ixidor’s Legacy deck, you’ll pick up right where he left off. +Deck Type=constructed +Set=PLC +Image=ixidors_legacy.jpg + +[Main] +1 Aeon Chronicler|PLC +2 Aquamorph Entity|PLC +1 Brine Elemental|TSP +2 Coral Trickster|TSP +1 Crookclaw Transmuter|TSP +1 Desert|TSB +2 Dream Stalker|TSP +2 Erratic Mutation|PLC +3 Fathom Seer|TSP +2 Fledgling Mawcor|TSP +23 Island|TSP|1 +1 Jodah's Avenger|PLC +1 Merfolk Thaumaturgist|PLC +2 Ovinize|PLC +1 Ovinomancer|TSB +1 Piracy Charm|PLC +1 Pongify|PLC +2 Primal Plasma|PLC +2 Riptide Pilferer|PLC +1 Serendib Sorcerer|PLC +2 Shaper Parasite|PLC +1 Slipstream Serpent|TSP +2 Tidewalker|PLC +2 Unstable Mutation|TSB +1 Willbender|TSB +[Sideboard] + + diff --git a/forge-gui/res/quest/precons/Nuts and Bolts.dck b/forge-gui/res/quest/precons/Nuts and Bolts.dck new file mode 100644 index 00000000000..89908e67427 --- /dev/null +++ b/forge-gui/res/quest/precons/Nuts and Bolts.dck @@ -0,0 +1,45 @@ +[shop] +WinsToUnlock=0 +Credits=3000 +MinDifficulty=0 +MaxDifficulty=5 +[metadata] +Name=Nuts and Bolts +Description=Small, inexpensive artifacts have been staples of the Magic game since its earliest days, but the Fifth Dawn expansion boosts their usefulness to another level. Cards like Auriok Salvagers and Leonin Squire bring cheap artifacts back from your graveyard and apply early attacking pressure. With sixteen artifacts that cost {1} or less, the Nuts and Bolts deck takes full advantage of your creatures' scavenging abilities. +Deck Type=constructed +Set=5DN +Image=nuts_and_bolts.jpg +[Main] +1 Aether Spellbomb|MRD +2 Ancient Den|MRD +1 Auriok Glaivemaster|DST +2 Auriok Salvagers|5DN +1 Auriok Windwalker|5DN +1 Bonesplitter|MRD +3 Chromatic Sphere|MRD +1 Conjurer's Bauble|5DN +1 Ferropede|5DN +1 Fold into Aether|5DN +1 Healer's Headdress|5DN +7 Island|MRD|1 +1 Leonin Bola|DST +2 Leonin Elder|MRD +3 Leonin Squire|5DN +1 Myr Moonvessel|DST +1 Ornithopter|MRD +12 Plains|MRD|1 +2 Qumulox|5DN +1 Salvaging Station|5DN +2 Seat of the Synod|MRD +1 Skullclamp|DST +2 Skyhunter Prowler|5DN +1 Skyhunter Skirmisher|5DN +1 Steelshaper's Gift|5DN +1 Sunbeam Spellbomb|MRD +2 Synod Centurion|5DN +3 Trinket Mage|5DN +1 Vanquish|5DN +1 Viridian Longbow|MRD +[Sideboard] + + diff --git a/forge-gui/res/quest/precons/Reality Fracture.dck b/forge-gui/res/quest/precons/Reality Fracture.dck new file mode 100644 index 00000000000..07022002296 --- /dev/null +++ b/forge-gui/res/quest/precons/Reality Fracture.dck @@ -0,0 +1,39 @@ +[shop] +WinsToUnlock=0 +Credits=1200 +MinDifficulty=0 +MaxDifficulty=5 + +[metadata] +Name=Reality Fracture +Description=The Reality Fracture deck highlights the interaction between suspend and storm. Manipulate the time stream just right, and you’ll set up a single, explosive, game-winning turn! +Deck Type=constructed +Set=TSP +Image=reality_fracture.jpg + +[Main] +1 Careful Consideration|TSP +2 Claws of Gix|TSB +2 Clockspinning|TSP +1 Clockwork Hydra|TSP +2 Coal Stoker|TSP +1 Deep-Sea Kraken|TSP +1 Dreadship Reef|TSP +3 Empty the Warrens|TSP +1 Errant Ephemeron|TSP +2 Giant Oyster|TSB +4 Grapeshot|TSP +1 Ground Rift|TSP +2 Ignite Memories|TSP +12 Island|TSP|1 +1 Jhoira's Timebug|TSP +2 Keldon Halberdier|TSP +11 Mountain|TSP|1 +1 Pardic Dragon|TSP +1 Rift Bolt|TSP +3 Riftwing Cloudskate|TSP +1 Sage of Epityr|TSP +1 Serrated Arrows|TSB +3 Viscerid Deepwalker|TSP +1 Whispers of the Muse|TSB +[Sideboard] diff --git a/forge-gui/res/quest/precons/Sliver Evolution.dck b/forge-gui/res/quest/precons/Sliver Evolution.dck new file mode 100644 index 00000000000..ad94fbb1689 --- /dev/null +++ b/forge-gui/res/quest/precons/Sliver Evolution.dck @@ -0,0 +1,37 @@ +[shop] +WinsToUnlock=0 +Credits=1200 +MinDifficulty=0 +MaxDifficulty=5 + +[metadata] +Name=Sliver Evolution +Description=Slivers share a hive mind. Whatever one thinks, they all think. Whatever one can do, they can all do. Slivers have mutated over the years, and the Sliver Evolution deck shows off their new, deadlier skills. But they still think the same thing they always did: “Smash anything that’s not a Sliver.” +Deck Type=constructed +Set=TSP +Image=sliver_evolution.jpg + +[Main] +1 Avoid Fate|TSB +3 Bonesplitter Sliver|TSP +8 Forest|TSP|1 +1 Fungus Sliver|TSP +2 Fury Sliver|TSP +4 Gemhide Sliver|TSP +1 Gemstone Mine|TSB +1 Harmonic Sliver|TSP +2 Might Sliver|TSP +1 Molder|TSP +6 Mountain|TSP|1 +8 Plains|TSP|1 +1 Pulmonic Sliver|TSP +3 Quilled Sliver|TSP +3 Sidewinder Sliver|TSP +2 Spined Sliver|TSB +2 Spirit Loop|TSP +2 Strength in Numbers|TSP +2 Terramorphic Expanse|TSP +2 Two-Headed Sliver|TSP +2 Venser's Sliver|TSP +3 Watcher Sliver|TSP +[Sideboard] diff --git a/forge-gui/res/quest/precons/Snakes Path.dck b/forge-gui/res/quest/precons/Snakes Path.dck new file mode 100644 index 00000000000..c04a8bbe9af --- /dev/null +++ b/forge-gui/res/quest/precons/Snakes Path.dck @@ -0,0 +1,34 @@ +[shop] +WinsToUnlock=0 +Credits=3000 +MinDifficulty=0 +MaxDifficulty=5 +[metadata] +Name=Snake's Path +Description=If your opponents weren't afraid of snakes before, the "Snake's Path" deck will give them a new phobia! With tons of sss-slithery creatures with sss-super abilities, you will sss-seize control in mere sss-seconds! +Deck Type=constructed +Set=CHK +Image=snakes_path.jpg + +[Main] +24 Forest|CHK|1 +2 Hankyu|CHK +1 Junkyo Bell|CHK +3 Kashi-Tribe Reaver|CHK +2 Kashi-Tribe Warriors|CHK +1 Lure|CHK +3 Matsu-Tribe Decoy|CHK +1 Orochi Eggwatcher|CHK +1 Orochi Hatchery|CHK +3 Orochi Leafcaller|CHK +3 Orochi Ranger|CHK +4 Orochi Sustainer|CHK +1 Sachi, Daughter of Seshiro|CHK +3 Sakura-Tribe Elder|CHK +1 Sensei's Divining Top|CHK +2 Serpent Skin|CHK +1 Sosuke, Son of Seshiro|CHK +2 Strength of Cedars|CHK +1 Time of Need|CHK +1 Wear Away|CHK +[Sideboard] diff --git a/forge-gui/res/quest/precons/Soratamis Wisdom.dck b/forge-gui/res/quest/precons/Soratamis Wisdom.dck new file mode 100644 index 00000000000..ceea3b09c9f --- /dev/null +++ b/forge-gui/res/quest/precons/Soratamis Wisdom.dck @@ -0,0 +1,42 @@ +[shop] +WinsToUnlock=0 +Credits=3000 +MinDifficulty=0 +MaxDifficulty=5 +[metadata] +Name=Soratami's Wisdom +Description=Do you think you're smarter than your opponent? If you're playing the Soratami's Wisdom deck, you probably are! This deck focuses on two things: creatures and spells that get better the more cards you have in your hand, and spells and abilities that fill your hand with cards. Fueled by the massive brainpower of a giant grip of cards, your fleet of fliers and arsenal of combat tricks will let you outsmart anyone who challenges you. +Deck Type=constructed +Set=SOK +Image=soratamis_wisdom.jpg + +[Main] +2 Cage of Hands|CHK +1 Charge Across the Araba|SOK +2 Counsel of the Soratami|CHK +2 Cowed by Wisdom|SOK +2 Descendant of Kiyomaro|SOK +2 Descendant of Soramaro|SOK +1 Eiganjo Free-Riders|SOK +1 Floodbringer|BOK +1 Freed from the Real|SOK +1 Graceful Adept|CHK +1 Hail of Arrows|SOK +1 Hankyu|CHK +11 Island|CHK|1 +1 Kami of the Crescent Moon|SOK +1 Kiri-Onna|SOK +1 Kitsune Bonesetter|SOK +2 Kitsune Loreweaver|SOK +2 Minamo Scrollkeeper|SOK +2 Moonbow Illusionist|SOK +2 Oboro Envoy|SOK +1 Overwhelming Intellect|SOK +12 Plains|CHK|1 +2 Plow Through Reito|SOK +1 Presence of the Wise|SOK +1 Soramaro, First to Dream|SOK +2 Soratami Cloudskater|CHK +1 Soratami Rainshaper|CHK +1 Terashi's Verdict|BOK +[Sideboard] diff --git a/forge-gui/res/quest/precons/Special Forces.dck b/forge-gui/res/quest/precons/Special Forces.dck new file mode 100644 index 00000000000..873fcc29730 --- /dev/null +++ b/forge-gui/res/quest/precons/Special Forces.dck @@ -0,0 +1,39 @@ +[shop] +WinsToUnlock=0 +Credits=3000 +MinDifficulty=0 +MaxDifficulty=5 +[metadata] +Name=Special Forces +Description=The creatures of the "Special Forces" deck are all mission specialists - the attackers have huge power and the blockers have enormous toughness. Creatures like Dross Crocodile, Plasma Elemental, and Emissary of Despair inflict devastating damage, while Steel Wall and Arachnoid hold down a rock-solid defense. +Deck Type=constructed +Set=5DN +Image=special_forces.jpg +[Main] +1 Acquire|5DN +1 Annul|MRD +2 Arachnoid|5DN +2 Consume Spirit|MRD +2 Devour in Shadow|5DN +3 Dross Crocodile|5DN +1 Ebon Drake|5DN +2 Emissary of Despair|DST +1 Ensouled Scimitar|5DN +8 Island|MRD|1 +3 Leaden Myr|MRD +1 Loxodon Warhammer|MRD +1 Murderous Spoils|DST +2 Myr Quadropod|5DN +1 Pewter Golem|MRD +2 Plasma Elemental|5DN +1 Plunge into Darkness|5DN +1 Shattered Dreams|5DN +1 Silver Myr|MRD +1 Slagwurm Armor|MRD +1 Steel Wall|MRD +16 Swamp|MRD|1 +1 Vulshok Gauntlets|MRD +1 Whispersilk Cloak|DST +1 Wizard Replica|MRD +3 Yotian Soldier|MRD +[Sideboard] \ No newline at end of file diff --git a/forge-gui/res/quest/precons/Spiritbane.dck b/forge-gui/res/quest/precons/Spiritbane.dck new file mode 100644 index 00000000000..f136e49df65 --- /dev/null +++ b/forge-gui/res/quest/precons/Spiritbane.dck @@ -0,0 +1,31 @@ +[shop] +WinsToUnlock=0 +Credits=3000 +MinDifficulty=0 +MaxDifficulty=5 +[metadata] +Name=Spiritbane +Description=The yamabushi are mountain shamans skilled in the destructive magic needed to combat the spirit world, and the "Spiritbane" deck proves it. With nearly a third of its creatures and spells capable of dealing direct damage, this deck should have no trouble dispatching your opponents and their creatures. +Deck Type=constructed +Set=CHK +Image=spiritbane.jpg + +[Main] +4 Akki Avalanchers|CHK +2 Akki Coalflinger|CHK +3 Akki Rockspeaker|CHK +3 Battle-Mad Ronin|CHK +2 Blind with Anger|CHK +2 Brothers Yamazaki|CHK|1 +2 Crushing Pain|CHK +3 Frostwielder|CHK +2 Hanabi Blast|CHK +2 Kumano's Pupils|CHK +1 Kumano, Master Yamabushi|CHK +1 Kusari-Gama|CHK +24 Mountain|CHK|1 +2 No-Dachi|CHK +3 Ronin Houndmaster|CHK +1 Sideswipe|CHK +3 Yamabushi's Flame|CHK +[Sideboard] \ No newline at end of file diff --git a/forge-gui/res/quest/precons/Unraveling Mind.dck b/forge-gui/res/quest/precons/Unraveling Mind.dck new file mode 100644 index 00000000000..d09dd7e9bb7 --- /dev/null +++ b/forge-gui/res/quest/precons/Unraveling Mind.dck @@ -0,0 +1,40 @@ +[shop] +WinsToUnlock=0 +Credits=1200 +MinDifficulty=0 +MaxDifficulty=5 + +[metadata] +Name=Unraveling Mind +Description=Insanity gets a bad rap. The “Unraveling Mind” deck is built to take advantage of the madness ability. When you discard a card with madness, you can play it—usually for a discount, and at a time your opponent won’t expect. +Deck Type=constructed +Set=PLC +Image=unraveling_mind.jpg + +[Main] +2 Big Game Hunter|PLC +2 Brain Gorgers|PLC +1 Browbeat|TSB +1 Dark Withering|TSP +1 Dauthi Slayer|TSB +1 Disintegrate|TSB +1 Fiery Temper|TSB +2 Gorgon Recluse|TSP +1 Kor Dirge|PLC +2 Lightning Axe|TSP +1 Magus of the Arena|PLC +4 Mindlash Sliver|TSP +1 Mirri the Cursed|PLC +7 Mountain|TSP|1 +2 Muck Drubb|PLC +2 Nightshade Assassin|TSP +2 Phantasmagorian|PLC +2 Reckless Wurm|PLC +1 Ridged Kusite|PLC +14 Swamp|TSP|1 +3 Terramorphic Expanse|TSP +1 Treacherous Urge|PLC +3 Trespasser il-Vec|TSP +3 Undertaker|TSB +[Sideboard] + diff --git a/forge-gui/res/quest/precons/Way of the Warrior.dck b/forge-gui/res/quest/precons/Way of the Warrior.dck new file mode 100644 index 00000000000..29ade28471c --- /dev/null +++ b/forge-gui/res/quest/precons/Way of the Warrior.dck @@ -0,0 +1,33 @@ +[shop] +WinsToUnlock=0 +Credits=3000 +MinDifficulty=0 +MaxDifficulty=5 +[metadata] +Name=Way of the Warrior +Description=The "Way of the Warrior" deck enlists a new brigade into your army: Samurai! These fearless warriors showcase the Champions of Kamigawa set's new combat ability: bushido. Whenever a creature with bushido 1 blocks or becomes blocked, it gets +1/+1 until end of turn. Some creatures have bushido 2, or even more. This evocative talent comes as standard for Samurai, and that makes them a force to be reckoned with. Since the bushido bonus is given on both offense and defense, your side should always have the upper hand in battle. +Deck Type=constructed +Set=CHK +Image=way_of_the_warrior.jpg + +[Main] +1 Blessed Breath|CHK +1 Bushi Tenderfoot|CHK +2 Cage of Hands|CHK +2 Call to Glory|CHK +1 Candles' Glow|CHK +4 Devoted Retainer|CHK +1 Hold the Line|CHK +2 Indomitable Will|CHK +4 Kitsune Blademaster|CHK +3 Konda's Hatamoto|CHK +4 Mothrider Samurai|CHK +1 Nagao, Bound by Honor|CHK +2 No-Dachi|CHK +1 Otherworldly Journey|CHK +24 Plains|CHK|1 +2 Reciprocate|CHK +2 Samurai Enforcers|CHK +1 Takeno, Samurai General|CHK +2 Vigilance|CHK +[Sideboard] \ No newline at end of file diff --git a/forge-gui/res/skins/darkforge/bg_chaos_wheel.png b/forge-gui/res/skins/darkforge/bg_chaos_wheel.png index e0bb9aef867..9800f5aff45 100644 Binary files a/forge-gui/res/skins/darkforge/bg_chaos_wheel.png and b/forge-gui/res/skins/darkforge/bg_chaos_wheel.png differ diff --git a/forge-gui/res/skins/darkforge/bg_match.jpg b/forge-gui/res/skins/darkforge/bg_match.jpg index 1b97b6ac4dc..5fe8905fbb2 100644 Binary files a/forge-gui/res/skins/darkforge/bg_match.jpg and b/forge-gui/res/skins/darkforge/bg_match.jpg differ diff --git a/forge-gui/res/skins/darkforge/bg_splash.png b/forge-gui/res/skins/darkforge/bg_splash.png index b8828ce884a..9f686363ca5 100644 Binary files a/forge-gui/res/skins/darkforge/bg_splash.png and b/forge-gui/res/skins/darkforge/bg_splash.png differ diff --git a/forge-gui/res/skins/darkforge/bg_texture.jpg b/forge-gui/res/skins/darkforge/bg_texture.jpg index 950a54e2882..ab54820d1df 100644 Binary files a/forge-gui/res/skins/darkforge/bg_texture.jpg and b/forge-gui/res/skins/darkforge/bg_texture.jpg differ diff --git a/forge-gui/res/skins/darkforge/font1.ttf b/forge-gui/res/skins/darkforge/font1.ttf index 1f5704ed579..81aa8defb4b 100644 Binary files a/forge-gui/res/skins/darkforge/font1.ttf and b/forge-gui/res/skins/darkforge/font1.ttf differ diff --git a/forge-gui/res/skins/darkforge/sprite_avatars.png b/forge-gui/res/skins/darkforge/sprite_avatars.png deleted file mode 100644 index 63295091d8e..00000000000 Binary files a/forge-gui/res/skins/darkforge/sprite_avatars.png and /dev/null differ diff --git a/forge-gui/res/skins/darkforge/sprite_buttons.png b/forge-gui/res/skins/darkforge/sprite_buttons.png new file mode 100644 index 00000000000..35deb772ef9 Binary files /dev/null and b/forge-gui/res/skins/darkforge/sprite_buttons.png differ diff --git a/forge-gui/res/skins/darkforge/sprite_icons.png b/forge-gui/res/skins/darkforge/sprite_icons.png index e2a5fe0a12f..3f83d37da80 100644 Binary files a/forge-gui/res/skins/darkforge/sprite_icons.png and b/forge-gui/res/skins/darkforge/sprite_icons.png differ diff --git a/forge-gui/res/skins/darkforge/sprite_planar_conquest.png b/forge-gui/res/skins/darkforge/sprite_planar_conquest.png deleted file mode 100644 index 08a535dcf22..00000000000 Binary files a/forge-gui/res/skins/darkforge/sprite_planar_conquest.png and /dev/null differ diff --git a/forge-gui/res/skins/darkforge/sprite_start.png b/forge-gui/res/skins/darkforge/sprite_start.png new file mode 100644 index 00000000000..310eb073465 Binary files /dev/null and b/forge-gui/res/skins/darkforge/sprite_start.png differ diff --git a/forge-gui/res/skins/darkforge/sprite_trophies.png b/forge-gui/res/skins/darkforge/sprite_trophies.png new file mode 100644 index 00000000000..a9bc240154f Binary files /dev/null and b/forge-gui/res/skins/darkforge/sprite_trophies.png differ diff --git a/forge-gui/res/tokenscripts/cloud_sprite.txt b/forge-gui/res/tokenscripts/cloud_sprite.txt index 6cc79cb8d64..e53f71d94cb 100644 --- a/forge-gui/res/tokenscripts/cloud_sprite.txt +++ b/forge-gui/res/tokenscripts/cloud_sprite.txt @@ -5,5 +5,4 @@ PT:1/1 Types:Creature Faerie K:Flying K:CARDNAME can block only creatures with flying. -A:AB$ Tap | Cost$ W T | ValidTgts$ Creature | TgtPrompt$ Select target creature | SpellDescription$ Tap target creature. -Oracle:Flying\nCloud Sprite can block only creatures with flying. \ No newline at end of file +Oracle:Flying\nCloud Sprite can block only creatures with flying. diff --git a/forge-gui/res/tokenscripts/walker.txt b/forge-gui/res/tokenscripts/walker.txt new file mode 100644 index 00000000000..c0895372a56 --- /dev/null +++ b/forge-gui/res/tokenscripts/walker.txt @@ -0,0 +1,6 @@ +Name:Walker +ManaCost:no cost +Types:Creature Zombie +Colors:black +PT:2/2 +Oracle: diff --git a/forge-gui/src/main/java/forge/limited/BoosterDraft.java b/forge-gui/src/main/java/forge/limited/BoosterDraft.java index c54ae9d13c9..a3ffdf73ebe 100644 --- a/forge-gui/src/main/java/forge/limited/BoosterDraft.java +++ b/forge-gui/src/main/java/forge/limited/BoosterDraft.java @@ -225,7 +225,11 @@ public class BoosterDraft implements IBoosterDraft { final BoosterDraft draft = new BoosterDraft(draftType); for (String booster : boosters) { - draft.product.add(block.getBooster(booster)); + try { + draft.product.add(block.getBooster(booster)); + } catch (Exception ex) { + System.err.println("Booster Draft Error: "+ex.getMessage()); + } } IBoosterDraft.LAND_SET_CODE[0] = block.getLandSet(); diff --git a/forge-gui/src/main/java/forge/match/AbstractGuiGame.java b/forge-gui/src/main/java/forge/match/AbstractGuiGame.java index a626d36548f..fbff635cf47 100644 --- a/forge-gui/src/main/java/forge/match/AbstractGuiGame.java +++ b/forge-gui/src/main/java/forge/match/AbstractGuiGame.java @@ -272,6 +272,16 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards { } public boolean isGamePaused() { return gamePause; } public void setgamePause(boolean pause) { gamePause = pause; } + public void pauseMatch() { + IGameController controller = spectator; + if(controller != null && !isGamePaused()) + controller.selectButtonOk(); + } + public void resumeMatch() { + IGameController controller = spectator; + if(controller != null && isGamePaused()) + controller.selectButtonOk(); + } /** Concede game, bring up WinLose UI. */ public boolean concede() { diff --git a/forge-gui/src/main/java/forge/player/HumanPlay.java b/forge-gui/src/main/java/forge/player/HumanPlay.java index 33afd029f80..c30fc7064fd 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlay.java +++ b/forge-gui/src/main/java/forge/player/HumanPlay.java @@ -85,7 +85,9 @@ public class HumanPlay { } if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { - CharmEffect.makeChoices(sa); + if (!CharmEffect.makeChoices(sa)) { + return false; + } } sa = AbilityUtils.addSpliceEffects(sa); @@ -150,7 +152,9 @@ public class HumanPlay { if (!sa.isCopied()) { if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { - CharmEffect.makeChoices(sa); + if (!CharmEffect.makeChoices(sa)) { + return; + } } sa = AbilityUtils.addSpliceEffects(sa); } diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 784840224a1..7fc43b09581 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1,20 +1,8 @@ package forge.player; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; +import java.io.*; +import java.util.*; import java.util.Map.Entry; -import java.util.Set; import org.apache.commons.lang3.Range; import org.apache.commons.lang3.StringUtils; @@ -39,11 +27,7 @@ import forge.StaticData; import forge.achievement.AchievementCollection; import forge.ai.GameState; import forge.assets.FSkinProp; -import forge.card.CardDb; -import forge.card.CardType; -import forge.card.ColorSet; -import forge.card.ICardFace; -import forge.card.MagicColor; +import forge.card.*; import forge.card.mana.ManaCost; import forge.card.mana.ManaCostShard; import forge.control.FControlGamePlayback; @@ -51,27 +35,11 @@ import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckSection; import forge.events.UiEventNextGameDecision; -import forge.game.Game; -import forge.game.GameEntity; -import forge.game.GameEntityView; -import forge.game.GameEntityViewMap; -import forge.game.GameLogEntryType; -import forge.game.GameObject; -import forge.game.GameType; -import forge.game.PlanarDice; -import forge.game.ability.AbilityFactory; +import forge.game.*; import forge.game.ability.AbilityKey; import forge.game.ability.ApiType; -import forge.game.ability.effects.CharmEffect; -import forge.game.card.Card; -import forge.game.card.CardCollection; -import forge.game.card.CardCollectionView; -import forge.game.card.CardFaceView; -import forge.game.card.CardLists; -import forge.game.card.CardPredicates; -import forge.game.card.CardView; -import forge.game.card.CounterEnumType; -import forge.game.card.CounterType; +import forge.game.card.*; +import forge.game.card.token.TokenInfo; import forge.game.combat.Combat; import forge.game.combat.CombatUtil; import forge.game.cost.Cost; @@ -82,20 +50,10 @@ import forge.game.keyword.Keyword; import forge.game.keyword.KeywordInterface; import forge.game.mana.Mana; import forge.game.mana.ManaConversionMatrix; -import forge.game.player.DelayedReveal; -import forge.game.player.Player; -import forge.game.player.PlayerActionConfirmMode; -import forge.game.player.PlayerController; -import forge.game.player.PlayerView; +import forge.game.player.*; import forge.game.replacement.ReplacementEffect; import forge.game.replacement.ReplacementLayer; -import forge.game.spellability.AbilityManaPart; -import forge.game.spellability.AbilitySub; -import forge.game.spellability.OptionalCostValue; -import forge.game.spellability.SpellAbility; -import forge.game.spellability.SpellAbilityStackInstance; -import forge.game.spellability.SpellAbilityView; -import forge.game.spellability.TargetChoices; +import forge.game.spellability.*; import forge.game.trigger.Trigger; import forge.game.trigger.WrappedAbility; import forge.game.zone.MagicStack; @@ -109,19 +67,7 @@ import forge.interfaces.IMacroSystem; import forge.item.IPaperCard; import forge.item.PaperCard; import forge.match.NextGameDecision; -import forge.match.input.Input; -import forge.match.input.InputAttack; -import forge.match.input.InputBlock; -import forge.match.input.InputConfirm; -import forge.match.input.InputConfirmMulligan; -import forge.match.input.InputLondonMulligan; -import forge.match.input.InputPassPriority; -import forge.match.input.InputPayMana; -import forge.match.input.InputProxy; -import forge.match.input.InputQueue; -import forge.match.input.InputSelectCardsForConvokeOrImprovise; -import forge.match.input.InputSelectCardsFromList; -import forge.match.input.InputSelectEntitiesFromList; +import forge.match.input.*; import forge.model.FModel; import forge.properties.ForgeConstants; import forge.properties.ForgePreferences.FPref; @@ -624,7 +570,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont // create a mapping between a spell's view and the spell itself Map spellViewCache = SpellAbilityView.getMap(spells); - List chosen = getGui().many(title, "", num, Lists.newArrayList(spellViewCache.keySet()), sa.getHostCard().getView()); + //override generic + List chosen = getGui().getChoices(title, num, num, Lists.newArrayList(spellViewCache.keySet())); for(SpellAbilityView view : chosen) { if (spellViewCache.containsKey(view)) { @@ -1168,17 +1115,20 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont private void sortCreatureTypes(List types) { // build map of creature types in player's main deck against the // occurrences of each - CardCollection pool = CardLists.filterControlledBy(game.getCardsInGame(), player); Map typesInDeck = Maps.newHashMap(); // TODO JAVA 8 use getOrDefault - for (Card c : pool) { + for (Card c : player.getAllCards()) { // Changeling are all creature types, they are not interesting for // counting creature types if (c.hasStartOfKeyword(Keyword.CHANGELING.toString())) { continue; } + // same is true if it somehow has all creature types + if (c.getType().hasSubtype(CardType.AllCreatureTypes)) { + continue; + } // ignore cards that does enter the battlefield as clones boolean isClone = false; for (ReplacementEffect re : c.getReplacementEffects()) { @@ -1191,8 +1141,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont continue; } - Set cardCreatureTypes = c.getType().getCreatureTypes(); - for (String type : cardCreatureTypes) { + for (String type : c.getType().getCreatureTypes()) { Integer count = typesInDeck.get(type); if (count == null) { count = 0; @@ -1204,54 +1153,31 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont if (sa.getApi() != ApiType.Token) { continue; } - if (sa.hasParam("TokenTypes")) { - for (String var : sa.getParam("TokenTypes").split(",")) { - if (!CardType.isACreatureType(var)) { - continue; - } - Integer count = typesInDeck.get(var); + if (sa.hasParam("TokenScript")) { + Card protoType = TokenInfo.getProtoType(sa.getParam("TokenScript"), sa); + for (String type : protoType.getType().getCreatureTypes()) { + Integer count = typesInDeck.get(type); if (count == null) { count = 0; } - typesInDeck.put(var, count + 1); + typesInDeck.put(type, count + 1); } } } // same for Trigger that does make Tokens for (Trigger t : c.getTriggers()) { - SpellAbility sa = t.getOverridingAbility(); - String sTokenTypes = null; + SpellAbility sa = t.ensureAbility(); if (sa != null) { - if (sa.getApi() != ApiType.Token || !sa.hasParam("TokenTypes")) { - continue; + if (sa.hasParam("TokenScript")) { + Card protoType = TokenInfo.getProtoType(sa.getParam("TokenScript"), sa); + for (String type : protoType.getType().getCreatureTypes()) { + Integer count = typesInDeck.get(type); + if (count == null) { + count = 0; + } + typesInDeck.put(type, count + 1); + } } - sTokenTypes = sa.getParam("TokenTypes"); - } else if (t.hasParam("Execute")) { - String name = t.getParam("Execute"); - if (!c.hasSVar(name)) { - continue; - } - - Map params = AbilityFactory.getMapParams(c.getSVar(name)); - if (!params.containsKey("TokenTypes")) { - continue; - } - sTokenTypes = params.get("TokenTypes"); - } - - if (sTokenTypes == null) { - continue; - } - - for (String var : sTokenTypes.split(",")) { - if (!CardType.isACreatureType(var)) { - continue; - } - Integer count = typesInDeck.get(var); - if (count == null) { - count = 0; - } - typesInDeck.put(var, count + 1); } } // special rule for Fabricate and Servo @@ -1591,14 +1517,13 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont * spellability.SpellAbility, java.util.List, int, int) */ @Override - public List chooseModeForAbility(final SpellAbility sa, final int min, final int num, + public List chooseModeForAbility(final SpellAbility sa, List possible, final int min, final int num, boolean allowRepeat) { boolean trackerFrozen = game.getTracker().isFrozen(); if (trackerFrozen) { // The view tracker needs to be unfrozen to update the SpellAbilityViews at this point, or it may crash game.getTracker().unfreeze(); } - final List possible = CharmEffect.makePossibleOptions(sa); Map spellViewCache = SpellAbilityView.getMap(possible); if (trackerFrozen) { game.getTracker().freeze(); // refreeze if the tracker was frozen prior to this update @@ -3098,8 +3023,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont public void handleLandPlayed(Card land, Zone zone) { IGuiGame guiGame = getGui(); guiGame.handleLandPlayed(land,zone); - } + } + - } diff --git a/forge-gui/src/main/java/forge/properties/ForgeConstants.java b/forge-gui/src/main/java/forge/properties/ForgeConstants.java index 00c2bb02ecd..bf1de97acb9 100644 --- a/forge-gui/src/main/java/forge/properties/ForgeConstants.java +++ b/forge-gui/src/main/java/forge/properties/ForgeConstants.java @@ -48,6 +48,7 @@ public final class ForgeConstants { public static final String NET_DECKS_LIST_FILE = LISTS_DIR + "net-decks.txt"; public static final String NET_DECKS_COMMANDER_LIST_FILE = LISTS_DIR + "net-decks-commander.txt"; public static final String NET_DECKS_BRAWL_LIST_FILE = LISTS_DIR + "net-decks-brawl.txt"; + public static final String BORDERLESS_CARD_LIST_FILE = LISTS_DIR + "borderlessCardList.txt"; public static final String CHANGES_FILE = ASSETS_DIR + "README.txt"; diff --git a/forge-gui/src/main/java/forge/properties/PreferencesStore.java b/forge-gui/src/main/java/forge/properties/PreferencesStore.java index 39da97b9e99..302fdd663da 100644 --- a/forge-gui/src/main/java/forge/properties/PreferencesStore.java +++ b/forge-gui/src/main/java/forge/properties/PreferencesStore.java @@ -119,4 +119,8 @@ public abstract class PreferencesStore> { public final boolean getPrefBoolean(final T fp0) { return Boolean.parseBoolean(getPref(fp0)); } + + public final double getPrefDouble(final T fp0) { + return Double.parseDouble(getPref(fp0)); + } } diff --git a/forge-gui/src/main/java/forge/quest/MainWorldEventDuelManager.java b/forge-gui/src/main/java/forge/quest/MainWorldEventDuelManager.java new file mode 100644 index 00000000000..3421238909d --- /dev/null +++ b/forge-gui/src/main/java/forge/quest/MainWorldEventDuelManager.java @@ -0,0 +1,266 @@ +package forge.quest; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import forge.model.FModel; +import forge.quest.data.QuestPreferences; +import forge.quest.data.QuestPreferences.DifficultyPrefs; +import forge.quest.data.QuestPreferences.QPref; +import forge.quest.io.MainWorldDuelReader; +import forge.util.CollectionSuppliers; +import forge.util.MyRandom; +import forge.util.maps.EnumMapOfLists; +import forge.util.maps.MapOfLists; +import forge.util.storage.IStorage; +import forge.util.storage.StorageBase; + +public class MainWorldEventDuelManager implements QuestEventDuelManagerInterface { + + protected final MapOfLists sortedDuels = new EnumMapOfLists<>(QuestEventDifficulty.class, CollectionSuppliers.arrayLists()); + protected final IStorage allDuels; + + /** + * Instantiate all events and difficulty lists. + * + * @param dir   File object + */ + public MainWorldEventDuelManager(final File dir) { + allDuels = new StorageBase<>("Quest duels", new MainWorldDuelReader(dir)); + assembleDuelDifficultyLists(); + } + + public Iterable getAllDuels() { + return allDuels; + } + + public Iterable getDuels(QuestEventDifficulty difficulty) { + return sortedDuels.get(difficulty); + } + + // define fallback orders if there aren't enough opponents defined for a particular difficultly level + private static List easyOrder = Arrays.asList(QuestEventDifficulty.EASY, QuestEventDifficulty.MEDIUM, QuestEventDifficulty.HARD, QuestEventDifficulty.EXPERT); + private static List mediumOrder = Arrays.asList(QuestEventDifficulty.MEDIUM, QuestEventDifficulty.HARD, QuestEventDifficulty.EASY, QuestEventDifficulty.EXPERT); + private static List hardOrder = Arrays.asList(QuestEventDifficulty.HARD, QuestEventDifficulty.MEDIUM, QuestEventDifficulty.EASY, QuestEventDifficulty.EXPERT); + private static List expertOrder = Arrays.asList(QuestEventDifficulty.EXPERT, QuestEventDifficulty.HARD, QuestEventDifficulty.MEDIUM, QuestEventDifficulty.EASY); + private static List wildOrder = Arrays.asList(QuestEventDifficulty.WILD); + + private List getOrderForDifficulty(QuestEventDifficulty d) { + final List difficultyOrder; + + switch (d) { + case EASY: + difficultyOrder = easyOrder; + break; + case MEDIUM: + difficultyOrder = mediumOrder; + break; + case HARD: + difficultyOrder = hardOrder; + break; + case EXPERT: + difficultyOrder = expertOrder; + break; + case WILD: + difficultyOrder = wildOrder; + break; + default: + throw new RuntimeException("unhandled difficulty: " + d); + } + + return difficultyOrder; + } + + private void addDuel(List outList, QuestEventDifficulty targetDifficulty, int toAdd) { + + // if there's no way we can satisfy the request, return now + if (allDuels.size() <= toAdd) { + return; + } + + final List difficultyOrder = getOrderForDifficulty(targetDifficulty); + + for (QuestEventDifficulty d : difficultyOrder) { // will add duels from preferred difficulty, will use others if the former has too few options. + for (QuestEventDuel duel : sortedDuels.get(d)) { + if (toAdd <= 0) { + return; + } + if (!outList.contains(duel)) { + outList.add(duel); + toAdd--; + } + } + } + + } + + private void addRandomDuel(final List listOfDuels, final QuestEventDifficulty difficulty) { + + QuestEventDuel duel = new QuestEventDuel(); + + List difficultyOrder = getOrderForDifficulty(difficulty); + List possibleDuels = new ArrayList<>(); + for (QuestEventDifficulty diff : difficultyOrder) { + possibleDuels = new ArrayList<>(sortedDuels.get(diff)); + if (!possibleDuels.isEmpty()) { + break; + } + } + + QuestEventDuel randomOpponent = possibleDuels.get(((int) (possibleDuels.size() * MyRandom.getRandom().nextDouble()))); + + duel.setTitle("Random Opponent"); + duel.setIconImageKey(randomOpponent.getIconImageKey()); + duel.setOpponentName(randomOpponent.getTitle()); + duel.setDifficulty(difficulty); + duel.setProfile(randomOpponent.getProfile()); + duel.setShowDifficulty(false); + duel.setDescription("Fight a random opponent"); + duel.setEventDeck(randomOpponent.getEventDeck()); + + listOfDuels.add(duel); + + } + + /** + * Generates an array of new duel opponents based on current win conditions. + * + * @return an array of {@link java.lang.String} objects. + */ + public final List generateDuels() { + + final QuestPreferences questPreferences = FModel.getQuestPreferences(); + boolean moreDuelChoices = questPreferences.getPrefInt(QPref.MORE_DUEL_CHOICES) > 0; + + if (FModel.getQuest().getAchievements() == null) { + return null; + } + + final QuestController qCtrl = FModel.getQuest(); + final int numberOfWins = qCtrl.getAchievements().getWin(); + + final int index = qCtrl.getAchievements().getDifficulty(); + final List duelOpponents = new ArrayList<>(); + + QuestEventDifficulty randomDuelDifficulty = QuestEventDifficulty.EASY; + + double randomDouble = MyRandom.getRandom().nextDouble(); + + if (numberOfWins < questPreferences.getPrefInt(DifficultyPrefs.WINS_MEDIUMAI, index)) { + addDuel(duelOpponents, QuestEventDifficulty.EASY, 3); + if(areWildDecksWanted() && isWildDeckAvailable() && randomDouble * 2 < 1) { + randomDuelDifficulty = QuestEventDifficulty.WILD; + } else { + randomDuelDifficulty = QuestEventDifficulty.EASY; + } + } else if (numberOfWins == questPreferences.getPrefInt(DifficultyPrefs.WINS_MEDIUMAI, index)) { + addDuel(duelOpponents, QuestEventDifficulty.EASY, 1); + addDuel(duelOpponents, QuestEventDifficulty.MEDIUM, 2); + if(areWildDecksWanted() && isWildDeckAvailable() && randomDouble * 2 < 1) { + randomDuelDifficulty = QuestEventDifficulty.WILD; + } else { + randomDuelDifficulty = QuestEventDifficulty.MEDIUM; + } + } else if (numberOfWins < questPreferences.getPrefInt(DifficultyPrefs.WINS_HARDAI, index)) { + addDuel(duelOpponents, QuestEventDifficulty.MEDIUM, 3); + randomDuelDifficulty = QuestEventDifficulty.MEDIUM; + } else if (numberOfWins == questPreferences.getPrefInt(DifficultyPrefs.WINS_HARDAI, index)) { + addDuel(duelOpponents, QuestEventDifficulty.MEDIUM, 1); + addDuel(duelOpponents, QuestEventDifficulty.HARD, 2); + if(areWildDecksWanted() && isWildDeckAvailable() && randomDouble * 2 < 1) { + randomDuelDifficulty = QuestEventDifficulty.WILD; + } else { + randomDuelDifficulty = QuestEventDifficulty.HARD; + } + } else if (numberOfWins < questPreferences.getPrefInt(DifficultyPrefs.WINS_EXPERTAI, index)) { + addDuel(duelOpponents, QuestEventDifficulty.HARD, 3); + if(areWildDecksWanted() && isWildDeckAvailable() && randomDouble * 2 < 1) { + randomDuelDifficulty = QuestEventDifficulty.WILD; + } else { + randomDuelDifficulty = QuestEventDifficulty.HARD; + } + } else { + addDuel(duelOpponents, QuestEventDifficulty.HARD, 2); + addDuel(duelOpponents, QuestEventDifficulty.EXPERT, 1); + if(areWildDecksWanted() && isWildDeckAvailable()) { + if(randomDouble * 2 < 1) { + randomDuelDifficulty = QuestEventDifficulty.WILD; + } else if(randomDouble * 6 < 5) { + randomDuelDifficulty = QuestEventDifficulty.HARD; + } else { + randomDuelDifficulty = QuestEventDifficulty.EXPERT; + } + } else { + if (randomDouble * 3 < 2) { + randomDuelDifficulty = QuestEventDifficulty.HARD; + } else { + randomDuelDifficulty = QuestEventDifficulty.EXPERT; + } + } + + } + + if (moreDuelChoices) { + if (numberOfWins == questPreferences.getPrefInt(DifficultyPrefs.WINS_MEDIUMAI, index)) { + addDuel(duelOpponents, QuestEventDifficulty.EASY, 1); + } else if (numberOfWins < questPreferences.getPrefInt(DifficultyPrefs.WINS_HARDAI, index)) { + addDuel(duelOpponents, QuestEventDifficulty.EASY, 1); + } else if (numberOfWins == questPreferences.getPrefInt(DifficultyPrefs.WINS_HARDAI, index)) { + addDuel(duelOpponents, QuestEventDifficulty.MEDIUM, 1); + } else { + addDuel(duelOpponents, QuestEventDifficulty.MEDIUM, 1); + addDuel(duelOpponents, QuestEventDifficulty.EASY, 1); + } + } + + // Now to add the wild opponents + addDuel(duelOpponents, QuestEventDifficulty.WILD, FModel.getQuestPreferences().getPrefInt(QPref.WILD_OPPONENTS_NUMBER)); + addRandomDuel(duelOpponents, randomDuelDifficulty); + + return duelOpponents; + + } + + private boolean areWildDecksWanted() { + int wildOpponentsPreference = FModel.getQuestPreferences().getPrefInt(QPref.WILD_OPPONENTS_NUMBER); + return wildOpponentsPreference > 0; + } + + private boolean isWildDeckAvailable() { + List wildList = (List) sortedDuels.get(QuestEventDifficulty.WILD); + return !wildList.isEmpty(); + } + + /** + *

+ * assembleDuelDifficultyLists. + *

+ * Assemble duel deck difficulty lists + */ + protected void assembleDuelDifficultyLists() { + + sortedDuels.clear(); + sortedDuels.put(QuestEventDifficulty.EASY, new ArrayList<>()); + sortedDuels.put(QuestEventDifficulty.MEDIUM, new ArrayList<>()); + sortedDuels.put(QuestEventDifficulty.HARD, new ArrayList<>()); + sortedDuels.put(QuestEventDifficulty.EXPERT, new ArrayList<>()); + sortedDuels.put(QuestEventDifficulty.WILD, new ArrayList<>()); + + for (final QuestEventDuel qd : allDuels) { + sortedDuels.add(qd.getDifficulty(), qd); + } + + } + + /** */ + public void randomizeOpponents() { + for (QuestEventDifficulty qd : sortedDuels.keySet()) { + List list = (List) sortedDuels.get(qd); + Collections.shuffle(list, MyRandom.getRandom()); + } + } + +} diff --git a/forge-gui/src/main/java/forge/quest/QuestController.java b/forge-gui/src/main/java/forge/quest/QuestController.java index 57ed852e5c8..b782c039c60 100644 --- a/forge-gui/src/main/java/forge/quest/QuestController.java +++ b/forge-gui/src/main/java/forge/quest/QuestController.java @@ -17,8 +17,18 @@ */ package forge.quest; +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + import com.google.common.collect.Lists; import com.google.common.eventbus.Subscribe; + import forge.card.CardEdition; import forge.deck.Deck; import forge.deck.DeckGroup; @@ -32,16 +42,18 @@ import forge.properties.ForgeConstants; import forge.quest.bazaar.QuestBazaarManager; import forge.quest.bazaar.QuestItemType; import forge.quest.bazaar.QuestPetStorage; -import forge.quest.data.*; +import forge.quest.data.DeckConstructionRules; +import forge.quest.data.GameFormatQuest; +import forge.quest.data.QuestAchievements; +import forge.quest.data.QuestAssets; +import forge.quest.data.QuestData; import forge.quest.data.QuestPreferences.DifficultyPrefs; import forge.quest.data.QuestPreferences.QPref; +import forge.quest.data.StarRating; import forge.quest.io.QuestChallengeReader; import forge.util.storage.IStorage; import forge.util.storage.StorageBase; -import java.io.File; -import java.util.*; - /** * TODO: Write javadoc for this type. * @@ -456,13 +468,19 @@ public class QuestController { return; }else if (world.isCustom()) { path = world.getDuelsDir() == null ? ForgeConstants.DEFAULT_DUELS_DIR : ForgeConstants.USER_QUEST_WORLD_DIR + world.getDuelsDir(); + this.duelManager = new QuestEventDuelManager(new File(path)); } else { path = world.getDuelsDir() == null ? ForgeConstants.DEFAULT_DUELS_DIR : ForgeConstants.QUEST_WORLD_DIR + world.getDuelsDir(); + if(QuestWorld.MAINWORLDNAME.equals(world.getName())) { + this.duelManager = new MainWorldEventDuelManager(new File(path)); + } else { + this.duelManager = new QuestEventDuelManager(new File(path)); + } } - + } else { + this.duelManager = new QuestEventDuelManager(new File(path)); } - this.duelManager = new QuestEventDuelManager(new File(path)); } public HashSet GetRating() { diff --git a/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java b/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java index cfdb7d2b65a..dcf7db625e3 100644 --- a/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java +++ b/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java @@ -2,6 +2,9 @@ package forge.quest; import org.apache.commons.lang3.StringUtils; +import forge.model.FModel; +import forge.quest.data.QuestPreferences.QPref; + /** * TODO: Write javadoc for this type. * @@ -10,7 +13,8 @@ public enum QuestEventDifficulty { EASY ("easy", 1. ), MEDIUM("medium", 1.5), HARD ("hard", 2. ), - EXPERT("very hard", 3. ); + EXPERT("very hard", 3. ), + WILD("wild", FModel.getQuestPreferences().getPrefDouble(QPref.WILD_OPPONENTS_MULTIPLIER) ); private final String inFile; private final double multiplier; diff --git a/forge-gui/src/main/java/forge/quest/QuestTournamentController.java b/forge-gui/src/main/java/forge/quest/QuestTournamentController.java index 57f1616a122..9357e4a2c58 100644 --- a/forge-gui/src/main/java/forge/quest/QuestTournamentController.java +++ b/forge-gui/src/main/java/forge/quest/QuestTournamentController.java @@ -24,6 +24,7 @@ import forge.tournament.system.TournamentBracket; import forge.tournament.system.TournamentPairing; import forge.tournament.system.TournamentPlayer; import forge.util.TextUtil; +import forge.util.ThreadUtil; import forge.util.gui.SGuiChoose; import forge.util.gui.SOptionPane; import forge.util.storage.IStorage; @@ -381,29 +382,34 @@ public class QuestTournamentController { } public void startDraft() { - if (drafting) { - SOptionPane.showErrorDialog(localizer.getMessage("lblCurrentlyInDraft")); - return; - } + ThreadUtil.invokeInGameThread(new Runnable() { + @Override + public void run() { + if (drafting) { + SOptionPane.showErrorDialog(localizer.getMessage("lblCurrentlyInDraft")); + return; + } - final QuestEventDraft draftEvent = QuestUtil.getDraftEvent(); + final QuestEventDraft draftEvent = QuestUtil.getDraftEvent(); - final long creditsAvailable = FModel.getQuest().getAssets().getCredits(); - if (draftEvent.canEnter()) { - SOptionPane.showMessageDialog(localizer.getMessage("lblYouNeed") + QuestUtil.formatCredits(draftEvent.getEntryFee() - creditsAvailable) + " " + localizer.getMessage("lblMoreCredits"), localizer.getMessage("lblNotEnoughCredits"), SOptionPane.WARNING_ICON); - return; - } + final long creditsAvailable = FModel.getQuest().getAssets().getCredits(); + if (draftEvent.canEnter()) { + SOptionPane.showMessageDialog(localizer.getMessage("lblYouNeed") + QuestUtil.formatCredits(draftEvent.getEntryFee() - creditsAvailable) + " " + localizer.getMessage("lblMoreCredits"), localizer.getMessage("lblNotEnoughCredits"), SOptionPane.WARNING_ICON); + return; + } - final boolean okayToEnter = SOptionPane.showOptionDialog(localizer.getMessage("lblTournamentCosts") + QuestUtil.formatCredits(draftEvent.getEntryFee()) + localizer.getMessage("lblSureEnterTournament"), localizer.getMessage("lblEnterDraftTournament"), FSkinProp.ICO_QUEST_GOLD, ImmutableList.of(localizer.getMessage("lblYes"), localizer.getMessage("lblNo")), 1) == 0; + final boolean okayToEnter = SOptionPane.showOptionDialog(localizer.getMessage("lblTournamentCosts") + QuestUtil.formatCredits(draftEvent.getEntryFee()) + localizer.getMessage("lblSureEnterTournament"), localizer.getMessage("lblEnterDraftTournament"), FSkinProp.ICO_QUEST_GOLD, ImmutableList.of(localizer.getMessage("lblYes"), localizer.getMessage("lblNo")), 1) == 0; - if (!okayToEnter) { - return; - } + if (!okayToEnter) { + return; + } - drafting = true; + drafting = true; - final BoosterDraft draft = draftEvent.enter(); - view.startDraft(draft); + final BoosterDraft draft = draftEvent.enter(); + view.startDraft(draft); + } + }); } public boolean cancelDraft() { diff --git a/forge-gui/src/main/java/forge/quest/QuestWorld.java b/forge-gui/src/main/java/forge/quest/QuestWorld.java index 52ad44988f0..651e285624f 100644 --- a/forge-gui/src/main/java/forge/quest/QuestWorld.java +++ b/forge-gui/src/main/java/forge/quest/QuestWorld.java @@ -43,6 +43,7 @@ public class QuestWorld implements Comparable{ public static final String PIONEERWORLDNAME = "Random Pioneer"; public static final String MODERNWORLDNAME = "Random Modern"; public static final String RANDOMCOMMANDERWORLDNAME = "Random Commander"; + public static final String MAINWORLDNAME = "Main world"; private boolean isCustom; diff --git a/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java b/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java index 0442d2ddb7e..a60d03fbf92 100644 --- a/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java +++ b/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java @@ -19,6 +19,7 @@ package forge.quest.data; import forge.properties.ForgeConstants; import forge.properties.PreferencesStore; +import forge.util.Localizer; import forge.util.TextUtil; import java.io.Serializable; @@ -173,6 +174,8 @@ public class QuestPreferences extends PreferencesStore i SHOP_WINS_FOR_NO_SELL_LIMIT("50"), // Duels of the current difficulty only, or that and all difficulties below it? MORE_DUEL_CHOICES("0"), + WILD_OPPONENTS_MULTIPLIER("2.0"), + WILD_OPPONENTS_NUMBER("0"), //The number of cards to keep before selling PLAYSET_SIZE("4"), @@ -313,6 +316,11 @@ public class QuestPreferences extends PreferencesStore i return "Value too small (minimum 1)."; } break; + case WILD_OPPONENTS_NUMBER: + if(val < 0 || val > 3) { + return Localizer.getInstance().getMessage("lblWildOpponentNumberError"); + } + break; case BOOSTER_COMMONS: case BOOSTER_UNCOMMONS: case BOOSTER_RARES: diff --git a/forge-gui/src/main/java/forge/quest/io/MainWorldDuelReader.java b/forge-gui/src/main/java/forge/quest/io/MainWorldDuelReader.java new file mode 100644 index 00000000000..633d4d602ee --- /dev/null +++ b/forge-gui/src/main/java/forge/quest/io/MainWorldDuelReader.java @@ -0,0 +1,144 @@ +package forge.quest.io; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.TreeMap; + +import org.apache.commons.lang3.StringUtils; + +import forge.ImageKeys; +import forge.deck.Deck; +import forge.deck.io.DeckSerializer; +import forge.deck.io.DeckStorage; +import forge.model.FModel; +import forge.quest.QuestEvent; +import forge.quest.QuestEventDifficulty; +import forge.quest.QuestEventDuel; +import forge.util.FileSection; +import forge.util.FileUtil; +import forge.util.TextUtil; +import forge.util.storage.IStorage; +import forge.util.storage.StorageReaderFolder; + +public class MainWorldDuelReader extends StorageReaderFolder { + + private static final String WILD_DEFAULT_ICON_NAME = "Wild.jpg"; + private static final String WILD_DIR_NAME = "wild"; + + public MainWorldDuelReader(File deckDir0) { + super(deckDir0, QuestEvent.FN_GET_NAME); + } + + @Override + public Map readAll() { + + final Map result = new TreeMap<>(); + + // First I add wild decks in quest directory + try { + Files.walkFileTree(directory.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { + File actualFile = new File(path.toString()); + try { + final QuestEventDuel newDeck = read(actualFile); + if (null == newDeck) { + final String msg = "An object stored in " + actualFile.getPath() + " failed to load.\nPlease submit this as a bug with the mentioned file/directory attached."; + throw new RuntimeException(msg); + } + + String newKey = keySelector.apply(newDeck); + if (result.containsKey(newKey)) { + System.err.println("StorageReaderFolder: an object with key " + newKey + " is already present - skipping new entry"); + } else { + result.put(newKey, newDeck); + } + } catch (final NoSuchElementException ex) { + final String message = TextUtil.concatWithSpace( actualFile.getName(),"failed to load because ----", ex.getMessage()); + objectsThatFailedToLoad.add(message); + } + + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + // then I add wild decks in constructed directory + IStorage constructedDecks = FModel.getDecks().getConstructed(); + Iterator it = constructedDecks.iterator(); + while(it.hasNext()) { + Deck currDeck = (Deck) it.next(); + final QuestEventDuel newDeck = read(currDeck); + String newKey = keySelector.apply(newDeck); + if (result.containsKey(newKey)) { + System.err.println("StorageReaderFolder: an object with key " + newKey + " is already present - skipping new entry"); + } else { + result.put(newKey, newDeck); + } + } + + return result; + } + + @Override + protected QuestEventDuel read(File file) { + final Map> contents = FileSection.parseSections(FileUtil.readFile(file)); + final QuestEventDuel qc = new QuestEventDuel(); + + // Common properties + FileSection sectionMeta = FileSection.parse(contents.get("metadata"), FileSection.EQUALS_KV_SEPARATOR); + qc.setName(sectionMeta.get("Name")); // Challenges have unique titles + + boolean difficultySpecified = !StringUtils.isEmpty(sectionMeta.get("Difficulty")); + if(difficultySpecified) { + qc.setTitle(sectionMeta.get("Title")); + qc.setDifficulty(QuestEventDifficulty.fromString(sectionMeta.get("Difficulty"))); + qc.setDescription(sectionMeta.get("Description", "").replace("\\n", "\n")); + qc.setCardReward(sectionMeta.get("Card Reward")); + qc.setIconImageKey(ImageKeys.ICON_PREFIX + sectionMeta.get("Icon")); + if (sectionMeta.contains("Profile")) { + qc.setProfile(sectionMeta.get("Profile")); + } + } else { + qc.setDifficulty(QuestEventDifficulty.WILD); + qc.setTitle(sectionMeta.get("Title") != null ? sectionMeta.get("Title") : qc.getName()); + qc.setDescription(sectionMeta.get("Description") != null ? sectionMeta.get("Description") : "Wild opponent"); + qc.setIconImageKey(ImageKeys.ICON_PREFIX + (sectionMeta.get("Icon") != null ? sectionMeta.get("Icon") : WILD_DEFAULT_ICON_NAME)); + } + + // Deck + qc.setEventDeck(DeckSerializer.fromSections(contents)); + return qc; + } + + protected QuestEventDuel read(Deck deck) { + final QuestEventDuel qc = new QuestEventDuel(); + qc.setName(deck.getName()); + qc.setTitle(deck.getName()); + qc.setDifficulty(QuestEventDifficulty.WILD); + qc.setDescription("Wild opponent"); + qc.setIconImageKey(ImageKeys.ICON_PREFIX + WILD_DEFAULT_ICON_NAME); + qc.setEventDeck(deck); + + return qc; + } + + @Override + protected FilenameFilter getFileFilter() { + return DeckStorage.DCK_FILE_FILTER; + } + +} diff --git a/forge-gui/src/main/java/forge/quest/io/QuestDuelReader.java b/forge-gui/src/main/java/forge/quest/io/QuestDuelReader.java index 71bd23ace72..808df3e1616 100644 --- a/forge-gui/src/main/java/forge/quest/io/QuestDuelReader.java +++ b/forge-gui/src/main/java/forge/quest/io/QuestDuelReader.java @@ -35,7 +35,7 @@ public class QuestDuelReader extends StorageReaderFolder { qc.setCardReward(sectionMeta.get("Card Reward")); qc.setIconImageKey(ImageKeys.ICON_PREFIX + sectionMeta.get("Icon")); if (sectionMeta.contains("Profile")) { - qc.setProfile(sectionMeta.get("Profile")); + qc.setProfile(sectionMeta.get("Profile")); } // Deck diff --git a/forge-gui/src/main/java/forge/util/ImageFetcher.java b/forge-gui/src/main/java/forge/util/ImageFetcher.java index d255e1ba004..08fd46aef34 100644 --- a/forge-gui/src/main/java/forge/util/ImageFetcher.java +++ b/forge-gui/src/main/java/forge/util/ImageFetcher.java @@ -63,6 +63,11 @@ public abstract class ImageFetcher { final String filename = ImageUtil.getImageKey(paperCard, backFace, true); destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR + "/" + filename + ".jpg"); + //move priority of ftp image here + StringBuilder setDownload = new StringBuilder(ForgeConstants.URL_PIC_DOWNLOAD); + setDownload.append(ImageUtil.getDownloadUrl(paperCard, backFace)); + downloadUrls.add(setDownload.toString()); + int artIndex = 1; final Pattern pattern = Pattern.compile("^.:([^|]*\\|){2}(\\d+).*$"); Matcher matcher = pattern.matcher(imageKey); @@ -89,10 +94,6 @@ public abstract class ImageFetcher { editionMciCode, cardNum, suffix, langCode)); } - StringBuilder setDownload = new StringBuilder(ForgeConstants.URL_PIC_DOWNLOAD); - setDownload.append(ImageUtil.getDownloadUrl(paperCard, backFace)); - downloadUrls.add(setDownload.toString()); - } else if (prefix.equals(ImageKeys.TOKEN_PREFIX)) { if (tokenImages == null) { tokenImages = new HashMap<>();