diff --git a/forge-ai/pom.xml b/forge-ai/pom.xml index 999ab0f07ce..b3b53fc120f 100644 --- a/forge-ai/pom.xml +++ b/forge-ai/pom.xml @@ -6,7 +6,7 @@ forge forge - 1.6.16-SNAPSHOT + 1.6.18-SNAPSHOT forge-ai @@ -30,30 +30,4 @@ - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.0.0 - - - checkstyle-validation - validate - - ../checkstyle.xml - true - UTF-8 - true - true - true - - - check - - - - - - diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 2c761044964..2314c4867bb 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -38,6 +38,7 @@ import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.ability.SpellApiBased; import forge.game.card.*; +import forge.game.card.CardPredicates.Accessors; import forge.game.card.CardPredicates.Presets; import forge.game.combat.Combat; import forge.game.combat.CombatUtil; @@ -422,7 +423,8 @@ public class AiController { } } } - return true; + + return player.canPlayLand(c); } }); return landList; @@ -1174,7 +1176,7 @@ public class AiController { if (landsWannaPlay != null) { landsWannaPlay = filterLandsToPlay(landsWannaPlay); Log.debug("Computer " + game.getPhaseHandler().getPhase().nameForUi); - if (landsWannaPlay != null && !landsWannaPlay.isEmpty() && player.canPlayLand(null)) { + if (landsWannaPlay != null && !landsWannaPlay.isEmpty()) { // TODO search for other land it might want to play? Card land = chooseBestLandToPlay(landsWannaPlay); if (ComputerUtil.getDamageFromETB(player, land) < player.getLife() || !player.canLoseLife() @@ -1483,23 +1485,25 @@ public class AiController { boolean hasLeyline1 = false; SpellAbility saGemstones = null; - - for(int i = 0; i < result.size(); i++) { - SpellAbility sa = result.get(i); - + + List toRemove = Lists.newArrayList(); + for(SpellAbility sa : result) { String srcName = sa.getHostCard().getName(); if ("Gemstone Caverns".equals(srcName)) { if (saGemstones == null) saGemstones = sa; else - result.remove(i--); + toRemove.add(sa); } else if ("Leyline of Singularity".equals(srcName)) { if (!hasLeyline1) hasLeyline1 = true; else - result.remove(i--); + toRemove.add(sa); } } + for(SpellAbility sa : toRemove) { + result.remove(sa); + } // Play them last if (saGemstones != null) { @@ -1801,6 +1805,12 @@ public class AiController { return left.contains(ComputerUtilCard.getBestCreatureAI(all)); } } + if ("Aminatou".equals(sa.getParam("AILogic")) && game.getPlayers().size() > 2) { + CardCollection all = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.NONLAND_PERMANENTS); + CardCollection left = CardLists.filterControlledBy(all, game.getNextPlayerAfter(player, Direction.Left)); + CardCollection right = CardLists.filterControlledBy(all, game.getNextPlayerAfter(player, Direction.Right)); + return Aggregates.sum(left, Accessors.fnGetCmc) > Aggregates.sum(right, Accessors.fnGetCmc); + } return MyRandom.getRandom().nextBoolean(); } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java index 98df78bf24a..02ffc322634 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java @@ -913,6 +913,10 @@ public class ComputerUtilMana { // Make mana needed to avoid negative effect a mandatory cost for the AI for (String manaPart : card.getSVar("ManaNeededToAvoidNegativeEffect").split(",")) { // convert long color strings to short color strings + if (manaPart.isEmpty()) { + continue; + } + byte mask = ManaAtom.fromName(manaPart); // make mana mandatory for AI diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index e230c7bd04c..9edb07ce59c 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -26,6 +26,7 @@ import forge.game.card.CardPredicates.Presets; import forge.game.combat.Combat; import forge.game.cost.*; import forge.game.mana.Mana; +import forge.game.mana.ManaConversionMatrix; import forge.game.mana.ManaCostBeingPaid; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; @@ -921,7 +922,7 @@ public class PlayerControllerAi extends PlayerController { } @Override - public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt /* ai needs hints as well */, boolean isActivatedSa) { + public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt /* ai needs hints as well */, ManaConversionMatrix matrix, boolean isActivatedSa) { // TODO Auto-generated method stub ManaCostBeingPaid cost = isActivatedSa ? ComputerUtilMana.calculateManaCost(sa, false, 0) : new ManaCostBeingPaid(toPay); return ComputerUtilMana.payManaCost(cost, sa, player); diff --git a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java index d5b9473a39e..611161a59fb 100644 --- a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java @@ -79,12 +79,14 @@ public enum SpellApiToAi { .put(ApiType.FlipACoin, FlipACoinAi.class) .put(ApiType.Fog, FogAi.class) .put(ApiType.GainControl, ControlGainAi.class) + .put(ApiType.GainControlVariant, AlwaysPlayAi.class) .put(ApiType.GainLife, LifeGainAi.class) .put(ApiType.GainOwnership, CannotPlayAi.class) .put(ApiType.GameDrawn, CannotPlayAi.class) .put(ApiType.GenericChoice, ChooseGenericEffectAi.class) .put(ApiType.Goad, GoadAi.class) .put(ApiType.Haunt, HauntAi.class) + .put(ApiType.ImmediateTrigger, AlwaysPlayAi.class) .put(ApiType.LoseLife, LifeLoseAi.class) .put(ApiType.LosesGame, GameLossAi.class) .put(ApiType.Mana, ManaEffectAi.class) diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseDirectionAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseDirectionAi.java index 8e5f756af3c..3480f561d70 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseDirectionAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseDirectionAi.java @@ -1,8 +1,16 @@ package forge.ai.ability; import forge.ai.SpellAbilityAi; +import forge.game.Direction; +import forge.game.Game; +import forge.game.card.CardCollection; +import forge.game.card.CardLists; +import forge.game.card.CardPredicates; +import forge.game.card.CardPredicates.Presets; import forge.game.player.Player; import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; +import forge.util.Aggregates; public class ChooseDirectionAi extends SpellAbilityAi { @@ -12,10 +20,23 @@ public class ChooseDirectionAi extends SpellAbilityAi { @Override protected boolean canPlayAI(Player ai, SpellAbility sa) { final String logic = sa.getParam("AILogic"); + final Game game = sa.getActivatingPlayer().getGame(); if (logic == null) { return false; } else { - // TODO: default ai + if ("Aminatou".equals(logic)) { + CardCollection all = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.NONLAND_PERMANENTS); + CardCollection aiPermanent = CardLists.filterControlledBy(all, ai); + aiPermanent.remove(sa.getHostCard()); + int aiValue = Aggregates.sum(aiPermanent, CardPredicates.Accessors.fnGetCmc); + CardCollection left = CardLists.filterControlledBy(all, game.getNextPlayerAfter(ai, Direction.Left)); + CardCollection right = CardLists.filterControlledBy(all, game.getNextPlayerAfter(ai, Direction.Right)); + int leftValue = Aggregates.sum(left, CardPredicates.Accessors.fnGetCmc); + int rightValue = Aggregates.sum(right, CardPredicates.Accessors.fnGetCmc); + if (aiValue > leftValue || aiValue > rightValue) { + return false; + } + } } return true; } diff --git a/forge-core/pom.xml b/forge-core/pom.xml index 75670239273..33171490943 100644 --- a/forge-core/pom.xml +++ b/forge-core/pom.xml @@ -6,7 +6,7 @@ forge forge - 1.6.16-SNAPSHOT + 1.6.18-SNAPSHOT forge-core @@ -25,30 +25,4 @@ - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.0.0 - - - checkstyle-validation - validate - - ../checkstyle.xml - true - UTF-8 - true - true - true - - - check - - - - - - diff --git a/forge-core/src/main/java/forge/card/CardRules.java b/forge-core/src/main/java/forge/card/CardRules.java index f96411d4dc7..93f6e3e5f78 100644 --- a/forge-core/src/main/java/forge/card/CardRules.java +++ b/forge-core/src/main/java/forge/card/CardRules.java @@ -453,8 +453,6 @@ public final class CardRules implements ICardCharacteristics { this.removedFromRandomDecks = "True".equalsIgnoreCase(value); } else if ( "Picture".equals(variable) ) { this.pictureUrl[this.curFace] = value; - } else if ( "Rarity".equals(variable) ) { - // discard that, they should supply it in SetInfo } else this.faces[curFace].addSVar(variable, value); } else if ("SetInfo".equals(key)) { diff --git a/forge-core/src/main/java/forge/card/CardType.java b/forge-core/src/main/java/forge/card/CardType.java index e3713cf1f1b..ebc12e29266 100644 --- a/forge-core/src/main/java/forge/card/CardType.java +++ b/forge-core/src/main/java/forge/card/CardType.java @@ -188,6 +188,21 @@ public final class CardType implements Comparable, CardTypeView { return supertypes.remove(st); } + public boolean remove(final String str) { + boolean changed = false; + if (CardType.isASupertype(str) && supertypes.remove(stringToSupertype.get(str))) { + changed = true; + } else if (CardType.isACardType(str) && coreTypes.remove(stringToCoreType.get(str))) { + changed = true; + } else if (subtypes.remove(str)) { + changed = true; + } + if (changed) { + calculatedType = null; + } + return changed; + } + public boolean setCreatureTypes(Collection ctypes) { // if it isn't a creature then this has no effect if (!isCreature() && !isTribal()) { diff --git a/forge-core/src/main/java/forge/card/MagicColor.java b/forge-core/src/main/java/forge/card/MagicColor.java index bc452e19520..37e6294a056 100644 --- a/forge-core/src/main/java/forge/card/MagicColor.java +++ b/forge-core/src/main/java/forge/card/MagicColor.java @@ -103,15 +103,6 @@ public final class MagicColor { } } - public static int getIndexOfFirstColor(final byte color){ - for (int i = 0; i < NUMBER_OR_COLORS; i++) { - if ((color & WUBRG[i]) != 0) { - return i; - } - } - return -1; // colorless - } - /** * The Interface Color. */ diff --git a/forge-core/src/main/java/forge/card/mana/ManaAtom.java b/forge-core/src/main/java/forge/card/mana/ManaAtom.java index 1416139cda5..5a38b3a3310 100644 --- a/forge-core/src/main/java/forge/card/mana/ManaAtom.java +++ b/forge-core/src/main/java/forge/card/mana/ManaAtom.java @@ -14,6 +14,9 @@ public abstract class ManaAtom { public static final byte[] MANACOLORS = new byte[] { WHITE, BLUE, BLACK, RED, GREEN }; public static final byte[] MANATYPES = new byte[] { WHITE, BLUE, BLACK, RED, GREEN, COLORLESS }; + public static final byte ALL_MANA_COLORS = WHITE | BLUE | BLACK | RED | GREEN; + public static final byte ALL_MANA_TYPES = ALL_MANA_COLORS | COLORLESS; + public static final int GENERIC = 1 << 6; // Below here skip due to byte conversion shenanigans @@ -62,6 +65,6 @@ public abstract class ManaAtom { return i; } } - return -1; // colorless + return -1; // somehow the mana is not colored or colorless? } } \ No newline at end of file diff --git a/forge-core/src/main/java/forge/deck/DeckFormat.java b/forge-core/src/main/java/forge/deck/DeckFormat.java index 131b4360e42..23ffa77fbe5 100644 --- a/forge-core/src/main/java/forge/deck/DeckFormat.java +++ b/forge-core/src/main/java/forge/deck/DeckFormat.java @@ -473,6 +473,10 @@ public enum DeckFormat { if (paperCardPoolFilter != null) { for (final Entry cp : deck.getAllCardsInASinglePool()) { if (!paperCardPoolFilter.apply(cp.getKey())) { + System.err.println( + "Excluding deck: '" + deck.toString() + + "' Reason: '" + cp.getKey() + "' is not legal." + ); return false; } } diff --git a/forge-core/src/main/java/forge/item/generation/ChaosBoosterSupplier.java b/forge-core/src/main/java/forge/item/generation/ChaosBoosterSupplier.java new file mode 100644 index 00000000000..a6dc60d6d83 --- /dev/null +++ b/forge-core/src/main/java/forge/item/generation/ChaosBoosterSupplier.java @@ -0,0 +1,26 @@ +package forge.item.generation; + +import forge.card.CardEdition; +import forge.item.BoosterPack; +import forge.item.PaperCard; + +import java.util.List; + +public class ChaosBoosterSupplier implements IUnOpenedProduct { + private List sets; + + public ChaosBoosterSupplier(List sets) { + this.sets = sets; + } + + @Override + public List get() { + if (sets.size() == 0) { + System.out.println("No chaos boosters left to supply."); + return null; + } + final CardEdition set = sets.remove(0); + final BoosterPack pack = new BoosterPack(set.getCode(), set.getBoosterTemplate()); + return pack.getCards(); + } +} diff --git a/forge-game/pom.xml b/forge-game/pom.xml index 363022a7855..c9659499c2d 100644 --- a/forge-game/pom.xml +++ b/forge-game/pom.xml @@ -6,7 +6,7 @@ forge forge - 1.6.16-SNAPSHOT + 1.6.18-SNAPSHOT forge-game @@ -37,30 +37,4 @@ - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.0.0 - - - checkstyle-validation - validate - - ../checkstyle.xml - true - UTF-8 - true - true - true - - - check - - - - - - diff --git a/forge-game/src/main/java/forge/game/CardTraitBase.java b/forge-game/src/main/java/forge/game/CardTraitBase.java index b59c994a80c..aacc1d389e1 100644 --- a/forge-game/src/main/java/forge/game/CardTraitBase.java +++ b/forge-game/src/main/java/forge/game/CardTraitBase.java @@ -46,6 +46,11 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView { protected Map sVars = Maps.newHashMap(); + protected Map intrinsicChangedTextColors = Maps.newHashMap(); + protected Map intrinsicChangedTextTypes = Maps.newHashMap(); + protected Map changedTextColors = Maps.newHashMap(); + protected Map changedTextTypes = Maps.newHashMap(); + /** Keys of descriptive (text) parameters. */ private static final ImmutableList descriptiveKeys = ImmutableList.builder() .add("Description", "SpellDescription", "StackDescription", "TriggerDescription").build(); @@ -53,6 +58,11 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView { private static final ImmutableList mutableKeys = ImmutableList.builder() .add("AddAbility").build(); + /** + * Keys that should not changed + */ + private static final ImmutableList noChangeKeys = ImmutableList.builder() + .add("TokenScript", "LegacyImage", "TokenImage", "NewName").build(); /** * Sets the temporary. * @@ -449,9 +459,15 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView { } public void changeText() { + // copy changed text words into card trait there + this.changedTextColors = getHostCard().getChangedTextColorWords(); + this.changedTextTypes = getHostCard().getChangedTextTypeWords(); + for (final String key : this.mapParams.keySet()) { final String value = this.originalMapParams.get(key), newValue; - if (descriptiveKeys.contains(key)) { + if (noChangeKeys.contains(key)) { + continue; + } else if (descriptiveKeys.contains(key)) { // change descriptions differently newValue = AbilityUtils.applyDescriptionTextChangeEffects(value, this); } else if (mutableKeys.contains(key)) { @@ -515,4 +531,53 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView { public Set getSVars() { return sVars.keySet(); } + + public Map getChangedTextColors() { + return _combineChangedMap(intrinsicChangedTextColors, changedTextColors); + } + public Map getChangedTextTypes() { + return _combineChangedMap(intrinsicChangedTextTypes, changedTextTypes); + } + + private Map _combineChangedMap(Map input, Map output) { + // no need to do something, just return hash + if (input.isEmpty()) { + return output; + } + if (output.isEmpty()) { + return input; + } + // magic combine them + Map result = Maps.newHashMap(output); + for (Map.Entry e : input.entrySet()) { + String value = e.getValue(); + result.put(e.getKey(), output.containsKey(value) ? output.get(value) : value); + } + return result; + } + + public void changeTextIntrinsic(Map colorMap, Map typeMap) { + intrinsicChangedTextColors = colorMap; + intrinsicChangedTextTypes = typeMap; + for (final String key : this.mapParams.keySet()) { + final String value = this.originalMapParams.get(key), newValue; + if (noChangeKeys.contains(key)) { + continue; + } else if (descriptiveKeys.contains(key)) { + // change descriptions differently + newValue = AbilityUtils.applyTextChangeEffects(value, true, colorMap, typeMap); + }else if (this.getHostCard().hasSVar(value)) { + // don't change literal SVar names! + continue; + } else { + newValue = AbilityUtils.applyTextChangeEffects(value, false, colorMap, typeMap); + } + + if (newValue != null) { + this.mapParams.put(key, newValue); + } + } + // this does overwrite the original MapParams + this.originalMapParams = Maps.newHashMap(this.mapParams); + } } diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 2741c83f892..076aa493db5 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -428,6 +428,7 @@ public class GameAction { if (!c.isToken() && !toBattlefield) { copied.clearDevoured(); copied.clearDelved(); + copied.clearConvoked(); } // rule 504.6: reveal a face-down card leaving the stack @@ -785,7 +786,9 @@ public class GameAction { game.getReplacementHandler().cleanUpTemporaryReplacements(); for (final Player p : game.getPlayers()) { - p.getManaPool().restoreColorReplacements(); + if (!game.getStack().isFrozen()) { + p.getManaPool().restoreColorReplacements(); + } p.clearStaticAbilities(); } @@ -798,16 +801,18 @@ public class GameAction { public boolean visit(final Card c) { // need to get Card from preList if able final Card co = preList.get(c); - for (int i = 0; i < co.getStaticAbilities().size(); i++) { - final StaticAbility stAb = co.getStaticAbilities().get(i); + List toRemove = Lists.newArrayList(); + for (StaticAbility stAb : co.getStaticAbilities()) { if (stAb.getMapParams().get("Mode").equals("Continuous")) { staticAbilities.add(stAb); } if (stAb.isTemporary()) { - co.removeStaticAbility(stAb); - i--; + toRemove.add(stAb); } } + for (StaticAbility stAb : toRemove) { + co.removeStaticAbility(stAb); + } if (!co.getStaticCommandList().isEmpty()) { staticList.add(co); } @@ -851,8 +856,8 @@ public class GameAction { } for (final Card c : staticList) { - for (int i = 0; i < c.getStaticCommandList().size(); i++) { - final Object[] staticCheck = c.getStaticCommandList().get(i); + List toRemove = Lists.newArrayList(); + for (Object[] staticCheck : c.getStaticCommandList()) { final String leftVar = (String) staticCheck[0]; final String rightVar = (String) staticCheck[1]; final Card affected = (Card) staticCheck[2]; @@ -863,11 +868,13 @@ public class GameAction { final int operandValue = AbilityUtils.calculateAmount(c, svarOperand, null); if (Expressions.compare(sVar, svarOperator, operandValue)) { ((GameCommand) staticCheck[3]).run(); - c.getStaticCommandList().remove(i); - i--; + toRemove.add(staticCheck); affectedCards.add(c); } } + for (Object[] staticCheck : c.getStaticCommandList()) { + c.getStaticCommandList().remove(staticCheck); + } } // Exclude cards in hidden zones from update Iterator it = affectedCards.iterator(); 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 3401a5d6a80..7f5be63dfd4 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -18,6 +18,7 @@ import forge.game.ability.AbilityFactory.AbilityRecordType; import forge.game.card.*; import forge.game.cost.Cost; import forge.game.keyword.KeywordInterface; +import forge.game.mana.ManaConversionMatrix; import forge.game.mana.ManaCostBeingPaid; import forge.game.player.Player; import forge.game.player.PlayerCollection; @@ -1642,7 +1643,7 @@ public class AbilityUtils { return CardFactoryUtil.xCount(c, s2); } - public static final void applyManaColorConversion(final Player p, final Map params) { + public static final void applyManaColorConversion(ManaConversionMatrix matrix, final Map params) { String conversionType = params.get("ManaColorConversion"); // Choices are Additives(OR) or Restrictive(AND) @@ -1655,14 +1656,15 @@ public class AbilityUtils { String convertTo = params.get(key); byte convertByte = 0; if ("All".equals(convertTo)) { - convertByte = ColorSet.ALL_COLORS.getColor(); + // IMPORTANT! We need to use Mana Color here not Card Color. + convertByte = ManaAtom.ALL_MANA_TYPES; } else { for (final String convertColor : convertTo.split(",")) { convertByte |= ManaAtom.fromName(convertColor); } } // AdjustColorReplacement has two different matrices handling final mana conversion under the covers - p.getManaPool().adjustColorReplacement(ManaAtom.fromName(c), convertByte, additive); + matrix.adjustColorReplacement(ManaAtom.fromName(c), convertByte, additive); } } } @@ -1724,12 +1726,18 @@ public class AbilityUtils { } private static final String applyTextChangeEffects(final String def, final Card card, final boolean isDescriptive) { + return applyTextChangeEffects(def, isDescriptive, + card.getChangedTextColorWords(), card.getChangedTextTypeWords()); + } + + public static final String applyTextChangeEffects(final String def, final boolean isDescriptive, + Map colorMap, Map typeMap) { if (StringUtils.isEmpty(def)) { return def; } String replaced = def; - for (final Entry e : card.getChangedTextColorWords().entrySet()) { + for (final Entry e : colorMap.entrySet()) { final String key = e.getKey(); String value; if (key.equals("Any")) { @@ -1750,7 +1758,7 @@ public class AbilityUtils { replaced = replaced.replaceAll("(?)" + key, value); } } - for (final Entry e : card.getChangedTextTypeWords().entrySet()) { + for (final Entry e : typeMap.entrySet()) { final String key = e.getKey(); final String pkey = CardType.getPluralType(key); final String pvalue = getReplacedText(pkey, CardType.getPluralType(e.getValue()), isDescriptive); diff --git a/forge-game/src/main/java/forge/game/ability/ApiType.java b/forge-game/src/main/java/forge/game/ability/ApiType.java index a5d9572fde2..650fd003de5 100644 --- a/forge-game/src/main/java/forge/game/ability/ApiType.java +++ b/forge-game/src/main/java/forge/game/ability/ApiType.java @@ -76,6 +76,7 @@ public enum ApiType { FlipACoin (FlipCoinEffect.class), Fog (FogEffect.class), GainControl (ControlGainEffect.class), + GainControlVariant (ControlGainVariantEffect.class), GainLife (LifeGainEffect.class), GainOwnership (OwnershipGainEffect.class), GameDrawn (GameDrawEffect.class), 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 749b72a277e..0c0d1be8836 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 @@ -892,9 +892,11 @@ public class ChangeZoneEffect extends SpellAbilityEffect { do { selectedCards = decider.getController().chooseCardsForZoneChange(destination, origin, sa, fetchList, delayedReveal, selectPrompt, decider); } while (selectedCards != null && selectedCards.size() > changeNum); - for (Card card : selectedCards) { - chosenCards.add(card); - }; + if (selectedCards != null) { + for (Card card : selectedCards) { + chosenCards.add(card); + } + } // maybe prompt the user if they selected fewer than the maximum possible? } else { // one at a time diff --git a/forge-game/src/main/java/forge/game/ability/effects/CloneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CloneEffect.java index aa0ab0f4215..0dccc07d374 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CloneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CloneEffect.java @@ -113,6 +113,7 @@ public class CloneEffect extends SpellAbilityEffect { } final boolean keepName = sa.hasParam("KeepName"); + final String newName = sa.getParamOrDefault("NewName", null); final String originalName = tgtCard.getName(); final boolean copyingSelf = (tgtCard == cardToCopy); final boolean isTransformed = cardToCopy.getCurrentStateName() == CardStateName.Transformed || cardToCopy.getCurrentStateName() == CardStateName.Meld; @@ -157,9 +158,13 @@ public class CloneEffect extends SpellAbilityEffect { } // restore name if it should be unchanged + // this should only be used for Sakashima the Impostor Avatar if (keepName) { tgtCard.setName(originalName); } + if (newName != null) { + tgtCard.setName(newName); + } // If target is a flip card, also set characteristics of the flipped // state. @@ -168,6 +173,9 @@ public class CloneEffect extends SpellAbilityEffect { if (keepName) { flippedState.setName(originalName); } + if (newName != null) { + tgtCard.setName(newName); + } //keep the Clone card image for the cloned card flippedState.setImageKey(imageFileName); } @@ -350,6 +358,18 @@ public class CloneEffect extends SpellAbilityEffect { tgtCard.setBasePower(4); tgtCard.setBaseToughness(4); } + + if (sa.hasParam("GainThisAbility")) { + SpellAbility root = sa.getRootAbility(); + + if (root.isTrigger() && root.getTrigger() != null) { + tgtCard.addTrigger(root.getTrigger().copy(tgtCard, false)); + } else if (root.isReplacementAbility()) { + tgtCard.addReplacementEffect(root.getReplacementEffect().copy(tgtCard, false)); + } else { + tgtCard.addSpellAbility(root.copy(tgtCard, false)); + } + } } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java index 556a2157fa1..83ed95b96b8 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java @@ -143,24 +143,31 @@ public class ControlGainEffect extends SpellAbilityEffect { } if (lose != null) { + final GameCommand loseControl = getLoseControlCommand(tgtC, tStamp, bTapOnLose, source, kws); if (lose.contains("LeavesPlay")) { - sa.getHostCard().addLeavesPlayCommand(getLoseControlCommand(tgtC, tStamp, bTapOnLose, source, kws)); + sa.getHostCard().addLeavesPlayCommand(loseControl); } if (lose.contains("Untap")) { - sa.getHostCard().addUntapCommand(getLoseControlCommand(tgtC, tStamp, bTapOnLose, source, kws)); + sa.getHostCard().addUntapCommand(loseControl); } if (lose.contains("LoseControl")) { - sa.getHostCard().addChangeControllerCommand(getLoseControlCommand(tgtC, tStamp, bTapOnLose, source, kws)); + sa.getHostCard().addChangeControllerCommand(loseControl); } if (lose.contains("EOT")) { - game.getEndOfTurn().addUntil(getLoseControlCommand(tgtC, tStamp, bTapOnLose, source, kws)); + game.getEndOfTurn().addUntil(loseControl); tgtC.setSVar("SacMe", "6"); } if (lose.contains("StaticCommandCheck")) { String leftVar = sa.getSVar(sa.getParam("StaticCommandCheckSVar")); String rightVar = sa.getParam("StaticCommandSVarCompare"); - sa.getHostCard().addStaticCommandList(new Object[]{leftVar, rightVar, tgtC, - getLoseControlCommand(tgtC, tStamp, bTapOnLose, source, kws)}); + sa.getHostCard().addStaticCommandList(new Object[]{leftVar, rightVar, tgtC, loseControl}); + } + if (lose.contains("UntilTheEndOfYourNextTurn")) { + if (game.getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer())) { + game.getEndOfTurn().registerUntilEnd(sa.getActivatingPlayer(), loseControl); + } else { + game.getEndOfTurn().addUntilEnd(sa.getActivatingPlayer(), loseControl); + } } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ControlGainVariantEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ControlGainVariantEffect.java new file mode 100644 index 00000000000..44c2deddebe --- /dev/null +++ b/forge-game/src/main/java/forge/game/ability/effects/ControlGainVariantEffect.java @@ -0,0 +1,49 @@ +package forge.game.ability.effects; + +import forge.game.Game; +import forge.game.ability.SpellAbilityEffect; +import forge.game.card.Card; +import forge.game.card.CardCollection; +import forge.game.card.CardLists; +import forge.game.player.Player; +import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; + +public class ControlGainVariantEffect extends SpellAbilityEffect { + /* (non-Javadoc) + * @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility) + */ + @Override + protected String getStackDescription(SpellAbility sa) { + return sa.getDescription(); + } + + @Override + public void resolve(SpellAbility sa) { + // Aminatou, the Fateshifter (multiple players gain control of multiple permanents in an effect) + // Consider migrating cards with similar effects + // GainControl embedded in RepeatEach effects don't work well with timestamps + final Card source = sa.getHostCard(); + final Game game = source.getGame(); + + CardCollection tgtCards = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), + sa.getParam("AllValid"), source.getController(), source); + + if ("NextPlayerInChosenDirection".equals(sa.getParam("ChangeController")) && (source.getChosenDirection() != null) ) { + long tStamp = game.getNextTimestamp(); + for (final Player p : game.getPlayers()) { + + CardCollection valid = CardLists.filterControlledBy(tgtCards, game.getNextPlayerAfter(p, source.getChosenDirection())); + + for (Card tgtC : valid) { + if (!tgtC.isInPlay() || !tgtC.canBeControlledBy(p)) { + continue; + } + tgtC.setController(p, tStamp); + tgtCards.remove(tgtC); // remove from the list if controller is changed + } + } + } + } + +} diff --git a/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java index 116b5aae57b..26ca842301d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java @@ -8,6 +8,7 @@ import forge.game.GameEntity; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; +import forge.game.card.CardCollection; import forge.game.card.CardFactory; import forge.game.card.CardLists; import forge.game.player.Player; @@ -123,7 +124,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { } } else {// Precursor Golem, Ink-Treader Nephilim final String type = sa.getParam("CopyForEachCanTarget"); - List valid = Lists.newArrayList(); + CardCollection valid = new CardCollection(); List players = Lists.newArrayList(); Player originalTargetPlayer = Iterables.getFirst(getTargetPlayers(chosenSA), null); for (final GameEntity o : candidates) { @@ -142,10 +143,17 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { Card originalTarget = Iterables.getFirst(getTargetCards(chosenSA), null); valid.remove(originalTarget); mayChooseNewTargets = false; - for (final Card c : valid) { + if (sa.hasParam("ChooseOnlyOne")) { + Card choice = controller.getController().chooseSingleEntityForEffect(valid, sa, "Choose one"); SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true); - resetFirstTargetOnCopy(copy, c, targetedSA); + resetFirstTargetOnCopy(copy, choice, targetedSA); copies.add(copy); + } else { + for (final Card c : valid) { + SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true); + resetFirstTargetOnCopy(copy, c, targetedSA); + copies.add(copy); + } } for (final Player p : players) { SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true); @@ -159,7 +167,20 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { "Select a spell to copy", ImmutableMap.of()); chosenSA.setActivatingPlayer(controller); for (int i = 0; i < amount; i++) { - copies.add(CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true)); + SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost( + card, chosenSA.getHostCard(), chosenSA, true); + + // extra case for Epic to remove the keyword and the last part of the SpellAbility + if (sa.hasParam("Epic")) { + copy.getHostCard().removeIntrinsicKeyword("Epic"); + SpellAbility sub = copy; + while (sub.getSubAbility() != null) { + sub = sub.getSubAbility(); + } + sub.getParent().setSubAbility(null); + } + + copies.add(copy); } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java index 365adf0855a..efa91cea1d2 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java @@ -286,7 +286,7 @@ public class DigEffect extends SpellAbilityEffect { } } - if (!changeValid.isEmpty() && !sa.hasParam("ExileFaceDown")) { + if (!changeValid.isEmpty() && !sa.hasParam("ExileFaceDown") && !sa.hasParam("NoReveal")) { game.getAction().reveal(movedCards, chooser, true, chooser + " picked " + (movedCards.size() == 1 ? "this card" : "these cards") + " from "); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/DigUntilEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DigUntilEffect.java index 5615f70b2de..46935002a90 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DigUntilEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DigUntilEffect.java @@ -105,6 +105,7 @@ public class DigUntilEffect extends SpellAbilityEffect { final ZoneType digSite = sa.hasParam("DigZone") ? ZoneType.smartValueOf(sa.getParam("DigZone")) : ZoneType.Library; boolean shuffle = sa.hasParam("Shuffle"); final boolean optional = sa.hasParam("Optional"); + final boolean optionalFound = sa.hasParam("OptionalFoundMove"); for (final Player p : getTargetPlayers(sa)) { if (p == null) { @@ -156,15 +157,20 @@ public class DigUntilEffect extends SpellAbilityEffect { final Iterator itr = found.iterator(); while (itr.hasNext()) { final Card c = itr.next(); - if (sa.hasParam("GainControl") && foundDest.equals(ZoneType.Battlefield)) { - c.setController(sa.getActivatingPlayer(), game.getNextTimestamp()); - game.getAction().moveTo(c.getController().getZone(foundDest), c, sa); - } else if (sa.hasParam("NoMoveFound") && foundDest.equals(ZoneType.Library)) { - //Don't do anything + if (optionalFound && !p.getController().confirmAction(sa, null, + "Do you want to put that card to " + foundDest.name() + "?")) { + continue; } else { - game.getAction().moveTo(foundDest, c, foundLibPos, sa); + if (sa.hasParam("GainControl") && foundDest.equals(ZoneType.Battlefield)) { + c.setController(sa.getActivatingPlayer(), game.getNextTimestamp()); + game.getAction().moveTo(c.getController().getZone(foundDest), c, sa); + } else if (sa.hasParam("NoMoveFound") && foundDest.equals(ZoneType.Library)) { + //Don't do anything + } else { + game.getAction().moveTo(foundDest, c, foundLibPos, sa); + } + revealed.remove(c); } - revealed.remove(c); } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java index e6c9e781eb3..bffeb0cda1e 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java @@ -264,6 +264,13 @@ public class EffectEffect extends SpellAbilityEffect { else if (duration.equals("UntilEndOfCombat")) { game.getEndOfCombat().addUntil(endEffect); } + else if (duration.equals("UntilTheEndOfYourNextTurn")) { + if (game.getPhaseHandler().isPlayerTurn(controller)) { + game.getEndOfTurn().registerUntilEnd(controller, endEffect); + } else { + game.getEndOfTurn().addUntilEnd(controller, endEffect); + } + } else if (duration.equals("ThisTurnAndNextTurn")) { game.getUntap().addAt(new GameCommand() { private static final long serialVersionUID = -5054153666503075717L; diff --git a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java index 5a1b9970375..7c598f302f0 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java @@ -121,7 +121,7 @@ public class ManaEffect extends SpellAbilityEffect { mask |= MagicColor.fromName(colorsNeeded.charAt(nChar)); } colorMenu = mask == 0 ? ColorSet.ALL_COLORS : ColorSet.fromMask(mask); - byte val = act.getController().chooseColor("Select Mana to Produce", sa, colorMenu); + byte val = p.getController().chooseColor("Select Mana to Produce", sa, colorMenu); if (0 == val) { throw new RuntimeException("ManaEffect::resolve() /*any mana*/ - " + act + " color mana choice is empty for " + card.getName()); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/SurveilEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SurveilEffect.java index 740ce564b33..f93f1765383 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SurveilEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SurveilEffect.java @@ -18,7 +18,7 @@ public class SurveilEffect extends SpellAbilityEffect { num = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Amount"), sa); } - sb.append(" surveil (").append(num).append(")."); + sb.append(" surveils (").append(num).append(")."); return sb.toString(); } 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 6fc7ffde41c..1a9ed880a56 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -98,7 +98,7 @@ public class Card extends GameEntity implements Comparable { private final KeywordCollection hiddenExtrinsicKeyword = new KeywordCollection(); // cards attached or otherwise linked to this card - private CardCollection equippedBy, fortifiedBy, hauntedBy, devouredCards, delvedCards, imprintedCards, encodedCards; + private CardCollection equippedBy, fortifiedBy, hauntedBy, devouredCards, delvedCards, convokedCards, imprintedCards, encodedCards; private CardCollection mustBlockCards, clones, gainControlTargets, chosenCards, blockedThisTurn, blockedByThisTurn; // if this card is attached or linked to something, what card is it currently attached to @@ -725,6 +725,20 @@ public class Card extends GameEntity implements Comparable { delvedCards = null; } + + public final CardCollectionView getConvoked() { + return CardCollection.getView(convokedCards); + } + public final void addConvoked(final Card c) { + if (convokedCards == null) { + convokedCards = new CardCollection(); + } + convokedCards.add(c); + } + public final void clearConvoked() { + convokedCards = null; + } + public MapOfLists getRememberMap() { return rememberMap; } @@ -3640,6 +3654,12 @@ public class Card extends GameEntity implements Comparable { } } + public final void removeIntrinsicKeyword(final KeywordInterface s) { + if (currentState.removeIntrinsicKeyword(s)) { + currentState.getView().updateKeywords(this, currentState); + } + } + public Collection getExtrinsicKeyword() { return extrinsicKeyword.getValues(); } diff --git a/forge-game/src/main/java/forge/game/card/CardChangedWords.java b/forge-game/src/main/java/forge/game/card/CardChangedWords.java index d62f15dde32..ae8719dee69 100644 --- a/forge-game/src/main/java/forge/game/card/CardChangedWords.java +++ b/forge-game/src/main/java/forge/game/card/CardChangedWords.java @@ -7,8 +7,6 @@ import java.util.SortedMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; -import forge.card.CardType; - public final class CardChangedWords { private final SortedMap map = Maps.newTreeMap(); @@ -68,14 +66,9 @@ public final class CardChangedWords { // the actual change (b->c) resultCache.put(ccw.getOriginalWord(), ccw.getNewWord()); - - // possible plural form - final String singular = CardType.getPluralType(ccw.getOriginalWord()); - if (!singular.equals(ccw.getOriginalWord())) { - resultCache.put(singular, ccw.getNewWord()); - } } + // TODO should that be removed? for (final String key : ImmutableList.copyOf(resultCache.keySet())) { if (!key.equals("Any")) { resultCache.put(key.toLowerCase(), resultCache.get(key).toLowerCase()); 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 452f49d69ea..acbefc4d72d 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -842,7 +842,11 @@ public class CardFactoryUtil { // only used by Opal Palace, and it does add the trigger to the card return doXMath(cc.getCommanderCast(c), m, c); } - + + if (l[0].startsWith("TotalCommanderCastFromCommandZone")) { + return doXMath(cc.getTotalCommanderCast(), m, c); + } + if (l[0].startsWith("MostProminentCreatureType")) { String restriction = l[0].split(" ")[1]; CardCollection list = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), restriction, cc, c); @@ -2010,18 +2014,6 @@ public class CardFactoryUtil { inst.createTraits(card, true); } - // AddCost - if (card.hasSVar("FullCost")) { - String k[] = card.getSVar("FullCost").split(":"); - final SpellAbility sa1 = card.getFirstSpellAbility(); - if (sa1 != null && sa1.isSpell()) { - sa1.setPayCosts(new Cost(k[0], sa1.isAbility())); - if (k.length > 1) { - sa1.getMapParams().put("AILogic", k[1]); - } - } - } - // AltCost String altCost = card.getSVar("AltCost"); if (StringUtils.isNotBlank(altCost)) { @@ -2030,7 +2022,6 @@ public class CardFactoryUtil { card.addSpellAbility(makeAltCostAbility(card, altCost, sa1)); } } - } private static ReplacementEffect createETBReplacement(final Card card, ReplacementLayer layer, @@ -3755,14 +3746,14 @@ public class CardFactoryUtil { // Epic does modify existing SA, and does not add new one // Add the Epic effect as a subAbility - String dbStr = "DB$ Effect | Triggers$ EpicTrigger | SVars$ EpicCopy | StaticAbilities$ EpicCantBeCast | Duration$ Permanent | Unique$ True"; + String dbStr = "DB$ Effect | Triggers$ EpicTrigger | SVars$ EpicCopy | StaticAbilities$ EpicCantBeCast | Duration$ Permanent"; final AbilitySub newSA = (AbilitySub) AbilityFactory.getAbility(dbStr.toString(), card); card.setSVar("EpicCantBeCast", "Mode$ CantBeCast | ValidCard$ Card | Caster$ You | EffectZone$ Command | Description$ For the rest of the game, you can't cast spells."); card.setSVar("EpicTrigger", "Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ EpicCopy | TriggerDescription$ " + "At the beginning of each of your upkeeps, copy " + card.toString() + " except for its epic ability."); - card.setSVar("EpicCopy", "DB$ CopySpellAbility | Defined$ EffectSource"); + card.setSVar("EpicCopy", "DB$ CopySpellAbility | Defined$ EffectSource | Epic$ True"); final SpellAbility origSA = card.getFirstSpellAbility(); diff --git a/forge-game/src/main/java/forge/game/card/CardProperty.java b/forge-game/src/main/java/forge/game/card/CardProperty.java index dcd3c6d0658..d2be541192c 100644 --- a/forge-game/src/main/java/forge/game/card/CardProperty.java +++ b/forge-game/src/main/java/forge/game/card/CardProperty.java @@ -1280,7 +1280,12 @@ public class CardProperty { FCollectionView p = AbilityUtils.getDefinedPlayers(source, property.split("ControlledBy")[1], null); cards = CardLists.filterControlledBy(cards, p); } - cards = CardLists.getType(cards, prop); + + if ("NonLandPermanent".equals(prop)) { + cards = CardLists.filter(cards, CardPredicates.Presets.NONLAND_PERMANENTS); + } else { + cards = CardLists.getType(cards, prop); + } cards = CardLists.getCardsWithHighestCMC(cards); if (!cards.contains(card)) { return false; @@ -1373,6 +1378,10 @@ public class CardProperty { if (!source.getDelved().contains(card)) { return false; } + } else if (property.startsWith("convoked")) { + if (!source.getConvoked().contains(card)) { + return false; + } } else if (property.startsWith("unequalPT")) { if (card.getNetPower() == card.getNetToughness()) { return false; 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 483077cae84..5372ddfa18e 100644 --- a/forge-game/src/main/java/forge/game/card/CardState.java +++ b/forge-game/src/main/java/forge/game/card/CardState.java @@ -231,6 +231,9 @@ public class CardState extends GameObject { public final boolean removeIntrinsicKeyword(final String s) { return intrinsicKeywords.remove(s); } + public final boolean removeIntrinsicKeyword(final KeywordInterface s) { + return intrinsicKeywords.remove(s); + } public final FCollectionView getSpellAbilities() { FCollection newCol = new FCollection(manaAbilities); @@ -539,7 +542,7 @@ public class CardState extends GameObject { intrinsicKeywords.insert(inst); } } - + public void updateChangedText() { final List allAbs = ImmutableList.builder() .addAll(manaAbilities) @@ -554,4 +557,19 @@ public class CardState extends GameObject { } } } + + public void changeTextIntrinsic(Map colorMap, Map typeMap) { + final List allAbs = ImmutableList.builder() + .addAll(manaAbilities) + .addAll(nonManaAbilities) + .addAll(triggers) + .addAll(replacementEffects) + .addAll(staticAbilities) + .build(); + for (final CardTraitBase ctb : allAbs) { + if (ctb.isIntrinsic()) { + ctb.changeTextIntrinsic(colorMap, typeMap); + } + } + } } 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 0f959f598d5..8db0b965455 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -281,6 +281,8 @@ public final class CardUtil { newCopy.setChangedCardKeywords(in.getChangedCardKeywords()); newCopy.setChangedCardTypes(in.getChangedCardTypesMap()); + newCopy.copyChangedTextFrom(in); + newCopy.setMeldedWith(in.getMeldedWith()); newCopy.setTimestamp(in.getTimestamp()); diff --git a/forge-game/src/main/java/forge/game/card/token/TokenInfo.java b/forge-game/src/main/java/forge/game/card/token/TokenInfo.java index d54b7b4256f..86f319baf80 100644 --- a/forge-game/src/main/java/forge/game/card/token/TokenInfo.java +++ b/forge-game/src/main/java/forge/game/card/token/TokenInfo.java @@ -12,6 +12,7 @@ import forge.game.Game; import forge.game.card.Card; import forge.game.card.CardFactory; import forge.game.card.CardFactoryUtil; +import forge.game.card.CardUtil; import forge.game.keyword.KeywordInterface; import forge.game.player.Player; import forge.game.spellability.SpellAbility; @@ -20,6 +21,8 @@ import forge.item.PaperToken; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.StringUtils; + public class TokenInfo { final String name; final String imageName; @@ -229,10 +232,121 @@ public class TokenInfo { String edition = host.getSetCode(); PaperToken token = StaticData.instance().getAllTokens().getToken(script, edition); - // TODO add Card Text Change from SpellAbility - if (token != null) { - return Card.fromPaperCard(token, null, game); + final Card result = Card.fromPaperCard(token, null, game); + + // update Token with CardTextChanges + Map colorMap = sa.getChangedTextColors(); + Map typeMap = sa.getChangedTextTypes(); + if (!colorMap.isEmpty()) { + if (!result.isColorless()) { + // change Token Colors + byte color = CardUtil.getColors(result).getColor(); + + for (final Map.Entry e : colorMap.entrySet()) { + byte v = MagicColor.fromName(e.getValue()); + // Any used by Swirl the Mists + if ("Any".equals(e.getKey())) { + for (final byte c : MagicColor.WUBRG) { + // try to replace color flips + if ((color & c) != 0) { + color &= ~c; + color |= v; + } + } + } else { + byte c = MagicColor.fromName(e.getKey()); + // try to replace color flips + if ((color & c) != 0) { + color &= ~c; + color |= v; + } + } + } + + result.setColor(color); + } + } + if (!typeMap.isEmpty()) { + String oldName = result.getName(); + + CardType type = new CardType(result.getType()); + String joinedName = StringUtils.join(type.getSubtypes(), " "); + final boolean nameGenerated = oldName.equals(joinedName); + boolean typeChanged = false; + + if (!Iterables.isEmpty(type.getSubtypes())) { + for (final Map.Entry e : typeMap.entrySet()) { + if (type.hasSubtype(e.getKey())) { + type.remove(e.getKey()); + type.add(e.getValue()); + typeChanged = true; + } + } + } + + if (typeChanged) { + result.setType(type); + + // update generated Name + if (nameGenerated) { + result.setName(StringUtils.join(type.getSubtypes(), " ")); + } + } + } + + // replace Intrinsic Keyword + List toRemove = Lists.newArrayList(); + List toAdd = Lists.newArrayList(); + for (final KeywordInterface k : result.getCurrentState().getIntrinsicKeywords()) { + final String o = k.getOriginal(); + // only Modifiable should go there + if (!CardUtil.isKeywordModifiable(o)) { + continue; + } + String r = new String(o); + // replace types + for (final Map.Entry e : typeMap.entrySet()) { + final String key = e.getKey(); + final String pkey = CardType.getPluralType(key); + final String value = e.getValue(); + final String pvalue = CardType.getPluralType(e.getValue()); + r = r.replaceAll(pkey, pvalue); + r = r.replaceAll(key, value); + } + // replace color words + for (final Map.Entry e : colorMap.entrySet()) { + final String vName = e.getValue(); + final String vCaps = StringUtils.capitalize(vName); + final String vLow = vName.toLowerCase(); + if ("Any".equals(e.getKey())) { + for (final byte c : MagicColor.WUBRG) { + final String cName = MagicColor.toLongString(c); + final String cNameCaps = StringUtils.capitalize(cName); + final String cNameLow = cName.toLowerCase(); + r = r.replaceAll(cNameCaps, vCaps); + r = r.replaceAll(cNameLow, vLow); + } + } else { + final String cName = e.getKey(); + final String cNameCaps = StringUtils.capitalize(cName); + final String cNameLow = cName.toLowerCase(); + r = r.replaceAll(cNameCaps, vCaps); + r = r.replaceAll(cNameLow, vLow); + } + } + if (!r.equals(o)) { + toRemove.add(k); + toAdd.add(r); + } + } + for (final KeywordInterface k : toRemove) { + result.getCurrentState().removeIntrinsicKeyword(k); + } + result.addIntrinsicKeywords(toAdd); + + result.getCurrentState().changeTextIntrinsic(colorMap, typeMap); + return result; } return null; diff --git a/forge-game/src/main/java/forge/game/combat/Combat.java b/forge-game/src/main/java/forge/game/combat/Combat.java index fb9c095306b..7bb0f1bda06 100644 --- a/forge-game/src/main/java/forge/game/combat/Combat.java +++ b/forge-game/src/main/java/forge/game/combat/Combat.java @@ -613,23 +613,36 @@ public class Combat { } // Call this method right after turn-based action of declare blockers has been performed - public final void fireTriggersForUnblockedAttackers() { + public final void fireTriggersForUnblockedAttackers(final Game game) { + boolean bFlag = false; + List defenders = Lists.newArrayList(); for (AttackingBand ab : attackedByBands.values()) { Collection blockers = blockedBands.get(ab); boolean isBlocked = blockers != null && !blockers.isEmpty(); ab.setBlocked(isBlocked); if (!isBlocked) { + bFlag = true; + defenders.add(getDefenderByAttacker(ab)); for (Card attacker : ab.getAttackers()) { // Run Unblocked Trigger final Map runParams = Maps.newHashMap(); runParams.put("Attacker", attacker); runParams.put("Defender",getDefenderByAttacker(attacker)); runParams.put("DefendingPlayer", getDefenderPlayerByAttacker(attacker)); - attacker.getGame().getTriggerHandler().runTrigger(TriggerType.AttackerUnblocked, runParams, false); + game.getTriggerHandler().runTrigger(TriggerType.AttackerUnblocked, runParams, false); } } } + if (bFlag) { + // triggers for Coveted Jewel + // currently there is only one attacking player + // should be updated when two-headed-giant is done + final Map runParams = Maps.newHashMap(); + runParams.put("AttackingPlayer", getAttackingPlayer()); + runParams.put("Defenders", defenders); + game.getTriggerHandler().runTrigger(TriggerType.AttackerUnblockedOnce, runParams, false); + } } private final boolean assignBlockersDamage(boolean firstStrikeDamage) { diff --git a/forge-game/src/main/java/forge/game/cost/CostAdjustment.java b/forge-game/src/main/java/forge/game/cost/CostAdjustment.java index 70d6c91083d..1ad50114869 100644 --- a/forge-game/src/main/java/forge/game/cost/CostAdjustment.java +++ b/forge-game/src/main/java/forge/game/cost/CostAdjustment.java @@ -237,6 +237,7 @@ public class CostAdjustment { } } if (sa.getHostCard().hasKeyword(Keyword.CONVOKE)) { + sa.getHostCard().clearConvoked(); adjustCostByConvokeOrImprovise(cost, sa, false, test); } if (sa.getHostCard().hasKeyword(Keyword.IMPROVISE)) { @@ -270,6 +271,9 @@ public class CostAdjustment { cost.decreaseShard(conv.getValue(), 1); if (!test) { conv.getKey().tap(); + if (!improvise) { + sa.getHostCard().addConvoked(conv.getKey()); + } } } } @@ -499,15 +503,6 @@ public class CostAdjustment { if (!sa.isSpell() || !((Spell) sa).isCastFaceDown()) { return false; } - } else if (type.equals("SelfMonstrosity")) { - if (!(sa instanceof AbilityActivated) || !sa.hasParam("Monstrosity") || sa.isTemporary()) { - // Nemesis of Mortals - return false; - } - } else if (type.equals("SelfIntrinsicAbility")) { - if (!(sa instanceof AbilityActivated) || sa.isReplacementAbility() || sa.isTemporary()) { - return false; - } } } if (params.containsKey("AffectedZone")) { diff --git a/forge-game/src/main/java/forge/game/cost/CostPartMana.java b/forge-game/src/main/java/forge/game/cost/CostPartMana.java index 81d94a288e2..32f1ae41f7b 100644 --- a/forge-game/src/main/java/forge/game/cost/CostPartMana.java +++ b/forge-game/src/main/java/forge/game/cost/CostPartMana.java @@ -19,6 +19,7 @@ package forge.game.cost; import forge.card.mana.ManaCost; import forge.card.mana.ManaCostShard; +import forge.game.mana.ManaConversionMatrix; import forge.game.player.Player; import forge.game.spellability.SpellAbility; @@ -37,6 +38,9 @@ public class CostPartMana extends CostPart { private boolean isEnchantedCreatureCost = false; private final String restriction; + private ManaConversionMatrix cardMatrix = null; + public void setCardMatrix(ManaConversionMatrix mtrx) { cardMatrix = mtrx; } + public int paymentOrder() { return shouldPayLast() ? 200 : 0; } public boolean shouldPayLast() { @@ -148,7 +152,7 @@ public class CostPartMana extends CostPart { sa.clearManaPaid(); // decision not used here, the whole payment is interactive! - return payer.getController().payManaCost(this, sa, null, true); + return payer.getController().payManaCost(this, sa, null, cardMatrix, true); } } diff --git a/forge-game/src/main/java/forge/game/cost/CostPayment.java b/forge-game/src/main/java/forge/game/cost/CostPayment.java index 9785a12a49b..ca002861212 100644 --- a/forge-game/src/main/java/forge/game/cost/CostPayment.java +++ b/forge-game/src/main/java/forge/game/cost/CostPayment.java @@ -21,6 +21,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import forge.game.Game; import forge.game.card.Card; +import forge.game.mana.ManaConversionMatrix; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; @@ -35,7 +36,7 @@ import java.util.Map; * @author Forge * @version $Id$ */ -public class CostPayment { +public class CostPayment extends ManaConversionMatrix { private final Cost cost; private Cost adjustedCost; private final SpellAbility ability; @@ -70,6 +71,7 @@ public class CostPayment { this.cost = cost; this.adjustedCost = cost; this.ability = abil; + restoreColorReplacements(); } /** @@ -137,6 +139,11 @@ public class CostPayment { PaymentDecision pd = part.accept(decisionMaker); + // RIght before we start paying as decided, we need to transfer the CostPayments matrix over? + if (part instanceof CostPartMana) { + ((CostPartMana)part).setCardMatrix(this); + } + if (pd == null || !part.payAsDecided(decisionMaker.getPlayer(), pd, ability)) { game.costPaymentStack.pop(); // cost is resolved return false; diff --git a/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java b/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java index f00b65cf76d..98623cf6d72 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java @@ -96,6 +96,10 @@ public class KeywordCollection implements Iterable, Serializable { return result; } + public boolean remove(KeywordInterface keyword) { + return map.remove(keyword.getKeyword(), keyword); + } + public boolean removeAll(Iterable keywords) { boolean result = false; for (String k : keywords) { diff --git a/forge-game/src/main/java/forge/game/mana/ManaConversionMatrix.java b/forge-game/src/main/java/forge/game/mana/ManaConversionMatrix.java new file mode 100644 index 00000000000..e8caf56d774 --- /dev/null +++ b/forge-game/src/main/java/forge/game/mana/ManaConversionMatrix.java @@ -0,0 +1,45 @@ +package forge.game.mana; + +import forge.card.mana.ManaAtom; + +public class ManaConversionMatrix { + static byte[] identityMatrix = { ManaAtom.WHITE, ManaAtom.BLUE, ManaAtom.BLACK, ManaAtom.RED, ManaAtom.GREEN, ManaAtom.COLORLESS }; + + // Conversion matrix ORs byte values to make mana more payable + // Restrictive matrix ANDs byte values to make mana less payable + byte[] colorConversionMatrix = new byte[ManaAtom.MANATYPES.length]; + byte[] colorRestrictionMatrix = new byte[ManaAtom.MANATYPES.length]; + + public void adjustColorReplacement(byte originalColor, byte replacementColor, boolean additive) { + // Fix the index without hardcodes + int rowIdx = ManaAtom.getIndexOfFirstManaType(originalColor); + rowIdx = rowIdx < 0 ? identityMatrix.length - 1 : rowIdx; + if (additive) { + colorConversionMatrix[rowIdx] |= replacementColor; + } + else { + colorRestrictionMatrix[rowIdx] &= replacementColor; + } + } + + public void applyCardMatrix(ManaConversionMatrix extraMatrix) { + for (int i = 0; i < colorConversionMatrix.length; i++) { + colorConversionMatrix[i] |= extraMatrix.colorConversionMatrix[i]; + } + + for (int i = 0; i < colorRestrictionMatrix.length; i++) { + colorRestrictionMatrix[i] &= extraMatrix.colorRestrictionMatrix[i]; + } + } + + public void restoreColorReplacements() { + // By default each color can only be paid by itself ( {G} -> {G}, {C} -> {C} + for (int i = 0; i < colorConversionMatrix.length; i++) { + colorConversionMatrix[i] = identityMatrix[i]; + } + // By default all mana types are unrestricted + for (int i = 0; i < colorRestrictionMatrix.length; i++) { + colorRestrictionMatrix[i] = ManaAtom.ALL_MANA_TYPES; + } + } +} \ No newline at end of file diff --git a/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java b/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java index f1f43259799..f5c381fb9ca 100644 --- a/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java +++ b/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java @@ -586,6 +586,7 @@ public class ManaCostBeingPaid { // Boolean addX used to add Xs into the returned value final StringBuilder sb = new StringBuilder(); + // TODO Prepend a line about paying with any type/color if available if (addX) { for (int i = 0; i < this.getXcounter(); i++) { sb.append("{X}"); @@ -595,10 +596,11 @@ public class ManaCostBeingPaid { int nGeneric = getGenericManaAmount(); List shards = new ArrayList(unpaidShards.keySet()); - if (pool != null) { //replace shards with generic mana if they can be paid with any color mana + // TODO Fix this. Should we really be changing Shards here? + if (false && pool != null) { //replace shards with generic mana if they can be paid with any color mana for (int i = 0; i < shards.size(); i++) { ManaCostShard shard = shards.get(i); - if (shard != ManaCostShard.GENERIC && pool.getPossibleColorUses(shard.getColorMask()) == MagicColor.ALL_COLORS) { + if (shard != ManaCostShard.GENERIC && pool.getPossibleColorUses(shard.getColorMask()) == ManaAtom.ALL_MANA_TYPES) { nGeneric += unpaidShards.get(shard).totalCount; shards.remove(i); i--; diff --git a/forge-game/src/main/java/forge/game/mana/ManaPool.java b/forge-game/src/main/java/forge/game/mana/ManaPool.java index 2d2de63d968..de59a57ef21 100644 --- a/forge-game/src/main/java/forge/game/mana/ManaPool.java +++ b/forge-game/src/main/java/forge/game/mana/ManaPool.java @@ -20,9 +20,7 @@ package forge.game.mana; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; - import forge.GameCommand; -import forge.card.ColorSet; import forge.card.MagicColor; import forge.card.mana.ManaAtom; import forge.card.mana.ManaCostShard; @@ -37,14 +35,9 @@ import forge.game.player.Player; import forge.game.spellability.AbilityManaPart; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; - import org.apache.commons.lang3.StringUtils; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; +import java.util.*; /** *

@@ -54,7 +47,7 @@ import java.util.List; * @author Forge * @version $Id$ */ -public class ManaPool implements Iterable { +public class ManaPool extends ManaConversionMatrix implements Iterable { private final Player owner; private final Multimap floatingMana = ArrayListMultimap.create(); @@ -355,37 +348,10 @@ public class ManaPool implements Iterable { Player p = sa.getActivatingPlayer(); p.getGame().fireEvent(new GameEventZone(ZoneType.Battlefield, p, EventValueChangeType.ComplexUpdate, null)); } - - // Conversion matrix ORs byte values to make mana more payable - // Restrictive matrix ANDs byte values to make mana less payable - private final byte[] colorConversionMatrix = new byte[ManaAtom.MANATYPES.length]; - private final byte[] colorRestrictionMatrix = new byte[ManaAtom.MANATYPES.length]; - private static final byte[] identityMatrix = { ManaAtom.WHITE, ManaAtom.BLUE, ManaAtom.BLACK, ManaAtom.RED, ManaAtom.GREEN, ManaAtom.COLORLESS }; - - public void adjustColorReplacement(byte originalColor, byte replacementColor, boolean additive) { - // Fix the index without hardcodes - int rowIdx = MagicColor.getIndexOfFirstColor(originalColor); - rowIdx = rowIdx < 0 ? identityMatrix.length - 1 : rowIdx; - if (additive) { - colorConversionMatrix[rowIdx] |= replacementColor; - } - else { - colorRestrictionMatrix[rowIdx] &= replacementColor; - } - } - - public void restoreColorReplacements() { - for (int i = 0; i < colorConversionMatrix.length; i++) { - colorConversionMatrix[i] = identityMatrix[i]; - } - for (int i = 0; i < colorRestrictionMatrix.length; i++) { - colorRestrictionMatrix[i] = ColorSet.ALL_COLORS.getColor(); - } - } public byte getPossibleColorUses(byte color) { // Take the current conversion value, AND with restrictions to get mana usage - int rowIdx = MagicColor.getIndexOfFirstColor(color); + int rowIdx = ManaAtom.getIndexOfFirstManaType(color); int matrixIdx = rowIdx < 0 ? identityMatrix.length - 1 : rowIdx; byte colorUse = colorConversionMatrix[matrixIdx]; @@ -394,14 +360,16 @@ public class ManaPool implements Iterable { } public boolean canPayForShardWithColor(ManaCostShard shard, byte color) { + // TODO Debug this for Paying Gonti, byte line = getPossibleColorUses(color); - for (int i = 0; i < MagicColor.NUMBER_OR_COLORS; i++) { - byte outColor = MagicColor.WUBRG[i]; + + for(byte outColor : ManaAtom.MANATYPES) { if ((line & outColor) != 0 && shard.canBePaidWithManaOfColor(outColor)) { return true; } } + // TODO The following may not be needed anymore? if (((color & (byte) ManaAtom.COLORLESS) != 0) && shard.canBePaidWithManaOfColor((byte) (byte)ManaAtom.COLORLESS)) { return true; } 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 3fbde336028..ba10cde1a85 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java @@ -372,6 +372,8 @@ public class PhaseHandler implements java.io.Serializable { game.getEndOfCombat().executeUntil(); //Repeat here in case Time Stop et. al. ends combat early game.getEndOfTurn().executeUntil(); + game.getEndOfTurn().executeUntilEndOfPhase(playerTurn); + game.getEndOfTurn().registerUntilEndCommand(playerTurn); for (Player player : game.getPlayers()) { player.onCleanupPhase(); @@ -664,7 +666,7 @@ public class PhaseHandler implements java.io.Serializable { combat.removeAbsentCombatants(); - combat.fireTriggersForUnblockedAttackers(); + combat.fireTriggersForUnblockedAttackers(game); final List declaredBlockers = combat.getAllBlockers(); if (!declaredBlockers.isEmpty()) { 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 f3e15e1d872..e4e5bfe45ce 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -1751,6 +1751,9 @@ public class Player extends GameEntity implements Comparable { return canPlayLand(land, false); } public final boolean canPlayLand(final Card land, final boolean ignoreZoneAndTiming) { + return canPlayLand(land, ignoreZoneAndTiming, null); + } + public final boolean canPlayLand(final Card land, final boolean ignoreZoneAndTiming, SpellAbility landSa) { if (!ignoreZoneAndTiming && !canCastSorcery()) { return false; } @@ -1766,7 +1769,7 @@ public class Player extends GameEntity implements Comparable { } if (land != null && !ignoreZoneAndTiming) { - final boolean mayPlay = !land.mayPlay(this).isEmpty(); + final boolean mayPlay = landSa == null ? !land.mayPlay(this).isEmpty() : landSa.getMayPlay() != null; if (land.getOwner() != this && !mayPlay) { return false; } @@ -2662,6 +2665,14 @@ public class Player extends GameEntity implements Comparable { commanderCast.put(commander, getCommanderCast(commander) + 1); } + public int getTotalCommanderCast() { + int result = 0; + for (Integer i : commanderCast.values()) { + result += i; + } + return result; + } + public boolean isPlayingExtraTurn() { return isPlayingExtraTrun; } 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 adc6bd77754..f603e7656e4 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -20,6 +20,7 @@ import forge.game.cost.Cost; import forge.game.cost.CostPart; import forge.game.cost.CostPartMana; import forge.game.mana.Mana; +import forge.game.mana.ManaConversionMatrix; import forge.game.replacement.ReplacementEffect; import forge.game.spellability.*; import forge.game.trigger.WrappedAbility; @@ -220,9 +221,13 @@ public abstract class PlayerController { public abstract void resetAtEndOfTurn(); // currently used by the AI to perform card memory cleanup public final boolean payManaCost(CostPartMana costPartMana, SpellAbility sa, String prompt, boolean isActivatedAbility) { - return payManaCost(costPartMana.getManaCostFor(sa), costPartMana, sa, prompt, isActivatedAbility); + return payManaCost(costPartMana, sa, prompt, null, isActivatedAbility); } - public abstract boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt, boolean isActivatedAbility); + + public final boolean payManaCost(CostPartMana costPartMana, SpellAbility sa, String prompt, ManaConversionMatrix matrix, boolean isActivatedAbility) { + return payManaCost(costPartMana.getManaCostFor(sa), costPartMana, sa, prompt, matrix, isActivatedAbility); + } + public abstract boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt, ManaConversionMatrix matrix, boolean isActivatedAbility); public abstract Map chooseCardsForConvokeOrImprovise(SpellAbility sa, ManaCost manaCost, CardCollectionView untappedCards, boolean improvise); diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java index c47dd86d932..f08e0b660a7 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java @@ -181,7 +181,7 @@ public class ReplacementHandler { final String effectAbString = host.getSVar(effectSVar); // TODO: the source of replacement effect should be the source of the original effect effectSA = AbilityFactory.getAbility(effectAbString, host); - effectSA.setTrigger(true); + //effectSA.setTrigger(true); SpellAbility tailend = effectSA; do { @@ -209,8 +209,9 @@ public class ReplacementHandler { if (replacementEffect.isIntrinsic()) { effectSA.setIntrinsic(true); effectSA.changeText(); - effectSA.setReplacementAbility(true); } + effectSA.setReplacementAbility(true); + effectSA.setReplacementEffect(replacementEffect); } // Decider gets to choose whether or not to apply the replacement. @@ -309,13 +310,15 @@ public class ReplacementHandler { game.forEachCardInGame(new Visitor() { @Override public boolean visit(Card c) { - for (int i = 0; i < c.getReplacementEffects().size(); i++) { - ReplacementEffect rep = c.getReplacementEffects().get(i); + List toRemove = Lists.newArrayList(); + for (ReplacementEffect rep : c.getReplacementEffects()) { if (rep.isTemporary()) { - c.removeReplacementEffect(rep); - i--; + toRemove.add(rep); } } + for (ReplacementEffect rep : toRemove) { + c.removeReplacementEffect(rep); + } return true; } }); diff --git a/forge-game/src/main/java/forge/game/spellability/LandAbility.java b/forge-game/src/main/java/forge/game/spellability/LandAbility.java index a524a7222a9..8b1ba1557ca 100644 --- a/forge-game/src/main/java/forge/game/spellability/LandAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/LandAbility.java @@ -17,13 +17,10 @@ */ package forge.game.spellability; -import forge.game.Game; import forge.game.card.Card; import forge.game.cost.Cost; import forge.game.player.Player; import forge.game.staticability.StaticAbility; -import forge.game.zone.Zone; -import forge.game.zone.ZoneType; public class LandAbility extends Ability { @@ -33,57 +30,14 @@ public class LandAbility extends Ability { setMayPlay(mayPlay); } public LandAbility(Card sourceCard) { - this(sourceCard, sourceCard.getController(), (StaticAbility)null); + this(sourceCard, sourceCard.getController(), null); } @Override public boolean canPlay() { final Card land = this.getHostCard(); final Player p = this.getActivatingPlayer(); - final Game game = p.getGame(); - if (!p.canCastSorcery()) { - return false; - } - // CantBeCast static abilities - for (final Card ca : game.getCardsIn(ZoneType.listValueOf("Battlefield,Command"))) { - final Iterable staticAbilities = ca.getStaticAbilities(); - for (final StaticAbility stAb : staticAbilities) { - if (stAb.applyAbility("CantPlayLand", land, this)) { - return false; - } - } - } - - if (land != null) { - final boolean mayPlay = getMayPlay() != null; - if (land.getOwner() != p && !mayPlay) { - return false; - } - - final Zone zone = game.getZoneOf(land); - if (zone != null && (zone.is(ZoneType.Battlefield) || (!zone.is(ZoneType.Hand) && !mayPlay))) { - return false; - } - } - - // **** Check for land play limit per turn **** - // Dev Mode - if (p.getController().canPlayUnlimitedLands() || p.hasKeyword("You may play any number of additional lands on each of your turns.")) { - return true; - } - - // check for adjusted max lands play per turn - int adjMax = 1; - for (String keyword : p.getKeywords()) { - if (keyword.startsWith("AdjustLandPlays")) { - final String[] k = keyword.split(":"); - adjMax += Integer.valueOf(k[1]); - } - } - if (p.getLandsPlayedThisTurn() < adjMax) { - return true; - } - return false; + return p.canPlayLand(land, false, this); } @Override public void resolve() { 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 afa679d269d..3e866b91fb1 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -38,7 +38,9 @@ import forge.game.cost.CostRemoveCounter; import forge.game.keyword.Keyword; import forge.game.mana.Mana; import forge.game.player.Player; +import forge.game.replacement.ReplacementEffect; import forge.game.staticability.StaticAbility; +import forge.game.trigger.Trigger; import forge.game.trigger.TriggerType; import forge.game.trigger.WrappedAbility; import forge.util.Expressions; @@ -87,8 +89,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit private boolean basicSpell = true; private boolean trigger = false; + private Trigger triggerObj = null; private boolean optionalTrigger = false; private boolean replacementAbility = false; + private ReplacementEffect replacementEffect = null; private int sourceTrigger = -1; private List triggerRemembered = Lists.newArrayList(); @@ -913,6 +917,14 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit trigger = trigger0; } + public Trigger getTrigger() { + return triggerObj; + } + + public void setTrigger(final Trigger t) { + triggerObj = t; + } + public boolean isOptionalTrigger() { return optionalTrigger; } @@ -934,6 +946,14 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit replacementAbility = replacement; } + public ReplacementEffect getReplacementEffect() { + return replacementEffect; + } + + public void setReplacementEffect(final ReplacementEffect re) { + this.replacementEffect = re; + } + public boolean isMandatory() { return false; } @@ -1709,6 +1729,31 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } } + /* (non-Javadoc) + * @see forge.game.CardTraitBase#changeTextIntrinsic(java.util.Map, java.util.Map) + */ + @Override + public void changeTextIntrinsic(Map colorMap, Map typeMap) { + super.changeTextIntrinsic(colorMap, typeMap); + + if (subAbility != null) { + // if the parent of the subability is not this, + // then there might be a loop + if (subAbility.getParent() == this) { + subAbility.changeTextIntrinsic(colorMap, typeMap); + } + } + for (AbilitySub sa : additionalAbilities.values()) { + sa.changeTextIntrinsic(colorMap, typeMap); + } + + for (List list : additionalAbilityLists.values()) { + for (AbilitySub sa : list) { + sa.changeTextIntrinsic(colorMap, typeMap); + } + } + } + @Override public void setIntrinsic(boolean i) { super.setIntrinsic(i); diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java index 49a95c13fa6..307d64d366a 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java @@ -160,6 +160,14 @@ public class StaticAbilityCantBeCast { return false; } + if (params.containsKey("Origin")) { + List src = ZoneType.listValueOf(params.get("Origin")); + + if (!src.contains(card.getZone().getZoneType())) { + return false; + } + } + if (params.containsKey("Player") && (player != null) && !player.isValid(params.get("Player"), hostCard.getController(), hostCard, null)) { return false; diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java index 30cf2ca1749..63e71ca52a1 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -41,7 +41,6 @@ import forge.game.trigger.Trigger; import forge.game.trigger.TriggerHandler; import forge.game.zone.ZoneType; import forge.util.TextUtil; - import org.apache.commons.lang3.StringUtils; import java.util.*; @@ -481,7 +480,7 @@ public final class StaticAbilityContinuous { } if (params.containsKey("ManaColorConversion")) { - AbilityUtils.applyManaColorConversion(p, params); + AbilityUtils.applyManaColorConversion(p.getManaPool(), params); } } } 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 8b39080b26f..fd97b6d6f9f 100644 --- a/forge-game/src/main/java/forge/game/trigger/Trigger.java +++ b/forge-game/src/main/java/forge/game/trigger/Trigger.java @@ -37,6 +37,7 @@ import java.util.*; import com.google.common.collect.Lists; import com.google.common.collect.Maps; + import forge.util.TextUtil; /** @@ -169,11 +170,7 @@ public abstract class Trigger extends TriggerReplacementBase { if (!desc.contains("ABILITY")) { return desc; } - SpellAbility sa = getOverridingAbility(); - if (sa == null && this.mapParams.containsKey("Execute")) { - sa = AbilityFactory.getAbility(state, this.mapParams.get("Execute")); - setOverridingAbility(sa); - } + SpellAbility sa = ensureAbility(); return replaceAbilityText(desc, sa); @@ -338,7 +335,22 @@ public abstract class Trigger extends TriggerReplacementBase { return false; } } - + + if (this.mapParams.containsKey("TriggerRememberedInZone")) { + // check delayed trigger remembered objects (Mnemonic Betrayal) + // make this check more general if possible + boolean bFlag = true; + for (Object o : getTriggerRemembered()) { + if (o instanceof Card && ((Card) o).isInZone(ZoneType.smartValueOf(this.mapParams.get("TriggerRememberedInZone")))) { + bFlag = false; + break; + } + } + if (bFlag) { + return false; + } + } + if ( !meetsCommonRequirements(this.mapParams)) return false; @@ -583,4 +595,48 @@ public abstract class Trigger extends TriggerReplacementBase { throw new RuntimeException("Trigger : clone() error, " + ex); } } + + + /* (non-Javadoc) + * @see forge.game.CardTraitBase#changeText() + */ + @Override + public void changeText() { + if (!isIntrinsic()) { + return; + } + super.changeText(); + + ensureAbility(); + + if (getOverridingAbility() != null) { + getOverridingAbility().changeText(); + } + } + + /* (non-Javadoc) + * @see forge.game.CardTraitBase#changeTextIntrinsic(java.util.Map, java.util.Map) + */ + @Override + public void changeTextIntrinsic(Map colorMap, Map typeMap) { + if (!isIntrinsic()) { + return; + } + super.changeTextIntrinsic(colorMap, typeMap); + + ensureAbility(); + + if (getOverridingAbility() != null) { + getOverridingAbility().changeTextIntrinsic(colorMap, typeMap); + } + } + + private SpellAbility ensureAbility() { + SpellAbility sa = getOverridingAbility(); + if (sa == null && hasParam("Execute")) { + sa = AbilityFactory.getAbility(getHostCard(), getParam("Execute")); + setOverridingAbility(sa); + } + return sa; + } } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerAttackerUnblockedOnce.java b/forge-game/src/main/java/forge/game/trigger/TriggerAttackerUnblockedOnce.java new file mode 100644 index 00000000000..66ed8f5c01b --- /dev/null +++ b/forge-game/src/main/java/forge/game/trigger/TriggerAttackerUnblockedOnce.java @@ -0,0 +1,98 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package forge.game.trigger; + +import forge.game.GameEntity; +import forge.game.card.Card; +import forge.game.spellability.SpellAbility; + +import java.util.List; +import java.util.Map; + +/** + *

+ * Trigger_AttackerUnblockedOnce class. + *

+ * + * @author Forge + * @version $Id$ + */ +public class TriggerAttackerUnblockedOnce extends Trigger { + + /** + *

+ * Constructor for Trigger_AttackerUnblocked. + *

+ * + * @param params + * a {@link java.util.HashMap} object. + * @param host + * a {@link forge.game.card.Card} object. + * @param intrinsic + * the intrinsic + */ + public TriggerAttackerUnblockedOnce(final java.util.Map params, final Card host, final boolean intrinsic) { + super(params, host, intrinsic); + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override + public final boolean performTest(final Map runParams2) { + if (hasParam("ValidDefenders")) { + boolean valid = false; + + final List srcs = (List) runParams2.get("Defenders"); + for (GameEntity c : srcs) { + if (c.isValid(this.mapParams.get("ValidDefenders").split(","), this.getHostCard().getController(), this.getHostCard(), null)) { + valid = true; + } + } + if (!valid) { + return false; + } + /* + if (hasParam("ValidAttackers")) { + // should be updated if a creature of a specific type attackes a defender + } + */ + } + if (hasParam("ValidAttackingPlayer")) { + if (!matchesValid(runParams2.get("AttackingPlayer"), + this.mapParams.get("ValidAttackingPlayer").split(","), this.getHostCard())) { + return false; + } + } + return true; + } + + /** {@inheritDoc} */ + @Override + public final void setTriggeringObjects(final SpellAbility sa) { + sa.setTriggeringObject("AttackingPlayer", this.getRunParams().get("AttackingPlayer")); + sa.setTriggeringObject("Defenders", this.getRunParams().get("Defenders")); + } + + @Override + public String getImportantStackObjects(SpellAbility sa) { + StringBuilder sb = new StringBuilder(); + sb.append("AttackingPlayer: ").append(sa.getTriggeringObject("AttackingPlayer")); + sb.append("Defenders: ").append(sa.getTriggeringObject("Defenders")); + return sb.toString(); + } +} diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java b/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java index cb098f9db61..cd6ceb7ceab 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java @@ -24,8 +24,10 @@ import java.util.Set; import com.google.common.collect.Sets; import forge.game.Game; +import forge.game.GameEntity; import forge.game.GameObject; import forge.game.card.Card; +import forge.game.card.CardCollection; import forge.game.card.CardLists; import forge.game.card.CardUtil; import forge.game.cost.Cost; @@ -158,6 +160,31 @@ public class TriggerSpellAbilityCast extends Trigger { } } + if (hasParam("CanTargetOtherCondition")) { + final CardCollection candidates = new CardCollection(); + SpellAbility targetedSA = spellAbility; + while (targetedSA != null) { + if (targetedSA.usesTargeting() && targetedSA.getTargets().getNumTargeted() != 0) { + break; + } + targetedSA = targetedSA.getSubAbility(); + } + if (targetedSA == null) { + return false; + } + final List candidateTargets = targetedSA.getTargetRestrictions().getAllCandidates(targetedSA, true); + for (GameEntity card : candidateTargets) { + if (card instanceof Card) { + candidates.add((Card) card); + } + } + candidates.removeAll(targetedSA.getTargets().getTargetCards()); + String valid = this.mapParams.get("CanTargetOtherCondition"); + if (CardLists.getValidCards(candidates, valid, spellAbility.getActivatingPlayer(), spellAbility.getHostCard()).isEmpty()) { + return false; + } + } + if (hasParam("NonTapCost")) { final Cost cost = (Cost) (runParams2.get("Cost")); if (cost.hasTapCost()) { @@ -241,6 +268,7 @@ public class TriggerSpellAbilityCast extends Trigger { sa.setTriggeringObject("Player", getRunParams().get("Player")); sa.setTriggeringObject("Activator", getRunParams().get("Activator")); sa.setTriggeringObject("CurrentStormCount", getRunParams().get("CurrentStormCount")); + sa.setTriggeringObject("CurrentCastSpells", getRunParams().get("CurrentCastSpells")); sa.setTriggeringObject("CastSACMC", getRunParams().get("CastSACMC")); } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerType.java b/forge-game/src/main/java/forge/game/trigger/TriggerType.java index ca2bb440d1e..f5119f70fd8 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerType.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerType.java @@ -20,6 +20,7 @@ public enum TriggerType { AttackerBlockedByCreature(TriggerAttackerBlockedByCreature.class), AttackersDeclared(TriggerAttackersDeclared.class), AttackerUnblocked(TriggerAttackerUnblocked.class), + AttackerUnblockedOnce(TriggerAttackerUnblockedOnce.class), Attacks(TriggerAttacks.class), BecomeMonarch(TriggerBecomeMonarch.class), BecomeMonstrous(TriggerBecomeMonstrous.class), diff --git a/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java b/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java index 927895756f3..b59580cd366 100644 --- a/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java +++ b/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java @@ -27,14 +27,13 @@ import com.google.common.collect.Lists; public class WrappedAbility extends Ability { private final SpellAbility sa; - private final Trigger regtrig; private final Player decider; boolean mandatory = false; public WrappedAbility(final Trigger regtrig0, final SpellAbility sa0, final Player decider0) { super(regtrig0.getHostCard(), ManaCost.ZERO, sa0.getView()); - regtrig = regtrig0; + setTrigger(regtrig0); sa = sa0; decider = decider0; sa.setDescription(this.getStackDescription()); @@ -49,10 +48,6 @@ public class WrappedAbility extends Ability { return true; } - public Trigger getTrigger() { - return regtrig; - } - public Player getDecider() { return decider; } @@ -218,6 +213,7 @@ public class WrappedAbility extends Ability { @Override public String getStackDescription() { + final Trigger regtrig = getTrigger(); final StringBuilder sb = new StringBuilder(regtrig.replaceAbilityText(regtrig.toString(true), this)); if (usesTargeting()) { sb.append(" (Targeting "); @@ -445,6 +441,7 @@ public class WrappedAbility extends Ability { @Override public void resolve() { final Game game = sa.getActivatingPlayer().getGame(); + final Trigger regtrig = getTrigger(); Map triggerParams = regtrig.getMapParams(); if (!(regtrig instanceof TriggerAlways) && !triggerParams.containsKey("NoResolvingCheck")) { @@ -476,6 +473,9 @@ public class WrappedAbility extends Ability { return; } + // set Trigger + sa.setTrigger(regtrig); + if (!triggerParams.containsKey("NoTimestampCheck")) { timestampCheck(); } 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 00c3536e15e..53e8e676291 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -42,6 +42,7 @@ import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.card.Card; +import forge.game.card.CardCollection; import forge.game.card.CardFactoryUtil; import forge.game.card.CardPredicates; import forge.game.cost.Cost; @@ -362,11 +363,13 @@ public class MagicStack /* extends MyObservable */ implements Iterable yyyyMMdd-HHmm jar - -Xms128m - -Xmx1024m - 1.6.15.003 + -Xms1024m + -Xmx1536m + 1.6.17.001 keystore alias storepass @@ -19,7 +19,7 @@ forge forge - 1.6.16-SNAPSHOT + 1.6.18-SNAPSHOT forge-gui-android @@ -36,28 +36,6 @@ 1.8 - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.0.0 - - - checkstyle-validation - validate - - ../checkstyle.xml - true - UTF-8 - true - true - true - - - check - - - - diff --git a/forge-gui-desktop/pom.xml b/forge-gui-desktop/pom.xml index 4b3fd81e123..6b78bad350c 100644 --- a/forge-gui-desktop/pom.xml +++ b/forge-gui-desktop/pom.xml @@ -1,795 +1,741 @@ - 4.0.0 + 4.0.0 forge forge - 1.6.16-SNAPSHOT + 1.6.18-SNAPSHOT - forge-gui-desktop - jar - Forge + forge-gui-desktop + jar + Forge - - - - com.google.code.maven-svn-revision-number-plugin - svn-revision-number-maven-plugin - - - - revision - - - - - false - - - forge - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - org.apache.ant - ant-nodeps - 1.8.1 - - - - - build-version-string - process-resources - - run - - - true - - - - - - - - - + + 0 + 0 + 0 + - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - - - true - true - - - ${fullversionstring} - - - - - - com.google.code.maven-replacer-plugin - replacer - 1.5.2 - - - package - - replace - - - - - ${basedir}/${configSourceDirectory} - forge.sh, forge.command - ${project.build.directory} - . - false - - - $project.build.finalName$ - ${project.build.finalName}-jar-with-dependencies.jar - - - - - - maven-assembly-plugin - - false - - jar-with-dependencies - - - - forge.view.Main - true - - - ${fullversionstring} - - - - - - make-assembly - - package - - - single - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.8 - - - released-version - validate - - released-version - - - - parse-version - - parse-version - - - - + + - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.0.0 - - - checkstyle-validation - validate - - ../checkstyle.xml - true - UTF-8 - true - true - true - - - check - - - - - - + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + true + true + + + + + + com.google.code.maven-replacer-plugin + replacer + 1.5.2 + + + package + + replace + + + + + ${basedir}/${configSourceDirectory} + forge.sh, forge.command + ${project.build.directory} + . + false + + + $project.build.finalName$ + ${project.build.finalName}-jar-with-dependencies.jar + + + + + + maven-assembly-plugin + + false + + jar-with-dependencies + + + + forge.view.Main + true + + + + + + make-assembly + + package + + + single + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.8 + + + released-version + validate + + released-version + + + + parse-version + + parse-version + + + + + + - - - forge - forge-core - ${project.version} - - - forge - forge-game - ${project.version} - - - forge - forge-ai - ${project.version} - - - forge - forge-gui - ${project.version} - - - com.miglayout - miglayout - 3.7.4 - - - com.mortennobel - java-image-scaling - 0.8.5 - - - com.google.guava - guava - 24.1-android - - - com.thoughtworks.xstream - xstream - 1.4.10 - - - org.testng - testng - 6.8.7 - test - - - org.powermock - powermock-module-testng - 1.5.4 - test - - - org.powermock - powermock-api-mockito - 1.5.4 - test - - - log4j - log4j - 1.2.17 - - - com.googlecode - minlog - 1.2 - - - org.apache.commons - commons-lang3 - 3.7 - - - org.freemarker - freemarker - 2.3.20 - - - com.googlecode.soundlibs - jlayer - 1.0.1-1 - - - com.beust - jcommander - 1.27 - jar - - + + + forge + forge-core + ${project.version} + + + forge + forge-game + ${project.version} + + + forge + forge-ai + ${project.version} + + + forge + forge-gui + ${project.version} + + + com.miglayout + miglayout + 3.7.4 + + + com.mortennobel + java-image-scaling + 0.8.5 + + + com.google.guava + guava + 24.1-android + + + com.thoughtworks.xstream + xstream + 1.4.10 + + + org.testng + testng + 6.8.7 + test + + + org.powermock + powermock-module-testng + 1.5.4 + test + + + org.powermock + powermock-api-mockito + 1.5.4 + test + + + log4j + log4j + 1.2.17 + + + com.googlecode + minlog + 1.2 + + + org.apache.commons + commons-lang3 + 3.7 + + + org.freemarker + freemarker + 2.3.20 + + + com.googlecode.soundlibs + jlayer + 1.0.1-1 + + + com.beust + jcommander + 1.27 + jar + + - - - windows-linux-release - - - - com.akathist.maven.plugins.launch4j - launch4j-maven-plugin - 1.5.2 - - - l4j-gui - package - - launch4j - - - gui - ${project.build.directory}/forge.exe - ${project.build.finalName}-jar-with-dependencies.jar - true - forge - src/main/config/forge.ico - - forge.view.Main - false - anything - - - 1.8.0 - 1024 - - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - Forge - Forge - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - Forge - forge - forge.exe - - - - - + + + windows-linux-release + + + + com.akathist.maven.plugins.launch4j + launch4j-maven-plugin + 1.5.2 + + + l4j-gui + package + + launch4j + + + gui + ${project.build.directory}/forge.exe + ${project.build.finalName}-jar-with-dependencies.jar + true + forge + src/main/config/forge.ico + + forge.view.Main + false + anything + + + 1.8.0 + 1024 + + + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + Forge + Forge + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + Forge + forge + forge.exe + + + + + - - org.apache.maven.plugins - maven-antrun-plugin - 1.7 - - - org.apache.ant - ant-nodeps - 1.8.1 - - - - - win-linux-app-bundle - pre-integration-test - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - run - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.8 - - - released-version - validate - - released-version - - - - parse-version - - parse-version - - - - attach-distribution - post-integration-test - - attach-artifact - - - - - ${project.build.directory}/${project.build.finalName}.tar.bz2 - tar.bz2 - - - - - - - - - + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + org.apache.ant + ant-nodeps + 1.8.1 + + + + + win-linux-app-bundle + pre-integration-test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.8 + + + released-version + validate + + released-version + + + + parse-version + + parse-version + + + + attach-distribution + post-integration-test + + attach-artifact + + + + + ${project.build.directory}/${project.build.finalName}.tar.bz2 + tar.bz2 + + + + + + + + + - - windows-linux - - - - com.akathist.maven.plugins.launch4j - launch4j-maven-plugin - 1.5.2 - - - l4j-gui - package - - launch4j - - - gui - ${project.build.directory}/forge.exe - ${project.build.finalName}-jar-with-dependencies.jar - true - forge - src/main/config/forge.ico - - forge.view.Main - false - anything - - - 1.8.0 - 1024 - - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - Forge - Forge - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - Forge - forge - forge.exe - - - - - + + windows-linux + + + + com.akathist.maven.plugins.launch4j + launch4j-maven-plugin + 1.5.2 + + + l4j-gui + package + + launch4j + + + gui + ${project.build.directory}/forge.exe + ${project.build.finalName}-jar-with-dependencies.jar + true + forge + src/main/config/forge.ico + + forge.view.Main + false + anything + + + 1.8.0 + 1024 + + + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + Forge + Forge + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + Forge + forge + forge.exe + + + + + - - org.apache.maven.plugins - maven-antrun-plugin - 1.7 - - - org.apache.ant - ant-nodeps - 1.8.1 - - - - - win-linux-app-bundle - pre-integration-test - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - run - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.8 - - - released-version - validate - - released-version - - - - parse-version - - parse-version - - - - attach-distribution - post-integration-test - - attach-artifact - - - - - ${project.build.directory}/${project.build.finalName}.tar.bz2 - tar.bz2 - - - - - - - - - + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + org.apache.ant + ant-nodeps + 1.8.1 + + + + + win-linux-app-bundle + pre-integration-test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.8 + + + released-version + validate + + released-version + + + + parse-version + + parse-version + + + + attach-distribution + post-integration-test + + attach-artifact + + + + + ${project.build.directory}/${project.build.finalName}.tar.bz2 + tar.bz2 + + + + + + + + + - - - "LICENSE.txt" - "CHANGES.txt" - "MANUAL.txt" - "Forge" - "Applications" - - osx - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.7 - - - org.apache.ant - ant-nodeps - 1.8.1 - - - - - osx-appbundle - pre-integration-test - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - run - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.8 - - - released-version - validate - - released-version - - - - parse-version - - parse-version - - - - attach-distribution-osx - post-integration-test - - attach-artifact - - - - - ${project.build.directory}/${project.build.finalName}-osx.tar.bz2 - - tar.bz2 - osx - - - - - - + + + "LICENSE.txt" + "CHANGES.txt" + "MANUAL.txt" + "Forge" + "Applications" + + osx + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + org.apache.ant + ant-nodeps + 1.8.1 + + + + + osx-appbundle + pre-integration-test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.8 + + + released-version + validate + + released-version + + + + parse-version + + parse-version + + + + attach-distribution-osx + post-integration-test + + attach-artifact + + + + + ${project.build.directory}/${project.build.finalName}-osx.tar.bz2 + + tar.bz2 + osx + + + + + + - - - + + + - - - "LICENSE.txt" - "README.txt" - "MANUAL.txt" - "Forge" - "Applications" - - osx-release - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.7 - - - org.apache.ant - ant-nodeps - 1.8.1 - - - - - osx-appbundle - pre-integration-test - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - run - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.8 - - - released-version - validate - - released-version - - - - parse-version - - parse-version - - - - attach-distribution-osx - post-integration-test - - attach-artifact - - - - - ${project.build.directory}/${project.build.finalName}-osx.tar.bz2 - - tar.bz2 - osx - - - - - - + + + "LICENSE.txt" + "README.txt" + "MANUAL.txt" + "Forge" + "Applications" + + osx-release + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + org.apache.ant + ant-nodeps + 1.8.1 + + + + + osx-appbundle + pre-integration-test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.8 + + + released-version + validate + + released-version + + + + parse-version + + parse-version + + + + attach-distribution-osx + post-integration-test + + attach-artifact + + + + + ${project.build.directory}/${project.build.finalName}-osx.tar.bz2 + + tar.bz2 + osx + + + + + + - - - - + + + + diff --git a/forge-gui-desktop/src/main/java/forge/deckchooser/DecksComboBox.java b/forge-gui-desktop/src/main/java/forge/deckchooser/DecksComboBox.java index 3d40e0efac1..1f59867d680 100644 --- a/forge-gui-desktop/src/main/java/forge/deckchooser/DecksComboBox.java +++ b/forge-gui-desktop/src/main/java/forge/deckchooser/DecksComboBox.java @@ -20,7 +20,7 @@ public class DecksComboBox extends FComboBoxWrapper { private DeckType selectedDeckType = null; public DecksComboBox() { - setSkinFont(FSkin.getBoldFont(14)); + setSkinFont(FSkin.getRelativeBoldFont(14)); setTextAlignment(TextAlignment.CENTER); addActionListener(getDeckTypeComboListener()); } diff --git a/forge-gui-desktop/src/main/java/forge/download/GuiDownloader.java b/forge-gui-desktop/src/main/java/forge/download/GuiDownloader.java index b7342dffed0..35c2ac36bfd 100644 --- a/forge-gui-desktop/src/main/java/forge/download/GuiDownloader.java +++ b/forge-gui-desktop/src/main/java/forge/download/GuiDownloader.java @@ -90,7 +90,7 @@ public class GuiDownloader extends DefaultBoundedRangeModel { radProxyNone.setSelected(true); btnClose.setBorder(new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_TEXT))); - btnStart.setFont(FSkin.getFont(18)); + btnStart.setFont(FSkin.getRelativeFont(18)); btnStart.setEnabled(false); progressBar.reset(); diff --git a/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java b/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java index 0575afbdaf1..4909b00b285 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java +++ b/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java @@ -85,13 +85,16 @@ public class CardDetailPanel extends SkinnedPanel { setInfoLabel = new JLabel(); setInfoLabel.setHorizontalAlignment(SwingConstants.CENTER); - final Font font = new Font("Dialog", 0, 14); + final Integer fontSizeR12 = FSkin.getRelativeFontSize(12); + final Integer fontSizeR14 = FSkin.getRelativeFontSize(14); + final Font font = new Font("Dialog", 0, fontSizeR14); nameCostLabel.setFont(font); typeLabel.setFont(font); idLabel.setFont(font); powerToughnessLabel.setFont(font); cdArea = new FHtmlViewer(); + cdArea.setFont(new Font("Dialog", 0, fontSizeR12)); cdArea.setBorder(new EmptyBorder(2, 6, 2, 6)); cdArea.setOpaque(false); scrArea = new FScrollPane(cdArea, false); diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/filters/ItemFilter.java b/forge-gui-desktop/src/main/java/forge/itemmanager/filters/ItemFilter.java index da5c74e9df5..8837618a8be 100644 --- a/forge-gui-desktop/src/main/java/forge/itemmanager/filters/ItemFilter.java +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/filters/ItemFilter.java @@ -27,7 +27,7 @@ public abstract class ItemFilter { public static void layoutCheckbox(SkinnedCheckBox cb) { cb.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); - cb.setFont(FSkin.getFont(12)); + cb.setFont(FSkin.getFont()); cb.setOpaque(false); cb.setFocusable(false); } diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java b/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java index 1bc5d5a8cc6..d5833b4f2c0 100644 --- a/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java @@ -63,7 +63,7 @@ public class ImageView extends ItemView { private static final float PILE_SPACING_Y = 0.1f; private static final SkinColor GROUP_HEADER_FORE_COLOR = FSkin.getColor(FSkin.Colors.CLR_TEXT); private static final SkinColor GROUP_HEADER_LINE_COLOR = GROUP_HEADER_FORE_COLOR.alphaColor(120); - private static final SkinFont GROUP_HEADER_FONT = FSkin.getFont(12); + private static final SkinFont GROUP_HEADER_FONT = FSkin.getFont(); private static final int GROUP_HEADER_HEIGHT = 19; private static final int GROUP_HEADER_GLYPH_WIDTH = 6; private static final int MIN_COLUMN_COUNT = 1; diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/views/ItemListView.java b/forge-gui-desktop/src/main/java/forge/itemmanager/views/ItemListView.java index 58c7163196c..855e2c8250c 100644 --- a/forge-gui-desktop/src/main/java/forge/itemmanager/views/ItemListView.java +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/views/ItemListView.java @@ -103,7 +103,7 @@ public final class ItemListView extends ItemView { static final SkinColor ALT_ROW_COLOR = BACK_COLOR.getContrastColor(-20); private static final SkinColor GRID_COLOR = BACK_COLOR.getContrastColor(20); private static final SkinBorder HEADER_BORDER = new FSkin.CompoundSkinBorder(new FSkin.MatteSkinBorder(0, 0, 1, 1, GRID_COLOR), new EmptyBorder(0, 1, 0, 0)); - private static final SkinFont ROW_FONT = FSkin.getFont(12); + private static final SkinFont ROW_FONT = FSkin.getFont(); private static final int ROW_HEIGHT = 19; private final ItemTable table = new ItemTable(); diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java index 8190f7e00bd..7b0dbe9978b 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java @@ -103,7 +103,7 @@ public class AddBasicLandsDialog { panel.add(pnlForest); panel.add(lblDeckInfo); - lblDeckInfo.setFont(FSkin.getFont(14)); + lblDeckInfo.setFont(FSkin.getRelativeFont(14)); lblDeckInfo.addMouseListener(new FMouseAdapter() { @Override public void onLeftDoubleClick(MouseEvent e) { diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java index f9287da68da..8c35c67ec10 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java @@ -257,7 +257,11 @@ public abstract class ACEditorBase getDeckController(); protected Deck getHumanDeck() { - return getDeckController().getModel().getHumanDeck(); + try { + return getDeckController().getModel().getHumanDeck(); + } catch (NullPointerException ex) { + return null; + } } /** diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/LblGroup.java b/forge-gui-desktop/src/main/java/forge/screens/home/LblGroup.java index 3f8c25273c2..69f92f1353d 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/LblGroup.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/LblGroup.java @@ -38,7 +38,7 @@ public class LblGroup extends SkinnedLabel implements ILocalRepaint { public LblGroup(final EMenuGroup e0) { super(" " + e0.getTitle()); - this.setFont(FSkin.getBoldFont(14)); + this.setFont(FSkin.getRelativeBoldFont(14)); this.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); this.addMouseListener(new MouseAdapter() { diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/LblHeader.java b/forge-gui-desktop/src/main/java/forge/screens/home/LblHeader.java index a7dd78a9d06..80780ed9cc5 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/LblHeader.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/LblHeader.java @@ -25,7 +25,7 @@ public class LblHeader extends SkinnedLabel { public LblHeader(final String txt0) { super(txt0); this.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); - this.setFont(FSkin.getFont(18)); + this.setFont(FSkin.getRelativeFont(18)); this.setBorder(new EmptyBorder(5, 30, 0, 0)); } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/LblMenuItem.java b/forge-gui-desktop/src/main/java/forge/screens/home/LblMenuItem.java index 2208eb93a55..0c504a3d96f 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/LblMenuItem.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/LblMenuItem.java @@ -36,7 +36,7 @@ public class LblMenuItem extends SkinnedLabel implements ILocalRepaint { public LblMenuItem(final IVSubmenu doc0) { super(" " + doc0.getMenuTitle()); - this.setFont(FSkin.getFont(14)); + this.setFont(FSkin.getRelativeFont(14)); this.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); this.addMouseListener(new MouseAdapter() { diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java b/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java index 875da3c0689..2068e3a4f05 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java @@ -663,7 +663,7 @@ public class PlayerPanel extends FPanel { txtPlayerName.setText(name); txtPlayerName.setFocusable(true); - txtPlayerName.setFont(FSkin.getFont(14)); + txtPlayerName.setFont(FSkin.getRelativeFont(14)); txtPlayerName.addActionListener(lobby.nameListener); txtPlayerName.addFocusListener(nameFocusListener); } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletQuick.java b/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletQuick.java index d01810b33d0..d3b7d0f2084 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletQuick.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletQuick.java @@ -107,7 +107,7 @@ public enum VSubmenuGauntletQuick implements IVSubmenu { sliOpponents.setSnapToTicks(true); sliOpponents.setOpaque(false); sliOpponents.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); - sliOpponents.setFont(FSkin.getFont(12)); + sliOpponents.setFont(FSkin.getFont()); pnlOptions.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); pnlOptions.add(lblOptions, "h 30px!, w 96%!, gap 2% 0 0 5px"); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/online/VSubmenuOnlineLobby.java b/forge-gui-desktop/src/main/java/forge/screens/home/online/VSubmenuOnlineLobby.java index 759d36b7bd2..f589f204c7d 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/online/VSubmenuOnlineLobby.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/online/VSubmenuOnlineLobby.java @@ -64,7 +64,7 @@ public enum VSubmenuOnlineLobby implements IVSubmenu, IOnli if (lobby == null) { final FButton btnConnect = new FButton("Connect to Server"); - btnConnect.setFont(FSkin.getFont(20)); + btnConnect.setFont(FSkin.getRelativeFont(20)); btnConnect.addActionListener(new ActionListener() { @Override public final void actionPerformed(final ActionEvent e) { diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlDraftEvent.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlDraftEvent.java index d320a394c17..6fe76f89de2 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlDraftEvent.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlDraftEvent.java @@ -27,17 +27,17 @@ public class PnlDraftEvent extends JPanel { super(); radButton = new FRadioButton(event.getTitle()); - radButton.setFont(FSkin.getBoldFont(20)); + radButton.setFont(FSkin.getRelativeBoldFont(20)); radButton.setIconTextGap(10); final FTextArea eventBoosters = new FTextArea(); final FTextArea eventFee = new FTextArea(); eventBoosters.setText(event.getBoosterList()); - eventBoosters.setFont(FSkin.getFont(12)); + eventBoosters.setFont(FSkin.getFont()); eventFee.setText(QuestUtil.formatCredits(event.getEntryFee()) + " Credit Entry Fee"); - eventFee.setFont(FSkin.getFont(12)); + eventFee.setFont(FSkin.getFont()); radButton.addChangeListener(new ChangeListener() { @Override diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlEvent.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlEvent.java index af0963e4dda..96b4d20336c 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlEvent.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlEvent.java @@ -56,11 +56,11 @@ class PnlEvent extends JPanel { // Title and description this.rad = new FRadioButton(event.getFullTitle()); - this.rad.setFont(FSkin.getBoldFont(16)); + this.rad.setFont(FSkin.getRelativeBoldFont(16)); final FTextArea tarDesc = new FTextArea(); tarDesc.setText(event.getDescription()); - tarDesc.setFont(FSkin.getItalicFont(12)); + tarDesc.setFont(FSkin.getItalicFont()); tarDesc.addMouseListener(new MouseAdapter() { @Override diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java index 2f3c2c66a82..0f56c273032 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java @@ -509,7 +509,7 @@ public enum VSubmenuQuestPrefs implements IVSubmenu { this.setOpaque(false); this.setBorder((Border)null); - this.setFont(FSkin.getFont(13)); + this.setFont(FSkin.getRelativeFont(13)); this.setForeground(clrText); this.setCaretColor(clrText); this.setBackground(clrHover); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/ViewStall.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/ViewStall.java index 9f3da1afc43..0eb32eff473 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/ViewStall.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/ViewStall.java @@ -80,7 +80,7 @@ public class ViewStall extends JPanel { this.tpnFluff.setOpaque(false); this.tpnFluff.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); - this.tpnFluff.setFont(FSkin.getItalicFont(15)); + this.tpnFluff.setFont(FSkin.getRelativeItalicFont(15)); this.tpnFluff.setFocusable(false); this.tpnFluff.setEditable(false); this.tpnFluff.setBorder((Border)null); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuSealed.java b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuSealed.java index f9bdc4dea6f..486d16860c9 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuSealed.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuSealed.java @@ -193,7 +193,7 @@ public enum VSubmenuSealed implements IVSubmenu { final SkinnedTextPane tpnDirections = new SkinnedTextPane(); tpnDirections.setOpaque(false); tpnDirections.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); - tpnDirections.setFont(FSkin.getFont(15)); + tpnDirections.setFont(FSkin.getRelativeFont(15)); tpnDirections.setAlignmentX(SwingConstants.CENTER); tpnDirections.setFocusable(false); tpnDirections.setEditable(false); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java index 3e32bdc8303..8cdefb16f8e 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java @@ -205,6 +205,7 @@ public enum CSubmenuPreferences implements ICDoc { initializeGameLogVerbosityComboBox(); initializeCloseActionComboBox(); + initializeDefaultFontSizeComboBox(); initializeAiProfilesComboBox(); initializeColorIdentityCombobox(); initializeAutoYieldModeComboBox(); @@ -329,6 +330,15 @@ public enum CSubmenuPreferences implements ICDoc { panel.setComboBox(comboBox, Singletons.getControl().getCloseAction()); } + private void initializeDefaultFontSizeComboBox() { + final String [] choices = {"10", "11", "12", "13", "14", "15", "16", "17", "18"}; + final FPref userSetting = FPref.UI_DEFAULT_FONT_SIZE; + final FComboBoxPanel panel = this.view.getCbpDefaultFontSizeComboBoxPanel(); + final FComboBox comboBox = createComboBox(choices, userSetting); + final String selectedItem = this.prefs.getPref(userSetting); + panel.setComboBox(comboBox, selectedItem); + } + private void initializeAiProfilesComboBox() { final FPref userSetting = FPref.UI_CURRENT_AI_PROFILE; final FComboBoxPanel panel = this.view.getAiProfilesComboBoxPanel(); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuAchievements.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuAchievements.java index 361b27c1ab8..bd5e3fc31d2 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuAchievements.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuAchievements.java @@ -48,8 +48,8 @@ public enum VSubmenuAchievements implements IVSubmenu { private static final int TROPHIES_PER_SHELVE = 4; private static final int PADDING = 5; private static final int TROPHY_PADDING = 45; - private static final SkinFont NAME_FONT = FSkin.getBoldFont(14); - private static final SkinFont DESC_FONT = FSkin.getFont(12); + private static final SkinFont NAME_FONT = FSkin.getRelativeBoldFont(14); + private static final SkinFont DESC_FONT = FSkin.getFont(); private static final SkinColor TEXT_COLOR = FSkin.getColor(Colors.CLR_TEXT); private static final SkinColor NOT_EARNED_COLOR = TEXT_COLOR.alphaColor(128); private static final SkinColor TEXTURE_OVERLAY_COLOR = FSkin.getColor(Colors.CLR_THEME); @@ -121,7 +121,7 @@ public enum VSubmenuAchievements implements IVSubmenu { AchievementCollection.buildComboBox(cbCollections); - cbCollections.setSkinFont(FSkin.getBoldFont(14)); + cbCollections.setSkinFont(FSkin.getRelativeBoldFont(14)); cbCollections.setTextAlignment(TextAlignment.CENTER); cbCollections.addActionListener(new ActionListener() { @Override @@ -264,8 +264,8 @@ public enum VSubmenuAchievements implements IVSubmenu { private static final SkinImage imgTop = FSkin.getImage(FSkinProp.IMG_TROPHY_CASE_TOP); private static final SkinImage imgShelf = FSkin.getImage(FSkinProp.IMG_TROPHY_SHELF); private static final SkinImage imgTrophyPlate = FSkin.getImage(FSkinProp.IMG_TROPHY_PLATE); - private static final Font font = FSkin.getFixedFont(14).deriveFont(Font.BOLD); - private static final Font subFont = FSkin.getFixedFont(12); + private static final Font font = FSkin.getRelativeFixedFont(14).deriveFont(Font.BOLD); + private static final Font subFont = FSkin.getFixedFont(); private static final Color foreColor = new Color(239, 220, 144); private AchievementCollection achievements; diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java index 40a96099df4..cbf2bd9cf40 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java @@ -105,6 +105,7 @@ public enum VSubmenuPreferences implements IVSubmenu { // ComboBox items are added in CSubmenuPreferences since this is just the View. private final FComboBoxPanel cbpGameLogEntryType = new FComboBoxPanel<>("Game Log Verbosity:"); private final FComboBoxPanel cbpCloseAction = new FComboBoxPanel<>("Close Action:"); + private final FComboBoxPanel cbpDefaultFontSize = new FComboBoxPanel<>("Default Font Size:"); private final FComboBoxPanel cbpAiProfiles = new FComboBoxPanel<>("AI Personality:"); private final FComboBoxPanel cbpDisplayCurrentCardColors = new FComboBoxPanel<>("Show Detailed Card Color:"); private final FComboBoxPanel cbpAutoYieldMode = new FComboBoxPanel<>("Auto-Yield:"); @@ -258,6 +259,9 @@ public enum VSubmenuPreferences implements IVSubmenu { // Graphic Options pnlPrefs.add(new SectionLabel("Graphic Options"), sectionConstraints + ", gaptop 2%"); + pnlPrefs.add(cbpDefaultFontSize, comboBoxConstraints); + pnlPrefs.add(new NoteLabel("The default font size within the UI. All font elements are scaled relative to this. (Needs restart)"), descriptionConstraints); + pnlPrefs.add(cbImageFetcher, titleConstraints); pnlPrefs.add(new NoteLabel("Enables live fetching of missing card images from an online resource."), descriptionConstraints); @@ -391,7 +395,7 @@ public enum VSubmenuPreferences implements IVSubmenu { private final class OptionsCheckBox extends FCheckBox { private OptionsCheckBox(final String txt0) { super(txt0); - this.setFont(FSkin.getBoldFont(12)); + this.setFont(FSkin.getBoldFont()); } } @@ -402,7 +406,7 @@ public enum VSubmenuPreferences implements IVSubmenu { super(txt0); this.setBorder(new FSkin.MatteSkinBorder(0, 0, 1, 0, FSkin.getColor(FSkin.Colors.CLR_BORDERS))); setHorizontalAlignment(SwingConstants.CENTER); - this.setFont(FSkin.getBoldFont(16)); + this.setFont(FSkin.getRelativeBoldFont(16)); this.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); } } @@ -412,7 +416,7 @@ public enum VSubmenuPreferences implements IVSubmenu { private final class NoteLabel extends SkinnedLabel { private NoteLabel(final String txt0) { super(txt0); - this.setFont(FSkin.getItalicFont(12)); + this.setFont(FSkin.getItalicFont()); this.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); } } @@ -436,7 +440,7 @@ public enum VSubmenuPreferences implements IVSubmenu { public KeyboardShortcutField(final Shortcut shortcut0) { super(); this.setEditable(false); - this.setFont(FSkin.getFont(14)); + this.setFont(FSkin.getRelativeFont(14)); final FPref prefKey = shortcut0.getPrefKey(); reload(prefKey); @@ -632,6 +636,10 @@ public enum VSubmenuPreferences implements IVSubmenu { return cbpCloseAction; } + public FComboBoxPanel getCbpDefaultFontSizeComboBoxPanel() { + return cbpDefaultFontSize; + } + public FComboBoxPanel getAutoYieldModeComboBoxPanel() { return cbpAutoYieldMode; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuReleaseNotes.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuReleaseNotes.java index 4ff741dd106..ce5f59a28e3 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuReleaseNotes.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuReleaseNotes.java @@ -60,7 +60,7 @@ public enum VSubmenuReleaseNotes implements IVSubmenu { tar.setEditable(false); tar.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - tar.setFont(FSkin.getFixedFont(16)); + tar.setFont(FSkin.getRelativeFixedFont(16)); tar.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); tar.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java index f8b22a27fe0..58c4f9da476 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java @@ -59,7 +59,7 @@ public class LimitedWinLose extends ControlWinLose { TitleLabel lblTemp1 = new TitleLabel(title); SkinnedLabel lblTemp2 = new SkinnedLabel(message); lblTemp2.setHorizontalAlignment(SwingConstants.CENTER); - lblTemp2.setFont(FSkin.getFont(17)); + lblTemp2.setFont(FSkin.getRelativeFont(17)); lblTemp2.setForeground(FORE_COLOR); lblTemp2.setIconTextGap(50); getView().getPnlCustom().add(lblTemp1, LimitedWinLose.CONSTRAINTS_TITLE); @@ -136,7 +136,7 @@ public class LimitedWinLose extends ControlWinLose { private class TitleLabel extends SkinnedLabel { TitleLabel(final String msg) { super(msg); - setFont(FSkin.getFont(18)); + setFont(FSkin.getRelativeFont(18)); setPreferredSize(new Dimension(200, 40)); setHorizontalAlignment(SwingConstants.CENTER); setForeground(FORE_COLOR); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java index b1c681d5b88..0c8c6b0b71c 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java @@ -110,24 +110,24 @@ public class ViewWinLose implements IWinLoseView { lblTitle.setForeground(Color.white); lblTitle.setHorizontalAlignment(SwingConstants.CENTER); - lblTitle.setFont(FSkin.getBoldFont(30)); + lblTitle.setFont(FSkin.getRelativeBoldFont(30)); lblStats.setForeground(Color.white); lblStats.setHorizontalAlignment(SwingConstants.CENTER); - lblStats.setFont(FSkin.getFont(26)); + lblStats.setFont(FSkin.getRelativeFont(26)); btnContinue.setText("Next Game"); - btnContinue.setFont(FSkin.getFont(22)); + btnContinue.setFont(FSkin.getRelativeFont(22)); btnRestart.setText("Start New Match"); - btnRestart.setFont(FSkin.getFont(22)); + btnRestart.setFont(FSkin.getRelativeFont(22)); btnQuit.setText("Quit Match"); - btnQuit.setFont(FSkin.getFont(22)); + btnQuit.setFont(FSkin.getRelativeFont(22)); btnContinue.setEnabled(!game0.isMatchOver()); // Assemble game log scroller. final FTextArea txtLog = new FTextArea(); txtLog.setText(StringUtils.join(game.getGameLog().getLogEntries(null), "\r\n").replace("[COMPUTER]", "[AI]")); - txtLog.setFont(FSkin.getFont(14)); + txtLog.setFont(FSkin.getRelativeFont(14)); txtLog.setFocusable(true); // allow highlighting and copying of log final FLabel btnCopyLog = new FLabel.ButtonBuilder().text("Copy to clipboard").build(); @@ -292,7 +292,7 @@ public class ViewWinLose implements IWinLoseView { message = "" + message.replace("\n", "
") + ""; } final SkinnedLabel lblMessage = new SkinnedLabel(message); - lblMessage.setFont(FSkin.getFont(14)); + lblMessage.setFont(FSkin.getRelativeFont(14)); lblMessage.setForeground(FORE_COLOR); lblMessage.setHorizontalAlignment(SwingConstants.CENTER); lblMessage.setIconTextGap(50); @@ -309,7 +309,7 @@ public class ViewWinLose implements IWinLoseView { private class TitleLabel extends SkinnedLabel { TitleLabel(final String msg) { super(msg); - setFont(FSkin.getFont(16)); + setFont(FSkin.getRelativeFont(16)); setPreferredSize(new Dimension(200, 40)); setHorizontalAlignment(SwingConstants.CENTER); setForeground(FORE_COLOR); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VPrompt.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VPrompt.java index 5a3ee81fc41..0e5d565d118 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VPrompt.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VPrompt.java @@ -116,11 +116,11 @@ public class VPrompt implements IVDoc { // wrap : 2 columns required for btnOk and btnCancel. container.setLayout(new MigLayout("wrap 2, gap 0px!, insets 1px 1px 3px 1px")); if (prefs.getPrefBoolean(FPref.UI_COMPACT_PROMPT)) { //hide header and use smaller font if compact prompt - tarMessage.setFont(FSkin.getFont(12)); + tarMessage.setFont(FSkin.getFont()); } else { container.add(lblGames, "span 2, w 10:100%, h 22px!"); - tarMessage.setFont(FSkin.getFont(14)); + tarMessage.setFont(FSkin.getRelativeFont(14)); } lblGames.setText("Game Setup"); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java index 7bf2c3694a0..0f78f73589a 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java @@ -191,7 +191,7 @@ public class VStack implements IVDoc { setFocusable(false); setEditable(false); setLineWrap(true); - setFont(FSkin.getFont(12)); + setFont(FSkin.getFont()); setWrapStyleWord(true); setMinimumSize(new Dimension(CARD_WIDTH + 2 * PADDING, CARD_HEIGHT + 2 * PADDING)); diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/FComboBoxPanel.java b/forge-gui-desktop/src/main/java/forge/toolbox/FComboBoxPanel.java index a11a6c74066..4e8f403e412 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/FComboBoxPanel.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/FComboBoxPanel.java @@ -82,7 +82,7 @@ public class FComboBoxPanel extends JPanel { if (comboBoxCaption != null && !comboBoxCaption.isEmpty()) { final SkinnedLabel comboLabel = new SkinnedLabel(comboBoxCaption); comboLabel.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); - comboLabel.setFont(FSkin.getBoldFont(12)); + comboLabel.setFont(FSkin.getBoldFont()); add(comboLabel); } } @@ -91,7 +91,7 @@ public class FComboBoxPanel extends JPanel { if (comboBox != null) { comboBox.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); comboBox.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); - comboBox.setFont(FSkin.getFont(12)); + comboBox.setFont(FSkin.getFont()); comboBox.setEditable(false); comboBox.setFocusable(true); comboBox.setOpaque(true); diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java b/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java index c9d86367d8a..56c535e6720 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java @@ -859,8 +859,12 @@ public class FSkin { private static Map avatars; private static Map fixedFonts = new HashMap<>(); + public static Font getFixedFont() { + return getFixedFont(defaultFontSize); + } + /** @return {@link java.awt.font} */ - public static Font getFixedFont(final int size) { + private static Font getFixedFont(final int size) { Font fixedFont = fixedFonts.get(size); if (fixedFont == null) { fixedFont = new Font("Monospaced", Font.PLAIN, size); @@ -869,6 +873,20 @@ public class FSkin { return fixedFont; } + public static Font getRelativeFixedFont(final int relative) { + return getFixedFont(getRelativeFontSize(relative)); + } + + private static double getMultiplier(final int relative) { + // don't know of a good way to get the preference default value + return relative / 12.0; + } + + public static Integer getRelativeFontSize(final int relative) { + double multiplier = getMultiplier(relative); + return (int)(defaultFontSize * multiplier); + } + /** * @return {@link forge.toolbox.FSkin.SkinFont} */ @@ -884,6 +902,10 @@ public class FSkin { return SkinFont.get(Font.PLAIN, size); } + public static SkinFont getRelativeFont(final int relative) { + return SkinFont.get(Font.PLAIN, getRelativeFontSize(relative)); + } + /** * @return {@link forge.toolbox.FSkin.SkinFont} */ @@ -899,6 +921,10 @@ public class FSkin { return SkinFont.get(Font.BOLD, size); } + public static SkinFont getRelativeBoldFont(final int relative) { + return SkinFont.get(Font.BOLD, getRelativeFontSize(relative)); + } + /** * @return {@link forge.toolbox.FSkin.SkinFont} */ @@ -914,6 +940,10 @@ public class FSkin { return SkinFont.get(Font.ITALIC, size); } + public static SkinFont getRelativeItalicFont(final int relative) { + return SkinFont.get(Font.ITALIC, getRelativeFontSize(relative)); + } + public static void setGraphicsFont(final Graphics g, final SkinFont skinFont) { g.setFont(skinFont.font); } @@ -1172,10 +1202,7 @@ public class FSkin { // Initialize fonts if (onInit) { //set default font size only once onInit - final Font f = UIManager.getDefaults().getFont("Label.font"); - if (f != null) { - defaultFontSize = f.getSize(); - } + defaultFontSize = FModel.getPreferences().getPrefInt(FPref.UI_DEFAULT_FONT_SIZE); } SkinFont.setBaseFont(GuiUtils.newFont(preferredDir + ForgeConstants.FONT_FILE)); diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/FTextEditor.java b/forge-gui-desktop/src/main/java/forge/toolbox/FTextEditor.java index 10b6c489766..202dbaaf1f1 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/FTextEditor.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/FTextEditor.java @@ -19,7 +19,7 @@ public class FTextEditor extends SkinnedScrollPane { public FTextEditor() { tarEditor = new SkinnedTextArea(); - tarEditor.setFont(FSkin.getFixedFont(16)); + tarEditor.setFont(FSkin.getRelativeFixedFont(16)); tarEditor.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); tarEditor.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); tarEditor.setCaretColor(FSkin.getColor(FSkin.Colors.CLR_TEXT)); diff --git a/forge-gui-desktop/src/main/java/forge/view/FNavigationBar.java b/forge-gui-desktop/src/main/java/forge/view/FNavigationBar.java index 0989fd51008..05eb0e2d3b6 100644 --- a/forge-gui-desktop/src/main/java/forge/view/FNavigationBar.java +++ b/forge-gui-desktop/src/main/java/forge/view/FNavigationBar.java @@ -382,7 +382,7 @@ public class FNavigationBar extends FTitleBarBase { setOpaque(false); this.setIcon(screen0.getTabIcon()); this.setForeground(foreColor.alphaColor(unhoveredAlpha)); - this.setFont(FSkin.getFont(fontSize)); + this.setFont(FSkin.getRelativeFont(fontSize)); int closeButtonOffset; if (screen.allowTabClose()) { @@ -434,7 +434,7 @@ public class FNavigationBar extends FTitleBarBase { private void setSelected(final boolean selected0) { if (this.selected == selected0) { return; } this.selected = selected0; - this.setFont(selected0 ? FSkin.getBoldFont(fontSize) : FSkin.getFont(fontSize)); + this.setFont(selected0 ? FSkin.getRelativeBoldFont(fontSize) : FSkin.getRelativeFont(fontSize)); repaintSelf(); } diff --git a/forge-gui-desktop/src/main/java/forge/view/FTitleBar.java b/forge-gui-desktop/src/main/java/forge/view/FTitleBar.java index 79cb67b87c2..8833bfb8cbd 100644 --- a/forge-gui-desktop/src/main/java/forge/view/FTitleBar.java +++ b/forge-gui-desktop/src/main/java/forge/view/FTitleBar.java @@ -9,7 +9,7 @@ import java.awt.*; @SuppressWarnings("serial") public class FTitleBar extends FTitleBarBase { - private static final FSkin.SkinFont skinFont = FSkin.getFont(12); + private static final FSkin.SkinFont skinFont = FSkin.getFont(); private final SkinnedLabel lblTitle = new SkinnedLabel(); diff --git a/forge-gui-desktop/src/main/java/forge/view/FView.java b/forge-gui-desktop/src/main/java/forge/view/FView.java index 24997a433e3..36b95e8f247 100644 --- a/forge-gui-desktop/src/main/java/forge/view/FView.java +++ b/forge-gui-desktop/src/main/java/forge/view/FView.java @@ -265,7 +265,7 @@ public enum FView { textPane.setOpaque(false); textPane.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT).getColor()); textPane.setBorder(null); - textPane.setFont(FSkin.getFont(14).getBaseFont()); + textPane.setFont(FSkin.getRelativeFont(14).getBaseFont()); final FLabel btnRemindMeLater = new FLabel.Builder().text("Remind Me Later").hoverable().opaque().build(); final FLabel btnDoNotRemindMe = new FLabel.Builder().text("Don't Remind Me Again").hoverable().opaque().build(); 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 4b0afe447b1..80e3e033579 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 @@ -30,6 +30,7 @@ import forge.game.cost.Cost; import forge.game.cost.CostPart; import forge.game.cost.CostPartMana; import forge.game.mana.Mana; +import forge.game.mana.ManaConversionMatrix; import forge.game.mana.ManaCostBeingPaid; import forge.game.player.*; import forge.game.replacement.ReplacementEffect; @@ -591,7 +592,7 @@ public class PlayerControllerForTests extends PlayerController { } @Override - public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt /* ai needs hints as well */, boolean isActivatedSa ) { + public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt /* ai needs hints as well */, ManaConversionMatrix matrix, boolean isActivatedSa) { // TODO Auto-generated method stub ManaCostBeingPaid cost = new ManaCostBeingPaid(toPay); return ComputerUtilMana.payManaCost(cost, sa, player); diff --git a/forge-gui-ios/pom.xml b/forge-gui-ios/pom.xml index a2d025b3e56..3a5a9720a78 100644 --- a/forge-gui-ios/pom.xml +++ b/forge-gui-ios/pom.xml @@ -6,13 +6,13 @@ jar -Xms128m -Xmx2048m - 1.6.15.003 + 1.6.17.001 forge forge - 1.6.16-SNAPSHOT + 1.6.18-SNAPSHOT forge-gui-ios diff --git a/forge-gui-mobile-dev/pom.xml b/forge-gui-mobile-dev/pom.xml index 3e186468f97..86c59d8ffe0 100644 --- a/forge-gui-mobile-dev/pom.xml +++ b/forge-gui-mobile-dev/pom.xml @@ -1,110 +1,84 @@ - 4.0.0 + 4.0.0 forge forge - 1.6.16-SNAPSHOT + 1.6.18-SNAPSHOT - forge-gui-mobile-dev - jar - Forge Mobile Dev + forge-gui-mobile-dev + jar + Forge Mobile Dev - - src - - - maven-compiler-plugin - - 1.8 - 1.8 - - + + src + + + maven-compiler-plugin + + 1.8 + 1.8 + + - - maven-assembly-plugin - - false - - jar-with-dependencies - - - - forge.app.Main - true - - - ${fullversionstring} - - - - - - make-assembly - - package - - - single - - - - + + maven-assembly-plugin + + false + + jar-with-dependencies + + + + forge.app.Main + true + + + + + + make-assembly + + package + + + single + + + + + + - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.0.0 - - - checkstyle-validation - validate - - ../checkstyle.xml - true - UTF-8 - true - true - true - - - check - - - - - - - - - - forge - forge-gui-mobile - ${project.version} - + + + forge + forge-gui-mobile + ${project.version} + com.badlogicgames.gdx gdx-backend-lwjgl 1.5.5 - - com.badlogicgames.gdx - gdx-platform - 1.2.0 - natives-desktop - - - com.badlogicgames.gdx - gdx-freetype-platform - 1.5.5 - natives-desktop - - - - commons-cli - commons-cli - 1.4 - - + + com.badlogicgames.gdx + gdx-platform + 1.2.0 + natives-desktop + + + com.badlogicgames.gdx + gdx-freetype-platform + 1.5.5 + natives-desktop + + + + commons-cli + commons-cli + 1.4 + + diff --git a/forge-gui-mobile/pom.xml b/forge-gui-mobile/pom.xml index 04ec8084755..cfaebbc7f52 100644 --- a/forge-gui-mobile/pom.xml +++ b/forge-gui-mobile/pom.xml @@ -1,65 +1,65 @@ - 4.0.0 + 4.0.0 - - forge - forge - 1.6.16-SNAPSHOT - + + forge + forge + 1.6.18-SNAPSHOT + - forge-gui-mobile - jar - Forge Mobile + forge-gui-mobile + jar + Forge Mobile - - src - - - maven-compiler-plugin - - 1.8 - 1.8 - - - - + + src + + + maven-compiler-plugin + + 1.8 + 1.8 + + + + - - - forge - forge-core - ${project.version} - - - forge - forge-game - ${project.version} - - - forge - forge-ai - ${project.version} - - - forge - forge-gui - ${project.version} - - - com.google.guava - guava - 24.1-android - - - com.thoughtworks.xstream - xstream - 1.4.7 - - - org.apache.commons - commons-lang3 - 3.7 - + + + forge + forge-core + ${project.version} + + + forge + forge-game + ${project.version} + + + forge + forge-ai + ${project.version} + + + forge + forge-gui + ${project.version} + + + com.google.guava + guava + 24.1-android + + + com.thoughtworks.xstream + xstream + 1.4.7 + + + org.apache.commons + commons-lang3 + 3.7 + com.badlogicgames.gdx gdx @@ -70,6 +70,6 @@ gdx-freetype 1.5.5 - + diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index 3c3d09cb743..ad9e7363cd6 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -34,7 +34,7 @@ import java.util.List; import java.util.Stack; public class Forge implements ApplicationListener { - public static final String CURRENT_VERSION = "1.6.15.003"; + public static final String CURRENT_VERSION = "1.6.17.001"; private static final ApplicationListener app = new Forge(); private static Clipboard clipboard; diff --git a/forge-gui-mobile/src/forge/toolbox/FFileChooser.java b/forge-gui-mobile/src/forge/toolbox/FFileChooser.java index 23f36530c0b..dadb04e2d9d 100644 --- a/forge-gui-mobile/src/forge/toolbox/FFileChooser.java +++ b/forge-gui-mobile/src/forge/toolbox/FFileChooser.java @@ -1,13 +1,7 @@ package forge.toolbox; -import java.io.File; -import java.io.FilenameFilter; - -import org.apache.commons.lang3.StringUtils; - import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment; - import forge.Forge; import forge.Graphics; import forge.assets.FSkinColor; @@ -15,11 +9,14 @@ import forge.assets.FSkinFont; import forge.assets.FSkinImage; import forge.menu.FMenuItem; import forge.menu.FPopupMenu; -import forge.toolbox.FEvent; import forge.toolbox.FEvent.FEventHandler; import forge.util.Callback; import forge.util.FileUtil; import forge.util.Utils; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.FilenameFilter; public class FFileChooser extends FDialog { private static final float BACK_ICON_THICKNESS = Utils.scale(2); @@ -321,7 +318,7 @@ public class FFileChooser extends FDialog { //draw back icon float w = getHeight(); float h = w; - float x = w * 0.35f; + float x = w * 0.35f; float y = h / 2; float offsetX = w / 8; float offsetY = h / 6; @@ -395,7 +392,7 @@ public class FFileChooser extends FDialog { if (value.isDirectory()) { float iconSize = h; g.drawImage(FSkinImage.FOLDER, x, y + (h - iconSize) / 2, iconSize, iconSize); - x += iconSize + FList.PADDING; + x += iconSize + FList.PADDING; } g.drawText(value.getName(), font, foreColor, x, y, w, h, false, HAlignment.LEFT, true); } diff --git a/forge-gui-mobile/src/forge/toolbox/ListChooser.java b/forge-gui-mobile/src/forge/toolbox/ListChooser.java index 070913984f8..9fd472230ed 100644 --- a/forge-gui-mobile/src/forge/toolbox/ListChooser.java +++ b/forge-gui-mobile/src/forge/toolbox/ListChooser.java @@ -6,12 +6,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -34,9 +34,7 @@ import forge.itemmanager.filters.ItemFilter; import forge.itemmanager.filters.ListLabelFilter; import forge.menu.FMenuItem; import forge.menu.FPopupMenu; -import forge.toolbox.FEvent; import forge.toolbox.FEvent.FEventHandler; -import forge.toolbox.FOptionPane; import forge.util.Callback; import forge.util.Utils; @@ -62,7 +60,7 @@ import java.util.List; *
  • If the dialog was canceled, the selection will be empty.
  • *
  • * - * + * * @param * the generic type * @author Forge @@ -228,7 +226,7 @@ public class ListChooser extends FContainer { /** * Shows the dialog and returns after the dialog was closed. - * + * * @param index0 index to select when shown * @return a boolean. */ diff --git a/forge-gui/pom.xml b/forge-gui/pom.xml index 47375e80764..1af393d28a6 100644 --- a/forge-gui/pom.xml +++ b/forge-gui/pom.xml @@ -4,7 +4,7 @@ forge forge - 1.6.16-SNAPSHOT + 1.6.18-SNAPSHOT forge-gui @@ -36,19 +36,19 @@ forge-ai ${project.version} - - com.google.guava - guava - 24.1-android - - - com.thoughtworks.xstream - xstream - 1.4.10 - - - org.apache.commons - commons-lang3 + + com.google.guava + guava + 24.1-android + + + com.thoughtworks.xstream + xstream + 1.4.10 + + + org.apache.commons + commons-lang3 3.7 @@ -63,9 +63,9 @@ 1.2.17 - org.fourthline.cling - cling-support - 2.0.1 + org.fourthline.cling + cling-support + 2.0.1 org.slf4j @@ -74,30 +74,4 @@ - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.0.0 - - - checkstyle-validation - validate - - ../checkstyle.xml - true - UTF-8 - true - true - true - - - check - - - - - - diff --git a/forge-gui/release-files/ANNOUNCEMENTS.txt b/forge-gui/release-files/ANNOUNCEMENTS.txt index 973e7e98943..554eaa194c4 100644 --- a/forge-gui/release-files/ANNOUNCEMENTS.txt +++ b/forge-gui/release-files/ANNOUNCEMENTS.txt @@ -1,5 +1,5 @@ #Add one announcement per line -M19 is here! Report your issues in the release thread, and we'll kick off a new release soon with fixes. +GRN is finished! Please let us know if you see any other bugs most especially for the newers cards. [b]Forge now requires Java 8 (or newer). You will not be able to start the game if you are not yet running Java 8.[/b] We have a Discord server for hanging out with Forge devs and other Forge fans. Feel free to [url=https://discord.gg/3v9JCVr]jump on in and say hi[/url]! Online Multiplayer is once again functional! \ No newline at end of file diff --git a/forge-gui/release-files/CHANGES.txt b/forge-gui/release-files/CHANGES.txt index 2b5571c599e..05f0bf1829e 100644 --- a/forge-gui/release-files/CHANGES.txt +++ b/forge-gui/release-files/CHANGES.txt @@ -1,6 +1,2 @@ -- Random Quest World - -Added Randomized Standard Quest World with LDA archetype generated decks as duels and standard card pool - this is designed so that there is always a quest world representing the current standard metagame - with a standard cardpool and decks generated using the LDA archetype based deck generation. To access this mode, select the "Random Standard" world in the world selection dropdown. -In this world as well as the random duel opponents, there are randomly generated challenges of varying difficulty and of 2 different types. One type pits your standard decks against modern, legacy or vintage opponents, the other gives the AI a standard deck, but with a headstart of one or more cards on the battlefield. - - Bug fixes - As always, this release of Forge features an assortment of bug fixes and improvements based on user feedback during the previous release run. diff --git a/forge-gui/release-files/ISSUES.txt b/forge-gui/release-files/ISSUES.txt index 00a6e947bd4..3755d9b8044 100644 --- a/forge-gui/release-files/ISSUES.txt +++ b/forge-gui/release-files/ISSUES.txt @@ -1,7 +1,3 @@ -Online multiplayer functionality has been restored, but is still a Work in Progress. We do have a dedicated developer actively working on the online multiplayer feature. - -"When you pay a cost" trigger for M19 cards don't work 100% correctly yet. We're still working on it. - -Other known issues are here: https://git.cardforge.org/core-developers/forge/issues +Known issues are here: https://git.cardforge.org/core-developers/forge/issues Feel free to report your own there if you have any. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/affectionate_indrik.txt b/forge-gui/res/cardsfolder/a/affectionate_indrik.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/affectionate_indrik.txt rename to forge-gui/res/cardsfolder/a/affectionate_indrik.txt diff --git a/forge-gui/res/cardsfolder/a/aminatou_the_fateshifter.txt b/forge-gui/res/cardsfolder/a/aminatou_the_fateshifter.txt new file mode 100644 index 00000000000..8b85918ca76 --- /dev/null +++ b/forge-gui/res/cardsfolder/a/aminatou_the_fateshifter.txt @@ -0,0 +1,13 @@ +Name:Aminatou, the Fateshifter +ManaCost:W U B +Types:Legendary Planeswalker Aminatou +Loyalty:3 +Text:CARDNAME can be your commander. +A:AB$ Draw | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | NumCards$ 1 | SubAbility$ DBTop | SpellDescription$ Draw a card, then put a card from your hand on top of your library. +SVar:DBTop:DB$ ChangeZone | Origin$ Hand | Destination$ Library | ChangeType$ Card | ChangeNum$ 1 | Mandatory$ True +A:AB$ ChangeZone | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Permanent.Other+YouOwn | TgtPrompt$ Select another target permanent you own | Origin$ Battlefield | Destination$ Exile | RememberTargets$ True | SubAbility$ DBReturn | SpellDescription$ Exile another target permanent you own, then return it to the battlefield under your control. +SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | GainControl$ True | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +A:AB$ ChooseDirection | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | SubAbility$ DBControl | AILogic$ Aminatou | SpellDescription$ Choose left or right. Each player gains control of all nonland permanents other than CARDNAME controlled by the next player in the chosen direction. +SVar:DBControl:DB$ GainControlVariant | AllValid$ Permanent.nonLand+Other | ChangeController$ NextPlayerInChosenDirection +Oracle:[+1]: Draw a card, then put a card from your hand on top of your library.\n[−1]: Exile another target permanent you own, then return it to the battlefield under your control.\n[−6]: Choose left or right. Each player gains control of all nonland permanents other than Aminatou, the Fateshifter controlled by the next player in the chosen direction.\nAminatou, the Fateshifter can be your commander. diff --git a/forge-gui/res/cardsfolder/a/anavolver.txt b/forge-gui/res/cardsfolder/a/anavolver.txt index 47991138802..838ec0bbf3a 100644 --- a/forge-gui/res/cardsfolder/a/anavolver.txt +++ b/forge-gui/res/cardsfolder/a/anavolver.txt @@ -3,14 +3,15 @@ ManaCost:3 G Types:Creature Volver PT:3/3 K:Kicker:1 U:B -T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked 1 | Origin$ Any | Destination$ Battlefield | Execute$ VolverStrength | Static$ True | TriggerDescription$ If CARDNAME was kicked with its {1}{U} kicker, it enters the battlefield with two +1/+1 counters on it and with flying. -SVar:VolverStrength:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ VolverLaunch -SVar:VolverLaunch:DB$ Pump | Defined$ Self | KW$ Flying | Permanent$ True -T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked 2 | Origin$ Any | Destination$ Battlefield | Execute$ VolverPumped | Static$ True | TriggerDescription$ If CARDNAME was kicked with its {B} kicker, it enters the battlefield with a +1/+1 counter on it and with "Pay 3 life: Regenerate CARDNAME." -SVar:VolverPumped:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ VolverResilience +K:ETBReplacement:Other:VolverStrength:Mandatory::Card.Self+kicked 1 +K:ETBReplacement:Other:VolverPumped:Mandatory::Card.Self+kicked 2 +SVar:VolverStrength:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | ETB$ True | SubAbility$ VolverLaunch | SpellDescription$ If CARDNAME was kicked with its {1}{U} kicker, it enters the battlefield with two +1/+1 counters on it and with flying. +SVar:VolverLaunch:DB$ Animate | Defined$ Self | Keywords$ Flying | Permanent$ True +SVar:VolverPumped:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ETB$ True | SubAbility$ VolverResilience | SpellDescription$ If CARDNAME was kicked with its {B} kicker, it enters the battlefield with a +1/+1 counter on it and with "Pay 3 life: Regenerate CARDNAME." SVar:VolverResilience:DB$ Animate | Defined$ Self | Abilities$ ABRegen | Permanent$ True SVar:ABRegen:AB$Regenerate | Cost$ PayLife<3> | SpellDescription$ Regenerate CARDNAME. SVar:RemRandomDeck:True DeckNeeds:Color$Blue|Black +DeckHas:Ability$Counters SVar:Picture:http://www.wizards.com/global/images/magic/general/anavolver.jpg Oracle:Kicker {1}{U} and/or {B} (You may pay an additional {1}{U} and/or {B} as you cast this spell.)\nIf Anavolver was kicked with its {1}{U} kicker, it enters the battlefield with two +1/+1 counters on it and with flying.\nIf Anavolver was kicked with its {B} kicker, it enters the battlefield with a +1/+1 counter on it and with "Pay 3 life: Regenerate Anavolver." diff --git a/forge-gui/res/cardsfolder/a/apex_of_power.txt b/forge-gui/res/cardsfolder/a/apex_of_power.txt index a10faab3ab4..a9580c21af1 100644 --- a/forge-gui/res/cardsfolder/a/apex_of_power.txt +++ b/forge-gui/res/cardsfolder/a/apex_of_power.txt @@ -5,5 +5,5 @@ A:SP$ Mill | Cost$ 7 R R R | Origin$ Library | Destination$ Exile | NumCards$ 7 SVar:DBEffect:DB$ Effect | RememberObjects$ RememberedCard | StaticAbilities$ EffSModeContinuous | SubAbility$ DBCleanup | ForgetOnMoved$ Exile SVar:EffSModeContinuous:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.nonLand+IsRemembered | AffectedZone$ Exile | Description$ You may cast nonland cards exiled this way. SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | SubAbility$ DBMana -SVar:DBMana:DB$ Mana | Produced$ Any | Amount$ 10 | ConditionPresent$ Card.wasCastFromHand+Self | ConditionCompare$ EQ1 +SVar:DBMana:DB$ Mana | Produced$ Any | Amount$ 10 | ConditionDefined$ Self | ConditionPresent$ Card.wasCastFromHand | ConditionCompare$ EQ1 Oracle:Exile the top seven cards of your library. Until end of turn, you may cast nonland cards exiled this way.\nIf this spell was cast from your hand, add ten mana of any one color. diff --git a/forge-gui/res/cardsfolder/upcoming/arboretum_elemental.txt b/forge-gui/res/cardsfolder/a/arboretum_elemental.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/arboretum_elemental.txt rename to forge-gui/res/cardsfolder/a/arboretum_elemental.txt diff --git a/forge-gui/res/cardsfolder/a/arclight_phoenix.txt b/forge-gui/res/cardsfolder/a/arclight_phoenix.txt new file mode 100644 index 00000000000..026a1c61c69 --- /dev/null +++ b/forge-gui/res/cardsfolder/a/arclight_phoenix.txt @@ -0,0 +1,11 @@ +Name:Arclight Phoenix +ManaCost:3 R +Types:Creature Phoenix +PT:3/2 +K:Flying +K:Haste +T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerZones$ Graveyard | CheckSVar$ X | SVarCompare$ GE3 | Execute$ TrigReturn | OptionalDecider$ You | TriggerDescription$ At the beginning of combat on your turn, if you've cast three or more instant and sorcery spells this turn, you may return CARDNAME from your graveyard to the battlefield. +SVar:TrigReturn:DB$ ChangeZone | Defined$ Self | Origin$ Graveyard | Destination$ Battlefield +SVar:X:Count$ThisTurnCast_Instant.YouCtrl,Sorcery.YouCtrl +DeckNeeds:Type$Instant|Sorcery +Oracle:Flying, Haste\nAt the beginning of combat on your turn, if you've cast three or more instant and sorcery spells this turn, you may return Arclight Phoenix from your graveyard to the battlefield. diff --git a/forge-gui/res/cardsfolder/upcoming/artful_takedown.txt b/forge-gui/res/cardsfolder/a/artful_takedown.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/artful_takedown.txt rename to forge-gui/res/cardsfolder/a/artful_takedown.txt diff --git a/forge-gui/res/cardsfolder/a/artisan_of_forms.txt b/forge-gui/res/cardsfolder/a/artisan_of_forms.txt index 2f6cc398319..dd18a306a46 100644 --- a/forge-gui/res/cardsfolder/a/artisan_of_forms.txt +++ b/forge-gui/res/cardsfolder/a/artisan_of_forms.txt @@ -3,8 +3,7 @@ ManaCost:1 U Types:Creature Human Wizard PT:1/1 T:Mode$ SpellCast | ValidActivatingPlayer$ You | TargetsValid$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigArtisanCopy | TriggerDescription$ Heroic — Whenever you cast a spell that targets CARDNAME, you may have CARDNAME become a copy of target creature and gain this ability. -SVar:TrigArtisanCopy:DB$ Clone | ValidTgts$ Creature | TgtPrompt$ Select target creature to copy | Optional$ True | AddTriggers$ ArtisanHeroicTrig | AddSVars$ TrigArtisanCopy,ArtisanHeroicTrig -SVar:ArtisanHeroicTrig:Mode$ SpellCast | ValidActivatingPlayer$ You | TargetsValid$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigArtisanCopy | TriggerDescription$ Heroic — Whenever you cast a spell that targets CARDNAME, you may have CARDNAME become a copy of target creature and gain this ability. +SVar:TrigArtisanCopy:DB$ Clone | ValidTgts$ Creature | TgtPrompt$ Select target creature to copy | Optional$ True | GainThisAbility$ True SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/artisan_of_forms.jpg Oracle:Heroic — Whenever you cast a spell that targets Artisan of Forms, you may have Artisan of Forms become a copy of target creature and gain this ability. diff --git a/forge-gui/res/cardsfolder/upcoming/assassins_trophy.txt b/forge-gui/res/cardsfolder/a/assassins_trophy.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/assassins_trophy.txt rename to forge-gui/res/cardsfolder/a/assassins_trophy.txt diff --git a/forge-gui/res/cardsfolder/upcoming/assure_assemble.txt b/forge-gui/res/cardsfolder/a/assure_assemble.txt similarity index 95% rename from forge-gui/res/cardsfolder/upcoming/assure_assemble.txt rename to forge-gui/res/cardsfolder/a/assure_assemble.txt index eb67e2204a3..255b81014fe 100644 --- a/forge-gui/res/cardsfolder/upcoming/assure_assemble.txt +++ b/forge-gui/res/cardsfolder/a/assure_assemble.txt @@ -12,5 +12,5 @@ Name:Assemble ManaCost:4 G W Types:Instant A:SP$ Token | Cost$ 4 G W | TokenAmount$ 3 | TokenScript$ wg_2_2_elf_knight_vigilance | SpellDescription$ Create three 2/2 green and white Elf Knight creature tokens with vigilance. -DeckHas:Ability$Token +DeckHas:Ability$Counters & Ability$Token Oracle:Create three 2/2 green and white Elf Knight creature tokens with vigilance. diff --git a/forge-gui/res/cardsfolder/upcoming/attendant_of_vraska.txt b/forge-gui/res/cardsfolder/a/attendant_of_vraska.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/attendant_of_vraska.txt rename to forge-gui/res/cardsfolder/a/attendant_of_vraska.txt index d31ef72a28f..f02fdcd7d51 100644 --- a/forge-gui/res/cardsfolder/upcoming/attendant_of_vraska.txt +++ b/forge-gui/res/cardsfolder/a/attendant_of_vraska.txt @@ -5,4 +5,5 @@ PT:3/3 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | IsPresent$ Planeswalker.Vraska+YouCtrl | Execute$ TrigGainLife | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, if you control a Vraska planeswalker, you gain life equal to CARDNAME's power. SVar:TrigGainLife:DB$GainLife | Defined$ You | LifeAmount$ X | References$ X SVar:X:TriggeredCard$CardPower +DeckNeeds:Type$Vraska Oracle:When Attendant of Vraska dies, if you control a Vraska planeswalker, you gain life equal to Attendant of Vraska's power. diff --git a/forge-gui/res/cardsfolder/upcoming/aurelia_exemplar_of_justice.txt b/forge-gui/res/cardsfolder/a/aurelia_exemplar_of_justice.txt similarity index 97% rename from forge-gui/res/cardsfolder/upcoming/aurelia_exemplar_of_justice.txt rename to forge-gui/res/cardsfolder/a/aurelia_exemplar_of_justice.txt index 5920bd231d3..b2a20a416f1 100644 --- a/forge-gui/res/cardsfolder/upcoming/aurelia_exemplar_of_justice.txt +++ b/forge-gui/res/cardsfolder/a/aurelia_exemplar_of_justice.txt @@ -9,4 +9,5 @@ SVar:DBPump:DB$ Pump | ValidTgts$ Creature.YouCtrl | NumAtt$ 2 | RememberTargets SVar:DBPump1:DB$Pump | Defined$ Remembered | KW$ Trample | ConditionDefined$ Remembered | ConditionPresent$ Card.Red | SubAbility$ DBPump2 SVar:DBPump2:DB$Pump | Defined$ Remembered | KW$ Vigilance | ConditionDefined$ Remembered | ConditionPresent$ Card.White | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +DeckHas:Ability$Counters Oracle:Flying\nMentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.)\nAt the beginning of combat on your turn, choose up to one target creature you control. Until end of turn, that creature gets +2/+0, gains trample if it's red, and gains vigilance if it's white. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/a/azra_bladeseeker.txt b/forge-gui/res/cardsfolder/a/azra_bladeseeker.txt new file mode 100644 index 00000000000..e128d0ea276 --- /dev/null +++ b/forge-gui/res/cardsfolder/a/azra_bladeseeker.txt @@ -0,0 +1,8 @@ +Name:Azra Bladeseeker +ManaCost:2 R +Types:Creature Azra Warrior +PT:3/2 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExploration | TriggerDescription$ When CARDNAME enters the battlefield, each player on your team may discard a card, then each player who discarded a card this way draws a card. +SVar:TrigExploration:DB$ RepeatEach | RepeatPlayers$ Player.YourTeam | RepeatSubAbility$ DBDiscardToDraw +SVar:DBDiscardToDraw:DB$ Draw | Defined$ Player.IsRemembered | UnlessCost$ Discard<1/Card> | UnlessPayer$ Player.IsRemembered | UnlessSwitched$ True +Oracle:When Azra Bladeseeker enters the battlefield, each player on your team may discard a card, then each player who discarded a card this way draws a card. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/barging_sergeant.txt b/forge-gui/res/cardsfolder/b/barging_sergeant.txt similarity index 89% rename from forge-gui/res/cardsfolder/upcoming/barging_sergeant.txt rename to forge-gui/res/cardsfolder/b/barging_sergeant.txt index e0e24d93c6f..595eb1697f0 100644 --- a/forge-gui/res/cardsfolder/upcoming/barging_sergeant.txt +++ b/forge-gui/res/cardsfolder/b/barging_sergeant.txt @@ -4,4 +4,5 @@ Types:Creature Minotaur Soldier PT:4/2 K:Haste K:Mentor +DeckHas:Ability$Counters Oracle:Haste\nMentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.) diff --git a/forge-gui/res/cardsfolder/b/barreling_attack.txt b/forge-gui/res/cardsfolder/b/barreling_attack.txt index 60ab3ef825c..dfee6d1044d 100644 --- a/forge-gui/res/cardsfolder/b/barreling_attack.txt +++ b/forge-gui/res/cardsfolder/b/barreling_attack.txt @@ -1,10 +1,10 @@ Name:Barreling Attack ManaCost:2 R R Types:Instant -A:SP$ Pump | Cost$ 2 R R | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ Trample | SubAbility$ DBAnimate | SpellDescription$ Target creature gains trample until end of turn. When that creature becomes blocked this turn, it gets +1/+1 until end of turn for each creature blocking it. -SVar:DBAnimate:DB$ Animate | Defined$ Targeted | Triggers$ TrigBounce | sVars$ ABBarrelingPump,BarrelingX -SVar:TrigBounce:Mode$ AttackerBlocked | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ ABBarrelingPump | TriggerDescription$ When CARDNAME becomes blocked this turn, it gets +1/+1 until end of turn for each creature blocking it. -SVar:ABBarrelingPump:DB$ Pump | Defined$ Self | NumAtt$ +BarrelingX | NumDef$ +BarrelingX | References$ BarrelingX +A:SP$ Pump | Cost$ 2 R R | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ Trample | SubAbility$ DBEffect | SpellDescription$ Target creature gains trample until end of turn. When that creature becomes blocked this turn, it gets +1/+1 until end of turn for each creature blocking it. +SVar:DBEffect:DB$ Effect | RememberObjects$ Targeted | Triggers$ TrigBounce | SVars$ ABBarrelingPump,BarrelingX | ForgetOnMoved$ Battlefield +SVar:TrigBounce:Mode$ AttackerBlocked | ValidCard$ Card.IsRemembered | TriggerZones$ Command | Execute$ ABBarrelingPump | TriggerDescription$ When CARDNAME becomes blocked this turn, it gets +1/+1 until end of turn for each creature blocking it. +SVar:ABBarrelingPump:DB$ Pump | Defined$ Remembered | NumAtt$ +BarrelingX | NumDef$ +BarrelingX | References$ BarrelingX SVar:BarrelingX:TriggerCount$NumBlockers SVar:Picture:http://www.wizards.com/global/images/magic/general/barreling_attack.jpg Oracle:Target creature gains trample until end of turn. When that creature becomes blocked this turn, it gets +1/+1 until end of turn for each creature blocking it. diff --git a/forge-gui/res/cardsfolder/upcoming/barrier_of_bones.txt b/forge-gui/res/cardsfolder/b/barrier_of_bones.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/barrier_of_bones.txt rename to forge-gui/res/cardsfolder/b/barrier_of_bones.txt index 4c092100c9f..ae3c126b121 100644 --- a/forge-gui/res/cardsfolder/upcoming/barrier_of_bones.txt +++ b/forge-gui/res/cardsfolder/b/barrier_of_bones.txt @@ -5,4 +5,5 @@ PT:0/3 K:Defender T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSurveil | TriggerDescription$ When CARDNAME enters the battlefield, surveil 1. (Look at the top card of your library. You may put that card into your graveyard.) SVar:TrigSurveil:DB$ Surveil | Amount$ 1 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Defender\nWhen Barrier of Bones enters the battlefield, surveil 1. (Look at the top card of your library. You may put that card into your graveyard.) diff --git a/forge-gui/res/cardsfolder/upcoming/bartizan_bats.txt b/forge-gui/res/cardsfolder/b/bartizan_bats.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/bartizan_bats.txt rename to forge-gui/res/cardsfolder/b/bartizan_bats.txt diff --git a/forge-gui/res/cardsfolder/upcoming/beacon_bolt.txt b/forge-gui/res/cardsfolder/b/beacon_bolt.txt similarity index 95% rename from forge-gui/res/cardsfolder/upcoming/beacon_bolt.txt rename to forge-gui/res/cardsfolder/b/beacon_bolt.txt index 76ebddf053b..52b23157897 100644 --- a/forge-gui/res/cardsfolder/upcoming/beacon_bolt.txt +++ b/forge-gui/res/cardsfolder/b/beacon_bolt.txt @@ -5,4 +5,5 @@ K:Jump-start A:SP$ DealDamage | Cost$ 1 U R | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ X | References$ X,Y | SpellDescription$ CARDNAME deals damage to target creature equal to the total number of instant and sorcery cards you own in exile and in your graveyard. SVar:X:Count$ValidGraveyard Instant.YouOwn,Sorcery.YouOwn/Plus.Y SVar:Y:Count$ValidExile Instant.YouOwn,Sorcery.YouOwn +DeckHints:Type$Instant|Sorcery Oracle:Beacon Bolt deals damage to target creature equal to the total number of instant and sorcery cards you own in exile and in your graveyard.\nJump-start (You may cast this card from your graveyard by discarding a card in addition to paying its other costs. Then exile this card.) diff --git a/forge-gui/res/cardsfolder/b/beamsplitter_mage.txt b/forge-gui/res/cardsfolder/b/beamsplitter_mage.txt new file mode 100644 index 00000000000..771b067a897 --- /dev/null +++ b/forge-gui/res/cardsfolder/b/beamsplitter_mage.txt @@ -0,0 +1,8 @@ +Name:Beamsplitter Mage +ManaCost:U R +Types:Creature Vedalken Wizard +PT:2/2 +T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | IsSingleTarget$ True | TargetsValid$ Card.Self | CanTargetOtherCondition$ Creature.YouCtrl | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast an instant or sorcery that targets only CARDNAME, if you control one or more other creatures that spell could target, choose one of those creatures. Copy that spell. The copy targets the chosen creature. +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ You | CopyForEachCanTarget$ Creature.YouCtrl | ChooseOnlyOne$ True +DeckHints:Type$Instant|Sorcery +Oracle:Whenever you cast an instant or sorcery spell that targets only Beamsplitter Mage, if you control one or more other creatures that spell could target, choose one of those creatures. Copy that spell. The copy targets the chosen creature. diff --git a/forge-gui/res/cardsfolder/upcoming/beast_whisperer.txt b/forge-gui/res/cardsfolder/b/beast_whisperer.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/beast_whisperer.txt rename to forge-gui/res/cardsfolder/b/beast_whisperer.txt diff --git a/forge-gui/res/cardsfolder/upcoming/blade_instructor.txt b/forge-gui/res/cardsfolder/b/blade_instructor.txt similarity index 88% rename from forge-gui/res/cardsfolder/upcoming/blade_instructor.txt rename to forge-gui/res/cardsfolder/b/blade_instructor.txt index a8969b6e857..dc0478e63b6 100644 --- a/forge-gui/res/cardsfolder/upcoming/blade_instructor.txt +++ b/forge-gui/res/cardsfolder/b/blade_instructor.txt @@ -3,4 +3,5 @@ ManaCost:2 W Types:Creature Human Soldier PT:3/1 K:Mentor +DeckHas:Ability$Counters Oracle:Mentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.) diff --git a/forge-gui/res/cardsfolder/upcoming/blood_operative.txt b/forge-gui/res/cardsfolder/b/blood_operative.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/blood_operative.txt rename to forge-gui/res/cardsfolder/b/blood_operative.txt diff --git a/forge-gui/res/cardsfolder/b/bloodspore_thrinax.txt b/forge-gui/res/cardsfolder/b/bloodspore_thrinax.txt index d47276c7def..5873dca7ecf 100644 --- a/forge-gui/res/cardsfolder/b/bloodspore_thrinax.txt +++ b/forge-gui/res/cardsfolder/b/bloodspore_thrinax.txt @@ -4,7 +4,7 @@ Types:Creature Lizard PT:2/2 K:Devour:1 R:Event$ Moved | ActiveZones$ Battlefield | Destination$ Battlefield | ValidCard$ Creature.YouCtrl+Other | ReplaceWith$ AddExtraCounter | Description$ Each other creature you control enters the battlefield with an additional X +1/+1 counters on it, where X is the number of +1/+1 counters on CARDNAME. -SVar:AddExtraCounter:DB$ PutCounter | ETB$ True | Defined$ ReplacedCard | CounterType$ P1P1 | CounterNum$ X | SubAbility$ MoveToBattlefield +SVar:AddExtraCounter:DB$ PutCounter | ETB$ True | Defined$ ReplacedCard | CounterType$ P1P1 | CounterNum$ X | References$ X | SubAbility$ MoveToBattlefield SVar:MoveToBattlefield:DB$ ChangeZone | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard SVar:X:Count$CardCounters.P1P1 SVar:Picture:http://www.wizards.com/global/images/magic/general/bloodspore_thrinax.jpg diff --git a/forge-gui/res/cardsfolder/upcoming/book_devourer.txt b/forge-gui/res/cardsfolder/b/book_devourer.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/book_devourer.txt rename to forge-gui/res/cardsfolder/b/book_devourer.txt diff --git a/forge-gui/res/cardsfolder/upcoming/boros_challenger.txt b/forge-gui/res/cardsfolder/b/boros_challenger.txt similarity index 93% rename from forge-gui/res/cardsfolder/upcoming/boros_challenger.txt rename to forge-gui/res/cardsfolder/b/boros_challenger.txt index 5e2da20eaf6..4106f4ddc17 100644 --- a/forge-gui/res/cardsfolder/upcoming/boros_challenger.txt +++ b/forge-gui/res/cardsfolder/b/boros_challenger.txt @@ -4,4 +4,5 @@ Types:Creature Human Soldier PT:2/3 K:Mentor A:AB$ Pump | Cost$ 2 R W | NumAtt$ +1 | NumDef$ +1 | SpellDescription$ CARDNAME gets +1/+1 until end of turn. +DeckHas:Ability$Counters Oracle:Mentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.)\n{2}{R}{W}: Boros Challenger gets +1/+1 until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/boros_locket.txt b/forge-gui/res/cardsfolder/b/boros_locket.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/boros_locket.txt rename to forge-gui/res/cardsfolder/b/boros_locket.txt diff --git a/forge-gui/res/cardsfolder/upcoming/bounty_agent.txt b/forge-gui/res/cardsfolder/b/bounty_agent.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/bounty_agent.txt rename to forge-gui/res/cardsfolder/b/bounty_agent.txt diff --git a/forge-gui/res/cardsfolder/upcoming/bounty_of_might.txt b/forge-gui/res/cardsfolder/b/bounty_of_might.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/bounty_of_might.txt rename to forge-gui/res/cardsfolder/b/bounty_of_might.txt diff --git a/forge-gui/res/cardsfolder/b/brood_keeper.txt b/forge-gui/res/cardsfolder/b/brood_keeper.txt index 6a8fbb1b53f..d2a5d38bd28 100644 --- a/forge-gui/res/cardsfolder/b/brood_keeper.txt +++ b/forge-gui/res/cardsfolder/b/brood_keeper.txt @@ -3,8 +3,7 @@ ManaCost:3 R Types:Creature Human Shaman PT:2/3 T:Mode$ Attached | ValidSource$ Aura | ValidTarget$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever an Aura becomes attached to CARDNAME, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn." -SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenName$ Dragon | TokenTypes$ Creature,Dragon | TokenOwner$ You | TokenColors$ Red | TokenPower$ 2 | TokenToughness$ 2 | TokenImage$ r 2 2 dragon M15 | TokenKeywords$ Flying | TokenAbilities$ BroodPump -SVar:BroodPump:AB$ Pump | Cost$ R | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn. +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | LegacyImage$ r 2 2 dragon M15 | TokenScript$ r_2_2_dragon_flying_firebreathing SVar:EnchantMe:Multiple SVar:Picture:http://www.wizards.com/global/images/magic/general/brood_keeper.jpg Oracle:Whenever an Aura becomes attached to Brood Keeper, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn." diff --git a/forge-gui/res/cardsfolder/upcoming/burglar_rat.txt b/forge-gui/res/cardsfolder/b/burglar_rat.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/burglar_rat.txt rename to forge-gui/res/cardsfolder/b/burglar_rat.txt diff --git a/forge-gui/res/cardsfolder/c/caller_of_the_hunt.txt b/forge-gui/res/cardsfolder/c/caller_of_the_hunt.txt index e973b31e704..84849bc4d9d 100644 --- a/forge-gui/res/cardsfolder/c/caller_of_the_hunt.txt +++ b/forge-gui/res/cardsfolder/c/caller_of_the_hunt.txt @@ -2,8 +2,8 @@ Name:Caller of the Hunt ManaCost:2 G Types:Creature Human PT:*/* +A:SP$ PermanentCreature | Cost$ 2 G ChooseCreatureType<1> | AILogic$ MostProminentOnBattlefield S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | SetToughness$ X | Description$ CARDNAME's power and toughness are each equal to the number of creatures of the chosen type on the battlefield. SVar:X:Count$Valid Creature.ChosenType -SVar:FullCost:2 G ChooseCreatureType<1>:MostProminentOnBattlefield SVar:Picture:http://www.wizards.com/global/images/magic/general/caller_of_the_hunt.jpg Oracle:As an additional cost to cast this spell, choose a creature type.\nCaller of the Hunt's power and toughness are each equal to the number of creatures of the chosen type on the battlefield. diff --git a/forge-gui/res/cardsfolder/upcoming/camaraderie.txt b/forge-gui/res/cardsfolder/c/camaraderie.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/camaraderie.txt rename to forge-gui/res/cardsfolder/c/camaraderie.txt diff --git a/forge-gui/res/cardsfolder/upcoming/candlelight_vigil.txt b/forge-gui/res/cardsfolder/c/candlelight_vigil.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/candlelight_vigil.txt rename to forge-gui/res/cardsfolder/c/candlelight_vigil.txt diff --git a/forge-gui/res/cardsfolder/upcoming/capture_sphere.txt b/forge-gui/res/cardsfolder/c/capture_sphere.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/capture_sphere.txt rename to forge-gui/res/cardsfolder/c/capture_sphere.txt diff --git a/forge-gui/res/cardsfolder/c/cemetery_puca.txt b/forge-gui/res/cardsfolder/c/cemetery_puca.txt index 4d7ca05cb20..32881d40dc6 100644 --- a/forge-gui/res/cardsfolder/c/cemetery_puca.txt +++ b/forge-gui/res/cardsfolder/c/cemetery_puca.txt @@ -4,8 +4,7 @@ Types:Creature Shapeshifter PT:1/2 # Make Svars for granting abilities and triggers on clones distinct to avoid SVars getting overwritten when cloning a clone T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature | TriggerZones$ Battlefield | Execute$ CemeteryPucaCopy | TriggerDescription$ Whenever a creature dies, you may pay {1}. If you do, CARDNAME becomes a copy of that creature and gains this ability. -SVar:CemeteryPucaCopy:AB$ Clone | Cost$ 1 | Defined$ TriggeredCardLKICopy | AddTriggers$ CemeteryPucaDiesTrig | AddSVars$ CemeteryPucaCopy,CemeteryPucaDiesTrig -SVar:CemeteryPucaDiesTrig:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature | TriggerZones$ Battlefield | Execute$ CemeteryPucaCopy | TriggerDescription$ Whenever a creature dies, you may pay {1}. If you do, CARDNAME becomes a copy of that creature and gains this ability. +SVar:CemeteryPucaCopy:AB$ Clone | Cost$ 1 | Defined$ TriggeredCardLKICopy | GainThisAbility$ True SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/cemetery_puca.jpg Oracle:Whenever a creature dies, you may pay {1}. If you do, Cemetery Puca becomes a copy of that creature and gains this ability. diff --git a/forge-gui/res/cardsfolder/upcoming/centaur_peacemaker.txt b/forge-gui/res/cardsfolder/c/centaur_peacemaker.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/centaur_peacemaker.txt rename to forge-gui/res/cardsfolder/c/centaur_peacemaker.txt diff --git a/forge-gui/res/cardsfolder/c/cetavolver.txt b/forge-gui/res/cardsfolder/c/cetavolver.txt index bcb10d7d046..d38439abd12 100644 --- a/forge-gui/res/cardsfolder/c/cetavolver.txt +++ b/forge-gui/res/cardsfolder/c/cetavolver.txt @@ -3,13 +3,14 @@ ManaCost:1 U Types:Creature Volver PT:1/1 K:Kicker:1 R:G -T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked 1 | Origin$ Any | Destination$ Battlefield | Execute$ VolverStrength | Static$ True | TriggerDescription$ If CARDNAME was kicked with its {1}{R} kicker, it enters the battlefield with two +1/+1 counters on it and with first strike. -SVar:VolverStrength:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ VolverSpeed -SVar:VolverSpeed:DB$ Pump | Defined$ Self | KW$ First Strike | Permanent$ True -T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked 2 | Origin$ Any | Destination$ Battlefield | Execute$ VolverPumped | Static$ True | TriggerDescription$ If CARDNAME was kicked with its {G} kicker, it enters the battlefield with a +1/+1 counter on it and with trample. -SVar:VolverPumped:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ VolverStomp -SVar:VolverStomp:DB$ Pump | Defined$ Self | KW$ Trample | Permanent$ True +K:ETBReplacement:Other:VolverStrength:Mandatory::Card.Self+kicked 1 +K:ETBReplacement:Other:VolverPumped:Mandatory::Card.Self+kicked 2 +SVar:VolverStrength:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | ETB$ True | SubAbility$ VolverSpeed | SpellDescription$ If CARDNAME was kicked with its {1}{R} kicker, it enters the battlefield with two +1/+1 counters on it and with first strike. +SVar:VolverSpeed:DB$ Animate | Defined$ Self | Keywords$ First Strike | Permanent$ True +SVar:VolverPumped:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ETB$ True | SubAbility$ VolverStomp | SpellDescription$ If CARDNAME was kicked with its {G} kicker, it enters the battlefield with a +1/+1 counter on it and with trample. +SVar:VolverStomp:DB$ Animate | Defined$ Self | Keywords$ Trample | Permanent$ True SVar:RemRandomDeck:True DeckNeeds:Color$Red|Green +DeckHas:Ability$Counters SVar:Picture:http://www.wizards.com/global/images/magic/general/cetavolver.jpg Oracle:Kicker {1}{R} and/or {G} (You may pay an additional {1}{R} and/or {G} as you cast this spell.)\nIf Cetavolver was kicked with its {1}{R} kicker, it enters the battlefield with two +1/+1 counters on it and with first strike.\nIf Cetavolver was kicked with its {G} kicker, it enters the battlefield with a +1/+1 counter on it and with trample. diff --git a/forge-gui/res/cardsfolder/upcoming/chamber_sentry.txt b/forge-gui/res/cardsfolder/c/chamber_sentry.txt similarity index 76% rename from forge-gui/res/cardsfolder/upcoming/chamber_sentry.txt rename to forge-gui/res/cardsfolder/c/chamber_sentry.txt index 69f7c2ac482..cbaa7f301cb 100644 --- a/forge-gui/res/cardsfolder/upcoming/chamber_sentry.txt +++ b/forge-gui/res/cardsfolder/c/chamber_sentry.txt @@ -3,9 +3,10 @@ ManaCost:X Types:Artifact Creature Construct PT:0/0 K:etbCounter:P1P1:Y:no Condition:CARDNAME enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it. -SVar:X:Count$Converge -A:AB$ DealDamage | Announce$ Y | Cost$ Y T SubCounter | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ Y | References$ Y | SpellDescription$ CARDNAME deals Y damage to any target. -SVar:Y:Count$xPaid +SVar:Y:Count$Converge +A:AB$ DealDamage | Announce$ X | Cost$ X T SubCounter | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals X damage to any target. +SVar:X:Count$xPaid A:AB$ ChangeZone | Cost$ W U B R G | Origin$ Graveyard | Destination$ Hand | ActivationZone$ Graveyard | SpellDescription$ Return CARDNAME from your graveyard to your hand. SVar:DiscardMe:1 +DeckHas:Ability$Counters Oracle:Chamber Sentry enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.\n{X}, {T}, Remove X +1/+1 counters from Chamber Sentry: It deals X damage to any target.\n{W}{U}{B}{R}{G}: Return Chamber Sentry from your graveyard to your hand. diff --git a/forge-gui/res/cardsfolder/upcoming/chance_for_glory.txt b/forge-gui/res/cardsfolder/c/chance_for_glory.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/chance_for_glory.txt rename to forge-gui/res/cardsfolder/c/chance_for_glory.txt diff --git a/forge-gui/res/cardsfolder/c/charnel_troll.txt b/forge-gui/res/cardsfolder/c/charnel_troll.txt new file mode 100644 index 00000000000..ab2e2318e6d --- /dev/null +++ b/forge-gui/res/cardsfolder/c/charnel_troll.txt @@ -0,0 +1,15 @@ +Name:Charnel Troll +ManaCost:1 B G +Types:Creature Troll +PT:4/4 +K:Trample +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigExile | TriggerDescription$ At the beginning of your upkeep, exile a creature card from your graveyard. If you do, put a +1/+1 counter on CARDNAME. Otherwise sacrifice it. +SVar:TrigExile:DB$ ChangeZone | Hidden$ True | Mandatory$ True | ChangeType$ Creature.YouOwn | ChangeNum$ 1 | Origin$ Graveyard | Destination$ Exile | RememberChanged$ True | SubAbility$ DBPutCounter +SVar:DBPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | ConditionDefined$ Remembered | ConditionPresent$ Card.Creature | ConditionCompare$ GE1 | SubAbility$ DBSac +SVar:DBSac:DB$ Sacrifice | SacValid# Self | ConditionDefined$ Remembered | ConditionPresent$ Card.Creature | ConditionCompare$ EQ0 | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +A:AB$ PutCounter | Cost$ B G Discard<1/Creature> | CounterType$ P1P1 | CounterNum$ 1 | SpellDescription$ Put a +1/+1 counter on CARDNAME. +SVar:RemRandomDeck:True +DeckNeeds:Ability$Graveyard +DeckHas:Ability$Counters +Oracle:Trample\nAt the beginning of your upkeep, exile a creature card from your graveyard. If you do, put a +1/+1 counter on Charnel Troll. Otherwise sacrifice it.\n{B}{G}, Discard a creature card: Put a +1/+1 counter on Charnel Troll. diff --git a/forge-gui/res/cardsfolder/c/cheering_fanatic.txt b/forge-gui/res/cardsfolder/c/cheering_fanatic.txt new file mode 100644 index 00000000000..e3fc1779b3f --- /dev/null +++ b/forge-gui/res/cardsfolder/c/cheering_fanatic.txt @@ -0,0 +1,10 @@ +Name:Cheering Fanatic +ManaCost:1 R +Types:Creature Goblin +PT:2/2 +T:Mode$ Attacks | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigNameCard | TriggerDescription$ Whenever CARDNAME attacks, choose a card name. Spells with the chosen name cost {1} less to cast this turn. +SVar:TrigNameCard:DB$ NameCard | Defined$ You | SubAbility$ DBEffect +SVar:DBEffect:DB$ Effect | StaticAbilities$ CFReduceCost +SVar:CFReduceCost:Mode$ ReduceCost | EffectZone$ Command | ValidCard$ Card.NamedCard | Type$ Spell | Amount$ 1 | Description$ Spells with the chosen name cost {1} less to cast this turn. +SVar:RemAIDeck:True +Oracle:Whenever Cheering Fanatic attacks, choose a card name. Spells with the chosen name cost {1} less to cast this turn. diff --git a/forge-gui/res/cardsfolder/upcoming/chemisters_insight.txt b/forge-gui/res/cardsfolder/c/chemisters_insight.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/chemisters_insight.txt rename to forge-gui/res/cardsfolder/c/chemisters_insight.txt diff --git a/forge-gui/res/cardsfolder/c/circu_dimir_lobotomist.txt b/forge-gui/res/cardsfolder/c/circu_dimir_lobotomist.txt index e9f0876ed71..9e7a6622855 100644 --- a/forge-gui/res/cardsfolder/c/circu_dimir_lobotomist.txt +++ b/forge-gui/res/cardsfolder/c/circu_dimir_lobotomist.txt @@ -2,15 +2,13 @@ Name:Circu, Dimir Lobotomist ManaCost:2 U B Types:Legendary Creature Human Wizard PT:2/3 -T:Mode$ SpellCast | ValidCard$ Card.Blue | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigLibraryChoice | TriggerDescription$ Whenever you cast a blue spell, exile the top card of target library. -T:Mode$ SpellCast | ValidCard$ Card.Black | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigLibraryChoice | TriggerDescription$ Whenever you cast a black spell, exile the top card of target library. -SVar:TrigLibraryChoice:DB$ ChoosePlayer | Defined$ You | AILogic$ Curse | SubAbility$ ExileTop | ChoiceTitle$ Choose target library -SVar:ExileTop:DB$ Mill | NumCards$ 1 | Defined$ ChosenPlayer | Destination$ Exile | RememberMilled$ True | StackDescription$ None | SubAbility$ DBCleanupChosen -SVar:DBCleanupChosen:DB$ Cleanup | ClearChosenPlayer$ True +T:Mode$ SpellCast | ValidCard$ Card.Blue | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ ExileTop | TriggerDescription$ Whenever you cast a blue spell, exile the top card of target player’s library. +T:Mode$ SpellCast | ValidCard$ Card.Black | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ ExileTop | TriggerDescription$ Whenever you cast a black spell, exile the top card of target player’s library. +SVar:ExileTop:DB$ Mill | NumCards$ 1 | ValidTgts$ Player | TgtPrompt$ Choose a player | Destination$ Exile | RememberMilled$ True S:Mode$ CantBeCast | ValidCard$ Card.nonLand+sharesNameWith Remembered.ExiledWithSource | Caster$ Opponent | Description$ Your opponents can't cast spells with the same name as a card exiled with CARDNAME. T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered+ExiledWithSource | Execute$ DBForget SVar:DBForget:DB$ Pump | ForgetObjects$ TriggeredCard T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | Static$ True | ValidCard$ Card.Self | Execute$ DBCleanup SVar:DBCleanup:DB$Cleanup | ClearRemembered$ True SVar:Picture:http://www.wizards.com/global/images/magic/general/circu_dimir_lobotomist.jpg -Oracle:Whenever you cast a blue spell, exile the top card of target library.\nWhenever you cast a black spell, exile the top card of target library.\nYour opponents can't cast spells with the same name as a card exiled with Circu, Dimir Lobotomist. +Oracle:Whenever you cast a blue spell, exile the top card of target player’s library.\nWhenever you cast a black spell, exile the top card of target player’s library.\nYour opponents can't cast spells with the same name as a card exiled with Circu, Dimir Lobotomist. diff --git a/forge-gui/res/cardsfolder/upcoming/circuitous_route.txt b/forge-gui/res/cardsfolder/c/circuitous_route.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/circuitous_route.txt rename to forge-gui/res/cardsfolder/c/circuitous_route.txt diff --git a/forge-gui/res/cardsfolder/upcoming/citywatch_sphinx.txt b/forge-gui/res/cardsfolder/c/citywatch_sphinx.txt similarity index 66% rename from forge-gui/res/cardsfolder/upcoming/citywatch_sphinx.txt rename to forge-gui/res/cardsfolder/c/citywatch_sphinx.txt index 53008ff4d60..9f332935c10 100644 --- a/forge-gui/res/cardsfolder/upcoming/citywatch_sphinx.txt +++ b/forge-gui/res/cardsfolder/c/citywatch_sphinx.txt @@ -3,6 +3,7 @@ ManaCost:5 U Types:Creature Sphinx PT:5/4 K:Flying -T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigSurveil | TriggerDescription$ When CARDNAME dies, exile 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on the top of your library in any order.) +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigSurveil | TriggerDescription$ When CARDNAME dies, surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on the top of your library in any order.) SVar:TrigSurveil:DB$Surveil | Defined$ You | Amount$ 2 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Flying\nWhen Citywatch Sphinx dies, surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on the top of your library in any order.) diff --git a/forge-gui/res/cardsfolder/upcoming/citywide_bust.txt b/forge-gui/res/cardsfolder/c/citywide_bust.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/citywide_bust.txt rename to forge-gui/res/cardsfolder/c/citywide_bust.txt diff --git a/forge-gui/res/cardsfolder/upcoming/collar_the_culprit.txt b/forge-gui/res/cardsfolder/c/collar_the_culprit.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/collar_the_culprit.txt rename to forge-gui/res/cardsfolder/c/collar_the_culprit.txt diff --git a/forge-gui/res/cardsfolder/upcoming/command_the_storm.txt b/forge-gui/res/cardsfolder/c/command_the_storm.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/command_the_storm.txt rename to forge-gui/res/cardsfolder/c/command_the_storm.txt diff --git a/forge-gui/res/cardsfolder/c/commune_with_lava.txt b/forge-gui/res/cardsfolder/c/commune_with_lava.txt index 091bc727b13..1e92a30b3f8 100644 --- a/forge-gui/res/cardsfolder/c/commune_with_lava.txt +++ b/forge-gui/res/cardsfolder/c/commune_with_lava.txt @@ -1,16 +1,10 @@ Name:Commune with Lava ManaCost:X R R Types:Instant -A:SP$ Mill | Cost$ X R R | Defined$ You | NumCards$ X | Destination$ Exile | RememberMilled$ True | References$ X | SubAbility$ DBStoreTurn | SpellDescription$ Exile the top X cards of your library. Until the end of your next turn, you may play those cards. -SVar:DBStoreTurn:DB$ StoreSVar | SVar$ CurrentTurn | Type$ Count | Expression$ YourTurns | SubAbility$ DBMayBePlay -SVar:DBMayBePlay:DB$ Effect | StaticAbilities$ STCommuned | Duration$ Permanent | RememberObjects$ Remembered | Triggers$ TrigDuration | SVars$ DBDuration,EndDuration,CurrentTurn | ForgetOnMoved$ Exile -# Even though the Effect is "Permanent", it's not really permanent +A:SP$ Mill | Cost$ X R R | Defined$ You | NumCards$ X | Destination$ Exile | RememberMilled$ True | References$ X | SubAbility$ DBMayBePlay | SpellDescription$ Exile the top X cards of your library. Until the end of your next turn, you may play those cards. +SVar:DBMayBePlay:DB$ Effect | StaticAbilities$ STCommuned | Duration$ UntilTheEndOfYourNextTurn | RememberObjects$ Remembered | ForgetOnMoved$ Exile SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:STCommuned:Mode$ Continuous | Affected$ Card.IsRemembered | EffectZone$ Command | AffectedZone$ Exile | MayPlay$ True | Description$ Until the end of your next turn, you may play those cards. -SVar:TrigDuration:Mode$ Phase | Phase$ Cleanup | Static$ True | TriggerZones$ Command | Execute$ DBDuration | CheckSVar$ EndDuration | SVarCompare$ GTCurrentTurn -SVar:DBDuration:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile -SVar:EndDuration:Count$YourTurns -SVar:CurrentTurn:Number$0 SVar:X:Count$xPaid SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/commune_with_lava.jpg diff --git a/forge-gui/res/cardsfolder/upcoming/conclave_cavalier.txt b/forge-gui/res/cardsfolder/c/conclave_cavalier.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/conclave_cavalier.txt rename to forge-gui/res/cardsfolder/c/conclave_cavalier.txt diff --git a/forge-gui/res/cardsfolder/upcoming/conclave_guildmage.txt b/forge-gui/res/cardsfolder/c/conclave_guildmage.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/conclave_guildmage.txt rename to forge-gui/res/cardsfolder/c/conclave_guildmage.txt diff --git a/forge-gui/res/cardsfolder/upcoming/conclave_tribunal.txt b/forge-gui/res/cardsfolder/c/conclave_tribunal.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/conclave_tribunal.txt rename to forge-gui/res/cardsfolder/c/conclave_tribunal.txt diff --git a/forge-gui/res/cardsfolder/upcoming/connive_concoct.txt b/forge-gui/res/cardsfolder/c/connive_concoct.txt similarity index 94% rename from forge-gui/res/cardsfolder/upcoming/connive_concoct.txt rename to forge-gui/res/cardsfolder/c/connive_concoct.txt index 3bc243c7625..1e45b353c28 100644 --- a/forge-gui/res/cardsfolder/upcoming/connive_concoct.txt +++ b/forge-gui/res/cardsfolder/c/connive_concoct.txt @@ -12,4 +12,5 @@ ManaCost:3 U B Types:Sorcery A:SP$ Surveil | Cost$ 3 U B | Amount$ 3 | SubAbility$ DBReturn | SpellDescription$ Surveil 3, then return a creature card from your graveyard to the battlefield. SVar:DBReturn:DB$ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.YouCtrl | ChangeNum$ 1 | Hidden$ True +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Surveil 3, then return a creature card from your graveyard to the battlefield. diff --git a/forge-gui/res/cardsfolder/upcoming/cosmotronic_wave.txt b/forge-gui/res/cardsfolder/c/cosmotronic_wave.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/cosmotronic_wave.txt rename to forge-gui/res/cardsfolder/c/cosmotronic_wave.txt diff --git a/forge-gui/res/cardsfolder/c/coveted_jewel.txt b/forge-gui/res/cardsfolder/c/coveted_jewel.txt new file mode 100644 index 00000000000..da77f2a0ac9 --- /dev/null +++ b/forge-gui/res/cardsfolder/c/coveted_jewel.txt @@ -0,0 +1,10 @@ +Name:Coveted Jewel +ManaCost:6 +Types:Artifact +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME enters the battlefield, draw three cards. +SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 3 +A:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 3 | SpellDescription$ Add three mana of any one color. +T:Mode$ AttackerUnblockedOnce | ValidAttackingPlayer$ Player.Opponent | ValidDefenders$ You | TriggerZones$ Battlefield | Execute$ TrigDraw2 | TriggerDescription$ Whenever one or more creatures an opponent controls attack you and aren't blocked, that player draws three cards and gains control of CARDNAME. Untap it. +SVar:TrigDraw2:DB$ Draw | Defined$ TriggeredAttackingPlayer | NumCards$ 3 | SubAbility$ DBGainGontrol +SVar:DBGainGontrol:DB$ GainControl | NewController$ TriggeredAttackingPlayer | Untap$ True +Oracle:When Coveted Jewel enters the battlefield, draw three cards.\n{T}: Add three mana of any one color.\nWhenever one or more creatures an opponent controls attack you and aren't blocked, that player draws three cards and gains control of Coveted Jewel. Untap it. diff --git a/forge-gui/res/cardsfolder/c/crackling_drake.txt b/forge-gui/res/cardsfolder/c/crackling_drake.txt new file mode 100644 index 00000000000..9cdd75848e4 --- /dev/null +++ b/forge-gui/res/cardsfolder/c/crackling_drake.txt @@ -0,0 +1,13 @@ +Name:Crackling Drake +ManaCost:U U R R +Types:Creature Drake +PT:*/4 +K:Flying +S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | References$ X,GraveCount,ExileCount | Description$ CARDNAME's power is equal to the total number of instant and sorcery cards you own in exile and in your graveyard. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME enters the battlefield, draw a card. +SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 +SVar:GraveCount:Count$ValidGraveyard Instant.YouOwn,Sorcery.YouOwn +SVar:ExileCount:Count$ValidExile Instant.YouOwn,Sorcery.YouOwn +SVar:X:SVar$GraveCount/Plus.ExileCount +DeckNeeds:Type$Instant|Sorcery +Oracle:Flying\nCrackling Drake's power is equal to the total number of instant and sorcery cards you own in exile and in your graveyard.\nWhen Crackling Drake enters the battlefield, draw a card. diff --git a/forge-gui/res/cardsfolder/upcoming/creeping_chill.txt b/forge-gui/res/cardsfolder/c/creeping_chill.txt similarity index 77% rename from forge-gui/res/cardsfolder/upcoming/creeping_chill.txt rename to forge-gui/res/cardsfolder/c/creeping_chill.txt index 48aaddf378e..8f9c247bf82 100644 --- a/forge-gui/res/cardsfolder/upcoming/creeping_chill.txt +++ b/forge-gui/res/cardsfolder/c/creeping_chill.txt @@ -1,7 +1,7 @@ Name:Creeping Chill ManaCost:3 B Types:Sorcery -A:SP$ DamageAll | Cost$ 3 B | ValidPlayers$ Player.Opponent | NumDmg$ 3 | SubAbility$ DBGainLife | SpellDescription$ CARDNAME deals 3 damage to each opponent and you gain 3 life. +A:SP$ DamageAll | StackDescription$ CARDNAME deals 3 damage to each opponent and | Cost$ 3 B | ValidPlayers$ Player.Opponent | NumDmg$ 3 | SubAbility$ DBGainLife | SpellDescription$ CARDNAME deals 3 damage to each opponent and you gain 3 life. T:Mode$ ChangesZone | Origin$ Library | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | OptionalDecider$ You | TriggerDescription$ When CARDNAME is put into your graveyard from your library, you may exile it. If you do, then a opponent and you gain 3 life. SVar:TrigExile:DB$ ChangeZone | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBDamage SVar:DBDamage:DB$ DealDamage | Defined$ Player.Opponent | NumDmg$ 3 | SubAbility$ DBGainLife diff --git a/forge-gui/res/cardsfolder/upcoming/crush_contraband.txt b/forge-gui/res/cardsfolder/c/crush_contraband.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/crush_contraband.txt rename to forge-gui/res/cardsfolder/c/crush_contraband.txt diff --git a/forge-gui/res/cardsfolder/c/cryptoplasm.txt b/forge-gui/res/cardsfolder/c/cryptoplasm.txt index 914174829f3..48335f9a6f7 100644 --- a/forge-gui/res/cardsfolder/c/cryptoplasm.txt +++ b/forge-gui/res/cardsfolder/c/cryptoplasm.txt @@ -4,8 +4,7 @@ Types:Creature Shapeshifter PT:2/2 # Make Svars for granting abilities and triggers on clones distinct to avoid SVars getting overwritten when cloning a clone T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ CryptoplasmCopy | OptionalDecider$ You | TriggerDescription$ At the beginning of your upkeep, you may have CARDNAME become a copy of another target creature. If you do, CARDNAME gains this ability. -SVar:CryptoplasmCopy:DB$ Clone | ValidTgts$ Creature.Other | TgtPrompt$ Select another target creature to copy. | Optional$ True | AddTriggers$ CryptoplasmUpkeepTrig | AddSVars$ CryptoplasmCopy,CryptoplasmUpkeepTrig -SVar:CryptoplasmUpkeepTrig:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ CryptoplasmCopy | TriggerDescription$ At the beginning of your upkeep, you may have CARDNAME become a copy of another target creature. If you do, CARDNAME gains this ability. +SVar:CryptoplasmCopy:DB$ Clone | ValidTgts$ Creature.Other | TgtPrompt$ Select another target creature to copy. | Optional$ True | GainThisAbility$ True SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/cryptoplasm.jpg Oracle:At the beginning of your upkeep, you may have Cryptoplasm become a copy of another target creature. If you do, Cryptoplasm gains this ability. diff --git a/forge-gui/res/cardsfolder/c/crystal_seer.txt b/forge-gui/res/cardsfolder/c/crystal_seer.txt index e8a3d309cfc..75e00bf20e8 100644 --- a/forge-gui/res/cardsfolder/c/crystal_seer.txt +++ b/forge-gui/res/cardsfolder/c/crystal_seer.txt @@ -5,6 +5,6 @@ PT:2/2 A:AB$ ChangeZone | Cost$ 4 U | Origin$ Battlefield | Destination$ Hand | Defined$ Self | SpellDescription$ Return CARDNAME to it's owner's hand. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRearrange | TriggerDescription$ When CARDNAME enters the battlefield, look at the top four cards of your library, then put them back in any order. SVar:TrigRearrange:DB$ RearrangeTopOfLibrary | Defined$ You | NumCards$ 4 -Svar:RemAIDeck:True +SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/crystal_seer.jpg Oracle:When Crystal Seer enters the battlefield, look at the top four cards of your library, then put them back in any order.\n{4}{U}: Return Crystal Seer to its owner's hand. diff --git a/forge-gui/res/cardsfolder/upcoming/darkblade_agent.txt b/forge-gui/res/cardsfolder/d/darkblade_agent.txt similarity index 69% rename from forge-gui/res/cardsfolder/upcoming/darkblade_agent.txt rename to forge-gui/res/cardsfolder/d/darkblade_agent.txt index 0f933fee1e8..d3a1b48e76e 100644 --- a/forge-gui/res/cardsfolder/upcoming/darkblade_agent.txt +++ b/forge-gui/res/cardsfolder/d/darkblade_agent.txt @@ -2,8 +2,9 @@ Name:Darkblade Agent ManaCost:1 U B Types:Creature Human Assassin PT:2/3 -S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Deathtouch | AddTrigger$ Trig1 | AddSVar$ TrigDraw | CheckSVar$ X | SVarCompare$ GE1 | Description$ As long as you've surveilled this turn, CARDNAME has deathtouch and and whenever Whenever this creature deals combat damage to a player, draw a card. +S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Deathtouch | AddTrigger$ Trig1 | AddSVar$ TrigDraw | CheckSVar$ X | SVarCompare$ GE1 | Description$ As long as you've surveilled this turn, CARDNAME has deathtouch and "Whenever this creature deals combat damage to a player, draw a card." SVar:Trig1:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigDraw | TriggerDescription$ Whenever this creature deals combat damage to a player, draw a card. SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 SVar:X:Count$YouSurveilThisTurn +DeckHints:Ability$Surveil Oracle:As long as you've surveilled this turn, Darkblade Agent has deathtouch and "Whenever this creature deals combat damage to a player, draw a card." diff --git a/forge-gui/res/cardsfolder/upcoming/dawn_of_hope.txt b/forge-gui/res/cardsfolder/d/dawn_of_hope.txt similarity index 93% rename from forge-gui/res/cardsfolder/upcoming/dawn_of_hope.txt rename to forge-gui/res/cardsfolder/d/dawn_of_hope.txt index b53adb802e6..65c4c6d514d 100644 --- a/forge-gui/res/cardsfolder/upcoming/dawn_of_hope.txt +++ b/forge-gui/res/cardsfolder/d/dawn_of_hope.txt @@ -4,5 +4,5 @@ Types:Enchantment T:Mode$ LifeGained | ValidPlayer$ You | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigDraw | TriggerDescription$ Whenever you gain life, you may pay {2}. If you do, draw a card. SVar:TrigDraw:AB$Draw | Cost$ 2 | Defined$ You | NumCards$ 1 A:AB$ Token | Cost$ 3 W | TokenAmount$ 1 | TokenScript$ w_1_1_soldier_lifelink | SpellDescription$ Create a 1/1 white Soldier creature token with lifelink. -DeckHas:Ability$Token +DeckHas:Ability$Token & Ability$LifeGain Oracle:Whenever you gain life, you may pay {2}. If you do, draw a card.\n{3}{W}: Create a 1/1 white Soldier creature token with lifelink. diff --git a/forge-gui/res/cardsfolder/upcoming/dazzling_lights.txt b/forge-gui/res/cardsfolder/d/dazzling_lights.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/dazzling_lights.txt rename to forge-gui/res/cardsfolder/d/dazzling_lights.txt index 76b9fdb89d6..8745c904b1a 100644 --- a/forge-gui/res/cardsfolder/upcoming/dazzling_lights.txt +++ b/forge-gui/res/cardsfolder/d/dazzling_lights.txt @@ -3,4 +3,5 @@ ManaCost:U Types:Instant A:SP$ Pump | Cost$ U | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ -3 | IsCurse$ True | Subability$ DBSurveil | SpellDescription$ Target creature gets -3/-0 until end of turn. Surveil 2. SVar:DBSurveil:DB$ Surveil | Defined$ You | Amount$ 2 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Target creature gets -3/-0 until end of turn.\nSurveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on the top of your library in any order.) diff --git a/forge-gui/res/cardsfolder/upcoming/deadly_visit.txt b/forge-gui/res/cardsfolder/d/deadly_visit.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/deadly_visit.txt rename to forge-gui/res/cardsfolder/d/deadly_visit.txt index 26792d9be3a..d211ef31cfb 100644 --- a/forge-gui/res/cardsfolder/upcoming/deadly_visit.txt +++ b/forge-gui/res/cardsfolder/d/deadly_visit.txt @@ -3,4 +3,5 @@ ManaCost:3 B B Types:Sorcery A:SP$ Destroy | Cost$ 3 B B | ValidTgts$ Creature | TgtPrompt$ Select target creature | Subability$ DBSurveil | SpellDescription$ Destroy target creature. Surveil 2 (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on top of your library in any order.) SVar:DBSurveil:DB$ Surveil | Amount$ 2 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Destroy target creature.\nSurveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on top of your library in any order.) diff --git a/forge-gui/res/cardsfolder/upcoming/deafening_clarion.txt b/forge-gui/res/cardsfolder/d/deafening_clarion.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/deafening_clarion.txt rename to forge-gui/res/cardsfolder/d/deafening_clarion.txt diff --git a/forge-gui/res/cardsfolder/d/degavolver.txt b/forge-gui/res/cardsfolder/d/degavolver.txt index 57e5cb5e15d..90a364e97ff 100644 --- a/forge-gui/res/cardsfolder/d/degavolver.txt +++ b/forge-gui/res/cardsfolder/d/degavolver.txt @@ -3,14 +3,15 @@ ManaCost:1 W Types:Creature Volver PT:1/1 K:Kicker:1 B:R -T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked 1 | Origin$ Any | Destination$ Battlefield | Execute$ VolverStrength | Static$ True | TriggerDescription$ If CARDNAME was kicked with its {1}{B} kicker, it enters the battlefield with two +1/+1 counters on it and with "Pay 3 life: Regenerate CARDNAME." -SVar:VolverStrength:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ VolverResilience +K:ETBReplacement:Other:VolverStrength:Mandatory::Card.Self+kicked 1 +K:ETBReplacement:Other:VolverPumped:Mandatory::Card.Self+kicked 2 +SVar:VolverStrength:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | ETB$ True | SubAbility$ VolverResilience | SpellDescription$ If CARDNAME was kicked with its {1}{B} kicker, it enters the battlefield with two +1/+1 counters on it and with "Pay 3 life: Regenerate CARDNAME." SVar:VolverResilience:DB$ Animate | Defined$ Self | Abilities$ ABRegen | Permanent$ True SVar:ABRegen:AB$Regenerate | Cost$ PayLife<3> | SpellDescription$ Regenerate CARDNAME. -T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked 2 | Origin$ Any | Destination$ Battlefield | Execute$ VolverPumped | Static$ True | TriggerDescription$ If CARDNAME was kicked with its {R} kicker, it enters the battlefield with a +1/+1 counter on it and with first strike. -SVar:VolverPumped:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ VolverSpeed -SVar:VolverSpeed:DB$ Pump | Defined$ Self | KW$ First Strike | Permanent$ True +SVar:VolverPumped:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ETB$ True | SubAbility$ VolverSpeed | SpellDescription$ If CARDNAME was kicked with its {R} kicker, it enters the battlefield with a +1/+1 counter on it and with first strike. +SVar:VolverSpeed:DB$ Animate | Defined$ Self | Keywords$ First Strike | Permanent$ True SVar:RemRandomDeck:True DeckNeeds:Color$Black|Red +DeckHas:Ability$Counters SVar:Picture:http://www.wizards.com/global/images/magic/general/degavolver.jpg Oracle:Kicker {1}{B} and/or {R} (You may pay an additional {1}{B} and/or {R} as you cast this spell.)\nIf Degavolver was kicked with its {1}{B} kicker, it enters the battlefield with two +1/+1 counters on it and with "Pay 3 life: Regenerate Degavolver."\nIf Degavolver was kicked with its {R} kicker, it enters the battlefield with a +1/+1 counter on it and with first strike. diff --git a/forge-gui/res/cardsfolder/d/delifs_cone.txt b/forge-gui/res/cardsfolder/d/delifs_cone.txt index 58dc5ac4468..5940d97a3e1 100644 --- a/forge-gui/res/cardsfolder/d/delifs_cone.txt +++ b/forge-gui/res/cardsfolder/d/delifs_cone.txt @@ -1,11 +1,11 @@ Name:Delif's Cone ManaCost:0 Types:Artifact -A:AB$ Animate | Cost$ T Sac<1/CARDNAME> | ValidTgts$ Creature.YouCtrl | Triggers$ TrigAttackerUnblocked | sVars$ GainLife,DBPump,DelifX | SpellDescription$ This turn, when target creature you control attacks and isn't blocked, you may gain life equal to its power. If you do, it assigns no combat damage this turn. -SVar:TrigAttackerUnblocked:Mode$ AttackerUnblocked | ValidCard$ Card.Self | Execute$ GainLife | OptionalDecider$ You | TriggerDescription$ This turn, when CARDNAME attacks and isn't blocked, you may gain life equal to its power. If you do, it assigns no combat damage this turn. +A:AB$ Effect | Cost$ T Sac<1/CARDNAME> | ValidTgts$ Creature.YouCtrl | Triggers$ TrigAttackerUnblocked | SVars$ GainLife,DBPump,DelifX | RememberObjects$ Targeted | ForgetOnMoved$ Battlefield | SpellDescription$ This turn, when target creature you control attacks and isn't blocked, you may gain life equal to its power. If you do, it assigns no combat damage this turn. +SVar:TrigAttackerUnblocked:Mode$ AttackerUnblocked | ValidCard$ Card.IsRemembered | Execute$ GainLife | OptionalDecider$ You | TriggerDescription$ This turn, when that creature attacks and isn't blocked, you may gain life equal to its power. If you do, it assigns no combat damage this turn. SVar:GainLife:DB$ GainLife | Defined$ You | LifeAmount$ DelifX | SubAbility$ DBPump | References$ DelifX -SVar:DBPump:DB$Pump | Defined$ Self | KW$ HIDDEN CARDNAME assigns no combat damage | StackDescription$ CARDNAME assigns no combat damage this turn. -SVar:DelifX:Count$CardPower +SVar:DBPump:DB$ Pump | Defined$ Remembered | KW$ HIDDEN CARDNAME assigns no combat damage | StackDescription$ {c:Remembered} assigns no combat damage this turn. +SVar:DelifX:Remembered$CardPower SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/delifs_cone.jpg Oracle:{T}, Sacrifice Delif's Cone: This turn, when target creature you control attacks and isn't blocked, you may gain life equal to its power. If you do, it assigns no combat damage this turn. diff --git a/forge-gui/res/cardsfolder/d/demon_of_catastrophes.txt b/forge-gui/res/cardsfolder/d/demon_of_catastrophes.txt index 46e66c30d4e..6430b6d7601 100644 --- a/forge-gui/res/cardsfolder/d/demon_of_catastrophes.txt +++ b/forge-gui/res/cardsfolder/d/demon_of_catastrophes.txt @@ -4,5 +4,5 @@ Types:Creature Demon PT:6/6 K:Flying K:Trample -SVar:FullCost:2 B B Sac<1/Creature> +A:SP$ PermanentCreature | Cost$ 2 B B Sac<1/Creature> Oracle:As an additional cost to cast this spell, sacrifice a creature\n Flying, trample \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/demotion.txt b/forge-gui/res/cardsfolder/d/demotion.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/demotion.txt rename to forge-gui/res/cardsfolder/d/demotion.txt diff --git a/forge-gui/res/cardsfolder/upcoming/devious_cover_up.txt b/forge-gui/res/cardsfolder/d/devious_cover_up.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/devious_cover_up.txt rename to forge-gui/res/cardsfolder/d/devious_cover_up.txt diff --git a/forge-gui/res/cardsfolder/upcoming/devkarin_dissident.txt b/forge-gui/res/cardsfolder/d/devkarin_dissident.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/devkarin_dissident.txt rename to forge-gui/res/cardsfolder/d/devkarin_dissident.txt diff --git a/forge-gui/res/cardsfolder/d/dimir_doppelganger.txt b/forge-gui/res/cardsfolder/d/dimir_doppelganger.txt index c8b7f3799a0..f12f300c4ba 100644 --- a/forge-gui/res/cardsfolder/d/dimir_doppelganger.txt +++ b/forge-gui/res/cardsfolder/d/dimir_doppelganger.txt @@ -4,8 +4,7 @@ Types:Creature Shapeshifter PT:0/2 # Make Svars for granting abilities and triggers on clones distinct to avoid SVars getting overwritten when cloning a clone A:AB$ ChangeZone | Cost$ 1 U B | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Creature | RememberTargets$ True | ForgetOtherTargets$ True | SubAbility$ DDCopy | SpellDescription$ Exile target creature card from a graveyard. CARDNAME becomes a copy of that card and gains this ability. -SVar:DDCopy:DB$ Clone | Defined$ Remembered | AddAbilities$ DDAbility | AddSVars$ DDAbility,DDCopy -SVar:DDAbility:AB$ ChangeZone | Cost$ 1 U B | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Creature | RememberTargets$ True | ForgetOtherTargets$ True | SubAbility$ DDCopy | SpellDescription$ Exile target creature card from a graveyard. CARDNAME becomes a copy of that card and gains this ability. +SVar:DDCopy:DB$ Clone | Defined$ Remembered | GainThisAbility$ True SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/dimir_doppelganger.jpg Oracle:{1}{U}{B}: Exile target creature card from a graveyard. Dimir Doppelganger becomes a copy of that card and gains this ability. diff --git a/forge-gui/res/cardsfolder/upcoming/dimir_informant.txt b/forge-gui/res/cardsfolder/d/dimir_informant.txt similarity index 93% rename from forge-gui/res/cardsfolder/upcoming/dimir_informant.txt rename to forge-gui/res/cardsfolder/d/dimir_informant.txt index 5cb18e6f8a1..cd9104c4b42 100644 --- a/forge-gui/res/cardsfolder/upcoming/dimir_informant.txt +++ b/forge-gui/res/cardsfolder/d/dimir_informant.txt @@ -4,4 +4,5 @@ Types:Creature Human Rogue PT:1/4 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSurveil | TriggerDescription$ When CARDNAME enters the battlefield, then surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on the top of your library in any order.) SVar:TrigSurveil:DB$Surveil | Defined$ You | Amount$ 2 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:When Dimir Informant enters the battlefield, surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on the top of your library in any order.) diff --git a/forge-gui/res/cardsfolder/upcoming/dimir_locket.txt b/forge-gui/res/cardsfolder/d/dimir_locket.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/dimir_locket.txt rename to forge-gui/res/cardsfolder/d/dimir_locket.txt diff --git a/forge-gui/res/cardsfolder/upcoming/dimir_spybug.txt b/forge-gui/res/cardsfolder/d/dimir_spybug.txt similarity index 90% rename from forge-gui/res/cardsfolder/upcoming/dimir_spybug.txt rename to forge-gui/res/cardsfolder/d/dimir_spybug.txt index a0ab2b0ff30..4880d824087 100644 --- a/forge-gui/res/cardsfolder/upcoming/dimir_spybug.txt +++ b/forge-gui/res/cardsfolder/d/dimir_spybug.txt @@ -6,4 +6,6 @@ K:Flying K:Menace T:Mode$ Surveil | ValidPlayer$ You | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ Whenever you surveil, put a +1/+1 counter on CARDNAME. SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 +DeckHints:Ability$Surveil +DeckHas:Ability$Counters Oracle:Flying\nMenace (This creature can't be blocked except by two or more creatures.)\nWhenever you surveil, put a +1/+1 counter on Dimir Spybug. diff --git a/forge-gui/res/cardsfolder/upcoming/direct_current.txt b/forge-gui/res/cardsfolder/d/direct_current.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/direct_current.txt rename to forge-gui/res/cardsfolder/d/direct_current.txt diff --git a/forge-gui/res/cardsfolder/d/discovery_dispersal.txt b/forge-gui/res/cardsfolder/d/discovery_dispersal.txt new file mode 100644 index 00000000000..bcf7d315b13 --- /dev/null +++ b/forge-gui/res/cardsfolder/d/discovery_dispersal.txt @@ -0,0 +1,20 @@ +Name:Discovery +ManaCost:1 U/B +Types:Sorcery +AlternateMode:Split +A:SP$ Surveil | Cost$ 1 U/B | Amount$ 2 | SubAbility$ DBDraw | SpellDescription$ Surveil 2, then draw a card. +SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 1 +DeckHas:Ability$Surveil & Ability$Graveyard +Oracle:Surveil 2, then draw a card. (To surveil 2, look at the top two cards of your library, then put any number of them into your graveyard and the rest on top of your library in any order.) + +ALTERNATE + +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: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 +Oracle: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. diff --git a/forge-gui/res/cardsfolder/upcoming/disinformation_campaign.txt b/forge-gui/res/cardsfolder/d/disinformation_campaign.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/disinformation_campaign.txt rename to forge-gui/res/cardsfolder/d/disinformation_campaign.txt index 3af7a783fff..4f4cc7c1072 100644 --- a/forge-gui/res/cardsfolder/upcoming/disinformation_campaign.txt +++ b/forge-gui/res/cardsfolder/d/disinformation_campaign.txt @@ -4,6 +4,7 @@ Types:Enchantment T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME enters the battlefield, you draw a card and each opponent discards a card. SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 | SubAbility$ DBDiscard SVar:DBDiscard:DB$ Discard | Defined$ Player.Opponent | NumCards$ 1 | Mode$ TgtChoose -T:Mode$ Surveil | ValidPlayer$ You | Execute$ TrigBounce | TriggerZones$ Battlefield | TriggerDescription$ Whenever you surveil, return Disinformation Campaign to its owner's hand. +T:Mode$ Surveil | ValidPlayer$ You | Execute$ TrigBounce | TriggerZones$ Battlefield | TriggerDescription$ Whenever you surveil, return CARDNAME to its owner's hand. SVar:TrigBounce:DB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Defined$ Self +DeckHints:Ability$Surveil Oracle:When Disinformation Campaign enters the battlefield, you draw a card and each opponent discards a card.\nWhenever you surveil, return Disinformation Campaign to its owner's hand. diff --git a/forge-gui/res/cardsfolder/upcoming/district_guide.txt b/forge-gui/res/cardsfolder/d/district_guide.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/district_guide.txt rename to forge-gui/res/cardsfolder/d/district_guide.txt diff --git a/forge-gui/res/cardsfolder/upcoming/divine_visitation.txt b/forge-gui/res/cardsfolder/d/divine_visitation.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/divine_visitation.txt rename to forge-gui/res/cardsfolder/d/divine_visitation.txt diff --git a/forge-gui/res/cardsfolder/upcoming/doom_whisperer.txt b/forge-gui/res/cardsfolder/d/doom_whisperer.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/doom_whisperer.txt rename to forge-gui/res/cardsfolder/d/doom_whisperer.txt index ea6bdf4f39a..469af683112 100644 --- a/forge-gui/res/cardsfolder/upcoming/doom_whisperer.txt +++ b/forge-gui/res/cardsfolder/d/doom_whisperer.txt @@ -5,4 +5,5 @@ PT:6/6 K:Flying K:Trample A:AB$ Surveil | Cost$ PayLife<2> | Amount$ 2 | SpellDescription$ Surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on the top of your library in any order.) +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Flying, trample\nPay 2 life: Surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on the top of your library in any order.) diff --git a/forge-gui/res/cardsfolder/upcoming/douser_of_lights.txt b/forge-gui/res/cardsfolder/d/douser_of_lights.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/douser_of_lights.txt rename to forge-gui/res/cardsfolder/d/douser_of_lights.txt diff --git a/forge-gui/res/cardsfolder/d/dragon_egg.txt b/forge-gui/res/cardsfolder/d/dragon_egg.txt index d863c2e64c3..547e764ae7c 100644 --- a/forge-gui/res/cardsfolder/d/dragon_egg.txt +++ b/forge-gui/res/cardsfolder/d/dragon_egg.txt @@ -4,8 +4,7 @@ Types:Creature Dragon Egg PT:0/2 K:Defender T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn". -SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenName$ Dragon | TokenTypes$ Creature,Dragon | TokenOwner$ You | TokenColors$ Red | TokenPower$ 2 | TokenToughness$ 2 | TokenImage$ r 2 2 dragon M14 | TokenKeywords$ Flying | TokenAbilities$ DragonPump -SVar:DragonPump:AB$ Pump | Cost$ R | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn. +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | LegacyImage$ r 2 2 dragon M14 | TokenScript$ r_2_2_dragon_flying_firebreathing SVar:SacMe:4 DeckHas:Ability$Token SVar:Picture:http://www.wizards.com/global/images/magic/general/dragon_egg.jpg diff --git a/forge-gui/res/cardsfolder/upcoming/dream_eater.txt b/forge-gui/res/cardsfolder/d/dream_eater.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/dream_eater.txt rename to forge-gui/res/cardsfolder/d/dream_eater.txt index fddbdb90ac9..99a06b972ac 100644 --- a/forge-gui/res/cardsfolder/upcoming/dream_eater.txt +++ b/forge-gui/res/cardsfolder/d/dream_eater.txt @@ -8,4 +8,5 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.S SVar:TrigSurveil:DB$ Surveil | Defined$ You | Amount$ 4 | SubAbility$ TrigImmediate SVar:TrigImmediate:DB$ ImmediateTrigger | Execute$ TrigBounce | OptionalDecider$ You | TriggerDescription$ When you do, you may return target nonland permanent an opponent controls to its owner's hand. SVar:TrigBounce:DB$ ChangeZone | ValidTgts$ Permanent.nonLand+OppCtrl | TgtPrompt$ Select target nonland permanent an opponent controls | Origin$ Battlefield | Destination$ Hand +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Flash\nFlying\nWhen Dream Eater enters the battlefield, surveil 4. When you do, you may return target nonland permanent an opponent controls to its owner's hand. (To surveil 4, look at the top four cards of your library, then put any number of them into your graveyard and the rest on top of your library in any order.) diff --git a/forge-gui/res/cardsfolder/upcoming/drowned_secrets.txt b/forge-gui/res/cardsfolder/d/drowned_secrets.txt similarity index 76% rename from forge-gui/res/cardsfolder/upcoming/drowned_secrets.txt rename to forge-gui/res/cardsfolder/d/drowned_secrets.txt index 2bf1b893bc0..d8e0e2153d0 100644 --- a/forge-gui/res/cardsfolder/upcoming/drowned_secrets.txt +++ b/forge-gui/res/cardsfolder/d/drowned_secrets.txt @@ -1,7 +1,8 @@ Name:Drowned Secrets ManaCost:1 U Types:Enchantment -T:Mode$ SpellCast | ValidCard$ Card.Blue | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigMill | TriggerDescription$ Whenever you cast a blue spell, target player puts the top two cards if their library into their graveyard. +T:Mode$ SpellCast | ValidCard$ Card.Blue | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigMill | TriggerDescription$ Whenever you cast a blue spell, target player puts the top two cards of their library into their graveyard. SVar:TrigMill:DB$Mill | NumCards$ 2 | ValidTgts$ Player | TgtPrompt$ Select target player SVar:BuffedBy:Card.Blue -Oracle:Whenever you cast a blue spell, target player puts the top two cards if their library into their graveyard. +DeckHas:Ability$Graveyard +Oracle:Whenever you cast a blue spell, target player puts the top two cards of their library into their graveyard. diff --git a/forge-gui/res/cardsfolder/e/echo_storm.txt b/forge-gui/res/cardsfolder/e/echo_storm.txt new file mode 100644 index 00000000000..24fb9ef5449 --- /dev/null +++ b/forge-gui/res/cardsfolder/e/echo_storm.txt @@ -0,0 +1,9 @@ +Name:Echo Storm +ManaCost:3 U U +Types:Sorcery +T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When you cast this spell, copy it for each time you've cast your commander from the command zone this game. +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:X:Count$TotalCommanderCastFromCommandZone +A:SP$ CopyPermanent | Cost$ 3 U U | ValidTgts$ Artifact | TgtPrompt$ Select target artifact. | SpellDescription$ Create a token that's a copy of target artifact. +DeckHas:Ability$Token +Oracle:When you cast this spell, copy it for each time you've cast your commander from the command zone this game. You may choose new targets for the copies.\nCreate a token that's a copy of target artifact. diff --git a/forge-gui/res/cardsfolder/upcoming/electrostatic_field.txt b/forge-gui/res/cardsfolder/e/electrostatic_field.txt similarity index 94% rename from forge-gui/res/cardsfolder/upcoming/electrostatic_field.txt rename to forge-gui/res/cardsfolder/e/electrostatic_field.txt index fbb8fdd3b2d..21044c85700 100644 --- a/forge-gui/res/cardsfolder/upcoming/electrostatic_field.txt +++ b/forge-gui/res/cardsfolder/e/electrostatic_field.txt @@ -5,4 +5,5 @@ PT:0/4 K:Defender T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDealDamage | TriggerDescription$ When you cast an instant or sorcery spell, CARDNAME deals 1 damage to each opponent. SVar:TrigDealDamage:DB$ DealDamage | Defined$ Player.Opponent | NumDmg$ 1 +DeckHints:Type$Instant|Sorcery Oracle:Defender\nWhen you cast an instant or sorcery spell, Electrostatic Field deals 1 damage to each opponent. diff --git a/forge-gui/res/cardsfolder/upcoming/emmara_soul_of_the_accord.txt b/forge-gui/res/cardsfolder/e/emmara_soul_of_the_accord.txt similarity index 91% rename from forge-gui/res/cardsfolder/upcoming/emmara_soul_of_the_accord.txt rename to forge-gui/res/cardsfolder/e/emmara_soul_of_the_accord.txt index 44da9af66e5..dcb4c3710bb 100644 --- a/forge-gui/res/cardsfolder/upcoming/emmara_soul_of_the_accord.txt +++ b/forge-gui/res/cardsfolder/e/emmara_soul_of_the_accord.txt @@ -4,4 +4,5 @@ Types:Legendary Creature Elf Cleric PT:2/2 T:Mode$ Taps | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME becomes tapped, create a 1/1 white Soldier creature token with lifelink. SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_soldier_lifelink +DeckHas:Ability$Token & Ability$LifeGain Oracle:Whenever Emmara, Soul of the Accord becomes tapped, create a 1/1 white Soldier creature token with lifelink. diff --git a/forge-gui/res/cardsfolder/e/empyrial_storm.txt b/forge-gui/res/cardsfolder/e/empyrial_storm.txt index f1ddd526249..b5c284f4edf 100644 --- a/forge-gui/res/cardsfolder/e/empyrial_storm.txt +++ b/forge-gui/res/cardsfolder/e/empyrial_storm.txt @@ -1,9 +1,9 @@ Name:Empyrial Storm ManaCost:4 W W Types:Sorcery -T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When you cast CARDNAME, copy it for each time you've cast your commander from the command zone this game. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility -SVar:X:Count$CommanderCastFromCommandZone -A:SP$ Token | Cost$ 4 W W | TokenAmount$ 1 | TokenName$ Angel | TokenTypes$ Creature,Angel | TokenOwner$ You | TokenColors$ White | TokenPower$ 4 | TokenToughness$ 4 | TokenKeywords$ Flying | TokenImage$ w 4 4 angel gtc | SpellDescription$ Create a 4/4 white Angel creature token with flying. +T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When you cast this spell, copy it for each time you've cast your commander from the command zone this game. +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:X:Count$TotalCommanderCastFromCommandZone +A:SP$ Token | Cost$ 4 W W | TokenAmount$ 1 | TokenName$ Angel | TokenTypes$ Creature,Angel | TokenOwner$ You | TokenColors$ White | TokenPower$ 4 | TokenToughness$ 4 | TokenKeywords$ Flying | TokenImage$ w 4 4 angel c18 | SpellDescription$ Create a 4/4 white Angel creature token with flying. DeckHas:Ability$Token Oracle:When you cast this spell, copy it for each time you've cast your commander from the command zone this game.\nCreate a 4/4 white Angel creature token with flying. diff --git a/forge-gui/res/cardsfolder/e/enchanters_bane.txt b/forge-gui/res/cardsfolder/e/enchanters_bane.txt index 2033cd0b195..4ce6a84073c 100644 --- a/forge-gui/res/cardsfolder/e/enchanters_bane.txt +++ b/forge-gui/res/cardsfolder/e/enchanters_bane.txt @@ -1,7 +1,11 @@ Name:Enchanter's Bane ManaCost:1 R Types:Enchantment -T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDamage | TriggerDescription$ At the beginning of your end step, target enchantment deals damage equal to its converted mana cost to its controller unless that player sacrifices it. -SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Enchantment | TgtPrompt$ Select target enchantment | NumDmg$ X | UnlessCost$ Sacrifice | UnlessPayer$ TargetedController | UnlessAI$ WhenPaid | References$ X -SVar:X:Targeted$CardManaCost +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigTarget | TriggerDescription$ At the beginning of your end step, target enchantment deals damage equal to its converted mana cost to its controller unless that player sacrifices it. +SVar:TrigTarget:DB$ Pump | ValidTgts$ Enchantment | TgtPrompt$ Select target enchantment | IsCurse$ True | ImprintCards$ Targeted | SubAbility$ DBSac +SVar:DBSac:DB$ Sacrifice | Defined$ TargetedController | SacValid$ TargetedCard.Self | Optional$ True | RememberSacrificed$ True | SubAbility$ TrigDamage +SVar:TrigDamage:DB$ DealDamage | NumDmg$ X | Defined$ ImprintedController | DamageSource$ Imprinted | References$ X,Y | ConditionCheckSVar$ Y | ConditionSVarCompare$ EQ0 | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True +SVar:Y:Remembered$Amount +SVar:X:Imprinted$CardManaCost Oracle:At the beginning of your end step, target enchantment deals damage equal to its converted mana cost to its controller unless that player sacrifices it. diff --git a/forge-gui/res/cardsfolder/upcoming/enhanced_surveillance.txt b/forge-gui/res/cardsfolder/e/enhanced_surveillance.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/enhanced_surveillance.txt rename to forge-gui/res/cardsfolder/e/enhanced_surveillance.txt index d8bb73b521c..e1f2f07462c 100644 --- a/forge-gui/res/cardsfolder/upcoming/enhanced_surveillance.txt +++ b/forge-gui/res/cardsfolder/e/enhanced_surveillance.txt @@ -5,4 +5,5 @@ R:Event$ Surveil | ActiveZones$ Battlefield | ValidPlayer$ You | ReplaceWith$ Ad SVar:AddTwoMore:DB$ ReplaceEffect | VarName$ SurveilNum | VarValue$ X | References$ X SVar:X:ReplaceCount$SurveilNum/Plus.2 A:AB$ ChangeZoneAll | Cost$ Exile<1/CARDNAME> | ChangeType$ Card.YouOwn | Origin$ Graveyard | Destination$ Library | Shuffle$ True | SpellDescription$ Shuffle your graveyard into your library. +DeckNeeds:Ability$Surveil Oracle:You may look at an additional two cards each you surveil.\nExile Enhanced Surveillance: Shuffle your graveyard into your library. diff --git a/forge-gui/res/cardsfolder/upcoming/erratic_cyclops.txt b/forge-gui/res/cardsfolder/e/erratic_cyclops.txt similarity index 95% rename from forge-gui/res/cardsfolder/upcoming/erratic_cyclops.txt rename to forge-gui/res/cardsfolder/e/erratic_cyclops.txt index 269664a5423..38c790f9854 100644 --- a/forge-gui/res/cardsfolder/upcoming/erratic_cyclops.txt +++ b/forge-gui/res/cardsfolder/e/erratic_cyclops.txt @@ -7,4 +7,5 @@ T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | Tr SVar:TrigPump:DB$ Pump | NumAtt$ +X | References$ X SVar:X:TriggerCount$CastSACMC SVar:BuffedBy:Instant,Sorcery +DeckHints:Type$Instant|Sorcery Oracle:Trample\nWhenever you cast an instant or sorcery spell, Erratic Cyclops gets +X/+0 until end of turn, where X is that spell's converted mana cost. diff --git a/forge-gui/res/cardsfolder/upcoming/erstwhile_trooper.txt b/forge-gui/res/cardsfolder/e/erstwhile_trooper.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/erstwhile_trooper.txt rename to forge-gui/res/cardsfolder/e/erstwhile_trooper.txt diff --git a/forge-gui/res/cardsfolder/upcoming/etrata_the_silencer.txt b/forge-gui/res/cardsfolder/e/etrata_the_silencer.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/etrata_the_silencer.txt rename to forge-gui/res/cardsfolder/e/etrata_the_silencer.txt diff --git a/forge-gui/res/cardsfolder/upcoming/expansion_explosion.txt b/forge-gui/res/cardsfolder/e/expansion_explosion.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/expansion_explosion.txt rename to forge-gui/res/cardsfolder/e/expansion_explosion.txt diff --git a/forge-gui/res/cardsfolder/e/experimental_frenzy.txt b/forge-gui/res/cardsfolder/e/experimental_frenzy.txt new file mode 100644 index 00000000000..d98744b9149 --- /dev/null +++ b/forge-gui/res/cardsfolder/e/experimental_frenzy.txt @@ -0,0 +1,10 @@ +Name:Experimental Frenzy +ManaCost:3 R +Types:Enchantment +S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl | AffectedZone$ Library | MayLookAt$ Player | Description$ You may look at the top card of your library any time. +S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl | AffectedZone$ Library | MayPlay$ True | Description$ You may play the top card of your library. +S:Mode$ CantPlayLand | Player$ You | Origin$ Hand | Description$ You can't play lands from your hand. +S:Mode$ CantBeCast | ValidCard$ Card | Caster$ You | Origin$ Hand | Description$ You can't play cards from your hand. +SVar:NonStackingEffect:True +A:AB$ Destroy | Cost$ 3 R | Defined$ Self | SpellDescription$ Destroy CARDNAME. +Oracle:You may look at the top card of your library any time.\nYou may play the top card of your library.\nYou can't play cards from your hand.\n{3}{R}: Destroy Experimental Frenzy. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/fearless_halberdier.txt b/forge-gui/res/cardsfolder/f/fearless_halberdier.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/fearless_halberdier.txt rename to forge-gui/res/cardsfolder/f/fearless_halberdier.txt diff --git a/forge-gui/res/cardsfolder/upcoming/find_finality.txt b/forge-gui/res/cardsfolder/f/find_finality.txt similarity index 56% rename from forge-gui/res/cardsfolder/upcoming/find_finality.txt rename to forge-gui/res/cardsfolder/f/find_finality.txt index 90bb97fd8c6..2b85d2313fd 100644 --- a/forge-gui/res/cardsfolder/upcoming/find_finality.txt +++ b/forge-gui/res/cardsfolder/f/find_finality.txt @@ -10,6 +10,9 @@ ALTERNATE Name:Finality ManaCost:4 B G Types:Sorcery -A:SP$ PutCounter | Cost$ 4 B G | ValidTgts$ Creature.YouCtrl | CounterNum$ 2 | CounterType$ P1P1 | SubAbility$ DBPumpAll | SpellDescription$ You may put two +1/+1 counters on a creature you control. Then all creatures get -4/-4 until end of turn. -SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Creature | NumAtt$ -4 | NumDef$ -4 | IsCurse$ True +A:SP$ ChooseCard | Cost$ 4 B G | Defined$ You | Amount$ 1 | MinAmount$ 0 | Choices$ Creature.YouCtrl | SubAbility$ DBPutCounter | SpellDescription$ You may put two +1/+1 counters on a creature you control. Then all creatures get -4/-4 until end of turn. +SVar:DBPutCounter:DB$ PutCounter | Defined$ ChosenCard | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ DBPumpAll +SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Creature | NumAtt$ -4 | NumDef$ -4 | IsCurse$ True | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True +DeckHas:Ability$Counters Oracle:You may put two +1/+1 counters on a creature you control. Then all creatures get -4/-4 until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/fire_urchin.txt b/forge-gui/res/cardsfolder/f/fire_urchin.txt similarity index 94% rename from forge-gui/res/cardsfolder/upcoming/fire_urchin.txt rename to forge-gui/res/cardsfolder/f/fire_urchin.txt index 4e4e22a9def..02cc79bb57e 100644 --- a/forge-gui/res/cardsfolder/upcoming/fire_urchin.txt +++ b/forge-gui/res/cardsfolder/f/fire_urchin.txt @@ -6,4 +6,5 @@ K:Trample T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever you cast an instant or sorcery spell, CARDNAME gets +1/+0 until end of turn. SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ 1 SVar:BuffedBy:Instant,Sorcery +DeckHints:Type$Instant|Sorcery Oracle:Trample\nWhenever you cast an instant or sorcery spell, Fire Urchin gets +1/+0 until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/fireminds_research.txt b/forge-gui/res/cardsfolder/f/fireminds_research.txt similarity index 97% rename from forge-gui/res/cardsfolder/upcoming/fireminds_research.txt rename to forge-gui/res/cardsfolder/f/fireminds_research.txt index b2a23c01b04..fc7c35836ce 100644 --- a/forge-gui/res/cardsfolder/upcoming/fireminds_research.txt +++ b/forge-gui/res/cardsfolder/f/fireminds_research.txt @@ -8,4 +8,5 @@ DeckHints:Type$Instant | Sorcery A:AB$ Draw | Cost$ 1 U SubCounter<2/CHARGE> | NumCards$ 1 | SpellDescription$ Draw a card. A:AB$ DealDamage | Cost$ 1 R SubCounter<5/CHARGE> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 5 | SpellDescription$ CARDNAME deals 5 damage to any target. SVar:RemRandomDeck:True +DeckNeeds:Type$Instant|Sorcery Oracle:Whenever you cast an instant or sorcery spell, put a charge counter on Firemind's Research.\n{1}{U}, Remove two charge counters from Firemind's Research: Draw a card.\n{1}{R}, Remove five charge counters from Firemind's Research: It deals 5 damage to any target. diff --git a/forge-gui/res/cardsfolder/upcoming/flight_of_equenauts.txt b/forge-gui/res/cardsfolder/f/flight_of_equenauts.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/flight_of_equenauts.txt rename to forge-gui/res/cardsfolder/f/flight_of_equenauts.txt diff --git a/forge-gui/res/cardsfolder/upcoming/flower_flourish.txt b/forge-gui/res/cardsfolder/f/flower_flourish.txt similarity index 71% rename from forge-gui/res/cardsfolder/upcoming/flower_flourish.txt rename to forge-gui/res/cardsfolder/f/flower_flourish.txt index 54a446e486e..3a5f46ed562 100644 --- a/forge-gui/res/cardsfolder/upcoming/flower_flourish.txt +++ b/forge-gui/res/cardsfolder/f/flower_flourish.txt @@ -2,7 +2,7 @@ Name:Flower ManaCost:G/W Types:Sorcery AlternateMode: Split -A:SP$ ChangeZone | Cost$ G/W | Origin$ Library | Destination$ Hand | ChangeType$ Land.Basic,Plains.Plains | ChangeNum$ 1 | SpellDescription$ Search your library for a basic Forest or Plains card, reveal it, put it into your hand, then shuffle your library. +A:SP$ ChangeZone | Cost$ G/W | Origin$ Library | Destination$ Hand | ChangeType$ Land.Forest+Basic,Land.Plains+Basic | ChangeNum$ 1 | SpellDescription$ Search your library for a basic Forest or Plains card, reveal it, put it into your hand, then shuffle your library. Oracle:Search your library for a basic Forest or Plains card, reveal it, put it into your hand, then shuffle your library. ALTERNATE diff --git a/forge-gui/res/cardsfolder/upcoming/fresh_faced_recruit.txt b/forge-gui/res/cardsfolder/f/fresh_faced_recruit.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/fresh_faced_recruit.txt rename to forge-gui/res/cardsfolder/f/fresh_faced_recruit.txt diff --git a/forge-gui/res/cardsfolder/f/fury_storm.txt b/forge-gui/res/cardsfolder/f/fury_storm.txt new file mode 100644 index 00000000000..6895b278dd6 --- /dev/null +++ b/forge-gui/res/cardsfolder/f/fury_storm.txt @@ -0,0 +1,8 @@ +Name:Fury Storm +ManaCost:2 R R +Types:Instant +T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When you cast this spell, copy it for each time you've cast your commander from the command zone this game. +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:X:Count$TotalCommanderCastFromCommandZone +A:SP$ CopySpellAbility | Cost$ 2 R R | ValidTgts$ Instant,Sorcery | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. +Oracle:When you cast this spell, copy it for each time you've cast your commander from the command zone this game. You may choose new targets for the copies.\nCopy target instant or sorcery spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/upcoming/garrison_sergeant.txt b/forge-gui/res/cardsfolder/g/garrison_sergeant.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/garrison_sergeant.txt rename to forge-gui/res/cardsfolder/g/garrison_sergeant.txt diff --git a/forge-gui/res/cardsfolder/upcoming/gatekeeper_gargoyle.txt b/forge-gui/res/cardsfolder/g/gatekeeper_gargoyle.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/gatekeeper_gargoyle.txt rename to forge-gui/res/cardsfolder/g/gatekeeper_gargoyle.txt diff --git a/forge-gui/res/cardsfolder/upcoming/gateway_plaza.txt b/forge-gui/res/cardsfolder/g/gateway_plaza.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/gateway_plaza.txt rename to forge-gui/res/cardsfolder/g/gateway_plaza.txt diff --git a/forge-gui/res/cardsfolder/upcoming/generous_stray.txt b/forge-gui/res/cardsfolder/g/generous_stray.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/generous_stray.txt rename to forge-gui/res/cardsfolder/g/generous_stray.txt diff --git a/forge-gui/res/cardsfolder/g/genesis_storm.txt b/forge-gui/res/cardsfolder/g/genesis_storm.txt new file mode 100644 index 00000000000..ed19640f1f0 --- /dev/null +++ b/forge-gui/res/cardsfolder/g/genesis_storm.txt @@ -0,0 +1,8 @@ +Name:Genesis Storm +ManaCost:4 G G +Types:Sorcery +T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When you cast this spell, copy it for each time you've cast your commander from the command zone this game. +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:X:Count$TotalCommanderCastFromCommandZone +A:SP$ DigUntil | Cost$ 4 G G | Valid$ Permanent.nonland | ValidDescription$ nonland permanent | FoundDestination$ Battlefield | OptionalFoundMove$ True | RevealedDestination$ Library | RevealedLibraryPosition$ -1 | RevealRandomOrder$ True | SpellDescription$ Reveal cards from the top of your library until you reveal a nonland permanent card. You may put that card onto the battlefield. Then put all cards revealed this way that weren't put onto the battlefield on the bottom of your library in a random order. +Oracle:When you cast this spell, copy it for each time you've cast your commander from the command zone this game. You may choose new targets for the copies.\nReveal cards from the top of your library until you reveal a nonland permanent card. You may put that card onto the battlefield. Then put all cards revealed this way that weren't put onto the battlefield on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/g/geode_golem .txt b/forge-gui/res/cardsfolder/g/geode_golem .txt new file mode 100644 index 00000000000..81410cd0ff4 --- /dev/null +++ b/forge-gui/res/cardsfolder/g/geode_golem .txt @@ -0,0 +1,8 @@ +Name:Geode Golem +ManaCost:5 +Types:Artifact Creature Golem +PT:5/3 +K:Trample +T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigPlay | TriggerZones$ Battlefield | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, you may cast your commander from the command zone without paying its mana cost. (You still pay any additional costs.) +SVar:TrigPlay:DB$ Play | Valid$ Card.IsCommander+YouOwn | ValidZone$ Command | WithoutManaCost$ True | Optional$ True +Oracle:Trample\nWhenever Geode Golem deals combat damage to a player, you may cast your commander from the command zone without paying its mana cost. (You still pay any additional costs.) diff --git a/forge-gui/res/cardsfolder/upcoming/gird_for_battle.txt b/forge-gui/res/cardsfolder/g/gird_for_battle.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/gird_for_battle.txt rename to forge-gui/res/cardsfolder/g/gird_for_battle.txt index 305c43656e3..0f10b839ce2 100644 --- a/forge-gui/res/cardsfolder/upcoming/gird_for_battle.txt +++ b/forge-gui/res/cardsfolder/g/gird_for_battle.txt @@ -2,4 +2,5 @@ Name:Gird for Battle ManaCost:W Types:Sorcery A:SP$ PutCounter | Cost$ W | ValidTgts$ Creature | TargetMin$ 0 | TargetMax$ 2 | CounterType$ P1P1 | CounterNum$ 1 | SpellDescription$ Put a +1/+1 counter on each of up to two target creatures. +DeckHas:Ability$Counters Oracle:Put a +1/+1 counter on each of up to two target creatures. diff --git a/forge-gui/res/cardsfolder/upcoming/glaive_of_the_guildpact.txt b/forge-gui/res/cardsfolder/g/glaive_of_the_guildpact.txt similarity index 72% rename from forge-gui/res/cardsfolder/upcoming/glaive_of_the_guildpact.txt rename to forge-gui/res/cardsfolder/g/glaive_of_the_guildpact.txt index e42184fb9e8..082cf91e31d 100644 --- a/forge-gui/res/cardsfolder/upcoming/glaive_of_the_guildpact.txt +++ b/forge-gui/res/cardsfolder/g/glaive_of_the_guildpact.txt @@ -1,10 +1,9 @@ Name:Glaive of the Guildpact ManaCost:2 Types:Artifact Equipment +K:Equip:3 S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ X | AddKeyword$ Vigilance & Menace | Description$ Equipped creature gets +1/+0 for each Gate you control and has vigilance and menace. SVar:X:Count$Valid Gate.YouCtrl -S:Mode$ Continuous | Affected$ Gate.YouCtrl | AddPower$ X | AddKeyword$ Vigilance & Menace | Description$ Equipped creature gets +1/+0 for each Gate you control and has vigilance and menace. -SVar:X:Count$Valid Gate.YouCtrl SVar:BuffedBy:Gate DeckHints:Type$Gate Oracle:Equipped creature gets +1/+0 for each Gate you control and has vigilance and menace. (A creature with menace can't be blocked except by two or more creatures.)\nEquip {3} ({3}: Attach to target creature you control. Equip only as a sorcery.) diff --git a/forge-gui/res/cardsfolder/upcoming/glowspore_shaman.txt b/forge-gui/res/cardsfolder/g/glowspore_shaman.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/glowspore_shaman.txt rename to forge-gui/res/cardsfolder/g/glowspore_shaman.txt index 518b808f7c1..c5c3d74e1e7 100644 --- a/forge-gui/res/cardsfolder/upcoming/glowspore_shaman.txt +++ b/forge-gui/res/cardsfolder/g/glowspore_shaman.txt @@ -5,4 +5,5 @@ PT:3/1 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigMill | TriggerDescription$ When CARDNAME enters the battlefield, put the top three cards of your library into your graveyard. You may put a land card from your graveyard on top of your library. SVar:TrigMill:DB$ Mill | NumCards$ 3 | Defined$ You | SubAbility$ DBChangeZone SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Library | OptionalDecider$ You | ChangeType$ Land.YouOwn | ChangeNum$ 1 | Hidden$ True | Optional$ True +DeckHas:Ability$Graveyard Oracle:When Glowspore Shaman enters the battlefield, put the top three cards of your library into your graveyard. You may put a land card from your graveyard on top of your library. diff --git a/forge-gui/res/cardsfolder/upcoming/goblin_banneret.txt b/forge-gui/res/cardsfolder/g/goblin_banneret.txt similarity index 93% rename from forge-gui/res/cardsfolder/upcoming/goblin_banneret.txt rename to forge-gui/res/cardsfolder/g/goblin_banneret.txt index 5419f82bfbc..b1bcc1bccd3 100644 --- a/forge-gui/res/cardsfolder/upcoming/goblin_banneret.txt +++ b/forge-gui/res/cardsfolder/g/goblin_banneret.txt @@ -4,4 +4,5 @@ Types:Creature Goblin Soldier PT:1/1 K:Mentor A:AB$ Pump | Cost$ 1 R | NumAtt$ +2 | SpellDescription$ CARDNAME gets +2/+0 until end of turn. +DeckHas:Ability$Counters Oracle:Mentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.)\n{1}{R}: Goblin Banneret gets +2/+0 until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/goblin_cratermaker.txt b/forge-gui/res/cardsfolder/g/goblin_cratermaker.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/goblin_cratermaker.txt rename to forge-gui/res/cardsfolder/g/goblin_cratermaker.txt diff --git a/forge-gui/res/cardsfolder/g/goblin_flotilla.txt b/forge-gui/res/cardsfolder/g/goblin_flotilla.txt index 5f93368b0ec..6bbd2584317 100644 --- a/forge-gui/res/cardsfolder/g/goblin_flotilla.txt +++ b/forge-gui/res/cardsfolder/g/goblin_flotilla.txt @@ -4,9 +4,9 @@ Types:Creature Goblin PT:2/2 K:Islandwalk T:Mode$ Phase | Phase$ BeginCombat | TriggerZones$ Battlefield | Execute$ AnimateDB | TriggerDescription$ At the beginning of each combat, unless you pay {R}, whenever CARDNAME blocks or becomes blocked by a creature this combat, that creature gains first strike until end of turn. -SVar:AnimateDB:DB$Animate | Triggers$ AttackerBlocked,Blocks | UnlessCost$ R | UnlessPayer$ You | UntilEndOfCombat$ True -SVar:AttackerBlocked:Mode$ AttackerBlockedByCreature | ValidCard$ Creature | ValidBlocker$ Card.Self | Execute$ PumpAttacker | TriggerDescription$ Whenever CARDNAME blocks or becomes blocked by a creature this combat, that creature gains first strike until end of turn. -SVar:Blocks:Mode$ AttackerBlockedByCreature | ValidCard$ Card.Self | ValidBlocker$ Creature | Execute$ PumpBlocker | TriggerDescription$ Whenever CARDNAME blocks or becomes blocked by a creature this combat, that creature gains first strike until end of turn. +SVar:AnimateDB:DB$ Effect | Triggers$ AttackerBlocked,Blocks | SVars$ PumpAttacker,PumpBlocker | UnlessCost$ R | UnlessPayer$ You | Duration$ UntilEndOfCombat +SVar:AttackerBlocked:Mode$ AttackerBlockedByCreature | ValidCard$ Creature | ValidBlocker$ Card.EffectSource | Execute$ PumpAttacker | TriggerDescription$ Whenever EFFECTSOURCE blocks or becomes blocked by a creature this combat, that creature gains first strike until end of turn. +SVar:Blocks:Mode$ AttackerBlockedByCreature | ValidCard$ Card.EffectSource | ValidBlocker$ Creature | Execute$ PumpBlocker | TriggerDescription$ Whenever EFFECTSOURCE blocks or becomes blocked by a creature this combat, that creature gains first strike until end of turn. SVar:PumpAttacker:DB$ Pump | Defined$ TriggeredAttacker | KW$ First Strike SVar:PumpBlocker:DB$ Pump | Defined$ TriggeredBlocker | KW$ First Strike SVar:Picture:http://www.wizards.com/global/images/magic/general/goblin_flotilla.jpg diff --git a/forge-gui/res/cardsfolder/upcoming/goblin_locksmith.txt b/forge-gui/res/cardsfolder/g/goblin_locksmith.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/goblin_locksmith.txt rename to forge-gui/res/cardsfolder/g/goblin_locksmith.txt diff --git a/forge-gui/res/cardsfolder/upcoming/golgari_findbroker.txt b/forge-gui/res/cardsfolder/g/golgari_findbroker.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/golgari_findbroker.txt rename to forge-gui/res/cardsfolder/g/golgari_findbroker.txt diff --git a/forge-gui/res/cardsfolder/upcoming/golgari_locket.txt b/forge-gui/res/cardsfolder/g/golgari_locket.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/golgari_locket.txt rename to forge-gui/res/cardsfolder/g/golgari_locket.txt diff --git a/forge-gui/res/cardsfolder/upcoming/golgari_raiders.txt b/forge-gui/res/cardsfolder/g/golgari_raiders.txt similarity index 94% rename from forge-gui/res/cardsfolder/upcoming/golgari_raiders.txt rename to forge-gui/res/cardsfolder/g/golgari_raiders.txt index 2edb4dec836..68b269f346b 100644 --- a/forge-gui/res/cardsfolder/upcoming/golgari_raiders.txt +++ b/forge-gui/res/cardsfolder/g/golgari_raiders.txt @@ -6,4 +6,5 @@ K:Haste K:etbCounter:P1P1:X:no Condition:Undergrowth - CARDNAME enters the battlefield with a +1/+1 counter on it for each creature card in your graveyard. SVar:X:Count$LastStateGraveyard Creature.YouCtrl SVar:NeedsToPlayVar:X GE3 +DeckHas:Ability$Counters Oracle:Haste\nUndergrowth — Golgari Raiders enters the battlefield with a +1/+1 counter on it for each creature card in your graveyard. diff --git a/forge-gui/res/cardsfolder/upcoming/grappling_sundew.txt b/forge-gui/res/cardsfolder/g/grappling_sundew.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/grappling_sundew.txt rename to forge-gui/res/cardsfolder/g/grappling_sundew.txt diff --git a/forge-gui/res/cardsfolder/upcoming/gravitic_punch.txt b/forge-gui/res/cardsfolder/g/gravitic_punch.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/gravitic_punch.txt rename to forge-gui/res/cardsfolder/g/gravitic_punch.txt diff --git a/forge-gui/res/cardsfolder/upcoming/gruesome_menagerie.txt b/forge-gui/res/cardsfolder/g/gruesome_menagerie.txt similarity index 95% rename from forge-gui/res/cardsfolder/upcoming/gruesome_menagerie.txt rename to forge-gui/res/cardsfolder/g/gruesome_menagerie.txt index 46c3ea0f004..8a28cd52744 100644 --- a/forge-gui/res/cardsfolder/upcoming/gruesome_menagerie.txt +++ b/forge-gui/res/cardsfolder/g/gruesome_menagerie.txt @@ -6,4 +6,5 @@ SVar:DBChoose2:DB$ ChooseCard | Defined$ You | Choices$ Creature.YouOwn+cmcEQ2 | SVar:DBChoose3:DB$ ChooseCard | Defined$ You | Choices$ Creature.YouOwn+cmcEQ3 | ChoiceZone$ Graveyard | Amount$ 1 | SubAbility$ DBReturn | RememberChosen$ True | SpellDescription$ Choose a creature card with converted mana cost 3 in your graveyard. SVar:DBReturn:DB$ ChangeZoneAll | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Card.IsRemembered | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:NeedsToPlay:Creature.YouCtrl+inZoneGraveyard+cmcLE3 Oracle:Choose a creature card with converted mana cost 1 in your graveyard, then do the same for creature cards with converted mana costs 2 and 3. Return those cards to the battlefield. diff --git a/forge-gui/res/cardsfolder/upcoming/guild_summit.txt b/forge-gui/res/cardsfolder/g/guild_summit.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/guild_summit.txt rename to forge-gui/res/cardsfolder/g/guild_summit.txt index 8d3e5aefb68..24608dbed49 100644 --- a/forge-gui/res/cardsfolder/upcoming/guild_summit.txt +++ b/forge-gui/res/cardsfolder/g/guild_summit.txt @@ -6,7 +6,7 @@ SVar:GuestList:DB$ ChooseCard | Defined$ You | MinAmount$ 0 | Amount$ X | Refere SVar:TrigTap:DB$ Tap | Defined$ Remembered | SubAbility$ DBDraw SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ Y | SubAbility$ DBCleanup | References$ Y SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:X:Count$Valid Creature.YouCtrl +SVar:X:Count$Valid Gate.untapped+YouCtrl SVar:Y:Remembered$Amount T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Gate.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever a Gate enters the battlefield under your control, draw a card. SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 diff --git a/forge-gui/res/cardsfolder/upcoming/guildmages_forum.txt b/forge-gui/res/cardsfolder/g/guildmages_forum.txt similarity index 95% rename from forge-gui/res/cardsfolder/upcoming/guildmages_forum.txt rename to forge-gui/res/cardsfolder/g/guildmages_forum.txt index 1eb1bca9658..0dfcfc4b524 100644 --- a/forge-gui/res/cardsfolder/upcoming/guildmages_forum.txt +++ b/forge-gui/res/cardsfolder/g/guildmages_forum.txt @@ -2,4 +2,5 @@ Name:Guildmages' Forum Types:Land A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. A:AB$ Mana | Cost$ 1 T | Produced$ Any | AddsCounters$ Card.Creature+MultiColor_P1P1_1 | SpellDescription$ Add one mana of any color. If that mana is spent on a multicolored creature spell, that creature enters the battlefield with an additional +1/+1 counter on it. +DeckHas:Ability$Counters Oracle:{T}: Add {C}.\n{1}, {T}: Add one mana of any color. If that mana is spent on a multicolored creature spell, that creature enters the battlefield with an additional +1/+1 counter on it. diff --git a/forge-gui/res/cardsfolder/upcoming/haazda_marshal.txt b/forge-gui/res/cardsfolder/h/haazda_marshal.txt similarity index 93% rename from forge-gui/res/cardsfolder/upcoming/haazda_marshal.txt rename to forge-gui/res/cardsfolder/h/haazda_marshal.txt index 5eb0f677523..06e8c1bce95 100644 --- a/forge-gui/res/cardsfolder/upcoming/haazda_marshal.txt +++ b/forge-gui/res/cardsfolder/h/haazda_marshal.txt @@ -5,4 +5,5 @@ PT:1/1 T:Mode$ Attacks | ValidCard$ Card.Self | TriggerZones$ Battlefield | CheckSVar$ AttackerTest | SVarCompare$ GE2 | NoResolvingCheck$ True | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME and at least two other creatures attack, create a 1/1 white Soldier creature token with lifelink. SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_soldier_lifelink SVar:AttackerTest:Count$Valid Creature.attacking+Other +DeckHas:Ability$Token & Ability$LifeGain Oracle:Whenever Haazda Marshal and at least two other creatures attack, create a 1/1 white Soldier creature token with lifelink. diff --git a/forge-gui/res/cardsfolder/upcoming/hammer_dropper.txt b/forge-gui/res/cardsfolder/h/hammer_dropper.txt similarity index 88% rename from forge-gui/res/cardsfolder/upcoming/hammer_dropper.txt rename to forge-gui/res/cardsfolder/h/hammer_dropper.txt index d0d0d0a3193..dd2b2f37495 100644 --- a/forge-gui/res/cardsfolder/upcoming/hammer_dropper.txt +++ b/forge-gui/res/cardsfolder/h/hammer_dropper.txt @@ -3,4 +3,5 @@ ManaCost:2 R W Types:Creature Giant Soldier PT:5/2 K:Mentor +DeckHas:Ability$Counters Oracle:Mentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.) diff --git a/forge-gui/res/cardsfolder/upcoming/hatchery_spider.txt b/forge-gui/res/cardsfolder/h/hatchery_spider.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/hatchery_spider.txt rename to forge-gui/res/cardsfolder/h/hatchery_spider.txt diff --git a/forge-gui/res/cardsfolder/h/headless_skaab.txt b/forge-gui/res/cardsfolder/h/headless_skaab.txt index 7d321382402..44f9e3cc5d1 100644 --- a/forge-gui/res/cardsfolder/h/headless_skaab.txt +++ b/forge-gui/res/cardsfolder/h/headless_skaab.txt @@ -3,6 +3,6 @@ ManaCost:2 U Types:Creature Zombie Warrior PT:3/6 K:CARDNAME enters the battlefield tapped. -SVar:FullCost:2 U ExileFromGrave<1/Creature> +A:SP$ PermanentCreature | Cost$ 2 U ExileFromGrave<1/Creature> SVar:Picture:http://www.wizards.com/global/images/magic/general/headless_skaab.jpg Oracle:As an additional cost to cast Headless Skaab, exile a creature card from your graveyard.\nHeadless Skaab enters the battlefield tapped. diff --git a/forge-gui/res/cardsfolder/upcoming/healers_hawk.txt b/forge-gui/res/cardsfolder/h/healers_hawk.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/healers_hawk.txt rename to forge-gui/res/cardsfolder/h/healers_hawk.txt diff --git a/forge-gui/res/cardsfolder/upcoming/hellkite_whelp.txt b/forge-gui/res/cardsfolder/h/hellkite_whelp.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/hellkite_whelp.txt rename to forge-gui/res/cardsfolder/h/hellkite_whelp.txt diff --git a/forge-gui/res/cardsfolder/upcoming/hired_poisoner.txt b/forge-gui/res/cardsfolder/h/hired_poisoner.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/hired_poisoner.txt rename to forge-gui/res/cardsfolder/h/hired_poisoner.txt diff --git a/forge-gui/res/cardsfolder/h/honor_the_fallen.txt b/forge-gui/res/cardsfolder/h/honor_the_fallen.txt index aa8e2e38f0d..e8ab7e78641 100644 --- a/forge-gui/res/cardsfolder/h/honor_the_fallen.txt +++ b/forge-gui/res/cardsfolder/h/honor_the_fallen.txt @@ -5,6 +5,6 @@ A:SP$ ChangeZoneAll | Cost$ 1 W | ChangeType$ Creature | Origin$ Graveyard | Des SVar:DBGainLife:DB$GainLife | Defined$ You | LifeAmount$ X | References$ X SVar:X:Remembered$Amount SVar:NeedsToPlayVar:Z GE2 -SVar:Count$ValidGraveyard Creature +SVar:Z:Count$ValidGraveyard Creature SVar:Picture:http://www.wizards.com/global/images/magic/general/honor_the_fallen.jpg Oracle:Exile all creature cards from all graveyards. You gain 1 life for each card exiled this way. diff --git a/forge-gui/res/cardsfolder/upcoming/house_guildmage.txt b/forge-gui/res/cardsfolder/h/house_guildmage.txt similarity index 70% rename from forge-gui/res/cardsfolder/upcoming/house_guildmage.txt rename to forge-gui/res/cardsfolder/h/house_guildmage.txt index ebfdeada89c..4a0c6f751c1 100644 --- a/forge-gui/res/cardsfolder/upcoming/house_guildmage.txt +++ b/forge-gui/res/cardsfolder/h/house_guildmage.txt @@ -3,5 +3,6 @@ ManaCost:U B Types:Creature Human Wizard PT:2/2 A:AB$ Pump | Cost$ 1 U T | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ HIDDEN This card doesn't untap during your next untap step. | Permanent$ True | IsCurse$ True | SpellDescription$ Target creature doesn't untap during its controller's next untap step. -A:AB$ Surveil | Cost$ 2 B T | SurveilNum$ 2 | SpellDescription$ Surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on top of your library in any order.) +A:AB$ Surveil | Cost$ 2 B T | Amount$ 2 | SpellDescription$ Surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on top of your library in any order.) +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:{1}{U}, {T}: Target creature doesn't untap during its controller's next untap step.\n{2}{B}, {T}: Surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on top of your library in any order.) diff --git a/forge-gui/res/cardsfolder/h/hunted_horror.txt b/forge-gui/res/cardsfolder/h/hunted_horror.txt index e6dbae0909c..91e6970860d 100644 --- a/forge-gui/res/cardsfolder/h/hunted_horror.txt +++ b/forge-gui/res/cardsfolder/h/hunted_horror.txt @@ -4,6 +4,6 @@ Types:Creature Horror PT:7/7 K:Trample T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, target opponent creates two 3/3 green Centaur creature tokens with protection from black. -SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenName$ Centaur | TokenImage$ g 3 3 centaur pro black | TokenTypes$ Creature,Centaur | ValidTgts$ Opponent | TokenOwner$ Targeted | TokenColors$ Green | TokenPower$ 3 | TokenToughness$ 3 | TokenKeywords$ Protection from black +SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ g_3_3_centaur_pro_black | ValidTgts$ Opponent | TokenOwner$ Targeted | LegacyImage$ g 3 3 centaur pro black SVar:Picture:http://www.wizards.com/global/images/magic/general/hunted_horror.jpg -Oracle:Trample\nWhen Hunted Horror enters the battlefield, target opponent creates two 3/3 green Centaur creature tokens with protection from black. \ No newline at end of file +Oracle:Trample\nWhen Hunted Horror enters the battlefield, target opponent creates two 3/3 green Centaur creature tokens with protection from black. diff --git a/forge-gui/res/cardsfolder/upcoming/hunted_witness.txt b/forge-gui/res/cardsfolder/h/hunted_witness.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/hunted_witness.txt rename to forge-gui/res/cardsfolder/h/hunted_witness.txt index 3f6aa70e840..39f16b0a11d 100644 --- a/forge-gui/res/cardsfolder/upcoming/hunted_witness.txt +++ b/forge-gui/res/cardsfolder/h/hunted_witness.txt @@ -4,6 +4,6 @@ Types:Creature Human PT:1/1 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create a 1/1 white Soldier creature token with lifelink. SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_soldier_lifelink -DeckHas:Ability$Token +DeckHas:Ability$Token & Ability$LifeGain SVar:SacMe:1 Oracle:When Hunted Witness dies, create a 1/1 white Soldier creature token with lifelink. diff --git a/forge-gui/res/cardsfolder/upcoming/hypothesizzle.txt b/forge-gui/res/cardsfolder/h/hypothesizzle.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/hypothesizzle.txt rename to forge-gui/res/cardsfolder/h/hypothesizzle.txt diff --git a/forge-gui/res/cardsfolder/i/imperiosaur.txt b/forge-gui/res/cardsfolder/i/imperiosaur.txt index 1ac3fcee99d..53c761e7050 100644 --- a/forge-gui/res/cardsfolder/i/imperiosaur.txt +++ b/forge-gui/res/cardsfolder/i/imperiosaur.txt @@ -2,7 +2,6 @@ Name:Imperiosaur ManaCost:2 G G Types:Creature Dinosaur Text:Spend only mana produced by basic lands to cast CARDNAME. -PT:5/5 -SVar:FullCost:Mana<2 G G\Basic> +A:SP$ PermanentCreature | Cost$ Mana<2 G G\Basic> SVar:Picture:http://resources.wizards.com/magic/cards/fut/en-us/card130634.jpg Oracle:Spend only mana produced by basic lands to cast Imperiosaur. diff --git a/forge-gui/res/cardsfolder/upcoming/impervious_greatwurm.txt b/forge-gui/res/cardsfolder/i/impervious_greatwurm.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/impervious_greatwurm.txt rename to forge-gui/res/cardsfolder/i/impervious_greatwurm.txt diff --git a/forge-gui/res/cardsfolder/upcoming/inescapable_blaze.txt b/forge-gui/res/cardsfolder/i/inescapable_blaze.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/inescapable_blaze.txt rename to forge-gui/res/cardsfolder/i/inescapable_blaze.txt diff --git a/forge-gui/res/cardsfolder/i/infernal_tutor.txt b/forge-gui/res/cardsfolder/i/infernal_tutor.txt index 4cca4d3556d..fd424c1be3e 100644 --- a/forge-gui/res/cardsfolder/i/infernal_tutor.txt +++ b/forge-gui/res/cardsfolder/i/infernal_tutor.txt @@ -1,7 +1,7 @@ Name:Infernal Tutor ManaCost:1 B Types:Sorcery -A:SP$ Reveal | Cost$ 1 B | RememberRevealed$ True | Defined$ You | SubAbility$ DBChangeZone | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SpellDescription$ Reveal a card from your hand. Search your library for a card with the same name as that card, reveal it, put it into your hand, then shuffle your library. Hellbent — If you have no cards in hand, instead search your library for a card, put it into your hand, then shuffle your library. +A:SP$ Reveal | Cost$ 1 B | RememberRevealed$ True | Defined$ You | SubAbility$ DBChangeZone | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | References$ X | SpellDescription$ Reveal a card from your hand. Search your library for a card with the same name as that card, reveal it, put it into your hand, then shuffle your library. Hellbent — If you have no cards in hand, instead search your library for a card, put it into your hand, then shuffle your library. SVar:DBChangeZone:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Remembered.sameName | ChangeNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBChangeZone2 | References$ X SVar:DBChangeZone2:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Card | ChangeNum$ 1 | Mandatory$ True | ConditionCheckSVar$ X | ConditionSVarCompare$ LT1 | SubAbility$ DBCleanup | References$ X SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/cardsfolder/upcoming/inspiring_unicorn.txt b/forge-gui/res/cardsfolder/i/inspiring_unicorn.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/inspiring_unicorn.txt rename to forge-gui/res/cardsfolder/i/inspiring_unicorn.txt diff --git a/forge-gui/res/cardsfolder/upcoming/integrity_intervention.txt b/forge-gui/res/cardsfolder/i/integrity_intervention.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/integrity_intervention.txt rename to forge-gui/res/cardsfolder/i/integrity_intervention.txt diff --git a/forge-gui/res/cardsfolder/upcoming/intrusive_packbeast.txt b/forge-gui/res/cardsfolder/i/intrusive_packbeast.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/intrusive_packbeast.txt rename to forge-gui/res/cardsfolder/i/intrusive_packbeast.txt diff --git a/forge-gui/res/cardsfolder/upcoming/invert_invent.txt b/forge-gui/res/cardsfolder/i/invert_invent.txt similarity index 84% rename from forge-gui/res/cardsfolder/upcoming/invert_invent.txt rename to forge-gui/res/cardsfolder/i/invert_invent.txt index e317e2bbce3..63f7d936e87 100644 --- a/forge-gui/res/cardsfolder/upcoming/invert_invent.txt +++ b/forge-gui/res/cardsfolder/i/invert_invent.txt @@ -2,7 +2,7 @@ Name:Invert ManaCost:U/R Types:Instant AlternateMode: Split -A:SP$ Pump | Cost$ U/R | ValidTgts$ Creature | TargetMin$ 0 | TargetMax$ 2 | TgtPrompt$ Select target creature | KW$ HIDDEN CARDNAME's power and toughness of each of CARDNAME. | SpellDescription$ Switch the power and toughness of each of up to two target creatures. +A:SP$ Pump | Cost$ U/R | ValidTgts$ Creature | TargetMin$ 0 | TargetMax$ 2 | TgtPrompt$ Select target creature | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch the power and toughness of each of up to two target creatures. Oracle:Switch the power and toughness of each of up to two target creatures. ALTERNATE @@ -13,4 +13,5 @@ Types:Instant A:SP$ ChangeZone | Cost$ 4 U R | Origin$ Library | Destination$ Hand | ChangeType$ Instant | ChangeNum$ 1 | SubAbility$ DBChange | SpellDescription$ Search your library for and instant permanent and/or a sorcery card, reveal them, put them into your hand, then shuffle your library. SVar:DBChange:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Sorcery | ChangeNum$ 1 | Shuffle$ True SVar:RemRandomDeck:True +DeckHints:Type$Instant|Sorcery Oracle:Search your library for an instant card and/or a sorcery card, reveal them, put them into your hand, then shuffle your library. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/ionize.txt b/forge-gui/res/cardsfolder/i/ionize.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/ionize.txt rename to forge-gui/res/cardsfolder/i/ionize.txt diff --git a/forge-gui/res/cardsfolder/i/ironshell_beetle.txt b/forge-gui/res/cardsfolder/i/ironshell_beetle.txt index 39ad66852ba..6cde56e4cc5 100644 --- a/forge-gui/res/cardsfolder/i/ironshell_beetle.txt +++ b/forge-gui/res/cardsfolder/i/ironshell_beetle.txt @@ -4,5 +4,6 @@ Types:Creature Insect PT:1/1 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPut | TriggerDescription$ When CARDNAME enters the battlefield, put a +1/+1 counter on target creature. SVar:TrigPut:DB$PutCounter | ValidTgts$ Creature | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ 1 +DeckHas:Ability$Counters SVar:Picture:http://www.wizards.com/global/images/magic/general/ironshell_beetle.jpg Oracle:When Ironshell Beetle enters the battlefield, put a +1/+1 counter on target creature. diff --git a/forge-gui/res/cardsfolder/i/isolated_watchtower.txt b/forge-gui/res/cardsfolder/i/isolated_watchtower.txt new file mode 100644 index 00000000000..a4c4749c084 --- /dev/null +++ b/forge-gui/res/cardsfolder/i/isolated_watchtower.txt @@ -0,0 +1,9 @@ +Name:Isolated Watchtower +ManaCost:no cost +Types:Land +A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. +A:AB$ Scry | Cost$ 2 T | ScryNum$ 1 | SubAbility$ DBReveal | CheckSVar$ X | SVarCompare$ GEY | References$ X,Y | SpellDescription$ Scry 1, then you may reveal the top card of your library. If a basic land card is revealed this way, put it onto the battlefield tapped. Activate this ability only if an opponent controls at least two more lands than you. +SVar:DBReveal:DB$ Dig | Optional$ True | DigNum$ 1 | Reveal$ True | ChangeValid$ Land.Basic | DestinationZone$ Battlefield | Tapped$ True | DestinationZone2$ Library | LibraryPosition2$ 0 +SVar:X:PlayerCountOpponents$HighestValid Land.YouCtrl +SVar:Y:Count$Valid Land.YouCtrl/Plus.2 +Oracle:{T}: Add {C}.\n{2}, {T}: Scry 1, then you may reveal the top card of your library. If a basic land card is revealed this way, put it onto the battlefield tapped. Activate this ability only if an opponent controls at least two more lands than you. diff --git a/forge-gui/res/cardsfolder/upcoming/izoni_thousand_eyed.txt b/forge-gui/res/cardsfolder/i/izoni_thousand_eyed.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/izoni_thousand_eyed.txt rename to forge-gui/res/cardsfolder/i/izoni_thousand_eyed.txt index c5fd38febe0..4f92a03e2f1 100644 --- a/forge-gui/res/cardsfolder/upcoming/izoni_thousand_eyed.txt +++ b/forge-gui/res/cardsfolder/i/izoni_thousand_eyed.txt @@ -7,4 +7,5 @@ SVar:TrigToken:DB$Token | TokenAmount$ X | TokenName$ Insect | TokenTypes$ Creat SVar:X:Count$TypeInYourYard.Creature A:AB$ GainLife | Cost$ B G Sac<1/Creature.Other/another creature> | Defined$ You | LifeAmount$ 1 | SubAbility$ DBDraw | SpellDescription$ You gain 1 life and draw a card. SVar:DBDraw:DB$ Draw | NumCards$ 1 +DeckHas:Ability$Token & Ability$LifeGain Oracle:Undergrowth — When Izoni, Thousand-Eyed enters the battlefield, create a 1/1 black and green Insect creature token for each creature card in your graveyard.\n{B}{G}, Sacrifice another creature: You gain 1 life and draw a card. diff --git a/forge-gui/res/cardsfolder/upcoming/izzet_locket.txt b/forge-gui/res/cardsfolder/i/izzet_locket.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/izzet_locket.txt rename to forge-gui/res/cardsfolder/i/izzet_locket.txt diff --git a/forge-gui/res/cardsfolder/j/jade_monolith.txt b/forge-gui/res/cardsfolder/j/jade_monolith.txt index 2913752b72f..fffbf478596 100644 --- a/forge-gui/res/cardsfolder/j/jade_monolith.txt +++ b/forge-gui/res/cardsfolder/j/jade_monolith.txt @@ -2,7 +2,7 @@ Name:Jade Monolith 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,ExileEffect | References$ SelflessDamage,OutOfSight,SelflessDamage,ExileEffect | Duration$ HostLeavesOrEOT | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | SubAbility$ DBCleanup | ConditionDefined$ ChosenCard | ConditionPresent$ Card,Emblem | ConditionCompare$ GE1 +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:SelflessDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ You | VarType$ Player | SubAbility$ ExileEffect #Zone Change for the source of your choice diff --git a/forge-gui/res/cardsfolder/j/jedit_ojanen_of_efrava.txt b/forge-gui/res/cardsfolder/j/jedit_ojanen_of_efrava.txt index b101c2d6aac..401d85ea186 100644 --- a/forge-gui/res/cardsfolder/j/jedit_ojanen_of_efrava.txt +++ b/forge-gui/res/cardsfolder/j/jedit_ojanen_of_efrava.txt @@ -5,7 +5,7 @@ PT:5/5 K:Forestwalk T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME attacks or blocks, create a 2/2 green Cat Warrior creature token with forestwalk. T:Mode$ Blocks | ValidCard$ Card.Self | Execute$ TrigToken | Secondary$ True | TriggerDescription$ Whenever CARDNAME attacks or blocks, create a 2/2 green Cat Warrior creature token with forestwalk. -SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenName$ Cat Warrior | TokenTypes$ Creature,Cat,Warrior | TokenOwner$ You | TokenColors$ Green | TokenPower$ 2 | TokenToughness$ 2 | TokenKeywords$ Forestwalk +SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ g_2_2_cat_warrior_forestwalk SVar:HasAttackEffect:TRUE SVar:HasBlockEffect:TRUE SVar:Picture:http://www.wizards.com/global/images/magic/general/jedit_ojanen_of_efrava.jpg diff --git a/forge-gui/res/cardsfolder/upcoming/join_shields.txt b/forge-gui/res/cardsfolder/j/join_shields.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/join_shields.txt rename to forge-gui/res/cardsfolder/j/join_shields.txt diff --git a/forge-gui/res/cardsfolder/upcoming/justice_strike.txt b/forge-gui/res/cardsfolder/j/justice_strike.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/justice_strike.txt rename to forge-gui/res/cardsfolder/j/justice_strike.txt diff --git a/forge-gui/res/cardsfolder/k/kalonian_twingrove.txt b/forge-gui/res/cardsfolder/k/kalonian_twingrove.txt index d8431f601fe..09459f1ef24 100644 --- a/forge-gui/res/cardsfolder/k/kalonian_twingrove.txt +++ b/forge-gui/res/cardsfolder/k/kalonian_twingrove.txt @@ -5,8 +5,7 @@ PT:*/* S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | SetToughness$ X | Description$ CARDNAMEs power and toughness are each equal to the number of Forests you control. SVar:X:Count$Valid Forest.YouCtrl T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a green Treefolk Warrior creature token with "This creature's power and toughness are each equal to the number of Forests you control." -SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenName$ Treefolk Warrior | TokenTypes$ Creature,Treefolk,Warrior | TokenOwner$ You | TokenColors$ Green | TokenPower$ X | TokenToughness$ X | TokenStaticAbilities$ TokenPT | TokenSVars$ X | References$ X | TokenImage$ g x x treefolk warrior -SVar:TokenPT:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | SetToughness$ X | Description$ CARDNAME's power and toughness are each equal to the number of Forests you control. +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ g_x_x_treefolk_warrior | LegacyImage$ g x x treefolk warrior SVar:BuffedBy:Forest SVar:NeedsToPlayVar:X GE3 SVar:Picture:http://www.wizards.com/global/images/magic/general/kalonian_twingrove.jpg diff --git a/forge-gui/res/cardsfolder/upcoming/knight_of_autumn.txt b/forge-gui/res/cardsfolder/k/knight_of_autumn.txt similarity index 97% rename from forge-gui/res/cardsfolder/upcoming/knight_of_autumn.txt rename to forge-gui/res/cardsfolder/k/knight_of_autumn.txt index 907e199df3c..773ea6207c9 100644 --- a/forge-gui/res/cardsfolder/upcoming/knight_of_autumn.txt +++ b/forge-gui/res/cardsfolder/k/knight_of_autumn.txt @@ -7,4 +7,5 @@ SVar:TrigCharm:DB$ Charm | Choices$ DBPump,DBDestroy,DBGainLife SVar:DBPump:DB$ PutCounter | CounterType$ P1P1 | CounterNum$ 2 | SpellDescription$ Put two +1/+1 counters on CARDNAME. SVar:DBDestroy:DB$ Destroy | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | SpellDescription$ Destroy target artifact or enchantment. SVar:DBGainLife:DB$ GainLife | LifeAmount$ 4 | SpellDescription$ You gain 4 life. +DeckHas:Ability$Counters Oracle:When Knight of Autumn enters the battlefield, choose one —\n• Put two +1/+1 counters on Knight of Autumn.\n• Destroy target artifact or enchantment.\n• You gain 4 life. diff --git a/forge-gui/res/cardsfolder/upcoming/kraul_foragers.txt b/forge-gui/res/cardsfolder/k/kraul_foragers.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/kraul_foragers.txt rename to forge-gui/res/cardsfolder/k/kraul_foragers.txt diff --git a/forge-gui/res/cardsfolder/upcoming/kraul_harpooner.txt b/forge-gui/res/cardsfolder/k/kraul_harpooner.txt similarity index 83% rename from forge-gui/res/cardsfolder/upcoming/kraul_harpooner.txt rename to forge-gui/res/cardsfolder/k/kraul_harpooner.txt index 6d35260d1b6..0fde4013fb2 100644 --- a/forge-gui/res/cardsfolder/upcoming/kraul_harpooner.txt +++ b/forge-gui/res/cardsfolder/k/kraul_harpooner.txt @@ -4,6 +4,7 @@ Types:Creature Insect Warrior PT:3/2 K:Reach T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ When CARDNAME enters the battlefield, choose up to one target creature with flying you don't control. CARDNAME gets +X/+0 until end of turn, where X is the number of creature cards in your graveyard, then you may have CARDNAME fight that creature. -SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ X | SubAbility$ DBFight -SVar:DBFight:DB$ Fight | Defined$ Self | ValidTgts$ Creature.withFlying+YouDontCtrl | TgtPrompt$ Select target creature with flying you don't control +SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ X | References$ X | SubAbility$ DBFight +SVar:DBFight:DB$ Fight | Defined$ Self | ValidTgts$ Creature.withFlying+YouDontCtrl | TgtPrompt$ Select target creature with flying you don't control | TargetMin$ 0 | TargetMax$ 1 +SVar:X:Count$TypeInYourYard.Creature Oracle:Reach\nUndergrowth — When Kraul Harpooner enters the battlefield, choose up to one target creature with flying you don't control. Kraul Harpooner gets +X/+0 until end of turn, where X is the number of creature cards in your graveyard, then you may have Kraul Harpooner fight that creature. diff --git a/forge-gui/res/cardsfolder/upcoming/kraul_raider.txt b/forge-gui/res/cardsfolder/k/kraul_raider.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/kraul_raider.txt rename to forge-gui/res/cardsfolder/k/kraul_raider.txt diff --git a/forge-gui/res/cardsfolder/upcoming/kraul_swarm.txt b/forge-gui/res/cardsfolder/k/kraul_swarm.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/kraul_swarm.txt rename to forge-gui/res/cardsfolder/k/kraul_swarm.txt diff --git a/forge-gui/res/cardsfolder/upcoming/lava_coil.txt b/forge-gui/res/cardsfolder/l/lava_coil.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/lava_coil.txt rename to forge-gui/res/cardsfolder/l/lava_coil.txt diff --git a/forge-gui/res/cardsfolder/l/lazav_dimir_mastermind.txt b/forge-gui/res/cardsfolder/l/lazav_dimir_mastermind.txt index 547047a35a0..a0bc6751f89 100644 --- a/forge-gui/res/cardsfolder/l/lazav_dimir_mastermind.txt +++ b/forge-gui/res/cardsfolder/l/lazav_dimir_mastermind.txt @@ -3,9 +3,8 @@ ManaCost:U U B B Types:Legendary Creature Shapeshifter PT:3/3 K:Hexproof -T:Mode$ ChangesZone | Origin$ Any | Destination$ Graveyard | ValidCard$ Creature.nonToken+OppOwn | TriggerZones$ Battlefield | Execute$ LazavCopy | OptionalDecider$ You | TriggerDescription$ Whenever a creature card is put into an opponent's graveyard from anywhere, you may have CARDNAME become a copy of that card except it's name is still CARDNAME, it's legendary in addition to it's other types, and it gains hexproof and this ability. -SVar:LazavCopy:DB$ Clone | Defined$ TriggeredCard | KeepName$ True | AddTypes$ Legendary | AddTriggers$ LazavTrig | AddKeywords$ Hexproof | AddSVars$ LazavCopy,LazavTrig -SVar:LazavTrig:Mode$ ChangesZone | Origin$ Any | Destination$ Graveyard | ValidCard$ Creature.OppOwn | TriggerZones$ Battlefield | Execute$ LazavCopy | OptionalDecider$ You | TriggerDescription$ Whenever a creature card is put into an opponent's graveyard from anywhere, you may have CARDNAME become a copy of that card except it's name is still CARDNAME, it's legendary in addition to it's other types, and it gains hexproof and this ability. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Graveyard | ValidCard$ Creature.nonToken+OppOwn | TriggerZones$ Battlefield | Execute$ LazavCopy | OptionalDecider$ You | TriggerDescription$ Whenever a creature card is put into an opponent’s graveyard from anywhere, you may have Lazav, Dimir Mastermind become a copy of that card, except its name is Lazav, Dimir Mastermind, it’s legendary in addition to its other types, and it has hexproof and this ability. +SVar:LazavCopy:DB$ Clone | Defined$ TriggeredCard | NewName$ Lazav, Dimir Mastermind | AddTypes$ Legendary | AddKeywords$ Hexproof | GainThisAbility$ True SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/lazav_dimir_mastermind.jpg -Oracle:Hexproof\nWhenever a creature card is put into an opponent's graveyard from anywhere, you may have Lazav, Dimir Mastermind become a copy of that card except its name is still Lazav, Dimir Mastermind, it's legendary in addition to its other types, and it gains hexproof and this ability. +Oracle:Hexproof\nWhenever a creature card is put into an opponent’s graveyard from anywhere, you may have Lazav, Dimir Mastermind become a copy of that card, except its name is Lazav, Dimir Mastermind, it’s legendary in addition to its other types, and it has hexproof and this ability. diff --git a/forge-gui/res/cardsfolder/l/lazav_the_multifarious.txt b/forge-gui/res/cardsfolder/l/lazav_the_multifarious.txt new file mode 100644 index 00000000000..374c88202d1 --- /dev/null +++ b/forge-gui/res/cardsfolder/l/lazav_the_multifarious.txt @@ -0,0 +1,10 @@ +Name:Lazav, the Multifarious +ManaCost:U B +Types:Legendary Creature Shapeshifter +PT:1/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSurveil | TriggerDescription$ When CARDNAME enters the battlefield, scry 1. (To scry 1, look at the top card of your library. You may put that card into your graveyard.) +SVar:TrigSurveil:DB$ Surveil | Amount$ 1 +A:AB$ Clone | Cost$ X | ValidTgts$ Creature.YouOwn | References$ X | TgtZone$ Graveyard | TgtPrompt$ Select target creature card in your graveyard | AddTypes$ Legendary | NewName$ Lazav, the Multifarious | GainThisAbility$ True | SpellDescription$ CARDNAME becomes a copy of target creature card in your graveyard with converted mana cost X, except its name is CARDNAME, it's legendary in addition to it's other types, and it has this ability. +SVar:X:Targeted$CardManaCost +DeckHas:Ability$Surveil & Ability$Graveyard +Oracle:When Lazav, the Multifarious enters the battlefield, surveil 1. (Look at the top card of your library. You may put that card into your graveyard.)\n{X}: Lazav, the Multifarious becomes a copy of target creature card in your graveyard with converted mana cost X, except its name is Lazav, the Multifarious, it's legendary in addition to its other types, and it has this ability. diff --git a/forge-gui/res/cardsfolder/upcoming/league_guildmage.txt b/forge-gui/res/cardsfolder/l/league_guildmage.txt similarity index 90% rename from forge-gui/res/cardsfolder/upcoming/league_guildmage.txt rename to forge-gui/res/cardsfolder/l/league_guildmage.txt index 01b6450215d..c0cdc4c664c 100644 --- a/forge-gui/res/cardsfolder/upcoming/league_guildmage.txt +++ b/forge-gui/res/cardsfolder/l/league_guildmage.txt @@ -4,4 +4,6 @@ Types:Creature Human Wizard PT:2/2 A:AB$ Draw | Cost$ 3 U T | NumCards$ 1 | SpellDescription$ Draw a card. A:AB$ CopySpellAbility | Cost$ X R T | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell you control with converted mana cost X. You may choose new targets for the copy. +SVar:X:Targeted$CardManaCost +DeckHints:Type$Instant|Sorcery Oracle:{3}{U}, {T}: Draw a card.\n{X}{R}, {T}: Copy target instant or sorcery spell you control with converted mana cost X. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/upcoming/leapfrog.txt b/forge-gui/res/cardsfolder/l/leapfrog.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/leapfrog.txt rename to forge-gui/res/cardsfolder/l/leapfrog.txt index 7a7ada2f5a2..345db3634bb 100644 --- a/forge-gui/res/cardsfolder/upcoming/leapfrog.txt +++ b/forge-gui/res/cardsfolder/l/leapfrog.txt @@ -4,4 +4,5 @@ Types:Creature Frog PT:3/1 S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Flying | CheckSVar$ X | SVarCompare$ GE1 | Description$ CARDNAME has flying as long as you've cast and instant or sorcery spell this turn. SVar:X:Count$ThisTurnCast_Instant.YouCtrl,Sorcery.YouCtrl +DeckHints:Type$Instant|Sorcery Oracle:Leapfrog has flying as long as you've cast and instant or sorcery spell this turn. diff --git a/forge-gui/res/cardsfolder/upcoming/ledev_champion.txt b/forge-gui/res/cardsfolder/l/ledev_champion.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/ledev_champion.txt rename to forge-gui/res/cardsfolder/l/ledev_champion.txt index 4f8e53d5f15..761277c4199 100644 --- a/forge-gui/res/cardsfolder/upcoming/ledev_champion.txt +++ b/forge-gui/res/cardsfolder/l/ledev_champion.txt @@ -11,5 +11,5 @@ SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:Count$Valid Creature.YouCtrl SVar:Y:Remembered$Amount A:AB$ Token | Cost$ 3 G W | TokenAmount$ 1 | TokenScript$ w_1_1_soldier_lifelink | SpellDescription$ Create a 1/1 white Soldier creature token with lifelink. -DeckHas:Ability$Token +DeckHas:Ability$Token & Ability$LifeGain Oracle:Whenever Ledev Champion attacks, you may tap any number of untapped creatures you control. Ledev Champion gets +1/+1 until end of turn for each creature tapped this way.\n{3}{G}{W}: Create a 1/1 white Soldier creature token with lifelink. diff --git a/forge-gui/res/cardsfolder/upcoming/ledev_guardian.txt b/forge-gui/res/cardsfolder/l/ledev_guardian.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/ledev_guardian.txt rename to forge-gui/res/cardsfolder/l/ledev_guardian.txt diff --git a/forge-gui/res/cardsfolder/upcoming/legion_guildmage.txt b/forge-gui/res/cardsfolder/l/legion_guildmage.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/legion_guildmage.txt rename to forge-gui/res/cardsfolder/l/legion_guildmage.txt diff --git a/forge-gui/res/cardsfolder/upcoming/legion_warboss.txt b/forge-gui/res/cardsfolder/l/legion_warboss.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/legion_warboss.txt rename to forge-gui/res/cardsfolder/l/legion_warboss.txt diff --git a/forge-gui/res/cardsfolder/upcoming/light_of_the_legion.txt b/forge-gui/res/cardsfolder/l/light_of_the_legion.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/light_of_the_legion.txt rename to forge-gui/res/cardsfolder/l/light_of_the_legion.txt diff --git a/forge-gui/res/cardsfolder/l/lithomancers_focus.txt b/forge-gui/res/cardsfolder/l/lithomancers_focus.txt index 62f5eabd196..5a8d0c5b51d 100644 --- a/forge-gui/res/cardsfolder/l/lithomancers_focus.txt +++ b/forge-gui/res/cardsfolder/l/lithomancers_focus.txt @@ -3,6 +3,6 @@ ManaCost:W Types:Instant A:SP$ Pump | Cost$ W | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +2 | NumDef$ +2 | SubAbility$ DBEffect | SpellDescription$ Target creature gets +2/+2 until end of turn. Prevent all damage that would be dealt to that creature this turn by colorless sources. SVar:DBEffect:DB$ Effect | Defined$ Targeted | ReplacementEffects$ PreventColorless | RememberObjects$ Targeted | ForgetOnMoved$ Battlefield -SVar:PreventColorless:Event$ DamageDone | Prevent$ True | ActiveZones$ Command | ValidSource$ Card.ColorlessSource | Description$ Prevent all damage that would be dealt to that creature this turn by colorless sources. +SVar:PreventColorless:Event$ DamageDone | Prevent$ True | ActiveZones$ Command | ValidSource$ Card.ColorlessSource | ValidTarget$ Card.IsRemembered | Description$ Prevent all damage that would be dealt to that creature this turn by colorless sources. SVar:Picture:http://www.wizards.com/global/images/magic/general/lithomancers_focus.jpg Oracle:Target creature gets +2/+2 until end of turn. Prevent all damage that would be dealt to that creature this turn by colorless sources. diff --git a/forge-gui/res/cardsfolder/l/lord_windgrace.txt b/forge-gui/res/cardsfolder/l/lord_windgrace.txt index d6223fe7aed..c6521a3129f 100644 --- a/forge-gui/res/cardsfolder/l/lord_windgrace.txt +++ b/forge-gui/res/cardsfolder/l/lord_windgrace.txt @@ -8,6 +8,6 @@ SVar:DBDraw2:DB$ Draw | NumCards$ 1 | ConditionDefined$ Remembered | ConditionPr SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True A:AB$ ChangeZone | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | Origin$ Graveyard | Destination$ Battlefield | TargetMin$ 0 | TargetMax$ 2 | TgtPrompt$ Choose target land card in your graveyard | ValidTgts$ Land.YouCtrl | SpellDescription$ Return up to two target land cards from your graveyard to the battlefield. A:AB$ Destroy | Cost$ SubCounter<11/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | TargetMin$ 0 | TargetMax$ 6 | SubAbility$ DBToken | SpellDescription$ Destroy up to six target nonland permanents, then create six 2/2 green Cat Warrior creature tokens with forestwalk. -SVar:DBToken:DB$ Token | TokenAmount$ 6 | TokenName$ Cat Warrior | TokenTypes$ Creature,Cat,Warrior | TokenOwner$ You | TokenColors$ Green | TokenPower$ 2 | TokenToughness$ 2 | TokenKeywords$ Forestwalk | TokenImage$ g 2 2 cat warrior c18 +SVar:DBToken:DB$ Token | TokenAmount$ 6 | TokenOwner$ You | TokenScript$ g_2_2_cat_warrior_forestwalk | LegacyImage$ g 2 2 cat warrior c18 K:CARDNAME can be your commander. Oracle:[+2]: Discard a card, then draw a card. If a land card is discarded this way, draw an additional card.\n[-3]: Return up to two target land cards from your graveyard to the battlefield.\n[-11]: Destroy up to six target nonland permanents, then create six 2/2 green Cat Warrior creature tokens with forestwalk.\nLord Windgrace can be your commander. diff --git a/forge-gui/res/cardsfolder/upcoming/lotleth_giant.txt b/forge-gui/res/cardsfolder/l/lotleth_giant.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/lotleth_giant.txt rename to forge-gui/res/cardsfolder/l/lotleth_giant.txt diff --git a/forge-gui/res/cardsfolder/upcoming/loxodon_restorer.txt b/forge-gui/res/cardsfolder/l/loxodon_restorer.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/loxodon_restorer.txt rename to forge-gui/res/cardsfolder/l/loxodon_restorer.txt diff --git a/forge-gui/res/cardsfolder/m/makeshift_mauler.txt b/forge-gui/res/cardsfolder/m/makeshift_mauler.txt index 6e15a9ea94c..bf5f2173f5d 100644 --- a/forge-gui/res/cardsfolder/m/makeshift_mauler.txt +++ b/forge-gui/res/cardsfolder/m/makeshift_mauler.txt @@ -2,6 +2,6 @@ Name:Makeshift Mauler ManaCost:3 U Types:Creature Zombie Horror PT:4/5 -SVar:FullCost:3 U ExileFromGrave<1/Creature> +A:SP$ PermanentCreature | Cost$ 3 U ExileFromGrave<1/Creature> SVar:Picture:http://www.wizards.com/global/images/magic/general/makeshift_mauler.jpg Oracle:As an additional cost to cast Makeshift Mauler, exile a creature card from your graveyard. diff --git a/forge-gui/res/cardsfolder/upcoming/march_of_the_multitudes.txt b/forge-gui/res/cardsfolder/m/march_of_the_multitudes.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/march_of_the_multitudes.txt rename to forge-gui/res/cardsfolder/m/march_of_the_multitudes.txt index 693f71a3d99..9eefe598548 100644 --- a/forge-gui/res/cardsfolder/upcoming/march_of_the_multitudes.txt +++ b/forge-gui/res/cardsfolder/m/march_of_the_multitudes.txt @@ -4,4 +4,5 @@ Types:Instant K:Convoke A:SP$ Token | Cost$ X G W W | TokenAmount$ X | References$ X | TokenScript$ w_1_1_soldier_lifelink | SpellDescription$ Create X 1/1 white Soldier creature tokens with lifelink. SVar:X:Count$xPaid +DeckHas:Ability$Token & Ability$LifeGain Oracle:Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of the creature's color.)\nCreate X 1/1 white Soldier creature tokens with lifelink. diff --git a/forge-gui/res/cardsfolder/upcoming/mausoleum_secrets.txt b/forge-gui/res/cardsfolder/m/mausoleum_secrets.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/mausoleum_secrets.txt rename to forge-gui/res/cardsfolder/m/mausoleum_secrets.txt diff --git a/forge-gui/res/cardsfolder/upcoming/maximize_altitude.txt b/forge-gui/res/cardsfolder/m/maximize_altitude.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/maximize_altitude.txt rename to forge-gui/res/cardsfolder/m/maximize_altitude.txt diff --git a/forge-gui/res/cardsfolder/upcoming/maximize_velocity.txt b/forge-gui/res/cardsfolder/m/maximize_velocity.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/maximize_velocity.txt rename to forge-gui/res/cardsfolder/m/maximize_velocity.txt diff --git a/forge-gui/res/cardsfolder/upcoming/mephitic_vapors.txt b/forge-gui/res/cardsfolder/m/mephitic_vapors.txt similarity index 91% rename from forge-gui/res/cardsfolder/upcoming/mephitic_vapors.txt rename to forge-gui/res/cardsfolder/m/mephitic_vapors.txt index 20328c8009e..eeca0cc0668 100644 --- a/forge-gui/res/cardsfolder/upcoming/mephitic_vapors.txt +++ b/forge-gui/res/cardsfolder/m/mephitic_vapors.txt @@ -3,4 +3,5 @@ ManaCost:2 B Types:Sorcery A:SP$ PumpAll | Cost$ 2 B | ValidCards$ Creature | NumAtt$ -1 | NumDef$ -1 | IsCurse$ True | Subability$ DBSurveil | SpellDescription$ All creatures get -1/-1 until end of turn. SVar:DBSurveil:DB$ Surveil | Amount$ 2 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:All creatures get -1/-1 until end of turn.\nSurveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on the top of your library in any order.) diff --git a/forge-gui/res/cardsfolder/m/michiko_konda_truth_seeker.txt b/forge-gui/res/cardsfolder/m/michiko_konda_truth_seeker.txt index 8b7e34ff4f7..91727132aff 100644 --- a/forge-gui/res/cardsfolder/m/michiko_konda_truth_seeker.txt +++ b/forge-gui/res/cardsfolder/m/michiko_konda_truth_seeker.txt @@ -4,6 +4,5 @@ Types:Legendary Creature Human Advisor PT:2/2 T:Mode$ DamageDone | ValidSource$ Card.OppCtrl | ValidTarget$ You | TriggerZones$ Battlefield | Execute$ TrigSac | TriggerDescription$ Whenever a source an opponent controls deals damage to you, that player sacrifices a permanent. SVar:TrigSac:DB$Sacrifice | Defined$ TriggeredSourceController | SacValid$ Permanent -Svar:Rarity:Rare SVar:Picture:http://www.wizards.com/global/images/magic/general/michiko_konda_truth_seeker.jpg Oracle:Whenever a source an opponent controls deals damage to you, that player sacrifices a permanent. diff --git a/forge-gui/res/cardsfolder/upcoming/midnight_reaper.txt b/forge-gui/res/cardsfolder/m/midnight_reaper.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/midnight_reaper.txt rename to forge-gui/res/cardsfolder/m/midnight_reaper.txt diff --git a/forge-gui/res/cardsfolder/m/mission_briefing.txt b/forge-gui/res/cardsfolder/m/mission_briefing.txt new file mode 100644 index 00000000000..3fc8640f76e --- /dev/null +++ b/forge-gui/res/cardsfolder/m/mission_briefing.txt @@ -0,0 +1,14 @@ +Name:Mission Briefing +ManaCost:U U +Types:Instant +A:SP$ Surveil | Cost$ U U | Amount$ 2 | SubAbility$ DBChooseCard | SpellDescription$ Surveil 2, then choose an instant or sorcery card in your graveyard. You may cast that card this turn. If that card would be put into your graveyard this turn, exile it instead. +SVar:DBChooseCard:DB$ ChooseCard | Choices$ Instant.YouCtrl,Sorcery.YouCtrl | ChoiceZone$ Graveyard | AILogic$ CastFromGraveThisTurn | Mandatory$ True | RememberChosen$ True | SubAbility$ DBEffect | SpellDescription$ You may cast that card this turn. If that card would be put into your graveyard this turn, exile it instead. +SVar:DBEffect:DB$ Effect | RememberObjects$ RememberedCard | StaticAbilities$ Play | SubAbility$ DBCleanup | ExileOnMoved$ Stack | ReplacementEffects$ ReplaceGraveyard | SVars$ MoveExile +SVar:Play:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Graveyard | Description$ You may play remembered card. +SVar:ReplaceGraveyard:Event$ Moved | ValidCard$ Card.IsRemembered | Origin$ Stack | Destination$ Graveyard | ReplaceWith$ MoveExile | Description$ If that card would be put into your graveyard this turn, exile it instead. +SVar:MoveExile:DB$ ChangeZone | Defined$ ReplacedCard | Origin$ Stack | Destination$ Exile +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:RemAIDeck:True +DeckHas:Ability$Surveil & Ability$Graveyard +SVar:Picture:http://www.wizards.com/global/images/magic/general/mission_briefing.jpg +Oracle:Surveil 2, then choose an instant or sorcery card in your graveyard. You may cast that card this turn. If that card would be put into your graveyard this turn, exile it instead. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/m/mitotic_slime.txt b/forge-gui/res/cardsfolder/m/mitotic_slime.txt index 74bc80efade..74bb2ec3300 100644 --- a/forge-gui/res/cardsfolder/m/mitotic_slime.txt +++ b/forge-gui/res/cardsfolder/m/mitotic_slime.txt @@ -3,8 +3,6 @@ ManaCost:4 G Types:Creature Ooze PT:4/4 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenSenior | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create two 2/2 green Ooze creature tokens. They have "When this creature dies, create two 1/1 green Ooze creature tokens." -SVar:TrigTokenSenior:DB$Token | TokenImage$ g 2 2 ooze | TokenName$ Ooze | TokenTypes$ Creature,Ooze | TokenColors$ Green | TokenOwner$ You | TokenPower$ 2 | TokenToughness$ 2 | TokenAmount$ 2 | TokenTriggers$ TriggerJunior | TokenSVars$ TrigTokenJunior -SVar:TriggerJunior:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenJunior | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create two 1/1 green Ooze creature tokens. -SVar:TrigTokenJunior:DB$Token | TokenImage$ g 1 1 ooze | TokenName$ Ooze | TokenTypes$ Creature,Ooze | TokenColors$ Green | TokenOwner$ You | TokenPower$ 1 | TokenToughness$ 1 | TokenAmount$ 2 +SVar:TrigTokenSenior:DB$Token | LegacyImage$ g 2 2 ooze | TokenScript$ g_2_2_ooze_mitotic | TokenOwner$ You | TokenAmount$ 2 SVar:Picture:http://www.wizards.com/global/images/magic/general/mitotic_slime.jpg Oracle:When Mitotic Slime dies, create two 2/2 green Ooze creature tokens. They have "When this creature dies, create two 1/1 green Ooze creature tokens." diff --git a/forge-gui/res/cardsfolder/m/mizzium_transreliquat.txt b/forge-gui/res/cardsfolder/m/mizzium_transreliquat.txt index 0888a589650..6799f7d0476 100644 --- a/forge-gui/res/cardsfolder/m/mizzium_transreliquat.txt +++ b/forge-gui/res/cardsfolder/m/mizzium_transreliquat.txt @@ -2,8 +2,7 @@ Name:Mizzium Transreliquat ManaCost:3 Types:Artifact A:AB$ Clone | Cost$ 3 | ValidTgts$ Artifact | TgtPrompt$ Select target artifact to copy until end of turn. | Duration$ UntilEndOfTurn | SpellDescription$ CARDNAME becomes a copy of target artifact until end of turn. -A:AB$ Clone | Cost$ 1 U R | ValidTgts$ Artifact | TgtPrompt$ Select target artifact to copy. | AddAbilities$ MizzCopy | AddSVars$ MizzCopy | SpellDescription$ CARDNAME becomes a copy of target artifact and gains this ability. -SVar:MizzCopy:AB$ Clone | Cost$ 1 U R | ValidTgts$ Artifact | TgtPrompt$ Select target artifact to copy. | AddAbilities$ MizzCopy | AddSVars$ MizzCopy | SpellDescription$ CARDNAME becomes a copy of target artifact and gains this ability. +A:AB$ Clone | Cost$ 1 U R | ValidTgts$ Artifact | TgtPrompt$ Select target artifact to copy. | GainThisAbility$ True | SpellDescription$ CARDNAME becomes a copy of target artifact and gains this ability. SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/mizzium_transreliquat.jpg Oracle:{3}: Mizzium Transreliquat becomes a copy of target artifact until end of turn.\n{1}{U}{R}: Mizzium Transreliquat becomes a copy of target artifact and gains this ability. diff --git a/forge-gui/res/cardsfolder/m/mnemonic_betrayal.txt b/forge-gui/res/cardsfolder/m/mnemonic_betrayal.txt new file mode 100644 index 00000000000..13104cb13b5 --- /dev/null +++ b/forge-gui/res/cardsfolder/m/mnemonic_betrayal.txt @@ -0,0 +1,10 @@ +Name:Mnemonic Betrayal +ManaCost:1 U B +Types:Sorcery +A:SP$ ChangeZoneAll | Cost$ 1 U B | Defined$ Player.Opponent | Origin$ Graveyard | Destination$ Exile | ChangeType$ Card | RememberChanged$ True | SubAbility$ DBEffect | SpellDescription$ Exile all card from all opponents' graveyards. You may cast those cards this turn, and you may spend it as though it were mana of any type to cast those spells. At the beginning of the next end step, if any of those cards remain exiled, return them to their owner's graveyards. Exile CARDNAME. +SVar:DBEffect:DB$ Effect | StaticAbilities$ STPlay | RememberObjects$ Remembered | ForgetOnMoved$ Exile | SubAbility$ DelTrig +SVar:STPlay:Mode$ Continuous | MayPlay$ True | MayPlayIgnoreType$ True | EffectZone$ Command | Affected$ Card.nonLand+IsRemembered | AffectedZone$ Exile | Description$ You may cast those cards this turn, and you may spend mana as though it were mana of any type to cast those spells. +SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | TriggerRememberedInZone$ Exile | RememberObjects$ Remembered | TriggerDescription$ At the beginning of the next end step, if any of those cards remain exiled, return them to their owner's graveyards. | SubAbility$ ExileSelf +SVar:TrigReturn:DB$ ChangeZone | Defined$ DelayTriggerRemembered | Origin$ Exile | Destination$ Graveyard +SVar:ExileSelf:DB$ ChangeZone | Defined$ Self | Origin$ Stack | Destination$ Exile +Oracle:Exile all card from all opponents' graveyards. You may cast those cards this turn, and you may spend mana as though it were mana of any type to cast those spells. At the beginning of the next end step, if any of those cards remain exiled, return them to their owner's graveyards.\nExile Mnemonic Betrayal. diff --git a/forge-gui/res/cardsfolder/upcoming/molderhulk.txt b/forge-gui/res/cardsfolder/m/molderhulk.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/molderhulk.txt rename to forge-gui/res/cardsfolder/m/molderhulk.txt diff --git a/forge-gui/res/cardsfolder/upcoming/moodmark_painter.txt b/forge-gui/res/cardsfolder/m/moodmark_painter.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/moodmark_painter.txt rename to forge-gui/res/cardsfolder/m/moodmark_painter.txt diff --git a/forge-gui/res/cardsfolder/upcoming/murmuring_mystic.txt b/forge-gui/res/cardsfolder/m/murmuring_mystic.txt similarity index 91% rename from forge-gui/res/cardsfolder/upcoming/murmuring_mystic.txt rename to forge-gui/res/cardsfolder/m/murmuring_mystic.txt index e564cee9162..76f848425af 100644 --- a/forge-gui/res/cardsfolder/upcoming/murmuring_mystic.txt +++ b/forge-gui/res/cardsfolder/m/murmuring_mystic.txt @@ -5,4 +5,6 @@ PT:1/5 T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever you cast an instant or sorcery spell, create a 1/1 blue Bird Illusion creature token with flying. SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenScript$ u_1_1_bird_illusion_flying SVar:BuffedBy:Instant,Sorcery +DeckHints:Type$Instant|Sorcery +DeckHas:Ability$Token Oracle:Whenever you cast an instant or sorcery spell, create a 1/1 blue Bird Illusion creature token with flying. diff --git a/forge-gui/res/cardsfolder/upcoming/muse_drake.txt b/forge-gui/res/cardsfolder/m/muse_drake.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/muse_drake.txt rename to forge-gui/res/cardsfolder/m/muse_drake.txt diff --git a/forge-gui/res/cardsfolder/m/myr_superion.txt b/forge-gui/res/cardsfolder/m/myr_superion.txt index 3d9a93a570d..b309044b89f 100644 --- a/forge-gui/res/cardsfolder/m/myr_superion.txt +++ b/forge-gui/res/cardsfolder/m/myr_superion.txt @@ -3,7 +3,7 @@ ManaCost:2 Types:Artifact Creature Myr PT:5/6 Text:Spend only mana produced by creatures to cast CARDNAME. -SVar:FullCost:Mana<2\Creature> +A:SP$ PermanentCreature | Cost$ Mana<2\Creature> SVar:RemRandomDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/myr_superion.jpg Oracle:Spend only mana produced by creatures to cast Myr Superion. diff --git a/forge-gui/res/cardsfolder/m/myth_unbound.txt b/forge-gui/res/cardsfolder/m/myth_unbound.txt index c304efb05e6..3855b57b5b0 100644 --- a/forge-gui/res/cardsfolder/m/myth_unbound.txt +++ b/forge-gui/res/cardsfolder/m/myth_unbound.txt @@ -1,9 +1,9 @@ Name:Myth Unbound ManaCost:2 G Types:Enchantment -S:Mode$ ReduceCost | ValidCard$ Card.IsCommander | Type$ Spell | Amount$ X | EffectZone$ Command | Description$ Your commander costs {1} less to cast for each time it's been cast from the command zone this game. -T:Mode$ ChangesZone | ValidCard$ Card.IsCommander+YouOwn | TriggerZones$ Command | Origin$ Any | Destination$ Command | Execute$ TrigDraw | TriggerDescription$ Whenever your commander is put into the command zone from anywhere, draw a card. +S:Mode$ ReduceCost | ValidCard$ Card.IsCommander+YouOwn | Type$ Spell | Amount$ AffectedX | Description$ Your commander costs {1} less to cast for each time it's been cast from the command zone this game. +T:Mode$ ChangesZoneAll | ValidCard$ Card.IsCommander+YouOwn | Origin$ Any | Destination$ Command | Execute$ TrigDraw | TriggerZones$ Battlefield | TriggerDescription$ Whenever your commander is put into the command zone from anywhere, draw a card. SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 -SVar:X:Count$CommanderCastFromCommandZone +SVar:AffectedX:Count$CommanderCastFromCommandZone SVar:RemRandomDeck:True Oracle:Your commander costs {1} less to cast for each time it's been cast from the command zone this game.\nWhenever your commander is put into the command zone from anywhere, draw a card. diff --git a/forge-gui/res/cardsfolder/n/necravolver.txt b/forge-gui/res/cardsfolder/n/necravolver.txt index 96b98a67fc4..a2075b1d36a 100644 --- a/forge-gui/res/cardsfolder/n/necravolver.txt +++ b/forge-gui/res/cardsfolder/n/necravolver.txt @@ -3,16 +3,17 @@ ManaCost:2 B Types:Creature Volver PT:2/2 K:Kicker:1 G:W -T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked 1 | Origin$ Any | Destination$ Battlefield | Execute$ VolverPumped | Static$ True | TriggerDescription$ If CARDNAME was kicked with its {1}{G} kicker, it enters the battlefield with two +1/+1 counters on it and with trample. -SVar:VolverPumped:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ VolverStomp -SVar:VolverStomp:DB$ Pump | Defined$ Self | KW$ Trample | Permanent$ True -T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked 2 | Origin$ Any | Destination$ Battlefield | Execute$ VolverPumped2 | Static$ True | TriggerDescription$ If CARDNAME was kicked with its {W} kicker, it enters the battlefield with a +1/+1 counter on it and with "Whenever CARDNAME deals damage, you gain that much life." -SVar:VolverPumped2:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ VolverLife +K:ETBReplacement:Other:VolverStrength:Mandatory::Card.Self+kicked 1 +K:ETBReplacement:Other:VolverPumped:Mandatory::Card.Self+kicked 2 +SVar:VolverPumped:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | ETB$ True | SubAbility$ VolverStomp | SpellDescription$ If CARDNAME was kicked with its {1}{G} kicker, it enters the battlefield with two +1/+1 counters on it and with trample. +SVar:VolverStomp:DB$ Animate | Defined$ Self | Keywords$ Trample | Permanent$ True +SVar:VolverPumped2:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ETB$ True | SubAbility$ VolverLife | SpellDescription$ If CARDNAME was kicked with its {W} kicker, it enters the battlefield with a +1/+1 counter on it and with "Whenever CARDNAME deals damage, you gain that much life." SVar:VolverLife:DB$ Animate | Defined$ Self | Triggers$ PseudoLifelink | sVars$ VolverTrigGain,VolverX | Permanent$ True SVar:PseudoLifelink:Mode$ DamageDealtOnce | ValidSource$ Card.Self | Execute$ VolverTrigGain | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME deals damage, you gain that much life. SVar:VolverTrigGain:DB$ GainLife | Defined$ You | LifeAmount$ VolverX | References$ VolverX SVar:VolverX:TriggerCount$DamageAmount SVar:RemRandomDeck:True DeckNeeds:Color$Green|White +DeckHas:Ability$Counters SVar:Picture:http://www.wizards.com/global/images/magic/general/necravolver.jpg Oracle:Kicker {1}{G} and/or {W} (You may pay an additional {1}{G} and/or {W} as you cast this spell.)\nIf Necravolver was kicked with its {1}{G} kicker, it enters the battlefield with two +1/+1 counters on it and with trample.\nIf Necravolver was kicked with its {W} kicker, it enters the battlefield with a +1/+1 counter on it and with "Whenever Necravolver deals damage, you gain that much life." diff --git a/forge-gui/res/cardsfolder/upcoming/necrotic_wound.txt b/forge-gui/res/cardsfolder/n/necrotic_wound.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/necrotic_wound.txt rename to forge-gui/res/cardsfolder/n/necrotic_wound.txt diff --git a/forge-gui/res/cardsfolder/n/nesting_dragon.txt b/forge-gui/res/cardsfolder/n/nesting_dragon.txt index c72018dc457..9b079008b9d 100644 --- a/forge-gui/res/cardsfolder/n/nesting_dragon.txt +++ b/forge-gui/res/cardsfolder/n/nesting_dragon.txt @@ -4,8 +4,5 @@ Types:Creature Dragon PT:5/4 K:Flying T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Landfall Whenever a land enters the battlefield under your control, create a 0/2 red Dragon creature token with defender and "When this creature dies, create a 2/2 red Dragon creature token with flying and '{R}: This creature gets +1/+0 until end of turn.'" -SVar:TrigToken:DB$ Token | TokenImage$ r 0 2 dragon egg | TokenAmount$ 1 | TokenName$ Dragon Egg | TokenTypes$ Creature,Dragon,Egg | TokenOwner$ You | TokenColors$ Red | TokenPower$ 0 | TokenToughness$ 2 | TokenKeywords$ Defender | TokenTriggers$ TriggerDies | TokenSVars$ TrigToken2,DragonPump -SVar:TriggerDies:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken2 | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create a 2/2 red Dragon creature token with flying and "{R}: This creature gets +1/+0 until end of turn." -SVar:TrigToken2:DB$Token | TokenImage$ r 2 2 dragon c18 | TokenAmount$ 1 | TokenName$ Dragon | TokenTypes$ Creature,Dragon | TokenOwner$ You | TokenColors$ Red | TokenPower$ 2 | TokenToughness$ 2 | TokenKeywords$ Flying | TokenAbilities$ DragonPump -SVar:DragonPump:AB$ Pump | Cost$ R | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn. -Oracle:Flying\nLandfall — Whenever a land enters the battlefield under your control, create a 0/2 red Dragon Egg creature token with defender and "When this creature dies, create a 2/2 red Dragon creature token with flying and '{R}: This creature gets +1/+0 until end of turn.'" \ No newline at end of file +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | LegacyImage$ r 0 2 dragon egg | TokenScript$ r_0_2_dragon_egg_defender_hatches_dragon +Oracle:Flying\nLandfall — Whenever a land enters the battlefield under your control, create a 0/2 red Dragon Egg creature token with defender and "When this creature dies, create a 2/2 red Dragon creature token with flying and '{R}: This creature gets +1/+0 until end of turn.'" diff --git a/forge-gui/res/cardsfolder/upcoming/never_happened.txt b/forge-gui/res/cardsfolder/n/never_happened.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/never_happened.txt rename to forge-gui/res/cardsfolder/n/never_happened.txt diff --git a/forge-gui/res/cardsfolder/upcoming/nightveil_predator.txt b/forge-gui/res/cardsfolder/n/nightveil_predator.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/nightveil_predator.txt rename to forge-gui/res/cardsfolder/n/nightveil_predator.txt diff --git a/forge-gui/res/cardsfolder/upcoming/nightveil_sprite.txt b/forge-gui/res/cardsfolder/n/nightveil_sprite.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/nightveil_sprite.txt rename to forge-gui/res/cardsfolder/n/nightveil_sprite.txt index 82043a4765a..bd2c50afe9f 100644 --- a/forge-gui/res/cardsfolder/upcoming/nightveil_sprite.txt +++ b/forge-gui/res/cardsfolder/n/nightveil_sprite.txt @@ -6,4 +6,5 @@ K:Flying T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigSurveil | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, surveil 1. (Look at the top card of your library. You may put that card into your graveyard.) SVar:TrigSurveil:DB$ Surveil | Amount$ 1 SVar:HasAttackEffect:TRUE +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Flying\nWhenever Nightveil Sprite attacks, surveil 1. (Look at the top card of your library. You may put that card into your graveyard.) diff --git a/forge-gui/res/cardsfolder/n/nimbus_champion.txt b/forge-gui/res/cardsfolder/n/nimbus_champion.txt new file mode 100644 index 00000000000..cb1a1d4771b --- /dev/null +++ b/forge-gui/res/cardsfolder/n/nimbus_champion.txt @@ -0,0 +1,12 @@ +Name:Nimbus Champion +ManaCost:5 U +Types:Creature Avatar Warrior +PT:4/4 +K:Flying +T:Mode$ Attacks | ValidCard$ Card.Self | OptionalDecider$ You | TriggerZones$ Battlefield | Execute$ TrigBounce | TriggerDescription$ Whenever CARDNAME attacks, you may return target creature to its owner's hand if that creature's power is less than or equal to the number of Warriors your team controls. +SVar:TrigBounce:DB$ ChangeZone | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Hand | IsCurse$ True | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ1 | References$ X,Y +SVar:Y:Count$Valid Warrior.YourTeamCtrl +SVar:X:Targeted$Valid Creature.powerLEY +SVar:HasAttackEffect:TRUE +SVar:BuffedBy:Warrior +Oracle:Flying\nWhenever Nimbus Champion attacks, you may return target creature to its owner’s hand if that creature’s power is less than or equal to the number of Warriors your team controls. diff --git a/forge-gui/res/cardsfolder/upcoming/niv_mizzet_parun.txt b/forge-gui/res/cardsfolder/n/niv_mizzet_parun.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/niv_mizzet_parun.txt rename to forge-gui/res/cardsfolder/n/niv_mizzet_parun.txt index 5e02fcdb3b0..225b2a575c5 100644 --- a/forge-gui/res/cardsfolder/upcoming/niv_mizzet_parun.txt +++ b/forge-gui/res/cardsfolder/n/niv_mizzet_parun.txt @@ -8,4 +8,5 @@ T:Mode$ Drawn | ValidCard$ Card.YouOwn | TriggerZones$ Battlefield | Execute$ Tr SVar:TrigDealDamage:DB$DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever a player casts an instant or sorcery spell, you draw a card. SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 +DeckHints:Type$Instant|Sorcery Oracle:Niv-Mizzet, Parun can't be countered.\nFlying\nWhenever you draw a card, Niv-Mizzet, Parun deals 1 damage to any target.\nWhenever a player casts an instant or sorcery spell, you draw a card. diff --git a/forge-gui/res/cardsfolder/upcoming/notion_rain.txt b/forge-gui/res/cardsfolder/n/notion_rain.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/notion_rain.txt rename to forge-gui/res/cardsfolder/n/notion_rain.txt index 2e49bc7cf74..c932c15d821 100644 --- a/forge-gui/res/cardsfolder/upcoming/notion_rain.txt +++ b/forge-gui/res/cardsfolder/n/notion_rain.txt @@ -4,4 +4,5 @@ Types:Sorcery A:SP$ Surveil | Cost$ 1 U B | Amount$ 2 | SubAbility$ DBDraw | SpellDescription$ Surveil 2, then draw two cards. CARDNAME deals 2 damage to you. SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 2 | SubAbility$ DBDamage SVar:DBDamage:DB$ DealDamage | Defined$ You | NumDmg$ 2 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Surveil 2, then draw two cards. Rain of Notions deals 2 damage to you. (To surveil 2, look at the top two cards of your library, then put any number of them into your graveyard and the rest on top of your library in any order.) \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/nullhide_ferox.txt b/forge-gui/res/cardsfolder/n/nullhide_ferox.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/nullhide_ferox.txt rename to forge-gui/res/cardsfolder/n/nullhide_ferox.txt diff --git a/forge-gui/res/cardsfolder/upcoming/ochran_assassin.txt b/forge-gui/res/cardsfolder/o/ochran_assassin.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/ochran_assassin.txt rename to forge-gui/res/cardsfolder/o/ochran_assassin.txt diff --git a/forge-gui/res/cardsfolder/upcoming/omnispell_adept.txt b/forge-gui/res/cardsfolder/o/omnispell_adept.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/omnispell_adept.txt rename to forge-gui/res/cardsfolder/o/omnispell_adept.txt diff --git a/forge-gui/res/cardsfolder/o/oni_possession.txt b/forge-gui/res/cardsfolder/o/oni_possession.txt index 430fa0818be..b4a55a197cd 100644 --- a/forge-gui/res/cardsfolder/o/oni_possession.txt +++ b/forge-gui/res/cardsfolder/o/oni_possession.txt @@ -8,7 +8,7 @@ S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddType$ Demon & Spirit | T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSac | TriggerDescription$ At the beginning of your upkeep, sacrifice a creature. SVar:TrigSac:DB$Sacrifice | Defined$ You | SacValid$ Creature SVar:NeedsToPlayVar:Z GE3 -SVar:Count$Valid Creature.YouCtrl +SVar:Z:Count$Valid Creature.YouCtrl SVar:RemRandomDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/oni_possession.jpg Oracle:Enchant creature\nAt the beginning of your upkeep, sacrifice a creature.\nEnchanted creature gets +3/+3 and has trample.\nEnchanted creature is a Demon Spirit. diff --git a/forge-gui/res/cardsfolder/upcoming/ornery_goblin.txt b/forge-gui/res/cardsfolder/o/ornery_goblin.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/ornery_goblin.txt rename to forge-gui/res/cardsfolder/o/ornery_goblin.txt diff --git a/forge-gui/res/cardsfolder/upcoming/packs_favor.txt b/forge-gui/res/cardsfolder/p/packs_favor.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/packs_favor.txt rename to forge-gui/res/cardsfolder/p/packs_favor.txt diff --git a/forge-gui/res/cardsfolder/upcoming/parhelion_patrol.txt b/forge-gui/res/cardsfolder/p/parhelion_patrol.txt similarity index 90% rename from forge-gui/res/cardsfolder/upcoming/parhelion_patrol.txt rename to forge-gui/res/cardsfolder/p/parhelion_patrol.txt index 35265bd259b..d4ed407ad8a 100644 --- a/forge-gui/res/cardsfolder/upcoming/parhelion_patrol.txt +++ b/forge-gui/res/cardsfolder/p/parhelion_patrol.txt @@ -5,4 +5,5 @@ PT:2/3 K:Flying K:Vigilance K:Mentor +DeckHas:Ability$Counters Oracle:Flying, vigilance\nMentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.) diff --git a/forge-gui/res/cardsfolder/upcoming/passwall_adept.txt b/forge-gui/res/cardsfolder/p/passwall_adept.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/passwall_adept.txt rename to forge-gui/res/cardsfolder/p/passwall_adept.txt diff --git a/forge-gui/res/cardsfolder/upcoming/pause_for_reflection.txt b/forge-gui/res/cardsfolder/p/pause_for_reflection.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/pause_for_reflection.txt rename to forge-gui/res/cardsfolder/p/pause_for_reflection.txt diff --git a/forge-gui/res/cardsfolder/upcoming/pelt_collector.txt b/forge-gui/res/cardsfolder/p/pelt_collector.txt similarity index 98% rename from forge-gui/res/cardsfolder/upcoming/pelt_collector.txt rename to forge-gui/res/cardsfolder/p/pelt_collector.txt index 1057ed08c4e..56e8b90ad45 100644 --- a/forge-gui/res/cardsfolder/upcoming/pelt_collector.txt +++ b/forge-gui/res/cardsfolder/p/pelt_collector.txt @@ -7,4 +7,5 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creatu T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouCtrl+powerGTX+Other | References$ X | TriggerZones$ Battlefield | Secondary$ True | Execute$ TrigPutCounter | TriggerDescription$ Whenever another creature you control enters the battlefield or dies, if that creature's power is greater than CARDNAME's, put a +1/+1 counter on CARDNAME. SVar:X:Count$CardPower SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 +DeckHas:Ability$Counters Oracle:Whenever another creature you control enters the battlefield or dies, if that creature's power is greater than Pelt Collector's, put a +1/+1 counter on Pelt Collector.\nAs long as Pelt Collector has three or more +1/+1 counters on it, it has trample. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/pilfering_imp.txt b/forge-gui/res/cardsfolder/p/pilfering_imp.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/pilfering_imp.txt rename to forge-gui/res/cardsfolder/p/pilfering_imp.txt diff --git a/forge-gui/res/cardsfolder/upcoming/piston_fist_cyclops.txt b/forge-gui/res/cardsfolder/p/piston_fist_cyclops.txt similarity index 86% rename from forge-gui/res/cardsfolder/upcoming/piston_fist_cyclops.txt rename to forge-gui/res/cardsfolder/p/piston_fist_cyclops.txt index e38563c5209..c632d6cad7b 100644 --- a/forge-gui/res/cardsfolder/upcoming/piston_fist_cyclops.txt +++ b/forge-gui/res/cardsfolder/p/piston_fist_cyclops.txt @@ -4,6 +4,7 @@ Types:Creature Cyclops PT:4/3 K:Defender S:Mode$ Continuous | Affected$ Card.Self | AddHiddenKeyword$ CARDNAME can attack as though it didn't have defender. | CheckSVar$ X | SVarCompare$ GE1 | Description$ As long as you've cast an instant or sorcery spell this turn, CARDNAME can attack as though it didn't have defender. -SVar:X:Count$ThisTurnCast_Instant.YouOwn +SVar:X:Count$ThisTurnCast_Instant.YouOwn,Sorcery.YouOwn SVar:BuffedBy:Instant,Sorcery +DeckHints:Type$Instant|Sorcery Oracle:Defender\nAs long as you've cast an instant or sorcery spell this turn, Piston-Fist Cyclops can attack as though it didn't have defender. diff --git a/forge-gui/res/cardsfolder/upcoming/pitiless_gorgon.txt b/forge-gui/res/cardsfolder/p/pitiless_gorgon.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/pitiless_gorgon.txt rename to forge-gui/res/cardsfolder/p/pitiless_gorgon.txt diff --git a/forge-gui/res/cardsfolder/p/plaguecrafter.txt b/forge-gui/res/cardsfolder/p/plaguecrafter.txt new file mode 100644 index 00000000000..d8608316796 --- /dev/null +++ b/forge-gui/res/cardsfolder/p/plaguecrafter.txt @@ -0,0 +1,12 @@ +Name:Plaguecrafter +ManaCost:2 B +Types:Creature Human Shaman +PT:3/2 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ DBRepeat | TriggerDescription$ When CARDNAME enters the battlefield, each player sacrifices a creature or planeswalker. Each player who can't discards a card. +SVar:DBRepeat:DB$ RepeatEach | RepeatPlayers$ Player | RepeatSubAbility$ ChooseSac | SubAbility$ RememberSac +SVar:ChooseSac:DB$ ChooseCard | Defined$ Remembered | Choices$ Creature.RememberedPlayerCtrl,Planeswalker.RememberedPlayerCtrl | ChoiceTitle$ Choose a creature or planeswalker to sacrifice | AILogic$ WorstCard | Mandatory$ True | RememberChosen$ True +SVar:RememberSac:DB$ Pump | RememberObjects$ RememberedController | SubAbility$ TrigSac +SVar:TrigSac:DB$ SacrificeAll | Defined$ Remembered | SubAbility$ Discard +SVar:Discard:DB$ Discard | Mode$ TgtChoose | NumCards$ 1 | Defined$ Player.IsNotRemembered | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +Oracle:When Plaguecrafter enters the battlefield, each player sacrifices a creature or planeswalker. Each player who can't discards a card. diff --git a/forge-gui/res/cardsfolder/upcoming/portcullis_vine.txt b/forge-gui/res/cardsfolder/p/portcullis_vine.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/portcullis_vine.txt rename to forge-gui/res/cardsfolder/p/portcullis_vine.txt diff --git a/forge-gui/res/cardsfolder/upcoming/precision_bolt.txt b/forge-gui/res/cardsfolder/p/precision_bolt.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/precision_bolt.txt rename to forge-gui/res/cardsfolder/p/precision_bolt.txt diff --git a/forge-gui/res/cardsfolder/upcoming/price_of_fame.txt b/forge-gui/res/cardsfolder/p/price_of_fame.txt similarity index 94% rename from forge-gui/res/cardsfolder/upcoming/price_of_fame.txt rename to forge-gui/res/cardsfolder/p/price_of_fame.txt index 4383c468503..83fd2baf529 100644 --- a/forge-gui/res/cardsfolder/upcoming/price_of_fame.txt +++ b/forge-gui/res/cardsfolder/p/price_of_fame.txt @@ -6,4 +6,5 @@ A:SP$ Destroy | Cost$ 3 B | ValidTgts$ Creature | SubAbility$ DBSurveil | TgtPro SVar:CostReduction:Count$Compare CheckTgt GE1.2.0 SVar:CheckTgt:Targeted$Valid Creature.Legendary SVar:DBSurveil:DB$ Surveil | Amount$ 2 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:This spell costs {2} less to cast if it targets a legendary creature.\nDestroy target creature.\nSurveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on top of your library in any order.) diff --git a/forge-gui/res/cardsfolder/p/primordial_mist.txt b/forge-gui/res/cardsfolder/p/primordial_mist.txt new file mode 100644 index 00000000000..3f626ac5b1d --- /dev/null +++ b/forge-gui/res/cardsfolder/p/primordial_mist.txt @@ -0,0 +1,9 @@ +Name:Primordial Mist +ManaCost:4 U +Types:Enchantment +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigManifest | OptionalDecider$ You | TriggerDescription$ At the beginning of your end step, you may manifest the top card of your library. +SVar:TrigManifest:DB$ Manifest | Amount$ 1 | Defined$ TopOfLibrary +A:AB$ Effect | Cost$ Exile<1/Permanent.faceDown>| RememberObjects$ ExiledCards | StaticAbilities$ Play | SubAbility$ DBCleanup | ExileOnMoved$ Exile | SpellDescription$ Exile a face-down permanent you control face up: You may play that card this turn. (You still pay its costs. Timing rules still apply.) +SVar:Play:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ You may play remembered card. +SVar:RemAIDeck:True +Oracle:At the beginning of your end step, you may manifest the top card of your library. (Put it onto the battlefield face down as a 2/2 creature. Turn it face up any time for its mana cost if it's a creature card.)\nExile a face-down permanent you control face up: You may play that card this turn. (You still pay its costs. Timing rules still apply.) diff --git a/forge-gui/res/cardsfolder/upcoming/quasiduplicate.txt b/forge-gui/res/cardsfolder/q/quasiduplicate.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/quasiduplicate.txt rename to forge-gui/res/cardsfolder/q/quasiduplicate.txt diff --git a/forge-gui/res/cardsfolder/upcoming/radical_idea.txt b/forge-gui/res/cardsfolder/r/radical_idea.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/radical_idea.txt rename to forge-gui/res/cardsfolder/r/radical_idea.txt diff --git a/forge-gui/res/cardsfolder/r/rakavolver.txt b/forge-gui/res/cardsfolder/r/rakavolver.txt index 7fd60cf97c4..e4c7af30b0a 100644 --- a/forge-gui/res/cardsfolder/r/rakavolver.txt +++ b/forge-gui/res/cardsfolder/r/rakavolver.txt @@ -3,16 +3,17 @@ ManaCost:2 R Types:Creature Volver PT:2/2 K:Kicker:1 W:U -T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked 1 | Origin$ Any | Destination$ Battlefield | Execute$ VolverStrength | Static$ True | TriggerDescription$ If CARDNAME was kicked with its {1}{W} kicker, it enters the battlefield with two +1/+1 counters on it and with "Whenever CARDNAME deals damage, you gain that much life." -SVar:VolverStrength:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ VolverLife +K:ETBReplacement:Other:VolverStrength:Mandatory::Card.Self+kicked 1 +K:ETBReplacement:Other:VolverPumped:Mandatory::Card.Self+kicked 2 +SVar:VolverStrength:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | ETB$ True | SubAbility$ VolverLife | SpellDescription$ If CARDNAME was kicked with its {1}{W} kicker, it enters the battlefield with two +1/+1 counters on it and with "Whenever CARDNAME deals damage, you gain that much life." SVar:VolverLife:DB$ Animate | Defined$ Self | Triggers$ PseudoLifelink | sVars$ VolverTrigGain,VolverX | Permanent$ True SVar:PseudoLifelink:Mode$ DamageDealtOnce | ValidSource$ Card.Self | Execute$ VolverTrigGain | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME deals damage, you gain that much life. SVar:VolverTrigGain:DB$ GainLife | Defined$ You | LifeAmount$ VolverX | References$ VolverX SVar:VolverX:TriggerCount$DamageAmount -T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked 2 | Origin$ Any | Destination$ Battlefield | Execute$ VolverPumped | Static$ True | TriggerDescription$ If CARDNAME was kicked with its {U} kicker, it enters the battlefield with a +1/+1 counter on it and with flying. -SVar:VolverPumped:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ VolverLaunch -SVar:VolverLaunch:DB$ Pump | Defined$ Self | KW$ Flying | Permanent$ True +SVar:VolverPumped:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ETB$ True | SubAbility$ VolverLaunch | SpellDescription$ If CARDNAME was kicked with its {U} kicker, it enters the battlefield with a +1/+1 counter on it and with flying. +SVar:VolverLaunch:DB$ Animate | Defined$ Self | Keywords$ Flying | Permanent$ True SVar:RemRandomDeck:True DeckNeeds:Color$White|Blue +DeckHas:Ability$Counters SVar:Picture:http://www.wizards.com/global/images/magic/general/rakavolver.jpg Oracle:Kicker {1}{W} and/or {U} (You may pay an additional {1}{W} and/or {U} as you cast this spell.)\nIf Rakavolver was kicked with its {1}{W} kicker, it enters the battlefield with two +1/+1 counters on it and with "Whenever Rakavolver deals damage, you gain that much life."\nIf Rakavolver was kicked with its {U} kicker, it enters the battlefield with a +1/+1 counter on it and with flying. diff --git a/forge-gui/res/cardsfolder/upcoming/ral_caller_of_storms.txt b/forge-gui/res/cardsfolder/r/ral_caller_of_storms.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/ral_caller_of_storms.txt rename to forge-gui/res/cardsfolder/r/ral_caller_of_storms.txt diff --git a/forge-gui/res/cardsfolder/upcoming/ral_izzet_viceroy.txt b/forge-gui/res/cardsfolder/r/ral_izzet_viceroy.txt similarity index 97% rename from forge-gui/res/cardsfolder/upcoming/ral_izzet_viceroy.txt rename to forge-gui/res/cardsfolder/r/ral_izzet_viceroy.txt index 82e83d9f78b..1383177de97 100644 --- a/forge-gui/res/cardsfolder/upcoming/ral_izzet_viceroy.txt +++ b/forge-gui/res/cardsfolder/r/ral_izzet_viceroy.txt @@ -12,4 +12,6 @@ SVar:TrigSpellCast:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatin SVar:EffSpellCast:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 4 | SubAbility$ EffDraw SVar:EffDraw:DB$ Draw | Defined$ You | NumCards$ 2 SVar:BuffedBy:Instant,Sorcery +DeckHints:Type$Instant|Sorcery +DeckHas:Ability$Graveyard Oracle:[+1]: Look at the top two cards of your library. Put one of them into your hand and the other into your graveyard.\n[-3]: Ral, Izzet Viceroy deals damage to target creature equal to the total number of instant and sorcery cards you own in exile and in your graveyard.\n[-8]: You get an emblem with "Whenever you cast an instant or sorcery spell, this emblem deals 4 damage to any target and you draw two cards." diff --git a/forge-gui/res/cardsfolder/upcoming/rals_dispersal.txt b/forge-gui/res/cardsfolder/r/rals_dispersal.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/rals_dispersal.txt rename to forge-gui/res/cardsfolder/r/rals_dispersal.txt diff --git a/forge-gui/res/cardsfolder/upcoming/rals_staticaster.txt b/forge-gui/res/cardsfolder/r/rals_staticaster.txt similarity index 97% rename from forge-gui/res/cardsfolder/upcoming/rals_staticaster.txt rename to forge-gui/res/cardsfolder/r/rals_staticaster.txt index 10dee68d58c..1c179895b30 100644 --- a/forge-gui/res/cardsfolder/upcoming/rals_staticaster.txt +++ b/forge-gui/res/cardsfolder/r/rals_staticaster.txt @@ -7,4 +7,5 @@ T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigPump | IsPresent$ Planeswa SVar:TrigPump:DB$ Pump | NumAtt$ X | References$ X SVar:X:Count$InYourHand SVar:BuffedBy:Ral +DeckNeeds:Type$Ral Oracle:Trample (This creature can deal excess combat damage to the player or planeswalker it's attacking.)\nWhenever Ral's Staticaster attacks, if you control a Ral planeswalker, Ral's Staticaster gets +1/+0 for each card in your hand until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/rampaging_monument.txt b/forge-gui/res/cardsfolder/r/rampaging_monument.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/rampaging_monument.txt rename to forge-gui/res/cardsfolder/r/rampaging_monument.txt index 82bd021bbef..b5b7db7fb21 100644 --- a/forge-gui/res/cardsfolder/upcoming/rampaging_monument.txt +++ b/forge-gui/res/cardsfolder/r/rampaging_monument.txt @@ -7,4 +7,5 @@ K:etbCounter:P1P1:3 T:Mode$ SpellCast | ValidCard$ Card.MultiColor | ValidActivatingPlayer$ You | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast a multicolored spell, put a +1/+1 counter on CARDNAME. SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 SVar:BuffedBy:Card.MultiColor +DeckHas:Ability$Counters Oracle:Trample\nRampaging Monument enters the battlefield with three +1/+1 counters on it.\nWhenever you cast a multicolored spell, put a +1/+1 counter on Rampaging Monument. diff --git a/forge-gui/res/cardsfolder/r/ravenous_slime.txt b/forge-gui/res/cardsfolder/r/ravenous_slime.txt index 39d9a888cb1..8714289faff 100644 --- a/forge-gui/res/cardsfolder/r/ravenous_slime.txt +++ b/forge-gui/res/cardsfolder/r/ravenous_slime.txt @@ -6,5 +6,5 @@ K:CantBeBlockedBy Creature.powerLE2 R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.OppCtrl | ReplaceWith$ Exile | Description$ If a creature an opponent controls would die, instead exile it and put a number of +1/+1 counters equal to that creature's power on CARDNAME. SVar:Exile:DB$ ChangeZone | Defined$ ReplacedCard | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBPutCounter SVar:DBPutCounter:DB$ PutCounter | CounterType$ P1P1 | CounterNum$ X | References$ X | Defined$ Self -SVar:X:ReplacedCard$CardPower +SVar:X:ReplacedCardLKI$CardPower Oracle:Ravenous Slime can't be blocked by creatures with power 2 or less.\nIf a creature an opponent controls would die, instead exile it and put a number of +1/+1 counters equal to that creature's power on Ravenous Slime. diff --git a/forge-gui/res/cardsfolder/r/reef_worm.txt b/forge-gui/res/cardsfolder/r/reef_worm.txt index 02a9657a8c4..bf72bb1a6ed 100644 --- a/forge-gui/res/cardsfolder/r/reef_worm.txt +++ b/forge-gui/res/cardsfolder/r/reef_worm.txt @@ -2,11 +2,7 @@ Name:Reef Worm ManaCost:3 U Types:Creature Worm PT:0/1 -T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenFish | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create a 3/3 blue Fish creature token with "When this creature dies, create a 6/6 blue Whale creature token with 'When this creature dies, create a 9/9 blue Kraken creature token.'" -SVar:TrigTokenFish:DB$Token | TokenImage$ u 3 3 fish | TokenName$ Fish | TokenTypes$ Creature,Fish | TokenColors$ Blue | TokenOwner$ You | TokenPower$ 3 | TokenToughness$ 3 | TokenAmount$ 1 | TokenTriggers$ TriggerWhale | TokenSVars$ TrigTokenWhale,TriggerKraken,TrigTokenKraken -SVar:TriggerWhale:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenWhale | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create a 6/6 blue Whale creature token with "When this creature dies, create a 9/9 blue Kraken creature token." -SVar:TrigTokenWhale:DB$Token | TokenImage$ u 6 6 whale | TokenName$ Whale | TokenTypes$ Creature,Whale | TokenColors$ Blue | TokenOwner$ You | TokenPower$ 6 | TokenToughness$ 6 | TokenAmount$ 1 | TokenTriggers$ TriggerKraken | TokenSVars$ TrigTokenKraken -SVar:TriggerKraken:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenKraken | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create a 9/9 blue Kraken creature token. -SVar:TrigTokenKraken:DB$Token | TokenImage$ u 9 9 kraken c14 | TokenName$ Kraken | TokenTypes$ Creature,Kraken | TokenColors$ Blue | TokenOwner$ You | TokenPower$ 9 | TokenToughness$ 9 | TokenAmount$ 1 +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create a 3/3 blue Fish creature token with "When this creature dies, create a 6/6 blue Whale creature token with 'When this creature dies, create a 9/9 blue Kraken creature token.'" +SVar:TrigToken:DB$Token | LegacyImage$ u 3 3 fish | TokenScript$ u_3_3_fish_hatches_whale | TokenOwner$ You | TokenAmount$ 1 SVar:Picture:http://www.wizards.com/global/images/magic/general/reef_worm.jpg -Oracle:When Reef Worm dies, create a 3/3 blue Fish creature token with "When this creature dies, create a 6/6 blue Whale creature token with 'When this creature dies, create a 9/9 blue Kraken creature token.'" \ No newline at end of file +Oracle:When Reef Worm dies, create a 3/3 blue Fish creature token with "When this creature dies, create a 6/6 blue Whale creature token with 'When this creature dies, create a 9/9 blue Kraken creature token.'" diff --git a/forge-gui/res/cardsfolder/r/relentless_skaabs.txt b/forge-gui/res/cardsfolder/r/relentless_skaabs.txt index e487dab907b..6d0879aa058 100644 --- a/forge-gui/res/cardsfolder/r/relentless_skaabs.txt +++ b/forge-gui/res/cardsfolder/r/relentless_skaabs.txt @@ -3,6 +3,6 @@ ManaCost:3 U U Types:Creature Zombie PT:4/4 K:Undying -SVar:FullCost:3 U U ExileFromGrave<1/Creature> +A:SP$ PermanentCreature | Cost$ 3 U U ExileFromGrave<1/Creature> SVar:Picture:http://www.wizards.com/global/images/magic/general/relentless_skaabs.jpg Oracle:As an additional cost to cast Relentless Skaabs, exile a creature card from your graveyard.\nUndying (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.) diff --git a/forge-gui/res/cardsfolder/upcoming/response_resurgence.txt b/forge-gui/res/cardsfolder/r/response_resurgence.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/response_resurgence.txt rename to forge-gui/res/cardsfolder/r/response_resurgence.txt diff --git a/forge-gui/res/cardsfolder/r/retaliator_griffin.txt b/forge-gui/res/cardsfolder/r/retaliator_griffin.txt index ceb70260099..e4111734bbc 100644 --- a/forge-gui/res/cardsfolder/r/retaliator_griffin.txt +++ b/forge-gui/res/cardsfolder/r/retaliator_griffin.txt @@ -6,6 +6,5 @@ K:Flying T:Mode$ DamageDone | ValidSource$ Card.OppCtrl | ValidTarget$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | OptionalDecider$ You | TriggerDescription$ Whenever a source an opponent controls deals damage to you, you may put that many +1/+1 counters on CARDNAME. SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ X | References$ X SVar:X:TriggerCount$DamageAmount -Svar:Rarity:Rare SVar:Picture:http://www.wizards.com/global/images/magic/general/retaliator_griffin.jpg Oracle:Flying\nWhenever a source an opponent controls deals damage to you, you may put that many +1/+1 counters on Retaliator Griffin. diff --git a/forge-gui/res/cardsfolder/upcoming/rhizome_lurcher.txt b/forge-gui/res/cardsfolder/r/rhizome_lurcher.txt similarity index 94% rename from forge-gui/res/cardsfolder/upcoming/rhizome_lurcher.txt rename to forge-gui/res/cardsfolder/r/rhizome_lurcher.txt index cee27cca260..0d374e6d17c 100644 --- a/forge-gui/res/cardsfolder/upcoming/rhizome_lurcher.txt +++ b/forge-gui/res/cardsfolder/r/rhizome_lurcher.txt @@ -5,4 +5,5 @@ PT:2/2 K:etbCounter:P1P1:X:no Condition:Undergrowth - CARDNAME enters the battlefield with a number of +1/+1 counters on it equal to the number of creature cards in your graveyard. SVar:X:Count$TypeInYourYard.Creature SVar:NeedsToPlayVar:X GE1 +DeckHas:Ability$Counters Oracle:Undergrowth — Rhizome Lurcher enters the battlefield with a number of +1/+1 counters on it equal to the number of creature cards in your graveyard. diff --git a/forge-gui/res/cardsfolder/r/riftmarked_knight.txt b/forge-gui/res/cardsfolder/r/riftmarked_knight.txt index ea73c94620e..b924807b1b8 100644 --- a/forge-gui/res/cardsfolder/r/riftmarked_knight.txt +++ b/forge-gui/res/cardsfolder/r/riftmarked_knight.txt @@ -6,6 +6,6 @@ K:Flanking K:Protection from black K:Suspend:3:1 W W T:Mode$ CounterRemoved | ValidCard$ Card.Self | TriggerZones$ Exile | CounterType$ TIME | Execute$ TrigToken | IsPresent$ Card.Self+counters_GE1_TIME | PresentZone$ Exile | PresentCompare$ EQ0 | TriggerDescription$ When the last time counter is removed from CARDNAME while it's exiled, create a 2/2 black Knight creature token with flanking, protection from white, and haste. -SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenName$ Knight | TokenTypes$ Creature,Knight | TokenOwner$ You | TokenColors$ Black | TokenPower$ 2 | TokenToughness$ 2 | TokenKeywords$ Flanking<>Protection from white<>Haste +SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ b_2_2_knight_flanking_pro_white_haste SVar:Picture:http://www.wizards.com/global/images/magic/general/riftmarked_knight.jpg Oracle:Protection from black, flanking (Whenever a creature without flanking blocks this creature, the blocking creature gets -1/-1 until end of turn.)\nSuspend 3—{1}{W}{W} (Rather than cast this card from your hand, you may pay {1}{W}{W} and exile it with three time counters on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost. It has haste.)\nWhen the last time counter is removed from Riftmarked Knight while it's exiled, create a 2/2 black Knight creature token with flanking, protection from white, and haste. diff --git a/forge-gui/res/cardsfolder/upcoming/risk_factor.txt b/forge-gui/res/cardsfolder/r/risk_factor.txt similarity index 58% rename from forge-gui/res/cardsfolder/upcoming/risk_factor.txt rename to forge-gui/res/cardsfolder/r/risk_factor.txt index d1519489f6b..6451e0530c0 100644 --- a/forge-gui/res/cardsfolder/upcoming/risk_factor.txt +++ b/forge-gui/res/cardsfolder/r/risk_factor.txt @@ -2,6 +2,6 @@ Name:Risk Factor ManaCost:2 R Types:Instant K:Jump-start -A:SP$ Pump | Cost$ 2 R | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | OptionalDecider$ Opponent | UnlessCost$ DamageYou<4> | SubAbility$ DBDraw | SpellDescription$ Target opponent may have CARDNAME deal 4 damage to them. If that player doesn't, you draw three cards. +A:SP$ Pump | StackDescription$ {p:Targeted} may have CARDNAME deal 4 damage to them. If {p:Targeted} doesn't, | Cost$ 2 R | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | UnlessCost$ DamageYou<4> | UnlessPayer$ Targeted | UnlessResolveSubs$ WhenNotPaid | SubAbility$ DBDraw | SpellDescription$ Target opponent may have CARDNAME deal 4 damage to them. If that player doesn't, you draw three cards. SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 3 Oracle:Target opponent may have Risk Factor deal 4 damage to them. If that player doesn't, you draw three cards.\nJump-start (You may cast this card from your graveyard by discarding a card in addition to paying its other costs. Then exile this card.) diff --git a/forge-gui/res/cardsfolder/upcoming/ritual_of_soot.txt b/forge-gui/res/cardsfolder/r/ritual_of_soot.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/ritual_of_soot.txt rename to forge-gui/res/cardsfolder/r/ritual_of_soot.txt diff --git a/forge-gui/res/cardsfolder/upcoming/roc_charger.txt b/forge-gui/res/cardsfolder/r/roc_charger.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/roc_charger.txt rename to forge-gui/res/cardsfolder/r/roc_charger.txt diff --git a/forge-gui/res/cardsfolder/upcoming/rosemane_centaur.txt b/forge-gui/res/cardsfolder/r/rosemane_centaur.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/rosemane_centaur.txt rename to forge-gui/res/cardsfolder/r/rosemane_centaur.txt diff --git a/forge-gui/res/cardsfolder/upcoming/rubblebelt_boar.txt b/forge-gui/res/cardsfolder/r/rubblebelt_boar.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/rubblebelt_boar.txt rename to forge-gui/res/cardsfolder/r/rubblebelt_boar.txt diff --git a/forge-gui/res/cardsfolder/upcoming/runaway_steam_kin.txt b/forge-gui/res/cardsfolder/r/runaway_steam_kin.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/runaway_steam_kin.txt rename to forge-gui/res/cardsfolder/r/runaway_steam_kin.txt index f43e7afe1e2..5c70f04198e 100644 --- a/forge-gui/res/cardsfolder/upcoming/runaway_steam_kin.txt +++ b/forge-gui/res/cardsfolder/r/runaway_steam_kin.txt @@ -5,4 +5,5 @@ PT:1/1 T:Mode$ SpellCast | ValidCard$ Card.Red | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | IsPresent$ Card.Self+counters_LE2_P1P1 | Execute$ TrigPutCounter | TriggerDescription$ Whenever you cast a red spell, if CARDNAME has fewer than three +1/+1 counters on it, put a +1/+1 counter on CARDNAME. SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 A:AB$ Mana | Cost$ SubCounter<3/P1P1> | Produced$ R | Amount$ 3 | SpellDescription$ Add {R}{R}{R}. +DeckHas:Ability$Counters Oracle:Whenever you cast a red spell, if Runaway Steam-Kin has fewer than three +1/+1 counters on it, put a +1/+1 counter on Runaway Steam-Kin.\nRemove three +1/+1 counters from Runaway Steam-Kin: Add {R}{R}{R}. diff --git a/forge-gui/res/cardsfolder/s/sage_eye_avengers.txt b/forge-gui/res/cardsfolder/s/sage_eye_avengers.txt index fd8fa8dbdfa..856c1cfb880 100644 --- a/forge-gui/res/cardsfolder/s/sage_eye_avengers.txt +++ b/forge-gui/res/cardsfolder/s/sage_eye_avengers.txt @@ -4,7 +4,7 @@ Types:Creature Djinn Monk PT:4/5 K:Prowess T:Mode$ Attacks | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigBounce | TriggerDescription$ Whenever CARDNAME attacks, you may return target creature to its owner's hand if its power is less than Sage-Eye Avengers's power. -SVar:TrigBounce:DB$ ChangeZone | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Hand | Curse$ True | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ1 | References$ X,Y +SVar:TrigBounce:DB$ ChangeZone | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Hand | IsCurse$ True | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ1 | References$ X,Y SVar:Y:Count$CardPower SVar:X:Targeted$Valid Creature.powerLTY SVar:HasAttackEffect:TRUE diff --git a/forge-gui/res/cardsfolder/s/saheeli_the_gifted.txt b/forge-gui/res/cardsfolder/s/saheeli_the_gifted.txt index acb0906840c..86f5b00299f 100644 --- a/forge-gui/res/cardsfolder/s/saheeli_the_gifted.txt +++ b/forge-gui/res/cardsfolder/s/saheeli_the_gifted.txt @@ -10,7 +10,7 @@ SVar:RemoveEffect:DB$ ChangeZone | Origin$ Command | Destination$ Exile SVar:X:Count$Valid Artifact.YouCtrl SVar:RemRandomDeck A:AB$ RepeatEach | Cost$ SubCounter<7/LOYALTY> | Planeswalker$ True | Ultimate$ True | RepeatSubAbility$ DBClone | RepeatCards$ Artifact.YouCtrl | AtEOT$ ExileCombat | AddSVars$ SneakAttackEOT | SpellDescription$ For each artifact you control, create a token that's a copy of it. Those tokens gain haste. Exile those tokens at the beginning of the next end step. -SVar:DBClone:DB$ CopyPermanent | Defined$ Remembered | Keywords$ Haste | AtEOT$ Exile | AddSVars$ SneakAttackEOT | AtEOT$ Exile +SVar:DBClone:DB$ CopyPermanent | Defined$ Remembered | Keywords$ Haste | AtEOT$ Exile | AddSVars$ SneakAttackEOT SVar:SneakAttackEOT:SVar:EndOfTurnLeavePlay:True K:CARDNAME can be your commander. -Oracle:[+1]: Create a 1/1 colorless Servo artifact creature token.\n[+1]: The next spell you cast this turn costs {1} less to cast for each artifact you control as you cast it.\n[-7]: For each artifact you control, create a token that's a copy of it. Those tokens gain haste. Exile those tokens at the beginning of the next end step.\nSaheeli, the Gifted can be your commander. \ No newline at end of file +Oracle:[+1]: Create a 1/1 colorless Servo artifact creature token.\n[+1]: The next spell you cast this turn costs {1} less to cast for each artifact you control as you cast it.\n[-7]: For each artifact you control, create a token that's a copy of it. Those tokens gain haste. Exile those tokens at the beginning of the next end step.\nSaheeli, the Gifted can be your commander. diff --git a/forge-gui/res/cardsfolder/s/sakashima_the_impostor.txt b/forge-gui/res/cardsfolder/s/sakashima_the_impostor.txt index db012d45c58..e9bdc7f16f1 100644 --- a/forge-gui/res/cardsfolder/s/sakashima_the_impostor.txt +++ b/forge-gui/res/cardsfolder/s/sakashima_the_impostor.txt @@ -4,8 +4,8 @@ Types:Legendary Creature Human Rogue PT:3/1 # Make Svars for granting abilities and triggers on clones distinct to avoid SVars getting overwritten when cloning a clone K:ETBReplacement:Copy:DBCopy:Optional -SVar:DBCopy:DB$ Clone | Choices$ Creature.Other | KeepName$ True | AddTypes$ Legendary | AddAbilities$ ReturnSakashima | AddSVars$ TrigReturnSak | SpellDescription$ You may have CARDNAME enter the battlefield as a copy of any creature on the battlefield, except its name is still CARDNAME, it's legendary in addition to its other types, and it gains "{2}{U}{U}: Return CARDNAME to its owner's hand at the beginning of the next end step." +SVar:DBCopy:DB$ Clone | Choices$ Creature.Other | NewName$ Sakashima the Impostor | AddTypes$ Legendary | AddAbilities$ ReturnSakashima | AddSVars$ TrigReturnSak | SpellDescription$ You may have CARDNAME enter the battlefield as a copy of any creature on the battlefield, except its name is Sakashima the Impostor, it’s legendary in addition to its other types, and it has “{2}{U}{U}: Return this creature to its owner’s hand at the beginning of the next end step.” SVar:ReturnSakashima:AB$ DelayedTrigger | Cost$ 2 U U | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturnSak | SpellDescription$ Return CARDNAME to it's owners hand at the beginning of the next end step. SVar:TrigReturnSak:DB$ ChangeZone | Defined$ Self | Origin$ Battlefield | Destination$ Hand SVar:Picture:http://www.wizards.com/global/images/magic/general/sakashima_the_impostor.jpg -Oracle:You may have Sakashima the Impostor enter the battlefield as a copy of any creature on the battlefield, except its name is still Sakashima the Impostor, it's legendary in addition to its other types, and it gains "{2}{U}{U}: Return Sakashima the Impostor to its owner's hand at the beginning of the next end step." +Oracle:You may have Sakashima the Impostor enter the battlefield as a copy of any creature on the battlefield, except its name is Sakashima the Impostor, it’s legendary in addition to its other types, and it has “{2}{U}{U}: Return this creature to its owner’s hand at the beginning of the next end step.” diff --git a/forge-gui/res/cardsfolder/s/selective_snare.txt b/forge-gui/res/cardsfolder/s/selective_snare.txt new file mode 100644 index 00000000000..78579ab38a4 --- /dev/null +++ b/forge-gui/res/cardsfolder/s/selective_snare.txt @@ -0,0 +1,7 @@ +Name:Selective Snare +ManaCost:X U +Types:Sorcery +A:SP$ ChangeZone | AnnounceType$ CreatureType | AILogic$ MostProminentOppControls | Cost$ X U | ValidTgts$ Creature.ChosenType | TargetMin$ 0 | TargetMax$ MaxTgts | TgtPrompt$ Select target creature of the chosen creature type | Origin$ Battlefield | Destination$ Hand | References$ X,MaxTgts | SpellDescription$ Return X target creatures of the creature type of your choice to their owner's hand. +SVar:X:Targeted$Amount +SVar:MaxTgts:Count$Valid Creature.ChosenType +Oracle:Return X target creatures of the creature type of your choice to their owner's hand. diff --git a/forge-gui/res/cardsfolder/upcoming/selesnya_locket.txt b/forge-gui/res/cardsfolder/s/selesnya_locket.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/selesnya_locket.txt rename to forge-gui/res/cardsfolder/s/selesnya_locket.txt diff --git a/forge-gui/res/cardsfolder/s/sentinel_tower.txt b/forge-gui/res/cardsfolder/s/sentinel_tower.txt new file mode 100644 index 00000000000..50f305c32d6 --- /dev/null +++ b/forge-gui/res/cardsfolder/s/sentinel_tower.txt @@ -0,0 +1,7 @@ +Name:Sentinel Tower +ManaCost:4 +Types:Artifact +T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | Execute$ TrigDmg | TriggerZones$ Battlefield | TriggerDescription$ Whenever an instant or sorcery spell is cast during your turn, CARDNAME deals damage to any target equal to 1 plus the number of instant and sorcery spells cast before that spell this turn. +SVar:TrigDmg:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | References$ X +SVar:X:TriggerObjectsCurrentCastSpells$Valid Sorcery,Instant +Oracle:Whenever an instant or sorcery spell is cast during your turn, Sentinel Tower deals damage to any target equal to 1 plus the number of instant and sorcery spells cast before that spell this turn. diff --git a/forge-gui/res/cardsfolder/upcoming/severed_strands.txt b/forge-gui/res/cardsfolder/s/severed_strands.txt similarity index 94% rename from forge-gui/res/cardsfolder/upcoming/severed_strands.txt rename to forge-gui/res/cardsfolder/s/severed_strands.txt index 1ee8c01646f..9eb18d533ed 100644 --- a/forge-gui/res/cardsfolder/upcoming/severed_strands.txt +++ b/forge-gui/res/cardsfolder/s/severed_strands.txt @@ -3,5 +3,5 @@ ManaCost:1 B Types:Sorcery A:SP$ GainLife | Cost$ 1 B Sac<1/Creature> | Defined$ You | LifeAmount$ X | SubAbility$ DBDestroy | References$ X | SpellDescription$ You gain life equal to that sacrificed creature's toughness. Destroy target creature an opponent controls. SVar:DBDestroy:DB$ Destroy | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls. -SVar:X:RememberedLKI$CardToughness +SVar:X:Sacrificed$CardToughness Oracle:As an additional cost to cast this spell, sacrifice a creature.\nYou gain life equal to that sacrificed creature's toughness. Destroy target creature an opponent controls. diff --git a/forge-gui/res/cardsfolder/upcoming/silent_dart.txt b/forge-gui/res/cardsfolder/s/silent_dart.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/silent_dart.txt rename to forge-gui/res/cardsfolder/s/silent_dart.txt diff --git a/forge-gui/res/cardsfolder/upcoming/sinister_sabotage.txt b/forge-gui/res/cardsfolder/s/sinister_sabotage.txt similarity index 91% rename from forge-gui/res/cardsfolder/upcoming/sinister_sabotage.txt rename to forge-gui/res/cardsfolder/s/sinister_sabotage.txt index 5dcbd3c772a..26b0076b909 100644 --- a/forge-gui/res/cardsfolder/upcoming/sinister_sabotage.txt +++ b/forge-gui/res/cardsfolder/s/sinister_sabotage.txt @@ -3,4 +3,5 @@ ManaCost:1 U U Types:Instant A:SP$ Counter | Cost$ 1 U U | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | Subability$ DBSurveil | SpellDescription$ Counter target spell. Surveil 1 (Look at the top card of your library. You may put that card into your graveyard.) SVar:DBSurveil:DB$ Surveil | Amount$ 1 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Counter target spell.\nSurveil 1. (Look at the top card of your library. You may put that card into your graveyard.) diff --git a/forge-gui/res/cardsfolder/s/skaab_goliath.txt b/forge-gui/res/cardsfolder/s/skaab_goliath.txt index 9b1f20a26f2..15f63a8a8e3 100644 --- a/forge-gui/res/cardsfolder/s/skaab_goliath.txt +++ b/forge-gui/res/cardsfolder/s/skaab_goliath.txt @@ -3,6 +3,6 @@ ManaCost:5 U Types:Creature Zombie Giant PT:6/9 K:Trample -SVar:FullCost:5 U ExileFromGrave<2/Creature> +A:SP$ PermanentCreature | Cost$ 5 U ExileFromGrave<2/Creature> SVar:Picture:http://www.wizards.com/global/images/magic/general/skaab_goliath.jpg Oracle:As an additional cost to cast Skaab Goliath, exile two creature cards from your graveyard.\nTrample diff --git a/forge-gui/res/cardsfolder/s/skaab_ruinator.txt b/forge-gui/res/cardsfolder/s/skaab_ruinator.txt index f13a8f42cae..38ab2d38e05 100644 --- a/forge-gui/res/cardsfolder/s/skaab_ruinator.txt +++ b/forge-gui/res/cardsfolder/s/skaab_ruinator.txt @@ -3,7 +3,7 @@ ManaCost:1 U U Types:Creature Zombie Horror PT:5/6 K:Flying -SVar:FullCost:1 U U ExileFromGrave<3/Creature> +A:SP$ PermanentCreature | Cost$ 1 U U ExileFromGrave<3/Creature> SVar:AltCost:Cost$ 1 U U ExileFromGrave<3/Creature.Other> | ActivationZone$ Graveyard | Description$ You may cast CARDNAME from your graveyard. SVar:Picture:http://www.wizards.com/global/images/magic/general/skaab_ruinator.jpg Oracle:As an additional cost to cast Skaab Ruinator, exile three creature cards from your graveyard.\nFlying\nYou may cast Skaab Ruinator from your graveyard. diff --git a/forge-gui/res/cardsfolder/s/skull_storm.txt b/forge-gui/res/cardsfolder/s/skull_storm.txt new file mode 100644 index 00000000000..8575431914b --- /dev/null +++ b/forge-gui/res/cardsfolder/s/skull_storm.txt @@ -0,0 +1,13 @@ +Name:Skull Storm +ManaCost:7 B B +Types:Sorcery +T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When you cast this spell, copy it for each time you've cast your commander from the command zone this game. +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:X:Count$TotalCommanderCastFromCommandZone +A:SP$ Sacrifice | Cost$ 7 B B | Defined$ Player.Opponent | SacValid$ Creature | RememberSacrificed$ True | SubAbility$ DBRepeatEach +SVar:DBRepeatEach:DB$ RepeatEach | RepeatPlayers$ Player.Opponent | RepeatSubAbility$ DBLoseLife | SubAbility$ DBCleanup +SVar:DBLoseLife:DB$ LoseLife | Defined$ Player.IsRemembered | LifeAmount$ Y | References$ Z,Y | ConditionCheckSVar$ Z | ConditionSVarCompare$ EQ0 | References$ Z +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:Y:PlayerCountRemembered$LifeTotal/HalfUp +SVar:Z:RememberedLKI$Valid Card.RememberedPlayerCtrl +Oracle:When you cast this spell, copy it for each time you've cast your commander from the command zone this game. You may choose new targets for the copies.\nEach opponent sacrifices a creature. Each opponent who can't loses half their life, rounded up. diff --git a/forge-gui/res/cardsfolder/upcoming/skyline_scout.txt b/forge-gui/res/cardsfolder/s/skyline_scout.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/skyline_scout.txt rename to forge-gui/res/cardsfolder/s/skyline_scout.txt diff --git a/forge-gui/res/cardsfolder/upcoming/smelt_ward_minotaur.txt b/forge-gui/res/cardsfolder/s/smelt_ward_minotaur.txt similarity index 95% rename from forge-gui/res/cardsfolder/upcoming/smelt_ward_minotaur.txt rename to forge-gui/res/cardsfolder/s/smelt_ward_minotaur.txt index 8c51a87d9a2..3c563b2f46a 100644 --- a/forge-gui/res/cardsfolder/upcoming/smelt_ward_minotaur.txt +++ b/forge-gui/res/cardsfolder/s/smelt_ward_minotaur.txt @@ -5,5 +5,5 @@ PT:2/3 T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever you cast an instant or sorcery spell, target creature an opponent controls can't block this turn. SVar:TrigPump:DB$ Pump | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls | KW$ HIDDEN CARDNAME can't block. | IsCurse$ True SVar:BuffedBy:Instant,Sorcery -DeckHints:Type$Instant | Sorcery +DeckHints:Type$Instant|Sorcery Oracle:Whenever you cast an instant or sorcery spell, target creature an opponent controls can't block this turn. diff --git a/forge-gui/res/cardsfolder/upcoming/sonic_assault.txt b/forge-gui/res/cardsfolder/s/sonic_assault.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/sonic_assault.txt rename to forge-gui/res/cardsfolder/s/sonic_assault.txt diff --git a/forge-gui/res/cardsfolder/s/spell_blast.txt b/forge-gui/res/cardsfolder/s/spell_blast.txt index 0e57debbf72..6e768fa0a90 100644 --- a/forge-gui/res/cardsfolder/s/spell_blast.txt +++ b/forge-gui/res/cardsfolder/s/spell_blast.txt @@ -1,7 +1,7 @@ Name:Spell Blast ManaCost:X U Types:Instant -A:SP$Counter | Cost$ X U | TargetType$ Spell | ValidTgts$ Card | SpellDescription$ Counter target spell with converted mana cost X. +A:SP$Counter | Cost$ X U | TargetType$ Spell | ValidTgts$ Card | References$ X | SpellDescription$ Counter target spell with converted mana cost X. SVar:X:Targeted$CardManaCost SVar:Picture:http://www.wizards.com/global/images/magic/general/spell_blast.jpg Oracle:Counter target spell with converted mana cost X. diff --git a/forge-gui/res/cardsfolder/upcoming/spinal_centipede.txt b/forge-gui/res/cardsfolder/s/spinal_centipede.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/spinal_centipede.txt rename to forge-gui/res/cardsfolder/s/spinal_centipede.txt diff --git a/forge-gui/res/cardsfolder/upcoming/sprouting_renewal.txt b/forge-gui/res/cardsfolder/s/sprouting_renewal.txt similarity index 97% rename from forge-gui/res/cardsfolder/upcoming/sprouting_renewal.txt rename to forge-gui/res/cardsfolder/s/sprouting_renewal.txt index 133ca46ab57..9f75927afbd 100644 --- a/forge-gui/res/cardsfolder/upcoming/sprouting_renewal.txt +++ b/forge-gui/res/cardsfolder/s/sprouting_renewal.txt @@ -5,4 +5,5 @@ K:Convoke A:SP$ Charm | Cost$ 2 G | Choices$ DBToken,DBDestroy SVar:DBDestroy:DB$ Destroy | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | SpellDescription$ Destroy target artifact or enchantment. SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ wg_2_2_elf_knight_vigilance | SpellDescription$ Create a 2/2 green and white Elf Knight creature token with vigilance. +DeckHas:Ability$Token Oracle:Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)\nChoose one —\n• Create a 2/2 green and white Elf Knight creature token with vigilance.\n• Destroy target artifact or enchantment. diff --git a/forge-gui/res/cardsfolder/s/stadium_vendors.txt b/forge-gui/res/cardsfolder/s/stadium_vendors.txt new file mode 100644 index 00000000000..25c391bdac9 --- /dev/null +++ b/forge-gui/res/cardsfolder/s/stadium_vendors.txt @@ -0,0 +1,9 @@ +Name:Stadium Vendors +ManaCost:3 R +Types:Creature Goblin +PT:3/3 +K:Flying +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChoosePlayer | TriggerDescription$ When CARDNAME enters the battlefield, choose a player. That player adds two mana of any one color they choose. +SVar:TrigChoosePlayer:DB$ ChoosePlayer | Defined$ You | Choices$ Player | ChoiceTitle$ Choose a player | AILogic$ Pump | SubAbility$ DBMana +SVar:DBMana:DB$ Mana | Produced$ Any | Defined$ ChosenPlayer | Amount$ 2 +Oracle:When Stadium Vendors enters the battlefield, choose a player. That player adds two mana of any one color they choose. diff --git a/forge-gui/res/cardsfolder/s/standstill.txt b/forge-gui/res/cardsfolder/s/standstill.txt index 005ad59d316..8236863e08b 100644 --- a/forge-gui/res/cardsfolder/s/standstill.txt +++ b/forge-gui/res/cardsfolder/s/standstill.txt @@ -9,6 +9,6 @@ SVar:X:Remembered$Amount SVar:Y:Count$Valid Creature.YouCtrl SVar:Z:Count$Valid Creature.OppCtrl SVar:NeedsToPlayVar:Y GTZ -Svar:RemAIDeck:True +SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/standstill.jpg Oracle:When a player casts a spell, sacrifice Standstill. If you do, each of that player's opponents draws three cards. diff --git a/forge-gui/res/cardsfolder/upcoming/status_statue.txt b/forge-gui/res/cardsfolder/s/status_statue.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/status_statue.txt rename to forge-gui/res/cardsfolder/s/status_statue.txt diff --git a/forge-gui/res/cardsfolder/s/stitched_drake.txt b/forge-gui/res/cardsfolder/s/stitched_drake.txt index a12f6807393..4330e399a22 100644 --- a/forge-gui/res/cardsfolder/s/stitched_drake.txt +++ b/forge-gui/res/cardsfolder/s/stitched_drake.txt @@ -3,6 +3,6 @@ ManaCost:1 U U Types:Creature Zombie Drake PT:3/4 K:Flying -SVar:FullCost:1 U U ExileFromGrave<1/Creature> +A:SP$ PermanentCreature | Cost$ 1 U U ExileFromGrave<1/Creature> SVar:Picture:http://www.wizards.com/global/images/magic/general/stitched_drake.jpg Oracle:As an additional cost to cast Stitched Drake, exile a creature card from your graveyard.\nFlying diff --git a/forge-gui/res/cardsfolder/upcoming/street_riot.txt b/forge-gui/res/cardsfolder/s/street_riot.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/street_riot.txt rename to forge-gui/res/cardsfolder/s/street_riot.txt diff --git a/forge-gui/res/cardsfolder/upcoming/sumala_woodshaper.txt b/forge-gui/res/cardsfolder/s/sumala_woodshaper.txt similarity index 88% rename from forge-gui/res/cardsfolder/upcoming/sumala_woodshaper.txt rename to forge-gui/res/cardsfolder/s/sumala_woodshaper.txt index 26db8431693..d398de4b996 100644 --- a/forge-gui/res/cardsfolder/upcoming/sumala_woodshaper.txt +++ b/forge-gui/res/cardsfolder/s/sumala_woodshaper.txt @@ -3,5 +3,5 @@ ManaCost:2 G W Types:Creature Elf Druid PT:2/1 T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigDig | TriggerDescription$ When CARDNAME enters the battlefield, look at the top four cards of your library. You may reveal a creature or enchantment card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. -SVar:TrigDig:DB$ Dig | DigNum$ 4 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Creature,Enchantment | RestRandomOrder$ True +SVar:TrigDig:DB$ Dig | DigNum$ 4 | ChangeNum$ 1 | Optional$ True | ForceRevealToController$ True | ChangeValid$ Creature,Enchantment | RestRandomOrder$ True Oracle:When Sumala Woodshaper enters the battlefield, look at the top four cards of your library. You may reveal a creature or enchantment card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/upcoming/sunhome_stalwart.txt b/forge-gui/res/cardsfolder/s/sunhome_stalwart.txt similarity index 90% rename from forge-gui/res/cardsfolder/upcoming/sunhome_stalwart.txt rename to forge-gui/res/cardsfolder/s/sunhome_stalwart.txt index 108c54611cd..3619e11a263 100644 --- a/forge-gui/res/cardsfolder/upcoming/sunhome_stalwart.txt +++ b/forge-gui/res/cardsfolder/s/sunhome_stalwart.txt @@ -4,4 +4,5 @@ Types:Creature Human Soldier PT:2/2 K:First Strike K:Mentor +DeckHas:Ability$Counters Oracle:First strike\nMentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.) diff --git a/forge-gui/res/cardsfolder/s/suspicious_bookcase.txt b/forge-gui/res/cardsfolder/s/suspicious_bookcase.txt index f66779c7f53..82db0515001 100644 --- a/forge-gui/res/cardsfolder/s/suspicious_bookcase.txt +++ b/forge-gui/res/cardsfolder/s/suspicious_bookcase.txt @@ -5,4 +5,4 @@ PT:0/4 K:Defender A:AB$ Pump | Cost$ 3 T | ValidTgts$ Creature | KW$ HIDDEN Unblockable | SpellDescription$ Target creature can't be blocked this turn. | TgtPrompt$ Select target creature. SVar:Picture:http://www.wizards.com/global/images/magic/general/suspicious_bookcase.jpg -Oracle:Defender\n{3}{T}: Target creature can't be blocked this turn. +Oracle:Defender\n{3}, {T}: Target creature can't be blocked this turn. diff --git a/forge-gui/res/cardsfolder/upcoming/swarm_guildmage.txt b/forge-gui/res/cardsfolder/s/swarm_guildmage.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/swarm_guildmage.txt rename to forge-gui/res/cardsfolder/s/swarm_guildmage.txt diff --git a/forge-gui/res/cardsfolder/upcoming/swathcutter_giant.txt b/forge-gui/res/cardsfolder/s/swathcutter_giant.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/swathcutter_giant.txt rename to forge-gui/res/cardsfolder/s/swathcutter_giant.txt diff --git a/forge-gui/res/cardsfolder/upcoming/swiftblade_vindicator.txt b/forge-gui/res/cardsfolder/s/swiftblade_vindicator.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/swiftblade_vindicator.txt rename to forge-gui/res/cardsfolder/s/swiftblade_vindicator.txt diff --git a/forge-gui/res/cardsfolder/upcoming/sworn_companions.txt b/forge-gui/res/cardsfolder/s/sworn_companions.txt similarity index 56% rename from forge-gui/res/cardsfolder/upcoming/sworn_companions.txt rename to forge-gui/res/cardsfolder/s/sworn_companions.txt index e2ed080c0a3..e8b5d817986 100644 --- a/forge-gui/res/cardsfolder/upcoming/sworn_companions.txt +++ b/forge-gui/res/cardsfolder/s/sworn_companions.txt @@ -1,6 +1,6 @@ Name:Sworn Companions ManaCost:2 W Types:Sorcery -A:SP$ Token | Cost$ 2 W | TokenAmount$ 2 | TokenScript$ w_1_1_soldier_lifelink -DeckHas:Ability$Token +A:SP$ Token | Cost$ 2 W | TokenAmount$ 2 | TokenScript$ w_1_1_soldier_lifelink | SpellDescription$ Creature two 1/1 white Soldier creature tokens with lifelink. +DeckHas:Ability$Token & Ability$LifeGain Oracle:Creature two 1/1 white Soldier creature tokens with lifelink. diff --git a/forge-gui/res/cardsfolder/upcoming/tajic_legions_edge.txt b/forge-gui/res/cardsfolder/t/tajic_legions_edge.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/tajic_legions_edge.txt rename to forge-gui/res/cardsfolder/t/tajic_legions_edge.txt index 4fd9fb0b3a4..dc2adc1103c 100644 --- a/forge-gui/res/cardsfolder/upcoming/tajic_legions_edge.txt +++ b/forge-gui/res/cardsfolder/t/tajic_legions_edge.txt @@ -6,4 +6,5 @@ K:Haste K:Mentor R:Event$ DamageDone | ActiveZones$ Battlefield | Prevent$ True | ValidTarget$ Creature.Other+YouCtrl | IsCombat$ False | Description$ Prevent all noncombat damage that would be dealt to other creatures you control. A:AB$ Pump | Cost$ R W | Defined$ Self | KW$ First Strike | SpellDescription$ CARDNAME gains first strike until end of turn. +DeckHas:Ability$Counters Oracle:Haste\nMentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.)\nPrevent all noncombat damage that would be dealt to other creatures you control.\n{R}{W}: Tajic, Legion's Edge gains first strike until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/take_heart.txt b/forge-gui/res/cardsfolder/t/take_heart.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/take_heart.txt rename to forge-gui/res/cardsfolder/t/take_heart.txt diff --git a/forge-gui/res/cardsfolder/t/tamanoa.txt b/forge-gui/res/cardsfolder/t/tamanoa.txt index 013368baacf..d164f782778 100644 --- a/forge-gui/res/cardsfolder/t/tamanoa.txt +++ b/forge-gui/res/cardsfolder/t/tamanoa.txt @@ -5,6 +5,5 @@ PT:2/4 T:Mode$ DamageDealtOnce | ValidSource$ Card.nonCreature+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigGainLife | TriggerDescription$ Whenever a noncreature source you control deals damage, you gain that much life. SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ X | References$ X SVar:X:TriggerCount$DamageAmount -Svar:Rarity:Rare SVar:Picture:http://www.wizards.com/global/images/magic/general/tamanoa.jpg Oracle:Whenever a noncreature source you control deals damage, you gain that much life. diff --git a/forge-gui/res/cardsfolder/t/tectonic_edge.txt b/forge-gui/res/cardsfolder/t/tectonic_edge.txt index 7e2c2ca78a9..d0a9c80fbfb 100644 --- a/forge-gui/res/cardsfolder/t/tectonic_edge.txt +++ b/forge-gui/res/cardsfolder/t/tectonic_edge.txt @@ -2,7 +2,8 @@ Name:Tectonic Edge ManaCost:no cost Types:Land A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. -A:AB$ Destroy | ValidTgts$ Land.nonBasic | TgtPrompt$ Select target nonbasic land. | Cost$ 1 T Sac<1/CARDNAME> | IsPresent$ Land.OppCtrl | PresentCompare$ GE4 | AILogic$ LandForLand | SpellDescription$ Destroy target nonbasic land. Activate this ability only if an opponent controls four or more lands. +A:AB$ Destroy | ValidTgts$ Land.nonBasic | TgtPrompt$ Select target nonbasic land. | Cost$ 1 T Sac<1/CARDNAME> | CheckSVar$ X | SVarCompare$ GE4 | References$ X | AILogic$ LandForLand | SpellDescription$ Destroy target nonbasic land. Activate this ability only if an opponent controls four or more lands. +SVar:X:PlayerCountOpponents$HighestValid Land.YouCtrl SVar:RemRandomDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/tectonic_edge.jpg Oracle:{T}: Add {C}.\n{1}, {T}, Sacrifice Tectonic Edge: Destroy target nonbasic land. Activate this ability only if an opponent controls four or more lands. diff --git a/forge-gui/res/cardsfolder/t/teferi_hero_of_dominaria.txt b/forge-gui/res/cardsfolder/t/teferi_hero_of_dominaria.txt index 29919a6d2e4..48f40466192 100644 --- a/forge-gui/res/cardsfolder/t/teferi_hero_of_dominaria.txt +++ b/forge-gui/res/cardsfolder/t/teferi_hero_of_dominaria.txt @@ -2,12 +2,12 @@ Name:Teferi, Hero of Dominaria ManaCost:3 W U Types:Legendary Planeswalker Teferi Loyalty:4 -A:AB$ Draw | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | Defined$ You | NumCards$ 1 | SubAbility$ DelTrigUntap | SpellDescription$ Draw a card. At the beginning of the next end step, untap two lands. +A:AB$ Draw | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | Defined$ You | NumCards$ 1 | SubAbility$ DelTrigUntap | SpellDescription$ Draw a card. At the beginning of the next end step, untap up to two lands. SVar:DelTrigUntap:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigUntap | TriggerDescription$ At the beginning of the next end step, untap two lands. -SVar:TrigUntap:DB$ Untap | UntapExactly$ True | UntapType$ Land | Amount$ 2 | Defined$ You +SVar:TrigUntap:DB$ Untap | UntapUpTo$ True | UntapType$ Land | Amount$ 2 | Defined$ You A:AB$ ChangeZone | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | Origin$ Battlefield | Destination$ Library | LibraryPosition$ 2 | IsCurse$ True | SpellDescription$ Put target nonland permanent into its owner's library third from the top. A:AB$ Effect | Cost$ SubCounter<8/LOYALTY> | Planeswalker$ True | Ultimate$ True | Name$ Emblem - Teferi, Hero of Dominaria | Image$ emblem_teferi_hero_of_dominaria | Triggers$ TrigDraw | SVars$ EffSpellCast | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Whenever you draw a card, exile target permanent an opponent controls." SVar:TrigDraw:Mode$ Drawn | ValidCard$ Card.YouCtrl | Execute$ EffSpellCast | TriggerDescription$ Whenever you draw a card, exile target permanent an opponent controls. SVar:EffSpellCast:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Permanent.OppCtrl | TgtPrompt$ Select target permanent an opponent controls SVar:Picture:http://www.wizards.com/global/images/magic/general/teferi_hero_of_dominaria.jpg -Oracle:[+1]: Draw a card. At the beginning of the next end step, untap two lands.\n[-3]: Put target nonland permanent into its owner's library third from the top.\n[-8]: You get an emblem with "Whenever you draw a card, exile target permanent an opponent controls." +Oracle:[+1]: Draw a card. At the beginning of the next end step, untap up to two lands.\n[-3]: Put target nonland permanent into its owner's library third from the top.\n[-8]: You get an emblem with "Whenever you draw a card, exile target permanent an opponent controls." diff --git a/forge-gui/res/cardsfolder/upcoming/tenth_district_guard.txt b/forge-gui/res/cardsfolder/t/tenth_district_guard.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/tenth_district_guard.txt rename to forge-gui/res/cardsfolder/t/tenth_district_guard.txt diff --git a/forge-gui/res/cardsfolder/t/tetsuo_umezawa.txt b/forge-gui/res/cardsfolder/t/tetsuo_umezawa.txt index 3912d5e5b42..006d1e82233 100644 --- a/forge-gui/res/cardsfolder/t/tetsuo_umezawa.txt +++ b/forge-gui/res/cardsfolder/t/tetsuo_umezawa.txt @@ -2,7 +2,7 @@ Name:Tetsuo Umezawa ManaCost:U B R Types:Legendary Creature Human Archer PT:3/3 -K:CARDNAME can't be the target of Aura spells. +S:Mode$ CantTarget | ValidCard$ Card.Self | ValidSource$ Aura | ValidSA$ Spell | Description$ CARDNAME can't be the target of Aura spells. A:AB$ Destroy | Cost$ U B B R T | ValidTgts$ Creature.tapped,Creature.blocking | TgtPrompt$ Select target tapped or blocking creature | SpellDescription$ Destroy target tapped or blocking creature. SVar:Picture:http://www.wizards.com/global/images/magic/general/tetsuo_umezawa.jpg Oracle:Tetsuo Umezawa can't be the target of Aura spells.\n{U}{B}{B}{R}, {T}: Destroy target tapped or blocking creature. diff --git a/forge-gui/res/cardsfolder/t/thespians_stage.txt b/forge-gui/res/cardsfolder/t/thespians_stage.txt index e6673ff8a1d..2a2b3db4896 100644 --- a/forge-gui/res/cardsfolder/t/thespians_stage.txt +++ b/forge-gui/res/cardsfolder/t/thespians_stage.txt @@ -2,8 +2,7 @@ Name:Thespian's Stage ManaCost:no cost Types:Land A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. -A:AB$ Clone | Cost$ 2 T | ValidTgts$ Land | TgtPrompt$ Select target land to copy. | AddAbilities$ ThespianCopy | AddSVars$ ThespianCopy | SpellDescription$ CARDNAME becomes a copy of target land and gains this ability. -SVar:ThespianCopy:AB$ Clone | Cost$ 2 T | ValidTgts$ Land | TgtPrompt$ Select target land to copy. | AddAbilities$ ThespianCopy | AddSVars$ ThespianCopy | SpellDescription$ CARDNAME becomes a copy of target land and gains this ability. +A:AB$ Clone | Cost$ 2 T | ValidTgts$ Land | TgtPrompt$ Select target land to copy. | GainThisAbility$ True | SpellDescription$ CARDNAME becomes a copy of target land and gains this ability. SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/thespians_stage.jpg Oracle:{T}: Add {C}.\n{2}, {T}: Thespian's Stage becomes a copy of target land and gains this ability. diff --git a/forge-gui/res/cardsfolder/t/thief_of_sanity.txt b/forge-gui/res/cardsfolder/t/thief_of_sanity.txt new file mode 100644 index 00000000000..c11142e1b2e --- /dev/null +++ b/forge-gui/res/cardsfolder/t/thief_of_sanity.txt @@ -0,0 +1,12 @@ +Name:Thief of Sanity +ManaCost:1 U B +Types:Creature Specter +PT:2/2 +K:Flying +T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigDig | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, look at the top three cards of that player's library, exile one of them face down, then put the rest into their graveyard. For as long as that card remains exiled, you may look at it, and you may spend mana as though it were mana of any type to cast it. +SVar:TrigDig:DB$ Dig | DigNum$ 3 | Defined$ TriggeredTarget | DestinationZone$ Exile | ExileFaceDown$ True | SkipReorder$ True | DestinationZone2$ Graveyard | RememberChanged$ True | ChangeValid$ Card | SubAbility$ DBEffect +SVar:DBEffect:DB$ Effect | RememberObjects$ Remembered | StaticAbilities$ STPlay1,STPlay2 | Duration$ Permanent | ForgetOnMoved$ Exile | SubAbility$ DBCleanup +SVar:STPlay1:Mode$ Continuous | MayLookAt$ You | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ You may look at it, and you may spend mana as though it were mana of any type to cast it. +SVar:STPlay2:Mode$ Continuous | MayPlay$ True | MayPlayIgnoreType$ True | EffectZone$ Command | Affected$ Card.IsRemembered+nonLand | AffectedZone$ Exile | Secondary$ True | Description$ You may look at it, and you may spend mana as though it were mana of any type to cast it. +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +Oracle:Flying\nWhenever Thief of Sanity deals combat damage to a player, look at the top three cards of that player's library, exile one of them face down, then put the rest into their graveyard. For as long as that card remains exiled, you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it. diff --git a/forge-gui/res/cardsfolder/t/thirsting_axe.txt b/forge-gui/res/cardsfolder/t/thirsting_axe.txt index a1b1326de42..cce75513ddd 100644 --- a/forge-gui/res/cardsfolder/t/thirsting_axe.txt +++ b/forge-gui/res/cardsfolder/t/thirsting_axe.txt @@ -3,7 +3,7 @@ ManaCost:3 Types:Artifact Equipment K:Equip:2 S:Mode$ Continuous | Affected$ Card.EquippedBy | AddPower$ 4 | Description$ Equipped creature gets +4/+0. -T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | IsPresent$ Card.EquippedBy+notDealtCombatDamageThisTurn Creature | TriggerZone$ Battlefield | Execute$ SacrificeEquippee | TriggerDescription$ At the beginning of your end step, if equipped creature didn't deal combat damage to a creature this turn, sacrifice it. +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | IsPresent$ Card.EquippedBy+notDealtCombatDamageThisTurn Creature | TriggerZones$ Battlefield | Execute$ SacrificeEquippee | TriggerDescription$ At the beginning of your end step, if equipped creature didn't deal combat damage to a creature this turn, sacrifice it. SVar:SacrificeEquippee:DB$ SacrificeAll | Defined$ Equipped SVar:Picture:http://www.wizards.com/global/images/magic/general/thirsting_axe.jpg Oracle:Equipped creature gets +4/+0.\nAt the beginning of your end step, if equipped creature didn't deal combat damage to a creature this turn, sacrifice it.\nEquip {2} diff --git a/forge-gui/res/cardsfolder/upcoming/thought_erasure.txt b/forge-gui/res/cardsfolder/t/thought_erasure.txt similarity index 93% rename from forge-gui/res/cardsfolder/upcoming/thought_erasure.txt rename to forge-gui/res/cardsfolder/t/thought_erasure.txt index 02aab8b1c92..57bdc88fe1c 100644 --- a/forge-gui/res/cardsfolder/upcoming/thought_erasure.txt +++ b/forge-gui/res/cardsfolder/t/thought_erasure.txt @@ -3,4 +3,5 @@ ManaCost:U B Types:Sorcery A:SP$ Discard | Cost$ U B | ValidTgts$ Opponent | DiscardValid$ Card.nonLand | NumCards$ 1 | Mode$ RevealYouChoose | Subability$ DBSurveil | SpellDescription$ Target opponent reveals their hand. You choose a nonland card from it. That player discards that card. Surveil 1 (Look at the top card of your library. You may put that card into your graveyard.) SVar:DBSurveil:DB$ Surveil | Amount$ 1 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Target opponent reveals their hand. You choose a nonland card from it. That player discards that card.\nSurveil 1. (Look at the top card of your library. You may put it into your graveyard.) diff --git a/forge-gui/res/cardsfolder/upcoming/thoughtbound_phantasm.txt b/forge-gui/res/cardsfolder/t/thoughtbound_phantasm.txt similarity index 93% rename from forge-gui/res/cardsfolder/upcoming/thoughtbound_phantasm.txt rename to forge-gui/res/cardsfolder/t/thoughtbound_phantasm.txt index 718268ba991..f2c53932858 100644 --- a/forge-gui/res/cardsfolder/upcoming/thoughtbound_phantasm.txt +++ b/forge-gui/res/cardsfolder/t/thoughtbound_phantasm.txt @@ -6,4 +6,6 @@ K:Defender T:Mode$ Surveil | ValidPlayer$ You | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ Whenever you surveil, put a +1/+1 counter on CARDNAME SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 S:Mode$ Continuous | Affected$ Card.Self+counters_GE3_P1P1 | AddHiddenKeyword$ CARDNAME can attack as though it didn't have defender. | Description$ As long as CARDNAME has three or more +1/+1 counters on it, it can attack +DeckNeeds:Ability$Surveil +DeckHas:Ability$Counters Oracle:Defender\nWhenever you surveil, put a +1/+1 counter on Thoughtbound Phantasm.\nAs long as Thoughtbound Phantasm has three or more +1/+1 counters on it, it can attack as though it didn't have defender. diff --git a/forge-gui/res/cardsfolder/t/thousand_year_storm.txt b/forge-gui/res/cardsfolder/t/thousand_year_storm.txt new file mode 100644 index 00000000000..e4425747b73 --- /dev/null +++ b/forge-gui/res/cardsfolder/t/thousand_year_storm.txt @@ -0,0 +1,8 @@ +Name:Thousand-Year Storm +ManaCost:4 U R +Types:Enchantment +T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast an instant or sorcery spell, copy it for each other instant and sorcery spell you've cast before it this turn. You may choose new targets for the copies. +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:X:TriggerObjectsCurrentCastSpells$Valid Sorcery.YouCtrl,Instant.YouCtrl/Minus.1 +DeckHints:Type$Instant|Sorcery +Oracle:Whenever you cast an instant or sorcery spell, copy it for each other instant and sorcery spell you've cast before it this turn. You may choose new targets for the copies. diff --git a/forge-gui/res/cardsfolder/upcoming/torch_courier.txt b/forge-gui/res/cardsfolder/t/torch_courier.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/torch_courier.txt rename to forge-gui/res/cardsfolder/t/torch_courier.txt diff --git a/forge-gui/res/cardsfolder/t/treasure_nabber.txt b/forge-gui/res/cardsfolder/t/treasure_nabber.txt new file mode 100644 index 00000000000..68d2bad4a93 --- /dev/null +++ b/forge-gui/res/cardsfolder/t/treasure_nabber.txt @@ -0,0 +1,7 @@ +Name:Treasure Nabber +ManaCost:2 R +Types:Creature Goblin Rogue +PT:3/2 +T:Mode$ TapsForMana | ValidCard$ Artifact.OppCtrl | TriggerZones$ Battlefield | Execute$ TrigControl | TriggerDescription$ Whenever an opponent taps an artifact for mana, gain control of that artifact until the end of your next turn. +SVar:TrigControl:DB$ GainControl | Defined$ TriggeredCard | LoseControl$ UntilTheEndOfYourNextTurn +Oracle:Whenever an opponent taps an artifact for mana, gain control of that artifact until the end of your next turn. diff --git a/forge-gui/res/cardsfolder/upcoming/trostani_discordant.txt b/forge-gui/res/cardsfolder/t/trostani_discordant.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/trostani_discordant.txt rename to forge-gui/res/cardsfolder/t/trostani_discordant.txt index 53c3ed895e4..f93ad01c605 100644 --- a/forge-gui/res/cardsfolder/upcoming/trostani_discordant.txt +++ b/forge-gui/res/cardsfolder/t/trostani_discordant.txt @@ -8,4 +8,5 @@ SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ w_1_1_soldier_lifelink T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigGainControl | TriggerDescription$ At the beginning of your end step, each player gains control of all creatures they own. SVar:TrigGainControl:DB$ RepeatEach | RepeatPlayers$ Player | AILogic$ GainControlOwns | RepeatSubAbility$ DBGainControl | SpellDescription$ Each player gains control of all creatures they own. SVar:DBGainControl:DB$ GainControl | AllValid$ Creature.RememberedPlayerOwn | NewController$ Player.IsRemembered +DeckHas:Ability$Token & Ability$LifeGain Oracle:Other creatures you control get +1/+1.\nWhen Trostani Discordant enters the battlefield, create two 1/1 white Soldier creature tokens with lifelink.\nAt the beginning of your end step, each player gains control of all creatures they own. diff --git a/forge-gui/res/cardsfolder/upcoming/truefire_captain.txt b/forge-gui/res/cardsfolder/t/truefire_captain.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/truefire_captain.txt rename to forge-gui/res/cardsfolder/t/truefire_captain.txt index 9686427b472..3c254c3ef0f 100644 --- a/forge-gui/res/cardsfolder/upcoming/truefire_captain.txt +++ b/forge-gui/res/cardsfolder/t/truefire_captain.txt @@ -7,4 +7,5 @@ T:Mode$ DamageDoneOnce | Execute$ TrigDamage | ValidTarget$ Card.Self | TriggerZ SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Player | TgtPrompt$ Select target player | NumDmg$ X | References$ X SVar:X:TriggerCount$DamageAmount SVar:HasCombatEffect:TRUE +DeckHas:Ability$Counters Oracle:Mentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.)\nWhenever Truefire Captain is dealt damage, it deals that much damage to target player. diff --git a/forge-gui/res/cardsfolder/t/turntimber_sower.txt b/forge-gui/res/cardsfolder/t/turntimber_sower.txt index b8c871a0564..972f5da9136 100644 --- a/forge-gui/res/cardsfolder/t/turntimber_sower.txt +++ b/forge-gui/res/cardsfolder/t/turntimber_sower.txt @@ -2,7 +2,7 @@ Name:Turntimber Sower ManaCost:2 G Types:Creature Elf Druid PT:3/3 -T:Mode$ ChangesZone | ValidCard$ Land.YouOwn | Origin$ Any | Destination$ Graveyard | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever one or more land cards are put into your graveyard from anywhere, create a 0/1 green Plant creature token. +T:Mode$ ChangesZone | ValidCard$ Land.YouOwn | Origin$ Any | Destination$ Graveyard | Execute$ TrigToken | OncePerEffect$ True | TriggerZones$ Battlefield | TriggerDescription$ Whenever one or more land cards are put into your graveyard from anywhere, create a 0/1 green Plant creature token. SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenName$ Plant | TokenTypes$ Creature,Plant | TokenOwner$ You | TokenColors$ Green | TokenPower$ 0 | TokenToughness$ 1 | TokenImage$ g 0 1 plant c18 SVar:RemRandomDeck:True A:AB$ ChangeZone | Cost$ G Sac<3/Creature> | TgtPrompt$ Choose target land card in your graveyard | ValidTgts$ Land.YouCtrl | Origin$ Graveyard | Destination$ Hand | SpellDescription$ Return target land card from your graveyard to your hand. diff --git a/forge-gui/res/cardsfolder/t/tuvasa_the_sunlit.txt b/forge-gui/res/cardsfolder/t/tuvasa_the_sunlit.txt index 54e048fd514..49c79afd743 100644 --- a/forge-gui/res/cardsfolder/t/tuvasa_the_sunlit.txt +++ b/forge-gui/res/cardsfolder/t/tuvasa_the_sunlit.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Merfolk Shaman PT:1/1 S:Mode$ Continuous | Affected$ Card.Self | AddPower$ X | AddToughness$ X | Description$ CARDNAME gets +1/+1 for each enchantment you control. SVar:X:Count$Valid Enchantment.YouCtrl -T:Mode$ SpellCast | ValidCard$ Enchantment | ValidActivatingPlayer$ You | CheckSVar$ Y | SVarCompare$ EQ1 | References$ Y | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever you cast your first enchantment spell each turn, draw a card. +T:Mode$ SpellCast | ValidCard$ Enchantment | ValidActivatingPlayer$ You | CheckSVar$ Y | SVarCompare$ EQ1 | References$ Y | NoResolvingCheck$ True | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever you cast your first enchantment spell each turn, draw a card. SVar:Y:Count$ThisTurnCast_Enchantment.YouCtrl SVar:TrigDraw:DB$ Draw | NumCards$ 1 | Defined$ You SVar:BuffedBy:Enchantment diff --git a/forge-gui/res/cardsfolder/upcoming/undercity_necrolisk.txt b/forge-gui/res/cardsfolder/u/undercity_necrolisk.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/undercity_necrolisk.txt rename to forge-gui/res/cardsfolder/u/undercity_necrolisk.txt diff --git a/forge-gui/res/cardsfolder/upcoming/undercity_uprising.txt b/forge-gui/res/cardsfolder/u/undercity_uprising.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/undercity_uprising.txt rename to forge-gui/res/cardsfolder/u/undercity_uprising.txt diff --git a/forge-gui/res/cardsfolder/upcoming/underrealm_lich.txt b/forge-gui/res/cardsfolder/u/underrealm_lich.txt similarity index 94% rename from forge-gui/res/cardsfolder/upcoming/underrealm_lich.txt rename to forge-gui/res/cardsfolder/u/underrealm_lich.txt index 5a4e13c31c1..31302c0e0b6 100644 --- a/forge-gui/res/cardsfolder/upcoming/underrealm_lich.txt +++ b/forge-gui/res/cardsfolder/u/underrealm_lich.txt @@ -3,7 +3,7 @@ ManaCost:3 B G Types:Creature Zombie Elf Shaman PT:4/3 R:Event$ Draw | ActiveZones$ Battlefield | ValidPlayer$ You | ReplaceWith$ Dig | Description$ If you would draw a card, instead look at the top three cards of your library, then put one into your hand and the rest into your graveyard. -SVar:Dig:DB$Dig | DigNum$ 3 | ChangeNum$ 1 | ChangeValid$ Card | DestinationZone2$ Graveyard +SVar:Dig:DB$Dig | DigNum$ 3 | ChangeNum$ 1 | ChangeValid$ Card | DestinationZone2$ Graveyard | NoReveal$ True A:AB$ Pump | Cost$ PayLife<4> | Defined$ Self | KW$ Indestructible | SubAbility$ DBTap | SpellDescription$ CARDNAME gains indestructible until end of turn. Tap it. SVar:DBTap:DB$Tap | Defined$ Self Oracle:If you would draw a card, instead look at the top three cards of your library, then put one into your hand and the rest into your graveyard.\nPay 4 life: Underrealm Lich gains indestructible until end of turn. Tap it. diff --git a/forge-gui/res/cardsfolder/upcoming/unexplained_disappearance.txt b/forge-gui/res/cardsfolder/u/unexplained_disappearance.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/unexplained_disappearance.txt rename to forge-gui/res/cardsfolder/u/unexplained_disappearance.txt index 5f90caabb59..761e0b83aea 100644 --- a/forge-gui/res/cardsfolder/upcoming/unexplained_disappearance.txt +++ b/forge-gui/res/cardsfolder/u/unexplained_disappearance.txt @@ -3,4 +3,5 @@ ManaCost:1 U Types:Instant A:SP$ ChangeZone | Cost$ 1 U | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Hand | Subability$ DBSurveil | SpellDescription$ Return target creature to its owner's hand. Surveil 1 (Look at the top card of your library. You may put that card into your graveyard.) SVar:DBSurveil:DB$ Surveil | Amount$ 1 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Return target creature to its owner's hand.\nSurveil 1. (Look at the top card of your library. You may put that card into your graveyard.) diff --git a/forge-gui/res/cardsfolder/u/unmoored_ego.txt b/forge-gui/res/cardsfolder/u/unmoored_ego.txt new file mode 100644 index 00000000000..e10afe55ecc --- /dev/null +++ b/forge-gui/res/cardsfolder/u/unmoored_ego.txt @@ -0,0 +1,13 @@ +Name:Unmoored Ego +ManaCost:1 U B +Types:Sorcery +A:SP$ NameCard | Cost$ 1 U B | Defined$ You | SubAbility$ ExileYard | StackDescription$ SpellDescription | SpellDescription$ Choose a card name. Search target opponent's graveyard, hand, and library for up to four cards with that name and exile them. That player shuffles their library, then draws a card for each card exiled from their hand this way. +SVar:ExileYard:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Player.Opponent | TgtPrompt$ Select target opponent | ChangeType$ Card.NamedCard | Chooser$ You | ChangeNum$ 4 | Hidden$ True | RememberChanged$ True | SubAbility$ ExileHand | StackDescription$ None +SVar:ExileHand:DB$ ChangeZone | Origin$ Hand | Destination$ Exile | DefinedPlayer$ Targeted | ChangeType$ Card.NamedCard | ChangeNum$ Y | Chooser$ You | RememberChanged$ True | Imprint$ True | SubAbility$ ExileLib | StackDescription$ None | References$ X,Y +SVar:ExileLib:DB$ ChangeZone | Origin$ Library | Destination$ Exile | DefinedPlayer$ Targeted | ChangeType$ Card.NamedCard | ChangeNum$ Y | Chooser$ You | RememberChanged$ True | Search$ True | Shuffle$ True | SubAbility$ DBDraw | StackDescription$ None | References$ X,Y +SVar:DBDraw:DB$ Draw | Defined$ Targeted | NumCards$ Z | SubAbility$ DBCleanup | StackDescription$ None | References$ Z +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True +SVar:X:Remembered$Amount +SVar:Y:SVar$X/NMinus.4 +SVar:Z:Imprinted$Amount +Oracle:Choose a card name. Search target opponent's graveyard, hand, and library for up to four cards with that name and exile them. That player shuffles their library, then draws a card for each card exiled from their hand this way. diff --git a/forge-gui/res/cardsfolder/u/unstable_shapeshifter.txt b/forge-gui/res/cardsfolder/u/unstable_shapeshifter.txt index af412f12b6b..f78b867c0e5 100644 --- a/forge-gui/res/cardsfolder/u/unstable_shapeshifter.txt +++ b/forge-gui/res/cardsfolder/u/unstable_shapeshifter.txt @@ -4,7 +4,6 @@ Types:Creature Shapeshifter PT:0/1 # Make SVars for granting abilities and triggers on clones distinct to avoid SVars getting overwritten when cloning a clone T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Other | TriggerZones$ Battlefield | Execute$ USCopy | TriggerDescription$ Whenever another creature enters the battlefield, CARDNAME becomes a copy of that creature and gains this ability. -SVar:USCopy:DB$ Clone | Defined$ TriggeredCard | AddTriggers$ USTrig | AddSVars$ USCopy,USTrig -SVar:USTrig:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Other | TriggerZones$ Battlefield | Execute$ USCopy | TriggerDescription$ Whenever another creature enters the battlefield, CARDNAME becomes a copy of that creature and gains this ability. +SVar:USCopy:DB$ Clone | Defined$ TriggeredCard | GainThisAbility$ True SVar:Picture:http://www.wizards.com/global/images/magic/general/unstable_shapeshifter.jpg Oracle:Whenever another creature enters the battlefield, Unstable Shapeshifter becomes a copy of that creature and gains this ability. diff --git a/forge-gui/res/cardsfolder/upcoming/urban_utopia.txt b/forge-gui/res/cardsfolder/u/urban_utopia.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/urban_utopia.txt rename to forge-gui/res/cardsfolder/u/urban_utopia.txt index a162ca7f0da..605d66f53b5 100644 --- a/forge-gui/res/cardsfolder/upcoming/urban_utopia.txt +++ b/forge-gui/res/cardsfolder/u/urban_utopia.txt @@ -2,7 +2,7 @@ Name:Urban Utopia ManaCost:1 G Types:Enchantment Aura K:Enchant land -A:SP$ Attach | Cost$ G | ValidTgts$ Land | AILogic$ Pump +A:SP$ Attach | Cost$ 1 G | ValidTgts$ Land | AILogic$ Pump T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ FreeCard | TriggerDescription$ When CARDNAME enters the battlefield, draw a card. SVar:FreeCard:DB$ Draw | Defined$ You | NumCards$ 1 S:Mode$ Continuous | Affected$ Card.EnchantedBy | AddAbility$ AbundantGrowthTap | Description$ Enchanted land has "{T}: Add one mana of any color." diff --git a/forge-gui/res/cardsfolder/upcoming/arclight_phoenix.txt b/forge-gui/res/cardsfolder/upcoming/arclight_phoenix.txt deleted file mode 100644 index b0a5aba865d..00000000000 --- a/forge-gui/res/cardsfolder/upcoming/arclight_phoenix.txt +++ /dev/null @@ -1,10 +0,0 @@ -Name:Arclight Phoenix -ManaCost:3 R -Types:Creature Phoenix -PT:3/2 -K:Flying -K:Haste -T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerZones$ Battlefield | CheckSVar$ X | SVarCompare$ GE3 | Execute$ TrigReturn | OptionalDecider$ You | TriggerDescription$ At the beginning of combat on your turn, if you cast 3 or more instand and/or game this turn, you may return CARDNAME to the battlefield. -SVar:TrigReturn:DB$ ChangeZone | Defined$ Self | Origin$ Battlefield | Destination$ Battlefield -SVar:X:Count$ThisTurnCast_Card.Instant.YouCtrl+Sorcery.YouCtrl -Oracle:Flying, Haste\nAt the beginning of combat on your turn, if you cast 3 or more instants and/or sorceries this turn, you may return Arclight Phoenix to the battlefield. diff --git a/forge-gui/res/cardsfolder/upcoming/hitchclaw_recluse.txt b/forge-gui/res/cardsfolder/upcoming/hitchclaw_recluse.txt deleted file mode 100644 index 96575340242..00000000000 --- a/forge-gui/res/cardsfolder/upcoming/hitchclaw_recluse.txt +++ /dev/null @@ -1,6 +0,0 @@ -Name:Hitchclaw Recluse -ManaCost:2 G -Types:Creature Spider -PT:1/4 -K:Reach -Oracle:Reach (This creature can block creatures with flying.) diff --git a/forge-gui/res/cardsfolder/upcoming/ironshell_beetle.txt b/forge-gui/res/cardsfolder/upcoming/ironshell_beetle.txt deleted file mode 100644 index 61ddcf70609..00000000000 --- a/forge-gui/res/cardsfolder/upcoming/ironshell_beetle.txt +++ /dev/null @@ -1,7 +0,0 @@ -Name:Ironshell Beetle -ManaCost:1 G -Types:Creature Insect -PT:1/1 -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPut | TriggerDescription$ When CARDNAME enters the battlefield, put a +1/+1 counter on target creature. -SVar:TrigPut:DB$PutCounter | ValidTgts$ Creature | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ 1 -Oracle:When Ironshell Beetle enters the battlefield, put a +1/+1 counter on target creature. diff --git a/forge-gui/res/cardsfolder/upcoming/might_of_the_masses.txt b/forge-gui/res/cardsfolder/upcoming/might_of_the_masses.txt deleted file mode 100644 index 055663bcfc4..00000000000 --- a/forge-gui/res/cardsfolder/upcoming/might_of_the_masses.txt +++ /dev/null @@ -1,6 +0,0 @@ -Name:Might of the Masses -ManaCost:G -Types:Instant -A:SP$ Pump | Cost$ G | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +X | NumDef$ +X | References$ X | SpellDescription$ Target creature gets +1/+1 until end of turn for each creature you control. -SVar:X:Count$TypeYouCtrl.Creature -Oracle:Target creature gets +1/+1 until end of turn for each creature you control. diff --git a/forge-gui/res/cardsfolder/v/varchild_betrayer_of_kjeldor.txt b/forge-gui/res/cardsfolder/v/varchild_betrayer_of_kjeldor.txt index 667ecd11252..9c248f8890d 100644 --- a/forge-gui/res/cardsfolder/v/varchild_betrayer_of_kjeldor.txt +++ b/forge-gui/res/cardsfolder/v/varchild_betrayer_of_kjeldor.txt @@ -5,8 +5,8 @@ PT:3/3 T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigToken | TriggerDescription$ When CARDNAME deals combat damage to a player, that player creates that many 1/1 red Survivor creature tokens. SVar:TrigToken:DB$ Token | TokenOwner$ TriggeredTarget | TokenAmount$ X | References$ X | TokenName$ Survivor | TokenTypes$ Creature,Survivor | TokenColors$ Red | TokenPower$ 1 | TokenToughness$ 1 | TokenImage$ r 1 1 survivor C18 SVar:X:TriggerCount$DamageAmount -S:Mode$ Continuous | Affected$ Survivor | AddHiddenKeyword$ CantBlock Creature | Description$ Survivors can't block. -S:Mode$ CantAttack | ValidCard$ Creature.Survivor | Target$ You,Planeswalker.YouCtrl | Description$ Survivors your opponent control can't attack you or planeswalkers you control. +S:Mode$ Continuous | Affected$ Survivor.OppCtrl | AddHiddenKeyword$ CantBlock Creature | Description$ Survivors your opponents control can't block. +S:Mode$ CantAttack | ValidCard$ Creature.Survivor+OppCtrl | Target$ You,Planeswalker.YouCtrl | Description$ Survivors your opponents control can't attack you or planeswalkers you control. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ TrigGainControl | TriggerDescription$ When CARDNAME leaves the battlefield, gain control of all Survivors. SVar:TrigGainControl:DB$ GainControl | AllValid$ Survivor | NewController$ You -Oracle:When Varchild, Betrayer of Kjeldor deals combat damage to a player, that player creates that many 1/1 red Survivor creature tokens.\nSurvivors your opponent control can't attack you or planeswalkers you control.\nWhen Varchild, Betrayer of Kjeldor leaves the battlefield, gain control of all Survivors. \ No newline at end of file +Oracle:When Varchild, Betrayer of Kjeldor deals combat damage to a player, that player creates that many 1/1 red Survivor creature tokens.\nSurvivors your opponents control can't block, and they can't attack you or a planeswalker you control.\nWhen Varchild, Betrayer of Kjeldor leaves the battlefield, gain control of all Survivors. diff --git a/forge-gui/res/cardsfolder/upcoming/vedalken_mesmerist.txt b/forge-gui/res/cardsfolder/v/vedalken_mesmerist.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/vedalken_mesmerist.txt rename to forge-gui/res/cardsfolder/v/vedalken_mesmerist.txt diff --git a/forge-gui/res/cardsfolder/upcoming/veiled_shade.txt b/forge-gui/res/cardsfolder/v/veiled_shade.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/veiled_shade.txt rename to forge-gui/res/cardsfolder/v/veiled_shade.txt diff --git a/forge-gui/res/cardsfolder/v/venerated_loxodon.txt b/forge-gui/res/cardsfolder/v/venerated_loxodon.txt new file mode 100644 index 00000000000..09f861fd655 --- /dev/null +++ b/forge-gui/res/cardsfolder/v/venerated_loxodon.txt @@ -0,0 +1,9 @@ +Name:Venerated Loxodon +ManaCost:4 W +Types:Creature Elephant Cleric +PT:4/4 +K:Convoke +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPutCounterAll | TriggerDescription$ When CARDNAME enters the battlefield, put a +1/+1 counter on each creature that convoked it. +SVar:TrigPutCounterAll:DB$ PutCounterAll | ValidCards$ Creature.convoked | CounterType$ P1P1 | CounterNum$ 1 +DeckHas:Ability$Counters +Oracle:Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of the creature's color.)\nWhen Venerated Loxodon enters the battlefield, put a +1/+1 counter on each creature that convoked it. diff --git a/forge-gui/res/cardsfolder/upcoming/vernadi_shieldmate.txt b/forge-gui/res/cardsfolder/v/vernadi_shieldmate.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/vernadi_shieldmate.txt rename to forge-gui/res/cardsfolder/v/vernadi_shieldmate.txt diff --git a/forge-gui/res/cardsfolder/v/vesuvan_doppelganger.txt b/forge-gui/res/cardsfolder/v/vesuvan_doppelganger.txt index 2b6a6aba2b3..5412e1a6616 100644 --- a/forge-gui/res/cardsfolder/v/vesuvan_doppelganger.txt +++ b/forge-gui/res/cardsfolder/v/vesuvan_doppelganger.txt @@ -7,7 +7,7 @@ K:ETBReplacement:Copy:ChooseCreature:Optional SVar:ChooseCreature:DB$ ChooseCard | Defined$ You | Amount$ 1 | Choices$ Creature.Other | SubAbility$ DBCopy | RememberChosen$ True | AILogic$ Clone | SpellDescription$ You may have CARDNAME enter the battlefield as a copy of any creature on the battlefield except it doesn't copy that creature's color and it gains "At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color. If you do, this creature gains this ability." SVar:DBCopy:DB$ Clone | Defined$ Remembered | Colors$ Blue | OverwriteColors$ True | AddTriggers$ VesDopUpkeepTrig | AddSVars$ VesDopCopy,VesDopUpkeepTrig SVar:VesDopUpkeepTrig:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ VesDopCopy | TriggerDescription$ At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color. If you do, this creature gains this ability. -SVar:VesDopCopy:DB$ Clone | ValidTgts$ Creature | TgtPrompt$ Select target creature to copy. | Optional$ True | Colors$ Blue | OverwriteColors$ True | AddTriggers$ VesDopUpkeepTrig | AddSVars$ VesDopCopy,VesDopUpkeepTrig | SubAbility$ DBCleanup +SVar:VesDopCopy:DB$ Clone | ValidTgts$ Creature | TgtPrompt$ Select target creature to copy. | Optional$ True | Colors$ Blue | OverwriteColors$ True | GainThisAbility$ True | SubAbility$ DBCleanup SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/vesuvan_doppelganger.jpg Oracle:You may have Vesuvan Doppelganger enter the battlefield as a copy of any creature on the battlefield except it doesn't copy that creature's color and it gains "At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color. If you do, this creature gains this ability." diff --git a/forge-gui/res/cardsfolder/upcoming/vicious_rumors.txt b/forge-gui/res/cardsfolder/v/vicious_rumors.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/vicious_rumors.txt rename to forge-gui/res/cardsfolder/v/vicious_rumors.txt diff --git a/forge-gui/res/cardsfolder/v/victory_chimes.txt b/forge-gui/res/cardsfolder/v/victory_chimes.txt index 308d832d7cb..f35a0eadea7 100644 --- a/forge-gui/res/cardsfolder/v/victory_chimes.txt +++ b/forge-gui/res/cardsfolder/v/victory_chimes.txt @@ -3,5 +3,5 @@ ManaCost:3 Types:Artifact K:CARDNAME untaps during each other player's untap step. A:AB$ ChoosePlayer | Cost$ T | Defined$ You | Choices$ Player | ChoiceTitle$ Choose an player | SubAbility$ DBMana | SpellDescription$ Choose a player. That player adds one mana of any color they choose. -SVar:DBMana:DB$ Mana | Produced$ Any | Defined$ ChosenPlayer +SVar:DBMana:DB$ Mana | Produced$ C | Defined$ ChosenPlayer Oracle:Untap Victory Chimes during each other player's untap step.\n{T}: A player of your choice adds {C}. diff --git a/forge-gui/res/cardsfolder/upcoming/vigorspore_wurm.txt b/forge-gui/res/cardsfolder/v/vigorspore_wurm.txt similarity index 91% rename from forge-gui/res/cardsfolder/upcoming/vigorspore_wurm.txt rename to forge-gui/res/cardsfolder/v/vigorspore_wurm.txt index 35007ee63e5..8e905664c33 100644 --- a/forge-gui/res/cardsfolder/upcoming/vigorspore_wurm.txt +++ b/forge-gui/res/cardsfolder/v/vigorspore_wurm.txt @@ -4,7 +4,7 @@ Types:Creature Wurm PT:6/4 K:CantBeBlockedByAmount GT1 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Undergrowth - When CARDNAME enters the battlefield, target creature gains vigilance and gets +X/+X until end of turn, where X is the number of creature cards in your graveyard. -SVar:TrigPump:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ X | NumDef$ X | References$ X +SVar:TrigPump:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ X | NumDef$ X | KW$ Vigilance | References$ X SVar:X:Count$TypeInYourYard.Creature SVar:PlayMain1:TRUE Oracle:Undergrowth — When Vigorspore Wurm enters the battlefield, target creature gains vigilance and gets +X/+X until end of turn, where X is the number of creature cards in your graveyard.\nVigorspore Wurm can't be blocked by more than one creature. diff --git a/forge-gui/res/cardsfolder/upcoming/vivid_revival.txt b/forge-gui/res/cardsfolder/v/vivid_revival.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/vivid_revival.txt rename to forge-gui/res/cardsfolder/v/vivid_revival.txt diff --git a/forge-gui/res/cardsfolder/v/viviens_jaguar.txt b/forge-gui/res/cardsfolder/v/viviens_jaguar.txt index 8bd2efacc7a..313d70b0e42 100644 --- a/forge-gui/res/cardsfolder/v/viviens_jaguar.txt +++ b/forge-gui/res/cardsfolder/v/viviens_jaguar.txt @@ -1,7 +1,8 @@ Name:Vivien's Jaguar ManaCost:2 G Types:Creature Cat Spirit +PT:3/2 +K:Reach A:AB$ ChangeZone | Cost$ 2 G | Origin$ Graveyard | Destination$ Hand | ActivationZone$ Graveyard | IsPresent$ Planeswalker.Vivien+YouCtrl | SpellDescription$ Return CARDNAME from your graveyard to your hand. Activate this ability only if you control a Vivien planeswalker. DeckHints:Type$Vivien -Oracle:{2}{G}: Return Vivien’s Jaguar from your graveyard to your hand. Activate this ability only if you control a Vivien planeswalker. -PT:3/2 +Oracle:Reach\n{2}{G}: Return Vivien's Jaguar from your graveyard to your hand. Activate this ability only if you control a Vivien planeswalker. diff --git a/forge-gui/res/cardsfolder/v/vraska_golgari_queen.txt b/forge-gui/res/cardsfolder/v/vraska_golgari_queen.txt new file mode 100644 index 00000000000..2b56a3f83b2 --- /dev/null +++ b/forge-gui/res/cardsfolder/v/vraska_golgari_queen.txt @@ -0,0 +1,13 @@ +Name:Vraska, Golgari Queen +ManaCost:2 B G +Types:Legendary Planeswalker Vraska +Loyalty:4 +A:AB$ Sacrifice | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | SacValid$ Permanent.Other | SacMessage$ another permanent | Optional$ True | RememberSacrificed$ True | SubAbility$ DBGainLife | SpellDescription$ You may sacrifice another permanent. If you do, you gain 1 life and draw a card. +SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1 | SubAbility$ DBDraw | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 +SVar:DBDraw:DB$ Draw | NumCards$ 1 | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +A:AB$ Destroy | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidTgts$ Permanent.nonLand+cmcLE3 | TgtPrompt$ Select target nonland permanent with converted mana cost 3 or less | SpellDescription$ Destroy target nonland permanent with converted mana cost 3 or less. +A:AB$ Effect | Cost$ SubCounter<9/LOYALTY> | Planeswalker$ True | Ultimate$ True | Stackable$ False | Name$ Emblem - Vraska, Golgari Queen | Image$ emblem_vraska_golgari_queen | Triggers$ TrigDamage | SVars$ LoseGame | References$ TrigDamage,LoseGame | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Whenever a creature you control deals combat damage to a player, that player loses the game." +SVar:TrigDamage:Mode$ DamageDone | ValidSource$ Creature.YouCtrl | ValidTarget$ Player | CombatDamage$ True | Execute$ LoseGame | TriggerZones$ Command | TriggerDescription$ Whenever a creature you control deals combat damage to a player, that player loses the game. +SVar:LoseGame:DB$ LosesGame | Defined$ TriggeredTarget +Oracle:[+2]: You may sacrifice another permanent. If you do, you gain 1 life and draw a card.\n[-3]: Destroy target nonland permanent with converted mana cost 3 or less.\n[-9]: You get an emblem with "Whenever a creature you control deals combat damage to a player, that player loses the game." diff --git a/forge-gui/res/cardsfolder/upcoming/vraska_regal_gorgon.txt b/forge-gui/res/cardsfolder/v/vraska_regal_gorgon.txt similarity index 97% rename from forge-gui/res/cardsfolder/upcoming/vraska_regal_gorgon.txt rename to forge-gui/res/cardsfolder/v/vraska_regal_gorgon.txt index af5df6d1ba6..97a352881c4 100644 --- a/forge-gui/res/cardsfolder/upcoming/vraska_regal_gorgon.txt +++ b/forge-gui/res/cardsfolder/v/vraska_regal_gorgon.txt @@ -7,4 +7,5 @@ SVar:DBPump:DB$ Pump | Defined$ Targeted | KW$ Menace A:AB$ Destroy | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | SpellDescription$ Destroy target creature. A:AB$ PutCounterAll | Cost$ SubCounter<10/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidCards$ Creature.YouCtrl | CounterType$ P1P1 | CounterNum$ X | Reference$ X | SpellDescription$ For each creature card in your graveyard, put a +1/+1 counter on each creature you control. SVar:X:Count$ValidGraveyard Creature.YouCtrl +DeckHas:Ability$Counters Oracle:[+2]: Put a +1/+1 counter on up to one target creature. That creature gains menace until end of turn.\n[-3]: Destroy target creature.\n[-10]: For each creature card in your graveyard, put a +1/+1 counter on each creature you control. diff --git a/forge-gui/res/cardsfolder/upcoming/vraskas_stoneglare.txt b/forge-gui/res/cardsfolder/v/vraskas_stoneglare.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/vraskas_stoneglare.txt rename to forge-gui/res/cardsfolder/v/vraskas_stoneglare.txt diff --git a/forge-gui/res/cardsfolder/upcoming/wand_of_vertebrae.txt b/forge-gui/res/cardsfolder/w/wand_of_vertebrae.txt similarity index 96% rename from forge-gui/res/cardsfolder/upcoming/wand_of_vertebrae.txt rename to forge-gui/res/cardsfolder/w/wand_of_vertebrae.txt index f110a982d8d..bea9f97917b 100644 --- a/forge-gui/res/cardsfolder/upcoming/wand_of_vertebrae.txt +++ b/forge-gui/res/cardsfolder/w/wand_of_vertebrae.txt @@ -3,4 +3,5 @@ ManaCost:1 Types:Artifact A:AB$ Mill | Cost$ T | Defined$ You | NumCards$ 1 | SpellDescription$ Put the top card of your library into your graveyard. A:AB$ ChangeZone | Cost$ 2 T Exile<1/CARDNAME> | Origin$ Graveyard | Destination$ Library | TargetMin$ 0 | TargetMax$ 5 | Shuffle$ True | TgtPrompt$ Select target card in your graveyard | ValidTgts$ Card.YouCtrl | SpellDescription$ Shuffle up to five target cards from your graveyard into your library. +DeckHas:Ability$Graveyard Oracle:{T}: Put the top card of your library into your graveyard.\n{2}, {T}, Exile Wand of Vertebrae: Shuffle up to five target cards from your graveyard into your library. diff --git a/forge-gui/res/cardsfolder/upcoming/wary_okapi.txt b/forge-gui/res/cardsfolder/w/wary_okapi.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/wary_okapi.txt rename to forge-gui/res/cardsfolder/w/wary_okapi.txt diff --git a/forge-gui/res/cardsfolder/upcoming/watcher_in_the_mist.txt b/forge-gui/res/cardsfolder/w/watcher_in_the_mist.txt similarity index 93% rename from forge-gui/res/cardsfolder/upcoming/watcher_in_the_mist.txt rename to forge-gui/res/cardsfolder/w/watcher_in_the_mist.txt index ba3f6aa313e..e2caac36008 100644 --- a/forge-gui/res/cardsfolder/upcoming/watcher_in_the_mist.txt +++ b/forge-gui/res/cardsfolder/w/watcher_in_the_mist.txt @@ -5,4 +5,5 @@ PT:3/4 K:Flying T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSurveil | TriggerDescription$ When CARDNAME enters the battlefield, surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on the top of your library in any order.) SVar:TrigSurveil:DB$ Surveil | Defined$ You | Amount$ 2 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Flying\nWhen Watcher in the Mist enters the battlefield, surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on the top of your library in any order.) diff --git a/forge-gui/res/cardsfolder/w/weathered_wayfarer.txt b/forge-gui/res/cardsfolder/w/weathered_wayfarer.txt index aee88cebe0f..4d06df624fc 100644 --- a/forge-gui/res/cardsfolder/w/weathered_wayfarer.txt +++ b/forge-gui/res/cardsfolder/w/weathered_wayfarer.txt @@ -2,7 +2,8 @@ Name:Weathered Wayfarer ManaCost:W Types:Creature Human Nomad Cleric PT:1/1 -A:AB$ ChangeZone | Cost$ W T | Origin$ Library | Destination$ Hand | ChangeType$ Land | ChangeNum$ 1 | IsPresent$ Land.OppCtrl | PresentCompare$ GTX | References$ X | SpellDescription$ Search your library for a land card, reveal it, put it into your hand, then shuffle your library. Activate this ability only if an opponent controls more lands than you. -SVar:X:Count$Valid Land.YouCtrl +A:AB$ ChangeZone | Cost$ W T | Origin$ Library | Destination$ Hand | ChangeType$ Land | ChangeNum$ 1 | CheckSVar$ X | SVarCompare$ GTY | References$ X,Y | SpellDescription$ Search your library for a land card, reveal it, put it into your hand, then shuffle your library. Activate this ability only if an opponent controls more lands than you. +SVar:X:PlayerCountOpponents$HighestValid Land.YouCtrl +SVar:Y:Count$Valid Land.YouCtrl SVar:Picture:http://resources.wizards.com/magic/cards/9ed/en-us/card83311.jpg Oracle:{W}, {T}: Search your library for a land card, reveal it, put it into your hand, then shuffle your library. Activate this ability only if an opponent controls more lands than you. diff --git a/forge-gui/res/cardsfolder/w/wee_dragonauts.txt b/forge-gui/res/cardsfolder/w/wee_dragonauts.txt index 029b30cf7d6..ca007c6b11c 100644 --- a/forge-gui/res/cardsfolder/w/wee_dragonauts.txt +++ b/forge-gui/res/cardsfolder/w/wee_dragonauts.txt @@ -6,5 +6,6 @@ K:Flying T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever you cast an instant or sorcery spell, CARDNAME gets +2/+0 until end of turn. SVar:TrigPump:DB$Pump | Defined$ Self | NumAtt$ 2 SVar:BuffedBy:Instant,Sorcery +DeckHints:Type$Instant|Sorcery SVar:Picture:http://www.wizards.com/global/images/magic/general/wee_dragonauts.jpg Oracle:Flying\nWhenever you cast an instant or sorcery spell, Wee Dragonauts gets +2/+0 until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/whisper_agent.txt b/forge-gui/res/cardsfolder/w/whisper_agent.txt similarity index 92% rename from forge-gui/res/cardsfolder/upcoming/whisper_agent.txt rename to forge-gui/res/cardsfolder/w/whisper_agent.txt index b681e45523c..8ed6266614a 100644 --- a/forge-gui/res/cardsfolder/upcoming/whisper_agent.txt +++ b/forge-gui/res/cardsfolder/w/whisper_agent.txt @@ -5,4 +5,5 @@ PT:3/2 K:Flash T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSurveil | TriggerDescription$ When CARDNAME enters the battlefield, surveil 1. (Look at the top card of your library. You may put it into your graveyard.) SVar:TrigSurveil:DB$ Surveil | Amount$ 1 +DeckHas:Ability$Surveil & Ability$Graveyard Oracle:Flash\nWhen Whisper Agent enters the battlefield, surveil 1. (Look at the top card of your library. You may put it into your graveyard.) diff --git a/forge-gui/res/cardsfolder/upcoming/whispering_snitch.txt b/forge-gui/res/cardsfolder/w/whispering_snitch.txt similarity index 58% rename from forge-gui/res/cardsfolder/upcoming/whispering_snitch.txt rename to forge-gui/res/cardsfolder/w/whispering_snitch.txt index 68021e7e6b1..3ae5c96b86e 100644 --- a/forge-gui/res/cardsfolder/upcoming/whispering_snitch.txt +++ b/forge-gui/res/cardsfolder/w/whispering_snitch.txt @@ -2,9 +2,9 @@ Name:Whispering Snitch ManaCost:1 B Types:Creature Vampire Rogue PT:1/3 -T:Mode$ Surveil | ValidCard$ You | TriggerZones$ Battlefield | OnlyFirst$ True | Execute$ TrigDamageAll | TriggerDescription$ Whenever you surveil for the first time each turn, CARDNAME deals 1 damage to each opponent and you gain 1 life. +T:Mode$ Surveil | ValidPlayer$ You | TriggerZones$ Battlefield | OnlyFirst$ True | Execute$ TrigDamageAll | TriggerDescription$ Whenever you surveil for the first time each turn, CARDNAME deals 1 damage to each opponent and you gain 1 life. SVar:TrigDamageAll:DB$ DamageAll | ValidPlayers$ Player.Opponent | NumDmg$ 1 | SubAbility$ DBGainLife SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1 -SVar:X:Count$YouSurveilThisTurn +DeckNeeds:Ability$Surveil DeckHas:Ability$LifeGain Oracle:Whenever you surveil for the first time each turn, Whispering Snitch deals 1 damage to each opponent and you gain 1 life. diff --git a/forge-gui/res/cardsfolder/upcoming/wild_ceratok.txt b/forge-gui/res/cardsfolder/w/wild_ceratok.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/wild_ceratok.txt rename to forge-gui/res/cardsfolder/w/wild_ceratok.txt diff --git a/forge-gui/res/cardsfolder/upcoming/wishcoin_crab.txt b/forge-gui/res/cardsfolder/w/wishcoin_crab.txt similarity index 100% rename from forge-gui/res/cardsfolder/upcoming/wishcoin_crab.txt rename to forge-gui/res/cardsfolder/w/wishcoin_crab.txt diff --git a/forge-gui/res/cardsfolder/upcoming/wojek_bodyguard.txt b/forge-gui/res/cardsfolder/w/wojek_bodyguard.txt similarity index 91% rename from forge-gui/res/cardsfolder/upcoming/wojek_bodyguard.txt rename to forge-gui/res/cardsfolder/w/wojek_bodyguard.txt index 99a850f5738..10290fc1976 100644 --- a/forge-gui/res/cardsfolder/upcoming/wojek_bodyguard.txt +++ b/forge-gui/res/cardsfolder/w/wojek_bodyguard.txt @@ -4,4 +4,5 @@ Types:Creature Human Soldier PT:3/3 K:Mentor K:CARDNAME can't attack or block alone. +DeckHas:Ability$Counters Oracle:Mentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.)\nWojek Bodyguard can't attack or block alone. diff --git a/forge-gui/res/cardsfolder/upcoming/worldsoul_colossus.txt b/forge-gui/res/cardsfolder/w/worldsoul_colossus.txt similarity index 93% rename from forge-gui/res/cardsfolder/upcoming/worldsoul_colossus.txt rename to forge-gui/res/cardsfolder/w/worldsoul_colossus.txt index 65cc976eb40..959f30246da 100644 --- a/forge-gui/res/cardsfolder/upcoming/worldsoul_colossus.txt +++ b/forge-gui/res/cardsfolder/w/worldsoul_colossus.txt @@ -5,4 +5,5 @@ PT:0/0 K:Convoke K:etbCounter:P1P1:X SVar:X:Count$xPaid +DeckHas:Ability$Counters Oracle:Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)\nWorldsoul Colossus enters the battlefield with X +1/+1 counters on it. diff --git a/forge-gui/res/deckgendecks/Standard.lda.dat b/forge-gui/res/deckgendecks/Standard.lda.dat index 5f6c6702cd4..26d6b00cc93 100644 Binary files a/forge-gui/res/deckgendecks/Standard.lda.dat and b/forge-gui/res/deckgendecks/Standard.lda.dat differ diff --git a/forge-gui/res/deckgendecks/Standard.raw.dat b/forge-gui/res/deckgendecks/Standard.raw.dat index 64f646413ad..5f937ee7bee 100644 Binary files a/forge-gui/res/deckgendecks/Standard.raw.dat and b/forge-gui/res/deckgendecks/Standard.raw.dat differ diff --git a/forge-gui/res/draft/rankings.txt b/forge-gui/res/draft/rankings.txt index f5db72c1884..da3b4448a9d 100644 --- a/forge-gui/res/draft/rankings.txt +++ b/forge-gui/res/draft/rankings.txt @@ -3,256 +3,251 @@ #2|Aurelia, Exemplar of Justice|M|GRN #3|Light of the Legion|R|GRN #4|Dream Eater|M|GRN -#5|March of the Multitudes|M|GRN +#5|Izoni, Thousand-Eyed|R|GRN #6|Vraska, Golgari Queen|M|GRN -#7|Assassin's Trophy|R|GRN -#8|Underrealm Lich|M|GRN -#9|Niv-Mizzet, Parun|R|GRN -#10|Trostani Discordant|M|GRN +#7|Niv-Mizzet, Parun|R|GRN +#8|Assassin's Trophy|R|GRN +#9|Trostani Discordant|M|GRN +#10|Underrealm Lich|M|GRN #11|Status Statue|U|GRN -#12|Price of Fame|U|GRN -#13|Conclave Tribunal|U|GRN -#14|Izoni, Thousand-Eyed|R|GRN -#15|Lava Coil|U|GRN -#16|Dawn of Hope|R|GRN -#17|Legion Warboss|R|GRN -#18|Find|R|GRN -#19|Integrity Intervention|U|GRN -#20|Justice Strike|U|GRN -#21|Tajic, Legion's Edge|R|GRN -#22|Pelt Collector|R|GRN -#23|Ral, Izzet Viceroy|M|GRN -#24|Emmara, Soul of the Accord|R|GRN -#25|Swiftblade Vindicator|R|GRN -#26|Assure|R|GRN -#27|Chamber Sentry|R|GRN -#28|Bounty of Might|R|GRN -#29|Nightveil Predator|U|GRN -#30|Venerated Loxodon|R|GRN +#12|Find Finality|R|GRN +#13|March of the Multitudes|M|GRN +#14|Price of Fame|U|GRN +#15|Conclave Tribunal|U|GRN +#16|Nullhide Ferox|M|GRN +#17|Tajic, Legion's Edge|R|GRN +#18|Ral, Izzet Viceroy|M|GRN +#19|Lava Coil|U|GRN +#20|Integrity Intervention|U|GRN +#21|Dawn of Hope|R|GRN +#22|Legion Warboss|R|GRN +#23|Venerated Loxodon|R|GRN +#24|Justice Strike|U|GRN +#25|Pelt Collector|R|GRN +#26|Swiftblade Vindicator|R|GRN +#27|Assure Assemble|R|GRN +#28|Chamber Sentry|R|GRN +#29|Bounty of Might|R|GRN +#30|Nightveil Predator|U|GRN #31|Crackling Drake|U|GRN #32|Etrata, the Silencer|R|GRN -#33|Nullhide Ferox|M|GRN -#34|Golgari Findbroker|U|GRN -#35|Knight of Autumn|R|GRN -#36|Conclave Cavalier|U|GRN -#37|Thief of Sanity|R|GRN -#38|Response|R|GRN -#39|Deafening Clarion|R|GRN -#40|Truefire Captain|U|GRN -#41|Deadly Visit|C|GRN -#42|Midnight Reaper|R|GRN -#43|Lazav, the Multifarious|M|GRN -#44|Boros Challenger|U|GRN -#45|Ritual of Soot|R|GRN -#46|Rampaging Monument|U|GRN -#47|Luminous Bonds|C|GRN -#48|Chemister's Insight|U|GRN -#49|Artful Takedown|C|GRN -#50|Beast Whisperer|R|GRN -#51|Expansion|R|GRN -#52|Affectionate Indrik|U|GRN -#53|Connive|R|GRN -#54|Hatchery Spider|R|GRN -#55|Charnel Troll|R|GRN -#56|Rosemane Centaur|C|GRN -#57|Hypothesizzle|C|GRN -#58|Arclight Phoenix|M|GRN -#59|Swarm Guildmage|U|GRN -#60|House Guildmage|U|GRN -#61|League Guildmage|U|GRN -#62|Legion Guildmage|U|GRN -#63|Glowspore Shaman|U|GRN -#64|Wee Dragonauts|U|GRN -#65|Kraul Harpooner|U|GRN -#66|Gravitic Punch|C|GRN -#67|Dead Weight|C|GRN -#68|District Guide|U|GRN -#69|Command the Storm|C|GRN -#70|Inescapable Blaze|U|GRN -#71|Conclave Guildmage|U|GRN -#72|Ledev Champion|U|GRN -#73|Discovery|U|GRN -#74|Roc Charger|U|GRN -#75|Citywide Bust|R|GRN -#76|Plaguecrafter|U|GRN -#77|Camaraderie|R|GRN -#78|Hired Poisoner|C|GRN -#79|Capture Sphere|C|GRN -#80|Firemind's Research|R|GRN -#81|Quasiduplicate|R|GRN -#82|Arboretum Elemental|U|GRN -#83|Unexplained Disappearance|C|GRN -#84|Sunhome Stalwart|U|GRN -#85|Chromatic Lantern|R|GRN -#86|Goblin Cratermaker|U|GRN -#87|Notion Rain|C|GRN -#88|Invert|U|GRN +#33|Emmara, Soul of the Accord|R|GRN +#34|Beast Whisperer|R|GRN +#35|Golgari Findbroker|U|GRN +#36|Knight of Autumn|R|GRN +#37|Blood Operative|R|GRN +#38|Conclave Cavalier|U|GRN +#39|Thief of Sanity|R|GRN +#40|Charnel Troll|R|GRN +#41|Deafening Clarion|R|GRN +#42|Truefire Captain|U|GRN +#43|Connive Concoct|R|GRN +#44|Hatchery Spider|R|GRN +#45|Quasiduplicate|R|GRN +#46|Response Resurgence|R|GRN +#47|Arclight Phoenix|M|GRN +#48|Midnight Reaper|R|GRN +#49|Lazav, the Multifarious|M|GRN +#50|Ritual of Soot|R|GRN +#51|Boros Challenger|U|GRN +#52|Deadly Visit|C|GRN +#53|Roc Charger|U|GRN +#54|Rampaging Monument|U|GRN +#55|Luminous Bonds|C|GRN +#56|Artful Takedown|C|GRN +#57|Expansion Explosion|R|GRN +#58|Murmuring Mystic|U|GRN +#59|Nightveil Sprite|U|GRN +#60|Swarm Guildmage|U|GRN +#61|House Guildmage|U|GRN +#62|League Guildmage|U|GRN +#63|Legion Guildmage|U|GRN +#64|Glowspore Shaman|U|GRN +#65|Disinformation Campaign|U|GRN +#66|Wee Dragonauts|U|GRN +#67|Discovery Dispersal|U|GRN +#68|Kraul Harpooner|U|GRN +#69|Flower Flourish|U|GRN +#70|Dead Weight|C|GRN +#71|Rosemane Centaur|C|GRN +#72|Hypothesizzle|C|GRN +#73|District Guide|U|GRN +#74|Chemister's Insight|U|GRN +#75|Command the Storm|C|GRN +#76|Inescapable Blaze|U|GRN +#77|Invert Invent|U|GRN +#78|Conclave Guildmage|U|GRN +#79|Affectionate Indrik|U|GRN +#80|Dimir Spybug|U|GRN +#81|Citywide Bust|R|GRN +#82|Plaguecrafter|U|GRN +#83|Camaraderie|R|GRN +#84|Capture Sphere|C|GRN +#85|Firemind's Research|R|GRN +#86|Arboretum Elemental|U|GRN +#87|Sunhome Stalwart|U|GRN +#88|Goblin Cratermaker|U|GRN #89|Erratic Cyclops|R|GRN #90|Citywatch Sphinx|U|GRN #91|Skyknight Legionnaire|C|GRN #92|Watcher in the Mist|C|GRN -#93|Dimir Spybug|U|GRN -#94|Siege Wurm|C|GRN -#95|Risk Factor|R|GRN -#96|Flower|U|GRN -#97|Inspiring Unicorn|U|GRN -#98|Prey Upon|C|GRN -#99|Severed Strands|C|GRN -#100|Kraul Swarm|U|GRN -#101|Demotion|U|GRN -#102|Murmuring Mystic|U|GRN -#103|Healer's Hawk|C|GRN -#104|Direct Current|C|GRN -#105|Nightveil Sprite|U|GRN -#106|Darkblade Agent|C|GRN -#107|Blood Operative|R|GRN -#108|Swathcutter Giant|U|GRN -#109|Loxodon Restorer|C|GRN -#110|Sprouting Renewal|U|GRN -#111|Beacon Bolt|U|GRN -#112|Undercity Uprising|C|GRN -#113|Flight of Equenauts|U|GRN -#114|Experimental Frenzy|R|GRN -#115|Undercity Necrolisk|U|GRN -#116|Selective Snare|U|GRN -#117|Collar the Culprit|C|GRN -#118|Sacred Foundry|R|GRN -#119|Watery Grave|R|GRN -#120|Temple Garden|R|GRN -#121|Overgrown Tomb|R|GRN -#122|Steam Vents|R|GRN -#123|Dimir Informant|C|GRN -#124|Runaway Steam-Kin|R|GRN -#125|Ionize|R|GRN -#126|Garrison Sergeant|C|GRN -#127|Hunted Witness|C|GRN -#128|Disinformation Campaign|U|GRN -#129|Piston-Fist Cyclops|C|GRN -#130|Parhelion Patrol|C|GRN -#131|Join Shields|U|GRN -#132|Gird for Battle|U|GRN -#133|Gatekeeper Gargoyle|U|GRN -#134|Drowned Secrets|R|GRN -#135|Hellkite Whelp|U|GRN -#136|Spinal Centipede|C|GRN -#137|Burglar Rat|C|GRN -#138|Righteous Blow|C|GRN -#139|Golgari Guildgate|C|GRN -#140|Izzet Guildgate|C|GRN -#141|Selesnya Guildgate|C|GRN -#142|Dimir Guildgate|C|GRN -#143|Boros Guildgate|C|GRN -#144|Thought Erasure|U|GRN -#145|Necrotic Wound|U|GRN -#146|Guild Summit|U|GRN -#147|Whispering Snitch|U|GRN -#148|Vivid Revival|R|GRN -#149|Guildmages' Forum|R|GRN -#150|Molderhulk|U|GRN -#151|Gruesome Menagerie|R|GRN -#152|Centaur Peacemaker|C|GRN -#153|Thoughtbound Phantasm|U|GRN -#154|Ochran Assassin|U|GRN -#155|Circuitous Route|U|GRN -#156|Lotleth Giant|U|GRN -#157|Book Devourer|U|GRN -#158|Worldsoul Colossus|U|GRN -#159|Haazda Marshal|U|GRN -#160|Erstwhile Trooper|C|GRN -#161|Might of the Masses|U|GRN -#162|Wild Ceratok|C|GRN -#163|Ironshell Beetle|C|GRN -#164|Smelt-Ward Minotaur|U|GRN -#165|Cosmotronic Wave|C|GRN -#166|Douser of Lights|C|GRN -#167|Sworn Companions|C|GRN -#168|Intrusive Packbeast|C|GRN -#169|Sinister Sabotage|U|GRN -#170|Barging Sergeant|C|GRN -#171|Hammer Dropper|C|GRN -#172|Goblin Electromancer|C|GRN -#173|Sumala Woodshaper|C|GRN -#174|Bounty Agent|R|GRN -#175|Blade Instructor|C|GRN -#176|Gateway Plaza|C|GRN -#177|Disdainful Stroke|C|GRN -#178|Goblin Banneret|U|GRN -#179|Wojek Bodyguard|C|GRN -#180|Enhanced Surveillance|U|GRN -#181|Ledev Guardian|C|GRN -#182|Beamsplitter Mage|U|GRN -#183|Generous Stray|C|GRN -#184|Vernadi Shieldmate|C|GRN -#185|Pitiless Gorgon|C|GRN -#186|Vigorspore Wurm|C|GRN -#187|Pack's Favor|C|GRN -#188|Hitchclaw Recluse|C|GRN -#189|Sure Strike|C|GRN -#190|Rubblebelt Boar|C|GRN -#191|Ornery Goblin|C|GRN -#192|Fire Urchin|C|GRN -#193|Pilfering Imp|U|GRN -#194|Bartizan Bats|C|GRN -#195|Vedalken Mesmerist|C|GRN -#196|Muse Drake|C|GRN -#197|Leapfrog|C|GRN -#198|Skyline Scout|C|GRN -#199|Radical Idea|C|GRN -#200|Moodmark Painter|C|GRN -#201|Fresh-Faced Recruit|C|GRN -#202|Whisper Agent|C|GRN -#203|Golgari Raiders|U|GRN -#204|Mission Briefing|R|GRN -#205|Chance for Glory|M|GRN -#206|Kraul Foragers|C|GRN -#207|Rhizome Lurcher|C|GRN -#208|Electrostatic Field|U|GRN -#209|Street Riot|U|GRN -#210|Fearless Halberdier|C|GRN -#211|Veiled Shade|C|GRN -#212|Child of Night|C|GRN -#213|Wishcoin Crab|C|GRN -#214|Tenth District Guard|C|GRN -#215|Take Heart|C|GRN -#216|Devkarin Dissident|C|GRN -#217|Narcomoeba|R|GRN -#218|Sonic Assault|C|GRN -#219|Wary Okapi|C|GRN -#220|Izzet Locket|C|GRN -#221|Selesnya Locket|C|GRN -#222|Golgari Locket|C|GRN -#223|Dimir Locket|C|GRN -#224|Boros Locket|C|GRN -#225|Passwall Adept|C|GRN -#226|Omnispell Adept|R|GRN -#227|Wand of Vertebrae|U|GRN -#228|Divine Visitation|M|GRN -#229|Mnemonic Betrayal|M|GRN -#230|Urban Utopia|C|GRN -#231|Wall of Mist|C|GRN -#232|Dazzling Lights|C|GRN -#233|Candlelight Vigil|C|GRN -#234|Mausoleum Secrets|R|GRN -#235|Glaive of the Guildpact|U|GRN -#236|Maximize Velocity|C|GRN -#237|Goblin Locksmith|C|GRN -#238|Grappling Sundew|U|GRN -#239|Crushing Canopy|C|GRN -#240|Torch Courier|C|GRN -#241|Maximize Altitude|C|GRN -#242|Never Happened|C|GRN -#243|Thousand-Year Storm|M|GRN -#244|Silent Dart|U|GRN -#245|Portcullis Vine|C|GRN -#246|Mephitic Vapors|C|GRN -#247|Crush Contraband|U|GRN -#248|Barrier of Bones|C|GRN -#249|Devious Cover-Up|C|GRN -#250|Maniacal Rage|C|GRN -#251|Pause for Reflection|C|GRN -#252|Vicious Rumors|C|GRN -#253|Creeping Chill|U|GRN -#254|Unmoored Ego|R|GRN +#93|Siege Wurm|C|GRN +#94|Risk Factor|R|GRN +#95|Kraul Swarm|U|GRN +#96|Demotion|U|GRN +#97|Healer's Hawk|C|GRN +#98|Direct Current|C|GRN +#99|Unexplained Disappearance|C|GRN +#100|Whisper Agent|C|GRN +#101|Notion Rain|C|GRN +#102|Ledev Champion|U|GRN +#103|Beacon Bolt|U|GRN +#104|Flight of Equenauts|U|GRN +#105|Experimental Frenzy|R|GRN +#106|Inspiring Unicorn|U|GRN +#107|Prey Upon|C|GRN +#108|Severed Strands|C|GRN +#109|Hired Poisoner|C|GRN +#110|Selective Snare|U|GRN +#111|Sacred Foundry|R|GRN +#112|Watery Grave|R|GRN +#113|Temple Garden|R|GRN +#114|Overgrown Tomb|R|GRN +#115|Steam Vents|R|GRN +#116|Chromatic Lantern|R|GRN +#117|Runaway Steam-Kin|R|GRN +#118|Ionize|R|GRN +#119|Whispering Snitch|U|GRN +#120|Goblin Banneret|U|GRN +#121|Thoughtbound Phantasm|U|GRN +#122|Swathcutter Giant|U|GRN +#123|Hunted Witness|C|GRN +#124|Enhanced Surveillance|U|GRN +#125|Piston-Fist Cyclops|C|GRN +#126|Parhelion Patrol|C|GRN +#127|Gird for Battle|U|GRN +#128|Undercity Uprising|C|GRN +#129|Gatekeeper Gargoyle|U|GRN +#130|Hellkite Whelp|U|GRN +#131|Undercity Necrolisk|U|GRN +#132|Spinal Centipede|C|GRN +#133|Burglar Rat|C|GRN +#134|Collar the Culprit|C|GRN +#135|Thought Erasure|U|GRN +#136|Necrotic Wound|U|GRN +#137|Hammer Dropper|C|GRN +#138|Dimir Informant|C|GRN +#139|Guild Summit|U|GRN +#140|Vivid Revival|R|GRN +#141|Guildmages' Forum|R|GRN +#142|Molderhulk|U|GRN +#143|Gruesome Menagerie|R|GRN +#144|Centaur Peacemaker|C|GRN +#145|Darkblade Agent|C|GRN +#146|Wojek Bodyguard|C|GRN +#147|Ochran Assassin|U|GRN +#148|Circuitous Route|U|GRN +#149|Loxodon Restorer|C|GRN +#150|Haazda Marshal|U|GRN +#151|Rhizome Lurcher|C|GRN +#152|Might of the Masses|U|GRN +#153|Generous Stray|C|GRN +#154|Wild Ceratok|C|GRN +#155|Ironshell Beetle|C|GRN +#156|Smelt-Ward Minotaur|U|GRN +#157|Rubblebelt Boar|C|GRN +#158|Cosmotronic Wave|C|GRN +#159|Muse Drake|C|GRN +#160|Sworn Companions|C|GRN +#161|Skyline Scout|C|GRN +#162|Righteous Blow|C|GRN +#163|Intrusive Packbeast|C|GRN +#164|Sinister Sabotage|U|GRN +#165|Barging Sergeant|C|GRN +#166|Sonic Assault|C|GRN +#167|Goblin Electromancer|C|GRN +#168|Sumala Woodshaper|C|GRN +#169|Fresh-Faced Recruit|C|GRN +#170|Bounty Agent|R|GRN +#171|Blade Instructor|C|GRN +#172|Gateway Plaza|C|GRN +#173|Disdainful Stroke|C|GRN +#174|Mission Briefing|R|GRN +#175|Lotleth Giant|U|GRN +#176|Book Devourer|U|GRN +#177|Sprouting Renewal|U|GRN +#178|Worldsoul Colossus|U|GRN +#179|Beamsplitter Mage|U|GRN +#180|Vernadi Shieldmate|C|GRN +#181|Pitiless Gorgon|C|GRN +#182|Vigorspore Wurm|C|GRN +#183|Pack's Favor|C|GRN +#184|Hitchclaw Recluse|C|GRN +#185|Sure Strike|C|GRN +#186|Fire Urchin|C|GRN +#187|Pilfering Imp|U|GRN +#188|Douser of Lights|C|GRN +#189|Bartizan Bats|C|GRN +#190|Leapfrog|C|GRN +#191|Take Heart|C|GRN +#192|Devkarin Dissident|C|GRN +#193|Radical Idea|C|GRN +#194|Golgari Raiders|U|GRN +#195|Ledev Guardian|C|GRN +#196|Chance for Glory|M|GRN +#197|Kraul Foragers|C|GRN +#198|Erstwhile Trooper|C|GRN +#199|Street Riot|U|GRN +#200|Ornery Goblin|C|GRN +#201|Gravitic Punch|C|GRN +#202|Child of Night|C|GRN +#203|Dazzling Lights|C|GRN +#204|Tenth District Guard|C|GRN +#205|Moodmark Painter|C|GRN +#206|Izzet Locket|C|GRN +#207|Selesnya Locket|C|GRN +#208|Golgari Locket|C|GRN +#209|Dimir Locket|C|GRN +#210|Boros Locket|C|GRN +#211|Maximize Altitude|C|GRN +#212|Passwall Adept|C|GRN +#213|Garrison Sergeant|C|GRN +#214|Omnispell Adept|R|GRN +#215|Join Shields|U|GRN +#216|Mnemonic Betrayal|M|GRN +#217|Electrostatic Field|U|GRN +#218|Urban Utopia|C|GRN +#219|Portcullis Vine|C|GRN +#220|Fearless Halberdier|C|GRN +#221|Veiled Shade|C|GRN +#222|Vedalken Mesmerist|C|GRN +#223|Wary Okapi|C|GRN +#224|Mausoleum Secrets|R|GRN +#225|Glaive of the Guildpact|U|GRN +#226|Maximize Velocity|C|GRN +#227|Divine Visitation|M|GRN +#228|Devious Cover-Up|C|GRN +#229|Goblin Locksmith|C|GRN +#230|Drowned Secrets|R|GRN +#231|Grappling Sundew|U|GRN +#232|Crushing Canopy|C|GRN +#233|Maniacal Rage|C|GRN +#234|Mephitic Vapors|C|GRN +#235|Wishcoin Crab|C|GRN +#236|Wall of Mist|C|GRN +#237|Candlelight Vigil|C|GRN +#238|Narcomoeba|R|GRN +#239|Never Happened|C|GRN +#240|Thousand-Year Storm|M|GRN +#241|Silent Dart|U|GRN +#242|Torch Courier|C|GRN +#243|Barrier of Bones|C|GRN +#244|Crush Contraband|U|GRN +#245|Wand of Vertebrae|U|GRN +#246|Creeping Chill|U|GRN +#247|Pause for Reflection|C|GRN +#248|Vicious Rumors|C|GRN +#249|Unmoored Ego|R|GRN //Rank|Name|Rarity|Set #1|Chromium, the Mutable|M|M19 #2|Palladia-Mors, the Ruiner|M|M19 diff --git a/forge-gui/res/formats/Casual/Brawl.txt b/forge-gui/res/formats/Casual/Brawl.txt index 84972f54ee9..8a2125573a6 100644 --- a/forge-gui/res/formats/Casual/Brawl.txt +++ b/forge-gui/res/formats/Casual/Brawl.txt @@ -3,5 +3,5 @@ Name:Brawl Order:101 Type:Casual Subtype:Commander -Sets:KLD, AER, AKH, W17, HOU, XLN, RIX, DOM, M19 -Banned:Baral, Chief of Compliance;Smuggler's Copter;Sorcerous Spyglass \ No newline at end of file +Sets:XLN, RIX, DOM, M19, GRN +Banned:Sorcerous Spyglass \ No newline at end of file diff --git a/forge-gui/res/formats/Sanctioned/Legacy.txt b/forge-gui/res/formats/Sanctioned/Legacy.txt index c2856eda962..08eda419476 100644 --- a/forge-gui/res/formats/Sanctioned/Legacy.txt +++ b/forge-gui/res/formats/Sanctioned/Legacy.txt @@ -3,4 +3,4 @@ Name:Legacy Order:105 Subtype:Legacy Type:Sanctioned -Banned:Adriana's Valor; Advantageous Proclamation; Assemble the Rank and Vile; Backup Plan; Brago's Favor; Double Stroke; Echoing Boon; Emissary's Ploy; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Incendiary Dissent; Iterative Analysis; Muzzio's Preparations; Natural Unity; Power Play; Secret Summoning; Secrets of Paradise; Sentinel Dispatch; Sovereign's Realm; Summoner's Bond; Unexpected Potential; Weight Advantage; Worldknit; Amulet of Quoz; Bronze Tablet; Contract from Below; Darkpact; Demonic Attorney; Jeweled Bird; Rebirth; Tempest Efreet; Timmerian Fiends; Ancestral Recall; Balance; Bazaar of Baghdad; Black Lotus; Channel; Chaos Orb; Demonic Consultation; Demonic Tutor; Dig Through Time; Earthcraft; Falling Star; Fastbond; Flash; Frantic Search; Goblin Recruiter; Gush; Hermit Druid; Imperial Seal; Library of Alexandria; Mana Crypt; Mana Drain; Mana Vault; Memory Jar; Mental Misstep; Mind Twist; Mind's Desire; Mishra's Workshop; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Mystical Tutor; Necropotence; Oath of Druids; Sensei's Divining Top; Shahrazad; Skullclamp; Sol Ring; Strip Mine; Survival of the Fittest; Time Vault; Time Walk; Timetwister; Tinker; Tolarian Academy; Treasure Cruise; Vampiric Tutor; Wheel of Fortune; Windfall; Yawgmoth's Bargain; Yawgmoth's Will +Banned:Adriana's Valor; Advantageous Proclamation; Assemble the Rank and Vile; Backup Plan; Brago's Favor; Deathrite Shaman; Double Stroke; Echoing Boon; Emissary's Ploy; Gitaxian Probe; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Incendiary Dissent; Iterative Analysis; Muzzio's Preparations; Natural Unity; Power Play; Secret Summoning; Secrets of Paradise; Sentinel Dispatch; Sovereign's Realm; Summoner's Bond; Unexpected Potential; Weight Advantage; Worldknit; Amulet of Quoz; Bronze Tablet; Contract from Below; Darkpact; Demonic Attorney; Jeweled Bird; Rebirth; Tempest Efreet; Timmerian Fiends; Ancestral Recall; Balance; Bazaar of Baghdad; Black Lotus; Channel; Chaos Orb; Demonic Consultation; Demonic Tutor; Dig Through Time; Earthcraft; Falling Star; Fastbond; Flash; Frantic Search; Goblin Recruiter; Gush; Hermit Druid; Imperial Seal; Library of Alexandria; Mana Crypt; Mana Drain; Mana Vault; Memory Jar; Mental Misstep; Mind Twist; Mind's Desire; Mishra's Workshop; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Mystical Tutor; Necropotence; Oath of Druids; Sensei's Divining Top; Shahrazad; Skullclamp; Sol Ring; Strip Mine; Survival of the Fittest; Time Vault; Time Walk; Timetwister; Tinker; Tolarian Academy; Treasure Cruise; Vampiric Tutor; Wheel of Fortune; Windfall; Yawgmoth's Bargain; Yawgmoth's Will diff --git a/forge-gui/res/formats/Sanctioned/Modern.txt b/forge-gui/res/formats/Sanctioned/Modern.txt index 738145f390b..12e45ae5ad3 100644 --- a/forge-gui/res/formats/Sanctioned/Modern.txt +++ b/forge-gui/res/formats/Sanctioned/Modern.txt @@ -3,5 +3,5 @@ Name:Modern Order:102 Subtype:Modern Type:Sanctioned -Sets:8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, LRW, EVE, SHM, MOR, ALA, CFX, ARB, M10, ZEN, WWK, ROE, M11, SOM, MBS, NPH, M12, ISD, DKA, AVR, M13, RTR, GTC, DGM, M14, THS, BNG, JOU, M15, KTK, FRF, DTK, MM2, ORI, BFZ, OGW, SOI, EMN, KLD, AER, AKH, W17, HOU, XLN, RIX, DOM, M19 +Sets:8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, LRW, EVE, SHM, MOR, ALA, CFX, ARB, M10, ZEN, WWK, ROE, M11, SOM, MBS, NPH, M12, ISD, DKA, AVR, M13, RTR, GTC, DGM, M14, THS, BNG, JOU, M15, KTK, FRF, DTK, MM2, ORI, BFZ, OGW, SOI, EMN, KLD, AER, AKH, W17, HOU, XLN, RIX, DOM, M19, GRN Banned:Ancient Den; Birthing Pod; Blazing Shoal; Chrome Mox; Cloudpost; Dark Depths; Deathrite Shaman; Dig Through Time; Dread Return; Eye of Ugin; Gitaxian Probe; Glimpse of Nature; Golgari Grave-Troll; Great Furnace; Green Sun's Zenith; Hypergenesis; Mental Misstep; Ponder; Preordain; Punishing Fire; Rite of Flame; Seat of the Synod; Second Sunrise; Seething Song; Sensei's Divining Top; Skullclamp; Splinter Twin; Stoneforge Mystic; Summer Bloom; Treasure Cruise; Tree of Tales; Umezawa's Jitte; Vault of Whispers diff --git a/forge-gui/res/formats/Sanctioned/Standard.txt b/forge-gui/res/formats/Sanctioned/Standard.txt index 6d8133d15d9..7413d4d97d2 100644 --- a/forge-gui/res/formats/Sanctioned/Standard.txt +++ b/forge-gui/res/formats/Sanctioned/Standard.txt @@ -3,5 +3,5 @@ Name:Standard Order:101 Subtype:Standard Type:Sanctioned -Sets:KLD, AER, AKH, W17, HOU, XLN, RIX, DOM, M19 -Banned: Attune with Aether; Rogue Refiner; Rampaging Ferocidon; Ramunap Ruins; Smuggler's Copter; Aetherworks Marvel; Felidar Guardian +Sets:XLN, RIX, DOM, M19, GRN +Banned: Rampaging Ferocidon diff --git a/forge-gui/res/lists/altwin-achievements.txt b/forge-gui/res/lists/altwin-achievements.txt index 0abdb1cc437..901042fb4f6 100644 --- a/forge-gui/res/lists/altwin-achievements.txt +++ b/forge-gui/res/lists/altwin-achievements.txt @@ -4,10 +4,12 @@ Barren Glory|The Clean Slate|When you have nothing, you can lose nothing... so y Battle of Wits|The Great Library|So many answers, so little time to look through them... Biovisionary|The Clique|And now my... I mean our plan is complete! Chance Encounter|The Accident|This victory was brought to you by a series of fortunate events. +Chance for Glory|The Big-Time|Sorry, you used it up. Coalition Victory|The Teamwork|Let's all be friends! Darksteel Reactor|The Machine|What are you going to do with all this power? Whatever you want! Door to Nothingness|The Door|And behind door #2 is... Epic Struggle|The Army|Let's just trample them into the ground already! +Etrata, the Silencer|The Silent Hit|Hey, where did everybody go? Felidar Sovereign|The Cat's Life|Just wait for his other eight lives! Hedron Alignment|The Alignment|The hedrons are right! Helix Pinnacle|The Tower|The view from the top is great! @@ -24,3 +26,4 @@ Phage the Untouchable|The Untouchable|None are immune to her deadly touch! Revel in Riches|The Dead Man's Chest|Yo-ho-ho, and a bottle of rum! Test of Endurance|The Test|So... did I pass? Triskaidekaphobia|The Fear of 13|It's just a silly ancient superstition... right? +Vraska, Golgari Queen|The Flurry of Assassins|How good is your dodging? diff --git a/forge-gui/res/lists/booster-images.txt b/forge-gui/res/lists/booster-images.txt index 48c8f261e7d..0ef670ef076 100644 --- a/forge-gui/res/lists/booster-images.txt +++ b/forge-gui/res/lists/booster-images.txt @@ -165,6 +165,11 @@ https://downloads.cardforge.org/images/products/boosters/GPT.png https://downloads.cardforge.org/images/products/boosters/GPT_1.jpg https://downloads.cardforge.org/images/products/boosters/GPT_2.jpg https://downloads.cardforge.org/images/products/boosters/GPT_3.jpg +https://downloads.cardforge.org/images/products/boosters/GRN_1.jpg +https://downloads.cardforge.org/images/products/boosters/GRN_2.jpg +https://downloads.cardforge.org/images/products/boosters/GRN_3.jpg +https://downloads.cardforge.org/images/products/boosters/GRN_4.jpg +https://downloads.cardforge.org/images/products/boosters/GRN_5.jpg https://downloads.cardforge.org/images/products/boosters/GTC.png https://downloads.cardforge.org/images/products/boosters/GTC_1.jpg https://downloads.cardforge.org/images/products/boosters/GTC_2.jpg diff --git a/forge-gui/res/lists/boosterbox-images.txt b/forge-gui/res/lists/boosterbox-images.txt index 6aab58512d5..5206382cd7b 100644 --- a/forge-gui/res/lists/boosterbox-images.txt +++ b/forge-gui/res/lists/boosterbox-images.txt @@ -39,6 +39,7 @@ https://downloads.cardforge.org/images/products/boosterboxes/FEM.jpg https://downloads.cardforge.org/images/products/boosterboxes/FRF.jpg https://downloads.cardforge.org/images/products/boosterboxes/FUT.jpg https://downloads.cardforge.org/images/products/boosterboxes/GPT.jpg +https://downloads.cardforge.org/images/products/boosterboxes/GRN.jpg https://downloads.cardforge.org/images/products/boosterboxes/GTC.jpg https://downloads.cardforge.org/images/products/boosterboxes/HML.jpg https://downloads.cardforge.org/images/products/boosterboxes/HOU.jpg diff --git a/forge-gui/res/lists/fatpack-images.txt b/forge-gui/res/lists/fatpack-images.txt index 49fe30ba636..a3649caf726 100644 --- a/forge-gui/res/lists/fatpack-images.txt +++ b/forge-gui/res/lists/fatpack-images.txt @@ -24,6 +24,7 @@ https://downloads.cardforge.org/images/products/fatpacks/EVE.jpg https://downloads.cardforge.org/images/products/fatpacks/FRF.jpg https://downloads.cardforge.org/images/products/fatpacks/FUT.jpg https://downloads.cardforge.org/images/products/fatpacks/GPT.jpg +https://downloads.cardforge.org/images/products/fatpacks/GRN.jpg https://downloads.cardforge.org/images/products/fatpacks/GTC.jpg https://downloads.cardforge.org/images/products/fatpacks/HOU.jpg https://downloads.cardforge.org/images/products/fatpacks/INV.jpg diff --git a/forge-gui/res/lists/planeswalker-achievements.txt b/forge-gui/res/lists/planeswalker-achievements.txt index c569542f319..dfe01f8c832 100644 --- a/forge-gui/res/lists/planeswalker-achievements.txt +++ b/forge-gui/res/lists/planeswalker-achievements.txt @@ -88,6 +88,8 @@ Nissa, Worldwaker|Nissa's Awakening|The whole country is here! Ob Nixilis of the Black Oath|Nixilis's Black Oath|We all have to bring sacrifices sometimes. Ob Nixilis Reignited|Ob Nixilis's Torment|I'll give you dreams from beyond the underworld! Ral Zarek|Ral's Long Day|So much work, so much time! +Ral, Caller of Storms|Ral's Invocation|The storm called and left a message. +Ral, Izzet Viceroy|Ral's Bonus|I was just researching lightning and then it hit me. Saheeli Rai|Saheeli's Creativity|I love when all the pieces come together! Saheeli, the Gifted|Saheeli's Doubling Season|Polished to mirror sheen. Samut, the Tested|Samut's Rapid Deployment|My friends will be here in a flash. @@ -117,9 +119,11 @@ Ugin, the Spirit Dragon|Ugin's Anti-Ultimatum|A ragtag band of misfits, brought Venser, the Sojourner|Venser's Oblivion|Let's just clean this up a bit... Vivien of the Arkbow|Vivien's Overrun|No, never heard of a 'Garruk' -- why do you ask? Vivien Reid|Vivien's Utter Pandemonium|They're so cute when they're stampeding. -Vraska, Scheming Gorgon|Vraska's Stone Gaze|I think we could use a new figurehead! Vraska the Unseen|Vraska's Crew|Say hello to my little friends! +Vraska, Golgari Queen|Vraska's Training Regime|Step one - give them a scratch. There's no step two. +Vraska, Regal Gorgon|Vraska's Scavenger Hunt|Death is not the opposite of life - it's its complement. Vraska, Relic Seeker|Vraska's Mark|Never play hide and seek with a Gorgon. +Vraska, Scheming Gorgon|Vraska's Stone Gaze|I think we could use a new figurehead! Xenagos, the Reveler|Xenagos's Reveal|Mwahahaha! Now I'm a god! Jiang Yanggu|Yanggu's Giant Growth|Now, Mowu! Fetch that tree! Mu Yanling|Yanling's Time Manipulation|Sleep now, for three days and three nights. diff --git a/forge-gui/res/puzzle/PS_GRN0a.pzl b/forge-gui/res/puzzle/PS_GRN0a.pzl new file mode 100644 index 00000000000..a2c9488a30c --- /dev/null +++ b/forge-gui/res/puzzle/PS_GRN0a.pzl @@ -0,0 +1,17 @@ +[metadata] +Name:Possibility Storm - Guilds of Ravnica #00a (Pre-Season Puzzle #2) +URL:https://i2.wp.com/www.possibilitystorm.com/wp-content/uploads/2018/09/082.-GRN002.jpg +Goal:Win +Turns:1 +Difficulty:Uncommon +Description:Win this turn. +[state] +humanlife=20 +ailife=9 +turn=1 +activeplayer=human +activephase=MAIN1 +humanhand=Impervious Greatwurm;Rhizome Lurcher;Ochran Assassin;Lava Coil +humangraveyard=Devkarin Dissident;Underrealm Lich;Golgari Findbroker;Erstwhile Trooper;Bone Dragon +humanbattlefield=Whisper Agent;Whisper, Blood Liturgist;Torch Courier;Dragonskull Summit;Dragonskull Summit;Dragonskull Summit;Woodland Cemetery;Woodland Cemetery;Woodland Cemetery;Woodland Cemetery +aibattlefield=Flight of Equenauts;Sunhome Stalwart;Wall of Mist;Hitchclaw Recluse diff --git a/forge-gui/res/puzzle/PS_GRN1.pzl b/forge-gui/res/puzzle/PS_GRN1.pzl new file mode 100644 index 00000000000..c0b3fd3668e --- /dev/null +++ b/forge-gui/res/puzzle/PS_GRN1.pzl @@ -0,0 +1,16 @@ +[metadata] +Name:Possibility Storm - Guilds of Ravnica #01 +URL:https://i0.wp.com/www.possibilitystorm.com/wp-content/uploads/2018/10/083.-GRN1.jpg +Goal:Win +Turns:1 +Difficulty:Rare +Description:Win this turn. +[state] +humanlife=20 +ailife=5 +turn=1 +activeplayer=human +activephase=MAIN1 +humanhand=Heroic Reinforcements;Aurelia, Exemplar of Justice;Garna, the Bloodflame;Deafening Clarion;Vraska's Contempt +humanbattlefield=Blade Instructor;Goblin Banneret;Barging Sergeant;Angrath, the Flame-Chained|Counters:LOYALTY=5;Sacred Foundry|Set:GRN|NoETBTrigs;Sacred Foundry|Set:GRN|NoETBTrigs;Sacred Foundry|Set:GRN|NoETBTrigs;Sacred Foundry|Set:GRN|NoETBTrigs;Dragonskull Summit;Dragonskull Summit +aibattlefield=Josu Vess, Lich Knight;t:Zombie Knight,P:2,T:2,Cost:no cost,Color:B,Types:Creature-Zombie-Knight,Keywords:Menace,Image:b_2_2_zombie_knight_dom;t:Zombie Knight,P:2,T:2,Cost:no cost,Color:B,Types:Creature-Zombie-Knight,Keywords:Menace,Image:b_2_2_zombie_knight_dom;t:Zombie Knight,P:2,T:2,Cost:no cost,Color:B,Types:Creature-Zombie-Knight,Keywords:Menace,Image:b_2_2_zombie_knight_dom;t:Zombie Knight,P:2,T:2,Cost:no cost,Color:B,Types:Creature-Zombie-Knight,Keywords:Menace,Image:b_2_2_zombie_knight_dom;t:Zombie Knight,P:2,T:2,Cost:no cost,Color:B,Types:Creature-Zombie-Knight,Keywords:Menace,Image:b_2_2_zombie_knight_dom;t:Zombie Knight,P:2,T:2,Cost:no cost,Color:B,Types:Creature-Zombie-Knight,Keywords:Menace,Image:b_2_2_zombie_knight_dom;t:Zombie Knight,P:2,T:2,Cost:no cost,Color:B,Types:Creature-Zombie-Knight,Keywords:Menace,Image:b_2_2_zombie_knight_dom;t:Zombie Knight,P:2,T:2,Cost:no cost,Color:B,Types:Creature-Zombie-Knight,Keywords:Menace,Image:b_2_2_zombie_knight_dom diff --git a/forge-gui/res/puzzle/PS_GRN2.pzl b/forge-gui/res/puzzle/PS_GRN2.pzl new file mode 100644 index 00000000000..84bfbcde0d8 --- /dev/null +++ b/forge-gui/res/puzzle/PS_GRN2.pzl @@ -0,0 +1,17 @@ +[metadata] +Name:Possibility Storm - Guilds of Ravnica #02 +URL:https://i1.wp.com/www.possibilitystorm.com/wp-content/uploads/2018/10/084.-GRN2.jpg +Goal:Win +Turns:1 +Difficulty:Rare +Description:Win this turn. Assume you have no instant or sorcery spells left in your library. +[state] +humanlife=20 +ailife=12 +turn=1 +activeplayer=human +activephase=MAIN1 +humanhand=Arclight Phoenix;Sonic Assault;Invert // Invent;Response // Resurgence +humanlibrary=Plains|Set:GRN;Island|Set:GRN;Swamp|Set:GRN;Mountain|Set:GRN;Forest|Set:GRN +humanbattlefield=Runaway Steam-Kin|Counters:P1P1=1|Id:1;Tilonalli's Crown|Attaching:1;Rampaging Monument|Counters:P1P1=3;Sacred Foundry|Set:GRN|NoETBTrigs;Sacred Foundry|Set:GRN|NoETBTrigs;Steam Vents|Set:GRN|NoETBTrigs;Steam Vents|Set:GRN|NoETBTrigs;Izzet Guildgate|Set:GRN;Izzet Guildgate|Set:GRN +aibattlefield=Looming Altisaur;Territorial Allosaurus;Verdant Sun's Avatar;Polyraptor;Emissary of Sunrise|Id:2;Forebear's Blade|Attaching:2 diff --git a/forge-gui/res/quest/precons/Ral, Caller of Storms.dck b/forge-gui/res/quest/precons/Ral, Caller of Storms.dck new file mode 100644 index 00000000000..3c5f8e6dc44 --- /dev/null +++ b/forge-gui/res/quest/precons/Ral, Caller of Storms.dck @@ -0,0 +1,36 @@ +[shop] +WinsToUnlock=0 +Credits=1200 +MinDifficulty=0 +MaxDifficulty=5 +[metadata] +Name=Ral, Caller of Storms +Description=U/R Guilds of Ravnica planeswalker deck with Ral, Caller of Storms. +Deck Type=constructed +Set=GRN +Image=ral_caller_of_storms.jpg +[Main] +1 Chemister's Insight|GRN +2 Command the Storm|GRN +1 Direct Current|GRN +1 Erratic Cyclops|GRN +3 Fearless Halberdier|GRN +2 Fire Urchin|GRN +2 Goblin Electromancer|GRN +2 Hellkite Whelp|GRN +10 Island|GRN +4 Izzet Guildgate|GRN +1 Leapfrog|GRN +1 Maximize Altitude|GRN +12 Mountain|GRN +1 Muse Drake|GRN +1 Omnispell Adept|GRN +1 Passwall Adept|GRN +4 Precision Bolt|GRN +2 Ral's Dispersal|GRN +3 Ral's Staticaster|GRN +1 Ral, Caller of Storms+|GRN +1 Rubblebelt Boar|GRN +1 Sonic Assault|GRN +1 Vedalken Mesmerist|GRN +2 Wee Dragonauts|GRN diff --git a/forge-gui/res/quest/precons/Vraska, Regal Gorgon.dck b/forge-gui/res/quest/precons/Vraska, Regal Gorgon.dck new file mode 100644 index 00000000000..58bfc941bcd --- /dev/null +++ b/forge-gui/res/quest/precons/Vraska, Regal Gorgon.dck @@ -0,0 +1,34 @@ +[shop] +WinsToUnlock=0 +Credits=1200 +MinDifficulty=0 +MaxDifficulty=5 +[metadata] +Name=Vraska, Regal Gorgon +Description=B/G Guilds of Ravnica planeswalker deck with Vraska, Regal Gorgon. +Deck Type=constructed +Set=GRN +Image=vraska_regal_gorgon.jpg +[Main] +3 Attendant of Vraska|GRN +2 Bartizan Bats|GRN +1 Beast Whisperer|GRN +1 Bounty of Might|GRN +3 Dead Weight|GRN +1 Devkarin Dissident|GRN +1 Douser of Lights|GRN +10 Forest|GRN +2 Glowspore Shaman|GRN +4 Golgari Guildgate|GRN +2 Ironshell Beetle|GRN +1 Kraul Foragers|GRN +4 Kraul Raider|GRN +1 Lotleth Giant|GRN +2 Prey Upon|GRN +2 Rhizome Lurcher|GRN +3 Spinal Centipede|GRN +12 Swamp|GRN +1 Swarm Guildmage|GRN +2 Vraska's Stoneglare|GRN +1 Vraska, Regal Gorgon+|GRN +1 Wild Ceratok|GRN diff --git a/forge-gui/res/quest/world/worlds.txt b/forge-gui/res/quest/world/worlds.txt index d71439419d0..b08931cde59 100644 --- a/forge-gui/res/quest/world/worlds.txt +++ b/forge-gui/res/quest/world/worlds.txt @@ -1,4 +1,5 @@ Name:Main world +Name:Random Standard Name:Amonkhet|Dir:Amonkhet|Sets:AKH, HOU Name:Jamuraa|Dir:jamuraa|Sets:5ED, ARN, MIR, VIS, WTH|Banned:Chaos Orb; Falling Star Name:Kamigawa|Dir:2004 Kamigawa|Sets:CHK, BOK, SOK diff --git a/forge-gui/res/skins/darky/bg_match.jpg b/forge-gui/res/skins/darky/bg_match.jpg new file mode 100644 index 00000000000..ace2bf45d10 Binary files /dev/null and b/forge-gui/res/skins/darky/bg_match.jpg differ diff --git a/forge-gui/res/skins/darky/bg_splash.png b/forge-gui/res/skins/darky/bg_splash.png new file mode 100644 index 00000000000..549afedbb77 Binary files /dev/null and b/forge-gui/res/skins/darky/bg_splash.png differ diff --git a/forge-gui/res/skins/darky/bg_texture.jpg b/forge-gui/res/skins/darky/bg_texture.jpg new file mode 100644 index 00000000000..9b0da179073 Binary files /dev/null and b/forge-gui/res/skins/darky/bg_texture.jpg differ diff --git a/forge-gui/res/skins/darky/font1.ttf b/forge-gui/res/skins/darky/font1.ttf new file mode 100644 index 00000000000..4b4ecc66671 Binary files /dev/null and b/forge-gui/res/skins/darky/font1.ttf differ diff --git a/forge-gui/res/skins/darky/sprite_icons.png b/forge-gui/res/skins/darky/sprite_icons.png new file mode 100644 index 00000000000..8ae0e68c4e9 Binary files /dev/null and b/forge-gui/res/skins/darky/sprite_icons.png differ diff --git a/forge-gui/res/tokenscripts/b_2_2_knight_flanking_pro_white_haste.txt b/forge-gui/res/tokenscripts/b_2_2_knight_flanking_pro_white_haste.txt new file mode 100644 index 00000000000..14e11cae9df --- /dev/null +++ b/forge-gui/res/tokenscripts/b_2_2_knight_flanking_pro_white_haste.txt @@ -0,0 +1,9 @@ +Name:Knight +ManaCost:no cost +Types:Creature Knight +Colors:black +PT:2/2 +K:Flanking +K:Protection from white +K:Haste +Oracle:Flanking\nProtection from white\nHaste diff --git a/forge-gui/res/tokenscripts/g_1_1_ooze.txt b/forge-gui/res/tokenscripts/g_1_1_ooze.txt new file mode 100644 index 00000000000..86dc06b7011 --- /dev/null +++ b/forge-gui/res/tokenscripts/g_1_1_ooze.txt @@ -0,0 +1,6 @@ +Name:Ooze +ManaCost:no cost +Types:Creature Ooze +Colors:green +PT:1/1 +Oracle: diff --git a/forge-gui/res/tokenscripts/g_2_2_cat_warrior_forestwalk.txt b/forge-gui/res/tokenscripts/g_2_2_cat_warrior_forestwalk.txt new file mode 100644 index 00000000000..9db0d4debe9 --- /dev/null +++ b/forge-gui/res/tokenscripts/g_2_2_cat_warrior_forestwalk.txt @@ -0,0 +1,7 @@ +Name:Cat Warrior +ManaCost:no cost +Types:Creature Cat Warrior +Colors:green +PT:2/2 +K:Forestwalk +Oracle:Forestwalk diff --git a/forge-gui/res/tokenscripts/g_2_2_ooze_mitotic.txt b/forge-gui/res/tokenscripts/g_2_2_ooze_mitotic.txt new file mode 100644 index 00000000000..f4c5e1023a2 --- /dev/null +++ b/forge-gui/res/tokenscripts/g_2_2_ooze_mitotic.txt @@ -0,0 +1,8 @@ +Name:Ooze +ManaCost:no cost +Types:Creature Ooze +Colors:green +PT:2/2 +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenJunior | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create two 1/1 green Ooze creature tokens. +SVar:TrigTokenJunior:DB$Token | LegacyImage$ g 1 1 ooze | TokenScript$ g_1_1_ooze | TokenOwner$ You | TokenAmount$ 2 +Oracle:When this creature dies, create two 1/1 green Ooze creature tokens. diff --git a/forge-gui/res/tokenscripts/g_3_3_centaur_pro_black.txt b/forge-gui/res/tokenscripts/g_3_3_centaur_pro_black.txt new file mode 100644 index 00000000000..d2788e73c36 --- /dev/null +++ b/forge-gui/res/tokenscripts/g_3_3_centaur_pro_black.txt @@ -0,0 +1,7 @@ +Name:Centaur +ManaCost:no cost +Types:Creature Centaur +Colors:green +PT:3/3 +K:Protection from black +Oracle:Protection from black diff --git a/forge-gui/res/tokenscripts/g_x_x_treefolk_warrior.txt b/forge-gui/res/tokenscripts/g_x_x_treefolk_warrior.txt new file mode 100644 index 00000000000..0332f619efd --- /dev/null +++ b/forge-gui/res/tokenscripts/g_x_x_treefolk_warrior.txt @@ -0,0 +1,9 @@ +Name:Treefolk Warrior +ManaCost:no cost +Types:Creature Treefolk Warrior +Colors:green +PT:*/* +S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | SetToughness$ X | Description$ CARDNAMEs power and toughness are each equal to the number of Forests you control. +SVar:X:Count$Valid Forest.YouCtrl +SVar:BuffedBy:Forest +Oracle:CARDNAMEs power and toughness are each equal to the number of Forests you control. diff --git a/forge-gui/res/tokenscripts/r_0_2_dragon_egg_defender_hatches_dragon.txt b/forge-gui/res/tokenscripts/r_0_2_dragon_egg_defender_hatches_dragon.txt new file mode 100644 index 00000000000..d07b22f0e4f --- /dev/null +++ b/forge-gui/res/tokenscripts/r_0_2_dragon_egg_defender_hatches_dragon.txt @@ -0,0 +1,10 @@ +Name:Dragon Egg +ManaCost:no cost +Types:Creature Dragon Egg +Colors:red +PT:0/2 +K:Defender +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn". +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | LegacyImage$ r 2 2 dragon c18 | TokenScript$ r_2_2_dragon_flying_firebreathing +SVar:SacMe:4 +Oracle:Defender\nWhen Dragon Egg dies, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn." diff --git a/forge-gui/res/tokenscripts/r_2_2_dragon_flying_firebreathing.txt b/forge-gui/res/tokenscripts/r_2_2_dragon_flying_firebreathing.txt new file mode 100644 index 00000000000..b3f28088d16 --- /dev/null +++ b/forge-gui/res/tokenscripts/r_2_2_dragon_flying_firebreathing.txt @@ -0,0 +1,8 @@ +Name:Dragon +ManaCost:no cost +Types:Creature Dragon +Colors:red +PT:2/2 +K:Flying +A:AB$ Pump | Cost$ R | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn. +Oracle:Flying\n{R}: This creature gets +1/+0 until end of turn. diff --git a/forge-gui/res/tokenscripts/u_3_3_fish_hatches_whale.txt b/forge-gui/res/tokenscripts/u_3_3_fish_hatches_whale.txt new file mode 100644 index 00000000000..b3cee428e2b --- /dev/null +++ b/forge-gui/res/tokenscripts/u_3_3_fish_hatches_whale.txt @@ -0,0 +1,8 @@ +Name:Fish +ManaCost:no cost +Types:Creature Fish +Colors:blue +PT:3/3 +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create a 6/6 blue Whale creature token with "When this creature dies, create a 9/9 blue Kraken creature token." +SVar:TrigToken:DB$Token | LegacyImage$ u 6 6 whale | TokenScript$ u_6_6_whale_hatches_kraken | TokenOwner$ You | TokenAmount$ 1 +Oracle:When this creature dies, create a 6/6 blue Whale creature token with "When this creature dies, create a 9/9 blue Kraken creature token.". diff --git a/forge-gui/res/tokenscripts/u_6_6_whale_hatches_kraken.txt b/forge-gui/res/tokenscripts/u_6_6_whale_hatches_kraken.txt new file mode 100644 index 00000000000..fb642b54f94 --- /dev/null +++ b/forge-gui/res/tokenscripts/u_6_6_whale_hatches_kraken.txt @@ -0,0 +1,8 @@ +Name:Whale +ManaCost:no cost +Types:Creature Whale +Colors:blue +PT:6/6 +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create a 9/9 blue Kraken creature token. +SVar:TrigToken:DB$Token | LegacyImage$ u 9 9 kraken | TokenScript$ u_9_9_kraken | TokenOwner$ You | TokenAmount$ 1 +Oracle:When this creature dies, create a 9/9 blue Kraken creature token. diff --git a/forge-gui/res/tokenscripts/u_9_9_kraken.txt b/forge-gui/res/tokenscripts/u_9_9_kraken.txt new file mode 100644 index 00000000000..e824b538c68 --- /dev/null +++ b/forge-gui/res/tokenscripts/u_9_9_kraken.txt @@ -0,0 +1,6 @@ +Name:Kraken +ManaCost:no cost +Types:Creature Kraken +Colors:blue +PT:9/9 +Oracle: diff --git a/forge-gui/src/main/java/forge/limited/BoosterDraft.java b/forge-gui/src/main/java/forge/limited/BoosterDraft.java index c2fcfe9e3c0..ef22d7b8e76 100644 --- a/forge-gui/src/main/java/forge/limited/BoosterDraft.java +++ b/forge-gui/src/main/java/forge/limited/BoosterDraft.java @@ -17,12 +17,17 @@ */ package forge.limited; +import com.google.common.base.Predicate; import com.google.common.base.Supplier; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import forge.StaticData; import forge.card.CardEdition; import forge.deck.CardPool; import forge.deck.Deck; import forge.item.PaperCard; import forge.item.SealedProduct; +import forge.item.generation.ChaosBoosterSupplier; import forge.item.generation.IUnOpenedProduct; import forge.item.generation.UnOpenedProduct; import forge.model.CardBlock; @@ -35,6 +40,7 @@ import forge.util.TextUtil; import forge.util.gui.SGuiChoose; import forge.util.gui.SOptionPane; import forge.util.storage.IStorage; +import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.ArrayUtils; import java.io.File; @@ -168,6 +174,40 @@ public class BoosterDraft implements IBoosterDraft { } break; + case Chaos: + final CardEdition.Collection allEditions = StaticData.instance().getEditions(); + final Iterable chaosDraftEditions = Iterables.filter(allEditions.getOrderedEditions(), new Predicate() { + @Override + public boolean apply(final CardEdition cardEdition) { + boolean isExpansion = cardEdition.getType().equals(CardEdition.Type.EXPANSION); + boolean isCoreSet = cardEdition.getType().equals(CardEdition.Type.CORE); + boolean isReprintSet = cardEdition.getType().equals(CardEdition.Type.REPRINT); + if (isExpansion || isCoreSet || isReprintSet) { + // Only allow sets with 15 cards in booster packs + if (cardEdition.hasBoosterTemplate()) { + final List> slots = cardEdition.getBoosterTemplate().getSlots(); + int boosterSize = 0; + for (Pair slot : slots) { + boosterSize += slot.getRight(); + } + return boosterSize == 15; + } + } + return false; + } + }); + + // Randomize order of sets + List shuffled = Lists.newArrayList(chaosDraftEditions); + Collections.shuffle(shuffled); + + final Supplier> ChaosDraftSupplier = new ChaosBoosterSupplier(shuffled); + + for (int i = 0; i < 3; i++) { + this.product.add(ChaosDraftSupplier); + } + break; + default: throw new NoSuchElementException("Draft for mode " + this.draftFormat + " has not been set up!"); } diff --git a/forge-gui/src/main/java/forge/limited/LimitedPoolType.java b/forge-gui/src/main/java/forge/limited/LimitedPoolType.java index 758d892a8fa..2f52015e1e8 100644 --- a/forge-gui/src/main/java/forge/limited/LimitedPoolType.java +++ b/forge-gui/src/main/java/forge/limited/LimitedPoolType.java @@ -4,7 +4,8 @@ public enum LimitedPoolType { Full("Full Cardpool"), Block("Block / Set"), FantasyBlock("Fantasy Block"), - Custom("Custom Cube"); + Custom("Custom Cube"), + Chaos("Chaos Draft"); private final String displayName; private LimitedPoolType(String name) { diff --git a/forge-gui/src/main/java/forge/match/input/InputPayManaOfCostPayment.java b/forge-gui/src/main/java/forge/match/input/InputPayManaOfCostPayment.java index 1f3fba6da55..15da37980f1 100644 --- a/forge-gui/src/main/java/forge/match/input/InputPayManaOfCostPayment.java +++ b/forge-gui/src/main/java/forge/match/input/InputPayManaOfCostPayment.java @@ -1,6 +1,7 @@ package forge.match.input; import forge.game.card.Card; +import forge.game.mana.ManaConversionMatrix; import forge.game.mana.ManaCostBeingPaid; import forge.game.player.Player; import forge.game.spellability.SpellAbility; @@ -10,13 +11,16 @@ import forge.properties.ForgePreferences; import forge.util.ITriggerEvent; public class InputPayManaOfCostPayment extends InputPayMana { - public InputPayManaOfCostPayment(final PlayerControllerHuman controller, ManaCostBeingPaid cost, SpellAbility spellAbility, Player payer) { + public InputPayManaOfCostPayment(final PlayerControllerHuman controller, ManaCostBeingPaid cost, SpellAbility spellAbility, Player payer, ManaConversionMatrix matrix) { super(controller, spellAbility, payer); manaCost = cost; + extraMatrix = matrix; + applyMatrix(); } private static final long serialVersionUID = 3467312982164195091L; private int phyLifeToLose = 0; + private ManaConversionMatrix extraMatrix; @Override protected final void onPlayerSelected(Player selected, final ITriggerEvent triggerEvent) { @@ -47,6 +51,8 @@ public class InputPayManaOfCostPayment extends InputPayMana { final String displayMana = manaCost.toString(false, player.getManaPool()); final StringBuilder msg = new StringBuilder(); + applyMatrix(); + if (messagePrefix != null) { msg.append(messagePrefix).append("\n"); } @@ -71,4 +77,12 @@ public class InputPayManaOfCostPayment extends InputPayMana { return msg.toString(); } + + private void applyMatrix() { + if (extraMatrix == null) { + return; + } + + player.getManaPool().applyCardMatrix(extraMatrix); + } } diff --git a/forge-gui/src/main/java/forge/net/ProtocolMethod.java b/forge-gui/src/main/java/forge/net/ProtocolMethod.java index 3035d5a3202..11ff02380d9 100644 --- a/forge-gui/src/main/java/forge/net/ProtocolMethod.java +++ b/forge-gui/src/main/java/forge/net/ProtocolMethod.java @@ -3,6 +3,7 @@ package forge.net; import java.io.Serializable; import java.lang.reflect.Method; import java.util.Collection; +import java.util.ConcurrentModificationException; import java.util.List; import java.util.Map; @@ -166,6 +167,9 @@ public enum ProtocolMethod { // not sure why this one would be thrown, but it is // it also doesn't prevent things from working, so, log for now, pending full network rewrite ex.printStackTrace(); + } catch(ConcurrentModificationException ex) { + // can't seem to avoid this from periodically happening + ex.printStackTrace(); } } } diff --git a/forge-gui/src/main/java/forge/player/HumanPlay.java b/forge-gui/src/main/java/forge/player/HumanPlay.java index fd96df17d56..8e7b84f42e3 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlay.java +++ b/forge-gui/src/main/java/forge/player/HumanPlay.java @@ -1,21 +1,8 @@ package forge.player; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import forge.game.cost.*; -import forge.game.spellability.LandAbility; -import forge.game.spellability.OptionalCostValue; -import forge.game.spellability.Spell; -import forge.util.TextUtil; -import org.apache.commons.lang3.StringUtils; - import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; - import forge.FThreads; import forge.card.mana.ManaCost; import forge.game.Game; @@ -25,30 +12,31 @@ import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.ability.effects.CharmEffect; import forge.game.ability.effects.FlipCoinEffect; -import forge.game.card.Card; -import forge.game.card.CardCollection; -import forge.game.card.CardCollectionView; -import forge.game.card.CardDamageMap; -import forge.game.card.CardLists; -import forge.game.card.CardPredicates; +import forge.game.card.*; import forge.game.card.CardPredicates.Presets; -import forge.game.card.CardView; -import forge.game.card.CounterType; +import forge.game.cost.*; +import forge.game.mana.ManaConversionMatrix; import forge.game.mana.ManaCostBeingPaid; import forge.game.player.Player; import forge.game.player.PlayerController; import forge.game.player.PlayerView; -import forge.game.spellability.SpellAbility; -import forge.game.spellability.TargetRestrictions; +import forge.game.spellability.*; import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; import forge.match.input.InputPayMana; import forge.match.input.InputPayManaOfCostPayment; import forge.match.input.InputPayManaSimple; import forge.match.input.InputSelectCardsFromList; -import forge.util.collect.FCollectionView; import forge.util.Lang; +import forge.util.TextUtil; +import forge.util.collect.FCollectionView; import forge.util.gui.SGuiChoose; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class HumanPlay { @@ -814,7 +802,7 @@ public class HumanPlay { return !manaInputCancelled; } - public static boolean payManaCost(final PlayerControllerHuman controller, final ManaCost realCost, final CostPartMana mc, final SpellAbility ability, final Player activator, String prompt, boolean isActivatedSa) { + public static boolean payManaCost(final PlayerControllerHuman controller, final ManaCost realCost, final CostPartMana mc, final SpellAbility ability, final Player activator, String prompt, ManaConversionMatrix matrix, boolean isActivatedSa) { final Card source = ability.getHostCard(); ManaCostBeingPaid toPay = new ManaCostBeingPaid(realCost, mc.getRestiction()); @@ -879,7 +867,7 @@ public class HumanPlay { } if (!toPay.isPaid()) { // Input is somehow clearing out the offering card? - inpPayment = new InputPayManaOfCostPayment(controller, toPay, ability, activator); + inpPayment = new InputPayManaOfCostPayment(controller, toPay, ability, activator, matrix); inpPayment.setMessagePrefix(prompt); inpPayment.showAndWait(); if (!inpPayment.isPaid()) { diff --git a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java index e03c8d89251..c349a80de42 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java +++ b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java @@ -17,14 +17,8 @@ */ package forge.player; -import java.util.Collections; -import java.util.Map; - -import org.apache.commons.lang3.StringUtils; - import com.google.common.collect.Iterables; import com.google.common.collect.Maps; - import forge.card.CardStateName; import forge.card.CardType; import forge.card.MagicColor; @@ -41,13 +35,13 @@ import forge.game.keyword.KeywordInterface; import forge.game.mana.ManaPool; import forge.game.player.Player; import forge.game.player.PlayerController; -import forge.game.spellability.AbilityActivated; -import forge.game.spellability.AbilitySub; -import forge.game.spellability.Spell; -import forge.game.spellability.SpellAbility; -import forge.game.spellability.TargetRestrictions; +import forge.game.spellability.*; import forge.game.zone.Zone; import forge.util.collect.FCollection; +import org.apache.commons.lang3.StringUtils; + +import java.util.Collections; +import java.util.Map; /** *

    @@ -122,13 +116,15 @@ public class HumanPlaySpellAbility { ability.resetPaidHash(); } + // TODO Apply this to the SAStackInstance instead of the Player if (manaTypeConversion) { - AbilityUtils.applyManaColorConversion(human, MagicColor.Constant.ANY_TYPE_CONVERSION); + AbilityUtils.applyManaColorConversion(payment, MagicColor.Constant.ANY_TYPE_CONVERSION); } else if (manaColorConversion) { - AbilityUtils.applyManaColorConversion(human, MagicColor.Constant.ANY_COLOR_CONVERSION); + AbilityUtils.applyManaColorConversion(payment, MagicColor.Constant.ANY_COLOR_CONVERSION); } + if (playerManaConversion) { - AbilityUtils.applyManaColorConversion(human, MagicColor.Constant.ANY_COLOR_CONVERSION); + AbilityUtils.applyManaColorConversion(manapool, MagicColor.Constant.ANY_COLOR_CONVERSION); human.incNumManaConversion(); } @@ -146,7 +142,7 @@ public class HumanPlaySpellAbility { } if (keywordColor) { - AbilityUtils.applyManaColorConversion(human, params); + AbilityUtils.applyManaColorConversion(payment, params); } } @@ -169,6 +165,7 @@ public class HumanPlaySpellAbility { ability.getHostCard().unanimateBestow(); } } + if (manaTypeConversion || manaColorConversion || keywordColor) { manapool.restoreColorReplacements(); } diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index e7d05e729a2..4f12d185493 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -31,6 +31,7 @@ import forge.game.cost.CostPart; import forge.game.cost.CostPartMana; import forge.game.keyword.Keyword; import forge.game.mana.Mana; +import forge.game.mana.ManaConversionMatrix; import forge.game.player.*; import forge.game.replacement.ReplacementEffect; import forge.game.replacement.ReplacementLayer; @@ -1745,8 +1746,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont @Override public boolean payManaCost(final ManaCost toPay, final CostPartMana costPartMana, final SpellAbility sa, - final String prompt, final boolean isActivatedSa) { - return HumanPlay.payManaCost(this, toPay, costPartMana, sa, player, prompt, isActivatedSa); + final String prompt, ManaConversionMatrix matrix, final boolean isActivatedSa) { + return HumanPlay.payManaCost(this, toPay, costPartMana, sa, player, prompt, matrix, isActivatedSa); } @Override diff --git a/forge-gui/src/main/java/forge/properties/ForgePreferences.java b/forge-gui/src/main/java/forge/properties/ForgePreferences.java index 22d13d973d7..2d6af689171 100644 --- a/forge-gui/src/main/java/forge/properties/ForgePreferences.java +++ b/forge-gui/src/main/java/forge/properties/ForgePreferences.java @@ -124,6 +124,7 @@ public class ForgePreferences extends PreferencesStore { UI_DYNAMIC_PLANECHASE_BG("false"), UI_DISABLE_IMAGES_EFFECT_CARDS("false"), UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED ("Never"), + UI_DEFAULT_FONT_SIZE("12"), UI_FOR_TOUCHSCREN("false"), diff --git a/forge-gui/src/main/java/forge/quest/QuestChallengeGenerator.java b/forge-gui/src/main/java/forge/quest/QuestChallengeGenerator.java new file mode 100644 index 00000000000..73c1dea1a5a --- /dev/null +++ b/forge-gui/src/main/java/forge/quest/QuestChallengeGenerator.java @@ -0,0 +1,202 @@ +package forge.quest; + +import com.google.common.base.Predicate; +import forge.deck.DeckgenUtil; +import forge.game.GameFormat; +import forge.item.PaperCard; +import forge.model.FModel; +import forge.util.MyRandom; +import forge.util.storage.IStorage; + +import java.util.*; + +public class QuestChallengeGenerator { + + public static QuestEventChallengeList generateChallenges(){ + Map challenges = new HashMap<>(); + int id = 0; + for (int i=0;i<5;++i) { + QuestEventChallenge qc = getFormatChallenge(FModel.getFormats().getModern()); + qc.setId(new Integer(id).toString()); + qc.setCreditsReward(1000); + qc.setWinsReqd(MyRandom.getRandom().nextInt(5)); + qc.setDifficulty(QuestEventDifficulty.MEDIUM); + qc.setCardReward("1 multicolor rare"); + challenges.put(Integer.toString(id),qc); + id++; + } + for (int i=0;i<5;++i) { + QuestEventChallenge qc = getAIHeadstartChallenge(1); + qc.setId(new Integer(id).toString()); + qc.setCreditsReward(1000); + qc.setCardReward("1 multicolor rare"); + qc.setWinsReqd(MyRandom.getRandom().nextInt(5)); + qc.setDifficulty(QuestEventDifficulty.EASY); + challenges.put(Integer.toString(id),qc); + id++; + } + for (int i=0;i<5;++i) { + QuestEventChallenge qc = getFormatChallenge(FModel.getFormats().get("Legacy")); + qc.setId(new Integer(id).toString()); + qc.setCreditsReward(5000); + qc.setCardReward("2 multicolor rares"); + qc.setWinsReqd(MyRandom.getRandom().nextInt(25)); + qc.setDifficulty(QuestEventDifficulty.HARD); + challenges.put(Integer.toString(id),qc); + id++; + } + for (int i=0;i<5;++i) { + QuestEventChallenge qc = getAIHeadstartChallenge(2); + qc.setId(new Integer(id).toString()); + qc.setCreditsReward(5000); + qc.setCardReward("2 multicolor rares"); + qc.setWinsReqd(MyRandom.getRandom().nextInt(25)); + qc.setDifficulty(QuestEventDifficulty.MEDIUM); + challenges.put(Integer.toString(id),qc); + id++; + } + for (int i=0;i<5;++i) { + QuestEventChallenge qc = getFormatChallenge(FModel.getFormats().get("Vintage")); + qc.setId(new Integer(id).toString()); + qc.setCreditsReward(10000); + qc.setCardReward("3 multicolor rares"); + qc.setWinsReqd(MyRandom.getRandom().nextInt(50)); + qc.setDifficulty(QuestEventDifficulty.EXPERT); + challenges.put(Integer.toString(id),qc); + id++; + } + for (int i=0;i<5;++i) { + QuestEventChallenge qc = getAIHeadstartChallenge(3); + qc.setId(new Integer(id).toString()); + qc.setCreditsReward(10000); + qc.setCardReward("3 multicolor rares"); + qc.setWinsReqd(MyRandom.getRandom().nextInt(50)); + qc.setDifficulty(QuestEventDifficulty.HARD); + challenges.put(Integer.toString(id),qc); + id++; + } + return new QuestEventChallengeList(challenges); + } + + public static QuestEventChallenge getFormatChallenge(GameFormat format){ + QuestEventChallenge qc = new QuestEventChallenge(); + + qc.setAiLife(20); + qc.setEventDeck(DeckgenUtil.buildLDACArchetypeDeck(format,true)); + qc.setTitle(format.getName() + " " + qc.getEventDeck().getName() + " challenge"); + qc.setName(format.getName() + " " + qc.getEventDeck().getName() + " challenge"); + qc.setOpponentName(qc.getEventDeck().getName()); + qc.setDescription("Take on a " + format.getName() + " format deck"); + qc.setOpponentName(qc.getEventDeck().getName()); + qc.setRepeatable(true); + return qc; + } + + public static QuestEventChallenge getAIHeadstartChallenge(int extras){ + QuestEventChallenge qc = new QuestEventChallenge(); + + qc.setAiLife(20); + qc.setEventDeck(DeckgenUtil.buildLDACArchetypeDeck(FModel.getFormats().getStandard(),true)); + qc.setTitle(qc.getEventDeck().getName() + " headstart challenge"); + qc.setName(qc.getEventDeck().getName() + " headstart challenge"); + qc.setOpponentName(qc.getEventDeck().getName()); + qc.setDescription("The AI gets a bit of a headstart..."); + ArrayList cards = new ArrayList<>(); + int i = 0; + while(i < extras) { + PaperCard card = qc.getEventDeck().getMain().toFlatList().get( + MyRandom.getRandom().nextInt(qc.getEventDeck().getMain().toFlatList().size())); + if(card.getRules().getType().isPermanent()){ + cards.add(card.getName()); + ++i; + } + } + qc.setAiExtraCards(cards); + qc.setOpponentName(qc.getEventDeck().getName()); + qc.setRepeatable(true); + return qc; + } + + public static class QuestEventChallengeList implements IStorage{ + + private Map challenges; + + public QuestEventChallengeList(Map list){ + challenges = list; + } + + @Override + public String getFullPath() { + return null; + } + + @Override + public QuestEventChallenge get(String id) { + return challenges.get(id); + } + + @Override + public QuestEventChallenge find(Predicate condition) { + for(QuestEventChallenge challenge:challenges.values()){ + if(condition.apply(challenge)){ + return challenge; + } + } + return null; + } + + @Override + public Collection getItemNames() { + List names = new ArrayList<>(); + for(QuestEventChallenge challenge:challenges.values()){ + names.add(challenge.getName()); + } + return names; + } + + @Override + public boolean contains(String id) { + return challenges.containsKey(id); + } + + @Override + public int size() { + return challenges.keySet().size(); + } + + @Override + public void add(QuestEventChallenge item) { + + } + + @Override + public void delete(String id) { + challenges.remove(id); + } + + @Override + public IStorage> getFolders() { + return null; + } + + @Override + public IStorage tryGetFolder(String path) { + return null; + } + + @Override + public IStorage getFolderOrCreate(String path) { + return null; + } + + @Override + public String getName() { + return "QuestChallenges"; + } + + @Override + public Iterator iterator() { + return challenges.values().iterator(); + } + } +} diff --git a/forge-gui/src/main/java/forge/quest/QuestController.java b/forge-gui/src/main/java/forge/quest/QuestController.java index 753e09e7c14..0b15c20ccb1 100644 --- a/forge-gui/src/main/java/forge/quest/QuestController.java +++ b/forge-gui/src/main/java/forge/quest/QuestController.java @@ -62,7 +62,7 @@ public class QuestController { /** The decks. */ private transient IStorage decks; - private QuestEventDuelManager duelManager = null; + private QuestEventDuelManagerInterface duelManager = null; private IStorage allChallenges = null; private QuestBazaarManager bazaar = null; @@ -149,7 +149,7 @@ public class QuestController { model.Ratings.add(r); } } - + /** * Gets the my decks. * @@ -405,7 +405,7 @@ public class QuestController { * * @return the event manager */ - public QuestEventDuelManager getDuelsManager() { + public QuestEventDuelManagerInterface getDuelsManager() { if (this.duelManager == null) { resetDuelsManager(); } @@ -429,15 +429,25 @@ public class QuestController { * Reset the duels manager. */ public void resetDuelsManager() { + QuestWorld world = getWorld(); - String path; - if (world == null || !world.isCustom()){ - path = world == null || world.getDuelsDir() == null ? ForgeConstants.DEFAULT_DUELS_DIR : ForgeConstants.QUEST_WORLD_DIR + world.getDuelsDir(); - }else{ - path = world == null || world.getDuelsDir() == null ? ForgeConstants.DEFAULT_DUELS_DIR : ForgeConstants.USER_QUEST_WORLD_DIR + world.getDuelsDir(); + String path = ForgeConstants.DEFAULT_CHALLENGES_DIR; + + if (world != null) { + + if (world.getName().equals(QuestWorld.STANDARDWORLDNAME)) { + this.duelManager = new QuestEventLDADuelManager(); + return; + } else if (world.isCustom()) { + path = world.getDuelsDir() == null ? ForgeConstants.DEFAULT_DUELS_DIR : ForgeConstants.USER_QUEST_WORLD_DIR + world.getDuelsDir(); + } else { + path = world.getDuelsDir() == null ? ForgeConstants.DEFAULT_DUELS_DIR : ForgeConstants.QUEST_WORLD_DIR + world.getDuelsDir(); + } + } this.duelManager = new QuestEventDuelManager(new File(path)); + } public HashSet GetRating() { @@ -449,15 +459,25 @@ public class QuestController { * Reset the challenges manager. */ public void resetChallengesManager() { + QuestWorld world = getWorld(); - String path; - if (world == null || !world.isCustom()){ - path = world == null || world.getChallengesDir() == null ? ForgeConstants.DEFAULT_CHALLENGES_DIR : ForgeConstants.QUEST_WORLD_DIR + world.getChallengesDir(); - }else{ - path = world == null || world.getChallengesDir() == null ? ForgeConstants.DEFAULT_CHALLENGES_DIR : ForgeConstants.USER_QUEST_WORLD_DIR + world.getChallengesDir(); + String path = ForgeConstants.DEFAULT_CHALLENGES_DIR; + + if (world != null) { + + if (world.getName().equals(QuestWorld.STANDARDWORLDNAME)) { + allChallenges = QuestChallengeGenerator.generateChallenges(); + return; + } else if (world.isCustom()) { + path = world.getChallengesDir() == null ? ForgeConstants.DEFAULT_CHALLENGES_DIR : ForgeConstants.QUEST_WORLD_DIR + world.getChallengesDir(); + } else { + path = world.getChallengesDir() == null ? ForgeConstants.DEFAULT_CHALLENGES_DIR : ForgeConstants.USER_QUEST_WORLD_DIR + world.getChallengesDir(); + } } - this.allChallenges = new StorageBase("Quest Challenges", new QuestChallengeReader(new File(path))); + + this.allChallenges = new StorageBase<>("Quest Challenges", new QuestChallengeReader(new File(path))); + } /** diff --git a/forge-gui/src/main/java/forge/quest/QuestEvent.java b/forge-gui/src/main/java/forge/quest/QuestEvent.java index 456290719c6..00a140c80e2 100644 --- a/forge-gui/src/main/java/forge/quest/QuestEvent.java +++ b/forge-gui/src/main/java/forge/quest/QuestEvent.java @@ -36,7 +36,7 @@ import java.util.List; */ public abstract class QuestEvent implements IQuestEvent { // Default vals if none provided in the event file. - private Deck eventDeck = null; + protected Deck eventDeck = null; private String title = "Mystery Event"; private String description = ""; private QuestEventDifficulty difficulty = QuestEventDifficulty.MEDIUM; @@ -83,7 +83,7 @@ public abstract class QuestEvent implements IQuestEvent { return description; } - public final Deck getEventDeck() { + public Deck getEventDeck() { return eventDeck; } diff --git a/forge-gui/src/main/java/forge/quest/QuestEventDuelManager.java b/forge-gui/src/main/java/forge/quest/QuestEventDuelManager.java index 80ac9e30988..7d54e178f13 100644 --- a/forge-gui/src/main/java/forge/quest/QuestEventDuelManager.java +++ b/forge-gui/src/main/java/forge/quest/QuestEventDuelManager.java @@ -38,7 +38,7 @@ import java.util.*; * @author Forge * @version $Id: QuestEventManager.java 20404 2013-03-17 05:34:13Z myk $ */ -public class QuestEventDuelManager { +public class QuestEventDuelManager implements QuestEventDuelManagerInterface { private final MapOfLists sortedDuels = new EnumMapOfLists<>(QuestEventDifficulty.class, CollectionSuppliers.arrayLists()); private final IStorage allDuels; diff --git a/forge-gui/src/main/java/forge/quest/QuestEventDuelManagerInterface.java b/forge-gui/src/main/java/forge/quest/QuestEventDuelManagerInterface.java new file mode 100644 index 00000000000..48052ce87e6 --- /dev/null +++ b/forge-gui/src/main/java/forge/quest/QuestEventDuelManagerInterface.java @@ -0,0 +1,10 @@ +package forge.quest; + +import java.util.List; + +public interface QuestEventDuelManagerInterface { + Iterable getAllDuels(); + Iterable getDuels(QuestEventDifficulty difficulty); + List generateDuels(); + void randomizeOpponents(); +} diff --git a/forge-gui/src/main/java/forge/quest/QuestEventLDADuel.java b/forge-gui/src/main/java/forge/quest/QuestEventLDADuel.java new file mode 100644 index 00000000000..162128048fc --- /dev/null +++ b/forge-gui/src/main/java/forge/quest/QuestEventLDADuel.java @@ -0,0 +1,45 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package forge.quest; + + +import forge.deck.DeckgenUtil; +import forge.deck.io.Archetype; +import forge.model.FModel; + +/** + *

    + * QuestDuel class. + *

    + * MODEL - A single duel event data instance, including meta and deck. + * + */ +public class QuestEventLDADuel extends QuestEventDuel { + + private Archetype archetype; + + /** + * Instantiates a new quest duel. + */ + public QuestEventLDADuel(Archetype archetype) { + super(); + this.archetype = archetype; + this.eventDeck = DeckgenUtil.buildLDACArchetypeDeck(archetype, FModel.getFormats().getStandard(),true); + } + +} diff --git a/forge-gui/src/main/java/forge/quest/QuestEventLDADuelManager.java b/forge-gui/src/main/java/forge/quest/QuestEventLDADuelManager.java new file mode 100644 index 00000000000..ba453988dbf --- /dev/null +++ b/forge-gui/src/main/java/forge/quest/QuestEventLDADuelManager.java @@ -0,0 +1,238 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package forge.quest; + +import forge.deck.CardArchetypeLDAGenerator; +import forge.deck.io.Archetype; +import forge.model.FModel; +import forge.quest.data.QuestPreferences; +import forge.quest.data.QuestPreferences.DifficultyPrefs; +import forge.quest.data.QuestPreferences.QPref; +import forge.util.CollectionSuppliers; +import forge.util.MyRandom; +import forge.util.maps.EnumMapOfLists; +import forge.util.maps.MapOfLists; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * QuestEventManager. + * + * @author Forge + * @version $Id: QuestEventManager.java 20404 2013-03-17 05:34:13Z myk $ + */ +public class QuestEventLDADuelManager implements QuestEventDuelManagerInterface { + + private List archetypes; + private final MapOfLists sortedDuels = new EnumMapOfLists<>(QuestEventDifficulty.class, CollectionSuppliers.arrayLists()); + + public QuestEventLDADuelManager(){ + archetypes = CardArchetypeLDAGenerator.ldaArchetypes.get(FModel.getFormats().getStandard().getName()); + assembleDuelDifficultyLists(); + } + + private 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()); + + int i=0; + for(Archetype archetype : archetypes){ + QuestEventLDADuel duel = new QuestEventLDADuel((archetype)); + duel.setDescription("Randomly generated "+archetype.getName()+" archetype deck."); + duel.setName(archetype.getName()); + duel.setTitle(archetype.getName()); + duel.setOpponentName(archetype.getName()); + QuestEventDifficulty diff = QuestEventDifficulty.EASY; + if(i <= (new Float(archetypes.size()))*.1){ + diff = QuestEventDifficulty.EXPERT; + }else if(i <= (new Float(archetypes.size()))*.4){ + diff = QuestEventDifficulty.HARD; + }else if(i <= (new Float(archetypes.size()))*.7) { + diff = QuestEventDifficulty.MEDIUM; + } + duel.setDifficulty(diff); + sortedDuels.add(diff, duel); + i++; + } + + + } + + 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); + + } + + 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; + + if (numberOfWins < questPreferences.getPrefInt(DifficultyPrefs.WINS_MEDIUMAI, index)) { + addDuel(duelOpponents, QuestEventDifficulty.EASY, 3); + randomDuelDifficulty = QuestEventDifficulty.EASY; + } else if (numberOfWins == questPreferences.getPrefInt(DifficultyPrefs.WINS_MEDIUMAI, index)) { + addDuel(duelOpponents, QuestEventDifficulty.EASY, 1); + addDuel(duelOpponents, QuestEventDifficulty.MEDIUM, 2); + 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); + randomDuelDifficulty = QuestEventDifficulty.HARD; + } else if (numberOfWins < questPreferences.getPrefInt(DifficultyPrefs.WINS_EXPERTAI, index)) { + addDuel(duelOpponents, QuestEventDifficulty.HARD, 3); + randomDuelDifficulty = QuestEventDifficulty.HARD; + } else { + addDuel(duelOpponents, QuestEventDifficulty.HARD, 2); + addDuel(duelOpponents, QuestEventDifficulty.EXPERT, 1); + if (MyRandom.getRandom().nextDouble() * 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); + } + } + + addRandomDuel(duelOpponents, randomDuelDifficulty); + + return duelOpponents; + + } + + private void addDuel(List outList, QuestEventDifficulty targetDifficulty, int toAdd) { + + 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--; + } + } + } + + } + + // 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 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; + default: + throw new RuntimeException("unhandled difficulty: " + d); + } + + return difficultyOrder; + } + + @Override + public Iterable getAllDuels() { + return new ArrayList(); + } + + public Iterable getDuels(QuestEventDifficulty difficulty) { + return sortedDuels.get(difficulty); + } + + @Override + /** */ + 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/QuestWorld.java b/forge-gui/src/main/java/forge/quest/QuestWorld.java index fe5a573113b..e20dcf98ce8 100644 --- a/forge-gui/src/main/java/forge/quest/QuestWorld.java +++ b/forge-gui/src/main/java/forge/quest/QuestWorld.java @@ -39,6 +39,7 @@ public class QuestWorld implements Comparable{ private final String name; private final String dir; private final GameFormatQuest format; + public static final String STANDARDWORLDNAME = "Random Standard"; private boolean isCustom; @@ -187,6 +188,12 @@ public class QuestWorld implements Comparable{ useFormat = new GameFormatQuest(useName, sets, bannedCards); } + if (useName.equalsIgnoreCase(QuestWorld.STANDARDWORLDNAME)){ + useFormat = new GameFormatQuest(QuestWorld.STANDARDWORLDNAME, + FModel.getFormats().getStandard().getAllowedSetCodes(), + FModel.getFormats().getStandard().getBannedCardNames(),false); + } + // System.out.println("Creating quest world " + useName + " (index " + useIdx + ", dir: " + useDir); // if (useFormat != null) { System.out.println("SETS: " + sets + "\nBANNED: " + bannedCards); } diff --git a/forge-gui/tools/migrateUpcoming.py b/forge-gui/tools/migrateUpcoming.py index 9303b7a2544..27eee53eb3b 100644 --- a/forge-gui/tools/migrateUpcoming.py +++ b/forge-gui/tools/migrateUpcoming.py @@ -12,6 +12,6 @@ for dirName, subdirList, fileList in os.walk(upcoming): newFile = os.path.join(cardsfolder, filename[0], filename) if os.path.exists(newFile): - subprocess.call('git rm %s' % (newFile), shell=True) + subprocess.call('git rm %s' % (curLocation), shell=True) else: subprocess.call('git mv %s %s' % (curLocation, newFile), shell=True) \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9f5856c47b6..f5046bc50ec 100644 --- a/pom.xml +++ b/pom.xml @@ -5,11 +5,10 @@ forge pom Forge Parent - 1.6.16-SNAPSHOT + 1.6.18-SNAPSHOT - Forge lets you play the card game Magic: The Gathering against a computer opponent - using all of the rules. + Forge lets you play the card game Magic: The Gathering against a computer opponent using all of the rules. https://www.cardforge.org/ @@ -179,10 +178,6 @@ HEAD - - 3.1.1 - - Forge Forum @@ -224,6 +219,7 @@ + org.apache.maven.wagon @@ -236,18 +232,27 @@ org.apache.maven.plugins - maven-site-plugin - 3.3 - - 8081 - - - - org.apache.maven.wagon - wagon-ftp - 2.6 - - + maven-enforcer-plugin + 3.0.0-M2 + + + enforce-versions + validate + + enforce + + + + + [3.5.9,) + + + [1.8,) + + + + + @@ -276,93 +281,82 @@ org.apache.maven.plugins maven-surefire-plugin 2.16 + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.1 + + + org.apache.maven.wagon + wagon-ftp + 2.6 + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + + maven-assembly-plugin + 2.4 + + + + maven-install-plugin + 2.5.1 + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.8 + + + + maven-release-plugin + 2.5 - - - + true + + - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.1 - - - org.apache.maven.wagon - wagon-ftp - 2.6 - - - + + maven-resources-plugin + 2.6 + - - com.google.code.maven-svn-revision-number-plugin - svn-revision-number-maven-plugin - 1.13 - + + org.apache.maven.plugins + maven-clean-plugin + 2.5 + - - org.apache.maven.plugins - maven-antrun-plugin - 1.7 - + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + - - maven-assembly-plugin - 2.4 - + + org.apache.maven.plugins + maven-scm-plugin + 1.9 + - - maven-install-plugin - 2.5.1 - + + org.apache.maven.wagon + wagon-ftp + 2.6 + - - org.apache.maven.plugins - maven-dependency-plugin - 2.8 - - - - maven-release-plugin - 2.5 - - true - - - - - maven-resources-plugin - 2.6 - - - - org.apache.maven.plugins - maven-clean-plugin - 2.5 - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - - org.apache.maven.plugins - maven-scm-plugin - 1.9 - - - - org.apache.maven.wagon - wagon-ftp - 2.6 - - - + org.eclipse.m2e lifecycle-mapping @@ -398,19 +392,6 @@ - - - com.google.code.maven-svn-revision-number-plugin - svn-revision-number-maven-plugin - [1.0.0,) - - revision - - - - - - org.apache.maven.plugins @@ -434,14 +415,49 @@ org.apache.maven.plugins - maven-deploy-plugin - - - org.apache.maven.wagon - wagon-ftp - 2.6 - - + maven-enforcer-plugin + 3.0.0-M2 + + + enforce-versions + validate + + enforce + + + + + [3.1.1,) + + + [1.8,) + + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.0.0 + + + checkstyle-validation + validate + + checkstyle.xml + true + UTF-8 + true + true + true + + + check + + +