diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index ff73d875785..c9eb6634f57 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -91,9 +91,6 @@ public class ComputerUtil { } } - source.setCastSA(sa); - sa.setLastStateBattlefield(game.getLastStateBattlefield()); - sa.setLastStateGraveyard(game.getLastStateGraveyard()); sa.setHostCard(game.getAction().moveToStack(source, sa)); } @@ -219,9 +216,6 @@ public class ComputerUtil { final Card source = sa.getHostCard(); if (sa.isSpell() && !source.isCopiedSpell()) { - source.setCastSA(sa); - sa.setLastStateBattlefield(game.getLastStateBattlefield()); - sa.setLastStateGraveyard(game.getLastStateGraveyard()); sa.setHostCard(game.getAction().moveToStack(source, sa)); } @@ -246,9 +240,6 @@ public class ComputerUtil { final Card source = sa.getHostCard(); if (sa.isSpell() && !source.isCopiedSpell()) { - source.setCastSA(sa); - sa.setLastStateBattlefield(game.getLastStateBattlefield()); - sa.setLastStateGraveyard(game.getLastStateGraveyard()); sa.setHostCard(game.getAction().moveToStack(source, sa)); } @@ -267,9 +258,6 @@ public class ComputerUtil { final Card source = newSA.getHostCard(); if (newSA.isSpell() && !source.isCopiedSpell()) { - source.setCastSA(newSA); - sa.setLastStateBattlefield(game.getLastStateBattlefield()); - sa.setLastStateGraveyard(game.getLastStateGraveyard()); newSA.setHostCard(game.getAction().moveToStack(source, sa)); if (newSA.getApi() == ApiType.Charm && !newSA.isWrapper()) { @@ -290,9 +278,6 @@ public class ComputerUtil { if (ComputerUtilCost.canPayCost(sa, ai)) { final Card source = sa.getHostCard(); if (sa.isSpell() && !source.isCopiedSpell()) { - source.setCastSA(sa); - sa.setLastStateBattlefield(game.getLastStateBattlefield()); - sa.setLastStateGraveyard(game.getLastStateGraveyard()); sa.setHostCard(game.getAction().moveToStack(source, sa)); } diff --git a/forge-ai/src/main/java/forge/ai/GameState.java b/forge-ai/src/main/java/forge/ai/GameState.java index 9d71da36c6a..e07b65d95c4 100644 --- a/forge-ai/src/main/java/forge/ai/GameState.java +++ b/forge-ai/src/main/java/forge/ai/GameState.java @@ -981,14 +981,27 @@ public abstract class GameState { spellDef = spellDef.substring(0, spellDef.indexOf("->")).trim(); } - PaperCard pc = StaticData.instance().getCommonCards().getCard(spellDef); + Card c = null; - if (pc == null) { - System.err.println("ERROR: Could not find a card with name " + spellDef + " to precast!"); - return; + if (StringUtils.isNumeric(spellDef)) { + // Precast from a specific host + c = idToCard.get(Integer.parseInt(spellDef)); + if (c == null) { + System.err.println("ERROR: Could not find a card with ID " + spellDef + " to precast!"); + return; + } + } else { + // Precast from a card by name + PaperCard pc = StaticData.instance().getCommonCards().getCard(spellDef); + + if (pc == null) { + System.err.println("ERROR: Could not find a card with name " + spellDef + " to precast!"); + return; + } + + c = Card.fromPaperCard(pc, activator); } - Card c = Card.fromPaperCard(pc, activator); SpellAbility sa = null; if (!scriptID.isEmpty()) { diff --git a/forge-core/src/main/java/forge/ImageKeys.java b/forge-core/src/main/java/forge/ImageKeys.java index e07f836566d..f2b976f3008 100644 --- a/forge-core/src/main/java/forge/ImageKeys.java +++ b/forge-core/src/main/java/forge/ImageKeys.java @@ -113,7 +113,11 @@ public final class ImageKeys { } //try fullborder... if (filename.contains(".full")) { - file = findFile(dir, TextUtil.fastReplace(filename, ".full", ".fullborder")); + String fullborderFile = TextUtil.fastReplace(filename, ".full", ".fullborder"); + file = findFile(dir, fullborderFile); + if (file != null) { return file; } + // if there's an art variant try without it + file = findFile(dir, TextUtil.fastReplace(fullborderFile, "1.fullborder", ".fullborder")); if (file != null) { return file; } } //if an image, like phenomenon or planes is missing .full in their filenames but you have an existing images that have .full/.fullborder diff --git a/forge-core/src/main/java/forge/card/CardDb.java b/forge-core/src/main/java/forge/card/CardDb.java index 2c4e54ad21a..7fcfbfd2a49 100644 --- a/forge-core/src/main/java/forge/card/CardDb.java +++ b/forge-core/src/main/java/forge/card/CardDb.java @@ -312,17 +312,21 @@ public final class CardDb implements ICardDatabase, IDeckGenPool { return tryGetCard(request); } - public int getCardCollectorNumber(String cardName, String reqEdition) { + public String getCardCollectorNumber(String cardName, String reqEdition, int artIndex) { cardName = getName(cardName); CardEdition edition = editions.get(reqEdition); if (edition == null) - return -1; + return null; + int numMatches = 0; for (CardInSet card : edition.getCards()) { if (card.name.equalsIgnoreCase(cardName)) { - return card.collectorNumber; + numMatches += 1; + if (numMatches == artIndex) { + return card.collectorNumber; + } } } - return -1; + return null; } private PaperCard tryGetCard(CardRequest request) { diff --git a/forge-core/src/main/java/forge/card/CardEdition.java b/forge-core/src/main/java/forge/card/CardEdition.java index e2b786c0322..ce6289bb5f5 100644 --- a/forge-core/src/main/java/forge/card/CardEdition.java +++ b/forge-core/src/main/java/forge/card/CardEdition.java @@ -38,6 +38,8 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** @@ -75,10 +77,10 @@ public final class CardEdition implements Comparable { // immutable public static class CardInSet { public final CardRarity rarity; - public final int collectorNumber; + public final String collectorNumber; public final String name; - public CardInSet(final String name, final int collectorNumber, final CardRarity rarity) { + public CardInSet(final String name, final String collectorNumber, final CardRarity rarity) { this.name = name; this.collectorNumber = collectorNumber; this.rarity = rarity; @@ -86,7 +88,7 @@ public final class CardEdition implements Comparable { // immutable public String toString() { StringBuilder sb = new StringBuilder(); - if (collectorNumber != -1) { + if (collectorNumber != null) { sb.append(collectorNumber); sb.append(' '); } @@ -190,6 +192,7 @@ public final class CardEdition implements Comparable { // immutable public boolean getSmallSetOverride() { return smallSetOverride; } public String getBoosterMustContain() { return boosterMustContain; } public CardInSet[] getCards() { return cards; } + public boolean isModern() { return getDate().after(parseDate("2003-07-27")); } //8ED and above are modern except some promo cards and others public Map getTokens() { return tokenNormalized; } @@ -266,24 +269,33 @@ public final class CardEdition implements Comparable { // immutable Map tokenNormalized = new HashMap<>(); List processedCards = new ArrayList<>(); if (contents.containsKey("cards")) { + final Pattern pattern = Pattern.compile( + /* + The following pattern will match the WAR Japanese art entries, + it should also match the Un-set and older alternate art cards + like Merseine from FEM (should the editions files ever be updated) + */ + //"(^(?[0-9]+.?) )?((?[SCURML]) )?(?.*)$" + /* Ideally we'd use the named group above, but Android 6 and + earlier don't appear to support named groups. + So, untill support for those devices is officially dropped, + we'll have to suffice with numbered groups. + We are looking for: + * cnum - grouping #2 + * rarity - grouping #4 + * name - grouping #5 + */ + "(^([0-9]+.?) )?(([SCURML]) )?(.*)$" + ); for(String line : contents.get("cards")) { - if (StringUtils.isBlank(line)) - continue; - - // Optional collector number at the start. - String[] split = line.split(" ", 2); - int collectorNumber = -1; - if (split.length >= 2 && StringUtils.isNumeric(split[0])) { - collectorNumber = Integer.parseInt(split[0]); - line = split[1]; + Matcher matcher = pattern.matcher(line); + if (matcher.matches()) { + String collectorNumber = matcher.group(2); + CardRarity r = CardRarity.smartValueOf(matcher.group(4)); + String cardName = matcher.group(5); + CardInSet cis = new CardInSet(cardName, collectorNumber, r); + processedCards.add(cis); } - - // You may omit rarity for early development - CardRarity r = CardRarity.smartValueOf(line.substring(0, 1)); - boolean hadRarity = r != CardRarity.Unknown && line.charAt(1) == ' '; - String cardName = hadRarity ? line.substring(2) : line; - CardInSet cis = new CardInSet(cardName, collectorNumber, r); - processedCards.add(cis); } } diff --git a/forge-core/src/main/java/forge/card/CardRules.java b/forge-core/src/main/java/forge/card/CardRules.java index 322c003b6f2..a27b60adf2c 100644 --- a/forge-core/src/main/java/forge/card/CardRules.java +++ b/forge-core/src/main/java/forge/card/CardRules.java @@ -222,7 +222,12 @@ public final class CardRules implements ICardCharacteristics { public boolean canBeBrawlCommander() { CardType type = mainPart.getType(); - return (type.isLegendary() && type.isCreature()) || type.isPlaneswalker(); + return type.isLegendary() && (type.isCreature() || type.isPlaneswalker()); + } + + public boolean canBeTinyLeadersCommander() { + CardType type = mainPart.getType(); + return type.isLegendary() && (type.isCreature() || type.isPlaneswalker()); } public String getMeldWith() { diff --git a/forge-core/src/main/java/forge/card/CardRulesPredicates.java b/forge-core/src/main/java/forge/card/CardRulesPredicates.java index 6679b3ad673..66dca47b592 100644 --- a/forge-core/src/main/java/forge/card/CardRulesPredicates.java +++ b/forge-core/src/main/java/forge/card/CardRulesPredicates.java @@ -594,8 +594,10 @@ public final class CardRulesPredicates { public static final Predicate IS_VANGUARD = CardRulesPredicates.coreType(true, CardType.CoreType.Vanguard); public static final Predicate IS_CONSPIRACY = CardRulesPredicates.coreType(true, CardType.CoreType.Conspiracy); public static final Predicate IS_NON_LAND = CardRulesPredicates.coreType(false, CardType.CoreType.Land); - public static final Predicate CAN_BE_BRAWL_COMMANDER = Predicates.or(Presets.IS_PLANESWALKER, - Predicates.and(Presets.IS_CREATURE, Presets.IS_LEGENDARY)); + public static final Predicate CAN_BE_BRAWL_COMMANDER = Predicates.and(Presets.IS_LEGENDARY, + Predicates.or(Presets.IS_CREATURE, Presets.IS_PLANESWALKER)); + public static final Predicate CAN_BE_TINY_LEADERS_COMMANDER = Predicates.and(Presets.IS_LEGENDARY, + Predicates.or(Presets.IS_CREATURE, Presets.IS_PLANESWALKER)); /** The Constant IS_NON_CREATURE_SPELL. **/ public static final Predicate IS_NON_CREATURE_SPELL = com.google.common.base.Predicates diff --git a/forge-core/src/main/java/forge/deck/DeckFormat.java b/forge-core/src/main/java/forge/deck/DeckFormat.java index 3ea356c6a6d..e369fccc075 100644 --- a/forge-core/src/main/java/forge/deck/DeckFormat.java +++ b/forge-core/src/main/java/forge/deck/DeckFormat.java @@ -463,6 +463,9 @@ public enum DeckFormat { if (this.equals(DeckFormat.Brawl)) { return rules.canBeBrawlCommander(); } + if (this.equals(DeckFormat.TinyLeaders)) { + return rules.canBeTinyLeadersCommander(); + } return rules.canBeCommander(); } diff --git a/forge-core/src/main/java/forge/util/TextUtil.java b/forge-core/src/main/java/forge/util/TextUtil.java index 4974a8e087f..06a706b20f0 100644 --- a/forge-core/src/main/java/forge/util/TextUtil.java +++ b/forge-core/src/main/java/forge/util/TextUtil.java @@ -5,6 +5,8 @@ import forge.item.PaperCard; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; +import com.google.common.collect.ImmutableSortedMap; + import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -17,6 +19,22 @@ import java.util.Map.Entry; */ public class TextUtil { + static ImmutableSortedMap romanMap = ImmutableSortedMap.naturalOrder() + .put(1000, "M").put(900, "CM") + .put(500, "D").put(400, "CD") + .put(100, "C").put(90, "XC") + .put(50, "L").put(40, "XL") + .put(10, "X").put(9, "IX") + .put(5, "V").put(4, "IV").put(1, "I").build(); + + public final static String toRoman(int number) { + if (number <= 0) { + return ""; + } + int l = romanMap.floorKey(number); + return romanMap.get(l) + toRoman(number-l); + } + /** * Safely converts an object to a String. * diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 16b67a2d4e7..16ec6662f0d 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -547,6 +547,13 @@ public class GameAction { c.setCastSA(null); } else if (zoneTo.is(ZoneType.Stack)) { c.setCastFrom(zoneFrom.getZoneType()); + if (cause != null && cause.isSpell() && c.equals(cause.getHostCard()) && !c.isCopiedSpell()) { + cause.setLastStateBattlefield(game.getLastStateBattlefield()); + cause.setLastStateGraveyard(game.getLastStateGraveyard()); + c.setCastSA(cause); + } else { + c.setCastSA(null); + } } else if (!(zoneTo.is(ZoneType.Battlefield) && zoneFrom.is(ZoneType.Stack))) { c.setCastFrom(null); c.setCastSA(null); diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index b54c727370f..6d9ed807964 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -22,8 +22,10 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import forge.card.MagicColor; import forge.card.mana.ManaCost; import forge.card.mana.ManaCostParser; +import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.card.*; @@ -32,9 +34,15 @@ import forge.game.cost.Cost; import forge.game.keyword.KeywordInterface; import forge.game.player.Player; import forge.game.player.PlayerController; +import forge.game.replacement.ReplacementEffect; +import forge.game.replacement.ReplacementHandler; +import forge.game.replacement.ReplacementLayer; import forge.game.spellability.*; import forge.game.trigger.Trigger; +import forge.game.trigger.TriggerHandler; +import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; +import forge.util.Lang; import forge.util.TextUtil; import org.apache.commons.lang3.StringUtils; @@ -363,10 +371,11 @@ public final class GameActionUtil { } SpellAbility result = null; final Card host = sa.getHostCard(); + final Game game = host.getGame(); final Player activator = sa.getActivatingPlayer(); final PlayerController pc = activator.getController(); - host.getGame().getAction().checkStaticAbilities(false); + game.getAction().checkStaticAbilities(false); boolean reset = false; @@ -429,7 +438,60 @@ public final class GameActionUtil { int v = pc.chooseNumberForKeywordCost(sa, cost, ki, str, Integer.MAX_VALUE); if (v > 0) { - host.addReplacementEffect(CardFactoryUtil.makeEtbCounter("etbCounter:P1P1:" + v, host, false)); + + final Card eff = new Card(game.nextCardId(), game); + eff.setTimestamp(game.getNextTimestamp()); + eff.setName(c.getName() + "'s Effect"); + eff.addType("Effect"); + eff.setToken(true); // Set token to true, so when leaving play it gets nuked + eff.setOwner(activator); + + eff.setImageKey(c.getImageKey()); + eff.setColor(MagicColor.COLORLESS); + eff.setImmutable(true); + // try to get the SpellAbility from the mana ability + //eff.setEffectSource((SpellAbility)null); + + eff.addRemembered(host); + + String abStr = "DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ " + v; + + SpellAbility saAb = AbilityFactory.getAbility(abStr, c); + + CardFactoryUtil.setupETBReplacementAbility(saAb); + + String desc = "It enters the battlefield with "; + desc += Lang.nounWithNumeral(v, CounterType.P1P1.getName() + " counter"); + desc += " on it."; + + String repeffstr = "Event$ Moved | ValidCard$ Card.IsRemembered | Destination$ Battlefield | Description$ " + desc; + + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, eff, true); + re.setLayer(ReplacementLayer.Other); + re.setOverridingAbility(saAb); + + eff.addReplacementEffect(re); + + // Forgot Trigger + String trig = "Mode$ ChangesZone | ValidCard$ Card.IsRemembered | Origin$ Stack | Destination$ Any | TriggerZones$ Command | Static$ True"; + String forgetEffect = "DB$ Pump | ForgetObjects$ TriggeredCard"; + String exileEffect = "DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile" + + " | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0"; + + SpellAbility saForget = AbilityFactory.getAbility(forgetEffect, eff); + AbilitySub saExile = (AbilitySub) AbilityFactory.getAbility(exileEffect, eff); + saForget.setSubAbility(saExile); + + final Trigger parsedTrigger = TriggerHandler.parseTrigger(trig, eff, true); + parsedTrigger.setOverridingAbility(saForget); + eff.addTrigger(parsedTrigger); + eff.updateStateForView(); + + // TODO: Add targeting to the effect so it knows who it's dealing with + game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); + game.getAction().moveTo(ZoneType.Command, eff, null); + game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); + if (result == null) { result = sa.copy(); } 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 0be3279d3e4..1d278409976 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -6353,6 +6353,10 @@ public class Card extends GameEntity implements Comparable { removeSVar("PayX"); // Temporary AI X announcement variable removeSVar("IsCastFromPlayEffect"); // Temporary SVar indicating that the spell is cast indirectly via AF Play setSunburstValue(0); // Sunburst + setXManaCostPaid(0); + setXManaCostPaidByColor(null); + setKickerMagnitude(0); + setPseudoMultiKickerMagnitude(0); } public final int getFinalChapterNr() { 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 e60f3e16bd1..88307959cdb 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -20,7 +20,6 @@ package forge.game.card; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Predicates; -import com.google.common.base.Strings; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -3010,24 +3009,43 @@ public class CardFactoryUtil { inst.addTrigger(parsedTrigger); } else if (keyword.startsWith("Saga")) { - // Saga there doesn't need Max value anymore? final String[] k = keyword.split(":"); - final String[] abs = k[2].split(","); + final List abs = Arrays.asList(k[2].split(",")); + if (abs.size() != Integer.valueOf(k[1])) { + throw new RuntimeException("Saga max differ from Ability amount"); + } - int i = 1; - for (String ab : abs) { - SpellAbility sa = AbilityFactory.getAbility(card, ab); - sa.setChapter(i); + int idx = 0; + int skipId = 0; + for(String ab : abs) { + idx += 1; + if (idx <= skipId) { + continue; + } - // TODO better logic for Roman numbers - // In the Description try to merge Chapter trigger with the Same Effect - String trigStr = "Mode$ CounterAdded | ValidCard$ Card.Self | TriggerZones$ Battlefield" - + "| CounterType$ LORE | CounterAmount$ EQ" + i - + "| TriggerDescription$ " + Strings.repeat("I", i) + " - " + sa.getDescription(); - final Trigger t = TriggerHandler.parseTrigger(trigStr, card, intrinsic); - t.setOverridingAbility(sa); - inst.addTrigger(t); - ++i; + skipId = idx + abs.subList(idx - 1, abs.size()).lastIndexOf(ab); + StringBuilder desc = new StringBuilder(); + for (int i = idx; i <= skipId; i++) { + if (i != idx) { + desc.append(", "); + } + desc.append(TextUtil.toRoman(i)); + } + + for (int i = idx; i <= skipId; i++) { + SpellAbility sa = AbilityFactory.getAbility(card, ab); + sa.setChapter(i); + + StringBuilder trigStr = new StringBuilder("Mode$ CounterAdded | ValidCard$ Card.Self | TriggerZones$ Battlefield"); + trigStr.append("| CounterType$ LORE | CounterAmount$ EQ").append(i); + if (i != idx) { + trigStr.append(" | Secondary$ True"); + } + trigStr.append("| TriggerDescription$ ").append(desc).append(" — ").append(sa.getDescription()); + final Trigger t = TriggerHandler.parseTrigger(trigStr.toString(), card, intrinsic); + t.setOverridingAbility(sa); + inst.addTrigger(t); + } } } else if (keyword.equals("Soulbond")) { // Setup ETB trigger for card with Soulbond keyword 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 4fc83734d74..4c85ccd5cac 100644 --- a/forge-game/src/main/java/forge/game/combat/Combat.java +++ b/forge-game/src/main/java/forge/game/combat/Combat.java @@ -882,6 +882,10 @@ public class Combat { return true; // is blocking something at the moment } + if (!blocker.isLKI()) { + return false; + } + CombatLki lki = lkiCache.get(blocker); return null != lki && !lki.isAttacker; // was blocking something anyway } @@ -892,7 +896,11 @@ public class Combat { if (blockers != null && blockers.contains(blocker)) { return true; // is blocking the attacker's band at the moment } - + + if (!blocker.isLKI()) { + return false; + } + CombatLki lki = lkiCache.get(blocker); return null != lki && !lki.isAttacker && lki.relatedBands.contains(ab); // was blocking that very band } 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 e90e6eb9b50..d11afbe776c 100644 --- a/forge-game/src/main/java/forge/game/mana/ManaPool.java +++ b/forge-game/src/main/java/forge/game/mana/ManaPool.java @@ -254,7 +254,7 @@ public class ManaPool extends ManaConversionMatrix implements Iterable { } } if (mana.addsCounters(sa)) { - mana.getManaAbility().createETBCounters(host); + mana.getManaAbility().createETBCounters(host, this.owner); } if (mana.triggersWhenSpent()) { mana.getManaAbility().addTriggersWhenSpent(sa, host); diff --git a/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java b/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java index da064a4cbd6..510458a6189 100644 --- a/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java +++ b/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.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 . */ @@ -19,9 +19,11 @@ package forge.game.spellability; import com.google.common.collect.Lists; import com.google.common.collect.Maps; + import forge.card.ColorSet; import forge.card.MagicColor; import forge.card.mana.ManaAtom; +import forge.game.Game; import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityKey; import forge.game.card.Card; @@ -34,6 +36,8 @@ import forge.game.replacement.*; import forge.game.trigger.Trigger; import forge.game.trigger.TriggerHandler; import forge.game.trigger.TriggerType; +import forge.game.zone.ZoneType; +import forge.util.Lang; import forge.util.TextUtil; import org.apache.commons.lang3.StringUtils; @@ -46,7 +50,7 @@ import java.util.regex.Pattern; *

* Abstract AbilityMana class. *

- * + * * @author Forge * @version $Id$ */ @@ -78,7 +82,7 @@ public class AbilityManaPart implements java.io.Serializable { *

* Constructor for AbilityMana. *

- * + * * @param sourceCard * a {@link forge.game.card.Card} object. */ @@ -111,7 +115,7 @@ public class AbilityManaPart implements java.io.Serializable { *

* produceMana. *

- * + * * @param produced * a {@link java.lang.String} object. * @param player @@ -169,7 +173,7 @@ public class AbilityManaPart implements java.io.Serializable { * cannotCounterPaidWith. *

* @param saBeingPaid - * + * * @return a {@link java.lang.String} object. */ public boolean cannotCounterPaidWith(SpellAbility saBeingPaid) { @@ -186,7 +190,7 @@ public class AbilityManaPart implements java.io.Serializable { * addKeywords. *

* @param saBeingPaid - * + * * @return a {@link java.lang.String} object. */ public boolean addKeywords(SpellAbility saBeingPaid) { @@ -205,7 +209,7 @@ public class AbilityManaPart implements java.io.Serializable { *

* getKeywords. *

- * + * * @return a {@link java.lang.String} object. */ public String getKeywords() { @@ -217,7 +221,7 @@ public class AbilityManaPart implements java.io.Serializable { * addsCounters. *

* @param saBeingPaid - * + * * @return a {@link java.lang.String} object. */ public boolean addsCounters(SpellAbility saBeingPaid) { @@ -227,10 +231,26 @@ public class AbilityManaPart implements java.io.Serializable { /** * createETBCounters */ - public void createETBCounters(Card c) { + public void createETBCounters(Card c, Player controller) { String[] parse = this.addsCounters.split("_"); // Convert random SVars if there are other cards with this effect if (c.isValid(parse[0], c.getController(), c, null)) { + final Game game = this.sourceCard.getGame(); + final Card eff = new Card(game.nextCardId(), game); + eff.setTimestamp(game.getNextTimestamp()); + eff.setName(sourceCard.getName() + "'s Effect"); + eff.addType("Effect"); + eff.setToken(true); // Set token to true, so when leaving play it gets nuked + eff.setOwner(controller); + + eff.setImageKey(sourceCard.getImageKey()); + eff.setColor(MagicColor.COLORLESS); + eff.setImmutable(true); + // try to get the SpellAbility from the mana ability + //eff.setEffectSource((SpellAbility)null); + + eff.addRemembered(c); + String abStr = "DB$ PutCounter | Defined$ ReplacedCard | CounterType$ " + parse[1] + " | ETB$ True | CounterNum$ " + parse[2]; @@ -240,15 +260,37 @@ public class AbilityManaPart implements java.io.Serializable { } CardFactoryUtil.setupETBReplacementAbility(sa); - String repeffstr = "Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield " - + " | Secondary$ True | Description$ CARDNAME" - + " enters the battlefield with " + CounterType.valueOf(parse[1]).getName() + " counters."; + String desc = "It enters the battlefield with "; + desc += Lang.nounWithNumeral(parse[2], CounterType.valueOf(parse[1]).getName() + " counter"); + desc += " on it."; - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, c, false); + String repeffstr = "Event$ Moved | ValidCard$ Card.IsRemembered | Destination$ Battlefield | Description$ " + desc; + + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, eff, true); re.setLayer(ReplacementLayer.Other); re.setOverridingAbility(sa); - c.addReplacementEffect(re); + eff.addReplacementEffect(re); + + // Forgot Trigger + String trig = "Mode$ ChangesZone | ValidCard$ Card.IsRemembered | Origin$ Stack | Destination$ Any | TriggerZones$ Command | Static$ True"; + String forgetEffect = "DB$ Pump | ForgetObjects$ TriggeredCard"; + String exileEffect = "DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile" + + " | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0"; + + SpellAbility saForget = AbilityFactory.getAbility(forgetEffect, eff); + AbilitySub saExile = (AbilitySub) AbilityFactory.getAbility(exileEffect, eff); + saForget.setSubAbility(saExile); + + final Trigger parsedTrigger = TriggerHandler.parseTrigger(trig, eff, true); + parsedTrigger.setOverridingAbility(saForget); + eff.addTrigger(parsedTrigger); + eff.updateStateForView(); + + // TODO: Add targeting to the effect so it knows who it's dealing with + game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); + game.getAction().moveTo(ZoneType.Command, eff, null); + game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); } } @@ -269,7 +311,7 @@ public class AbilityManaPart implements java.io.Serializable { *

* getManaRestrictions. *

- * + * * @return a {@link java.lang.String} object. */ public String getManaRestrictions() { @@ -280,7 +322,7 @@ public class AbilityManaPart implements java.io.Serializable { *

* meetsManaRestrictions. *

- * + * * @param sa * a {@link forge.game.spellability.SpellAbility} object. * @return a boolean. @@ -296,7 +338,7 @@ public class AbilityManaPart implements java.io.Serializable { if (restriction.equals("nonSpell")) { return !sa.isSpell(); } - + if (restriction.equals("CumulativeUpkeep")) { if (sa.isCumulativeupkeep()) { return true; @@ -349,7 +391,7 @@ public class AbilityManaPart implements java.io.Serializable { *

* mana. *

- * + * * @return a {@link java.lang.String} object. */ public final String mana() { @@ -438,7 +480,7 @@ public class AbilityManaPart implements java.io.Serializable { *

* canProduce. *

- * + * * @param s * a {@link java.lang.String} object. * @return a boolean. @@ -468,7 +510,7 @@ public class AbilityManaPart implements java.io.Serializable { *

* isBasic. *

- * + * * @return a boolean. */ public final boolean isBasic() { @@ -541,7 +583,7 @@ public class AbilityManaPart implements java.io.Serializable { public Card getSourceCard() { return sourceCard; } - + public void setSourceCard(final Card host) { sourceCard = host; } 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 75479eaadfc..2bfe8b388a4 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -1299,6 +1299,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit String announce = getParam("Announce"); if (StringUtils.isBlank(announce)) { mapParams.put("Announce", variable); + originalMapParams.put("Announce", variable); return; } String[] announcedOnes = TextUtil.split(announce, ','); @@ -1308,6 +1309,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } } mapParams.put("Announce", announce + ";" + variable); + originalMapParams.put("Announce", announce + ";" + variable); } public boolean isXCost() { diff --git a/forge-game/src/main/java/forge/trackable/TrackableTypes.java b/forge-game/src/main/java/forge/trackable/TrackableTypes.java index 6214563f8f7..0dce88f71e5 100644 --- a/forge-game/src/main/java/forge/trackable/TrackableTypes.java +++ b/forge-game/src/main/java/forge/trackable/TrackableTypes.java @@ -100,17 +100,21 @@ public class TrackableTypes { if (newCollection != null) { //swap in objects in old collection for objects in new collection for (int i = 0; i < newCollection.size(); i++) { - T newObj = newCollection.get(i); - if (newObj != null) { - T existingObj = from.getTracker().getObj(itemType, newObj.getId()); - if (existingObj != null) { //if object exists already, update its changed properties - existingObj.copyChangedProps(newObj); - newCollection.remove(i); - newCollection.add(i, existingObj); - } - else { //if object is new, cache in object lookup - from.getTracker().putObj(itemType, newObj.getId(), newObj); + try { + T newObj = newCollection.get(i); + if (newObj != null) { + T existingObj = from.getTracker().getObj(itemType, newObj.getId()); + if (existingObj != null) { //if object exists already, update its changed properties + existingObj.copyChangedProps(newObj); + newCollection.remove(i); + newCollection.add(i, existingObj); + } + else { //if object is new, cache in object lookup + from.getTracker().putObj(itemType, newObj.getId(), newObj); + } } + } catch (IndexOutOfBoundsException e) { + System.err.println("got an IndexOutOfBoundsException, trying to continue ..."); } } } diff --git a/forge-gui-android/AndroidManifest.xml b/forge-gui-android/AndroidManifest.xml index 5edbcfad66e..9a984611ed7 100644 --- a/forge-gui-android/AndroidManifest.xml +++ b/forge-gui-android/AndroidManifest.xml @@ -6,7 +6,7 @@ + android:targetSdkVersion="26" /> diff --git a/forge-gui-android/pom.xml b/forge-gui-android/pom.xml index 76158aee896..9afc4dcc9ab 100644 --- a/forge-gui-android/pom.xml +++ b/forge-gui-android/pom.xml @@ -142,7 +142,7 @@ true - 25 + 26 true ${project.basedir}/AndroidManifest.xml @@ -183,7 +183,7 @@ false - 25 + 26 false diff --git a/forge-gui-android/project.properties b/forge-gui-android/project.properties index 735ea3db305..94206b9059a 100644 --- a/forge-gui-android/project.properties +++ b/forge-gui-android/project.properties @@ -9,4 +9,4 @@ # Project target. project.type=0 -target=android-20 +target=android-26 diff --git a/forge-gui-android/res/mipmap-hdpi/ic_launcher.png b/forge-gui-android/res/mipmap-hdpi/ic_launcher.png index 13ac6220632..4271e4c73a0 100644 Binary files a/forge-gui-android/res/mipmap-hdpi/ic_launcher.png and b/forge-gui-android/res/mipmap-hdpi/ic_launcher.png differ diff --git a/forge-gui-android/res/mipmap-hdpi/ic_launcher_foreground.png b/forge-gui-android/res/mipmap-hdpi/ic_launcher_foreground.png index a29e46aa510..a749b470515 100644 Binary files a/forge-gui-android/res/mipmap-hdpi/ic_launcher_foreground.png and b/forge-gui-android/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/forge-gui-android/res/mipmap-hdpi/ic_launcher_round.png b/forge-gui-android/res/mipmap-hdpi/ic_launcher_round.png index 07a75d76bfa..23880358c4f 100644 Binary files a/forge-gui-android/res/mipmap-hdpi/ic_launcher_round.png and b/forge-gui-android/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/forge-gui-android/res/mipmap-ldpi/ic_launcher.png b/forge-gui-android/res/mipmap-ldpi/ic_launcher.png index ee25ac432d9..ae40d73a33c 100644 Binary files a/forge-gui-android/res/mipmap-ldpi/ic_launcher.png and b/forge-gui-android/res/mipmap-ldpi/ic_launcher.png differ diff --git a/forge-gui-android/res/mipmap-mdpi/ic_launcher.png b/forge-gui-android/res/mipmap-mdpi/ic_launcher.png index 5fdd9db84cf..75cac9e8a25 100644 Binary files a/forge-gui-android/res/mipmap-mdpi/ic_launcher.png and b/forge-gui-android/res/mipmap-mdpi/ic_launcher.png differ diff --git a/forge-gui-android/res/mipmap-mdpi/ic_launcher_foreground.png b/forge-gui-android/res/mipmap-mdpi/ic_launcher_foreground.png index 524a6232021..bcb5f32aa66 100644 Binary files a/forge-gui-android/res/mipmap-mdpi/ic_launcher_foreground.png and b/forge-gui-android/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/forge-gui-android/res/mipmap-mdpi/ic_launcher_round.png b/forge-gui-android/res/mipmap-mdpi/ic_launcher_round.png index bb574ba21ae..fa0400329c5 100644 Binary files a/forge-gui-android/res/mipmap-mdpi/ic_launcher_round.png and b/forge-gui-android/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/forge-gui-android/res/mipmap-xhdpi/ic_launcher.png b/forge-gui-android/res/mipmap-xhdpi/ic_launcher.png index 5d5de8a444f..ad7c6ed96bb 100644 Binary files a/forge-gui-android/res/mipmap-xhdpi/ic_launcher.png and b/forge-gui-android/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/forge-gui-android/res/mipmap-xhdpi/ic_launcher_foreground.png b/forge-gui-android/res/mipmap-xhdpi/ic_launcher_foreground.png index 0e93289f2d1..25275afddb0 100644 Binary files a/forge-gui-android/res/mipmap-xhdpi/ic_launcher_foreground.png and b/forge-gui-android/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/forge-gui-android/res/mipmap-xhdpi/ic_launcher_round.png b/forge-gui-android/res/mipmap-xhdpi/ic_launcher_round.png index 96328be12a9..42f78d72996 100644 Binary files a/forge-gui-android/res/mipmap-xhdpi/ic_launcher_round.png and b/forge-gui-android/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/forge-gui-android/res/mipmap-xxhdpi/ic_launcher.png b/forge-gui-android/res/mipmap-xxhdpi/ic_launcher.png index e6ea9ce1897..3f9d487ce92 100644 Binary files a/forge-gui-android/res/mipmap-xxhdpi/ic_launcher.png and b/forge-gui-android/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/forge-gui-android/res/mipmap-xxhdpi/ic_launcher_foreground.png b/forge-gui-android/res/mipmap-xxhdpi/ic_launcher_foreground.png index a01a5036f4f..a01aaa6e9df 100644 Binary files a/forge-gui-android/res/mipmap-xxhdpi/ic_launcher_foreground.png and b/forge-gui-android/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/forge-gui-android/res/mipmap-xxhdpi/ic_launcher_round.png b/forge-gui-android/res/mipmap-xxhdpi/ic_launcher_round.png index e4d1b24e68e..c1f4153cef3 100644 Binary files a/forge-gui-android/res/mipmap-xxhdpi/ic_launcher_round.png and b/forge-gui-android/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher.png b/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher.png index 3380a1063bb..6d186851cd6 100644 Binary files a/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher.png and b/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher_foreground.png index e8ccb890b9e..aaa2395dcb9 100644 Binary files a/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher_foreground.png and b/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher_round.png b/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher_round.png index 68aca8009d4..8ad3506407f 100644 Binary files a/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher_round.png and b/forge-gui-android/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/forge-gui-android/res/values/ic_launcher_background.xml b/forge-gui-android/res/values/ic_launcher_background.xml index 7f8bb682c03..ab983282473 100644 --- a/forge-gui-android/res/values/ic_launcher_background.xml +++ b/forge-gui-android/res/values/ic_launcher_background.xml @@ -1,4 +1,4 @@ - #f0f0f0 + #ffffff \ No newline at end of file diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java index eec8c20c98a..0d72be9a4e5 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java @@ -103,7 +103,7 @@ public final class CEditorConstructed extends CDeckEditor { case TinyLeaders: allSections.add(DeckSection.Commander); - commanderFilter = CardRulesPredicates.Presets.CAN_BE_COMMANDER; + commanderFilter = CardRulesPredicates.Presets.CAN_BE_TINY_LEADERS_COMMANDER; commanderPool = ItemPool.createFrom(FModel.getMagicDb().getCommonCards().getAllCards(Predicates.compose(commanderFilter, PaperCard.FN_GET_RULES)), PaperCard.class); normalPool = ItemPool.createFrom(FModel.getMagicDb().getCommonCards().getAllCards(), PaperCard.class); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuDownloaders.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuDownloaders.java index 53a0814f8c3..b3fd57d9a7f 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuDownloaders.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuDownloaders.java @@ -23,6 +23,13 @@ public enum CSubmenuDownloaders implements ICDoc { VSubmenuDownloaders.SINGLETON_INSTANCE.showLicensing(); } }; + private final UiCommand cmdCheckForUpdates = new UiCommand() { + @Override + public void run() { + new AutoUpdater(false).attemptToUpdate(); + } + }; + private final UiCommand cmdPicDownload = new UiCommand() { @Override public void run() { new GuiDownloader(new GuiDownloadPicturesLQ()).show(); @@ -84,6 +91,7 @@ public enum CSubmenuDownloaders implements ICDoc { @Override public void initialize() { final VSubmenuDownloaders view = VSubmenuDownloaders.SINGLETON_INSTANCE; + view.setCheckForUpdatesCommand(cmdCheckForUpdates); view.setDownloadPicsCommand(cmdPicDownload); view.setDownloadPicsHQCommand(cmdPicDownloadHQ); view.setDownloadSetPicsCommand(cmdSetDownload); 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 96080f2a500..3e26afdf007 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 @@ -3,6 +3,7 @@ package forge.screens.home.settings; import forge.*; import forge.ai.AiProfileUtil; import forge.control.FControl.CloseAction; +import forge.download.AutoUpdater; import forge.game.GameLogEntryType; import forge.gui.framework.FScreen; import forge.gui.framework.ICDoc; @@ -225,6 +226,7 @@ public enum CSubmenuPreferences implements ICDoc { initializeGameLogVerbosityComboBox(); initializeCloseActionComboBox(); initializeDefaultFontSizeComboBox(); + initializeAutoUpdaterComboBox(); initializeMulliganRuleComboBox(); initializeAiProfilesComboBox(); initializeStackAdditionsComboBox(); @@ -378,6 +380,16 @@ public enum CSubmenuPreferences implements ICDoc { panel.setComboBox(comboBox, selectedItem); } + private void initializeAutoUpdaterComboBox() { + // TODO: Ideally we would filter out update paths based on the type of Forge people have + final String[] updatePaths = AutoUpdater.updateChannels; + final FPref updatePreference = FPref.AUTO_UPDATE; + final FComboBoxPanel panel = this.view.getCbpAutoUpdater(); + final FComboBox comboBox = createComboBox(updatePaths, updatePreference); + final String selectedItem = this.prefs.getPref(updatePreference); + panel.setComboBox(comboBox, selectedItem); + } + private void initializeMulliganRuleComboBox() { final String [] choices = MulliganDefs.getMulliganRuleNames(); final FPref userSetting = FPref.MULLIGAN_RULE; diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuDownloaders.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuDownloaders.java index 6e1354a6727..2f48c1841ef 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuDownloaders.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuDownloaders.java @@ -55,6 +55,7 @@ public enum VSubmenuDownloaders implements IVSubmenu { private final JPanel pnlContent = new JPanel(new MigLayout("insets 0, gap 0, wrap, ay center")); private final FScrollPane scrContent = new FScrollPane(pnlContent, false); + private final FLabel btnCheckForUpdates = _makeButton(localizer.getMessage("btnCheckForUpdates")); private final FLabel btnDownloadSetPics = _makeButton(localizer.getMessage("btnDownloadSetPics")); private final FLabel btnDownloadPics = _makeButton(localizer.getMessage("btnDownloadPics")); private final FLabel btnDownloadPicsHQ = _makeButton(localizer.getMessage("btnDownloadPicsHQ")); @@ -80,6 +81,9 @@ public enum VSubmenuDownloaders implements IVSubmenu { if (javaRecentEnough()) { + pnlContent.add(btnCheckForUpdates, constraintsBTN); + pnlContent.add(_makeLabel(localizer.getMessage("lblCheckForUpdates")), constraintsLBL); + pnlContent.add(btnDownloadPics, constraintsBTN); pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPics")), constraintsLBL); @@ -162,6 +166,7 @@ public enum VSubmenuDownloaders implements IVSubmenu { return EMenuGroup.SETTINGS; } + public void setCheckForUpdatesCommand(UiCommand command) { btnCheckForUpdates.setCommand(command); } public void setDownloadPicsCommand(UiCommand command) { btnDownloadPics.setCommand(command); } public void setDownloadPicsHQCommand(UiCommand command) { btnDownloadPicsHQ.setCommand(command); } public void setDownloadSetPicsCommand(UiCommand command) { btnDownloadSetPics.setCommand(command); } 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 e5d6c8658cf..567a017c0e1 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 @@ -25,8 +25,8 @@ import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; -import java.util.*; import java.util.List; +import java.util.*; /** @@ -123,6 +123,7 @@ public enum VSubmenuPreferences implements IVSubmenu { private final FComboBoxPanel cbpCounterDisplayLocation =new FComboBoxPanel<>(localizer.getMessage("cbpCounterDisplayLocation")+":"); private final FComboBoxPanel cbpGraveyardOrdering = new FComboBoxPanel<>(localizer.getMessage("cbpGraveyardOrdering")+":"); private final FComboBoxPanel cbpDefaultLanguage = new FComboBoxPanel<>(localizer.getMessage("cbpSelectLanguage")+":"); + private final FComboBoxPanel cbpAutoUpdater = new FComboBoxPanel<>(localizer.getMessage("cbpAutoUpdater")+":"); /** * Constructor. @@ -157,6 +158,10 @@ public enum VSubmenuPreferences implements IVSubmenu { pnlPrefs.add(new SectionLabel(localizer.getMessage("GeneralConfiguration")), sectionConstraints); // language + + pnlPrefs.add(cbpAutoUpdater, comboBoxConstraints); + pnlPrefs.add(new NoteLabel(localizer.getMessage("nlAutoUpdater")), descriptionConstraints); + pnlPrefs.add(cbpDefaultLanguage, comboBoxConstraints); pnlPrefs.add(new NoteLabel(localizer.getMessage("nlSelectLanguage")), descriptionConstraints); @@ -531,6 +536,10 @@ public enum VSubmenuPreferences implements IVSubmenu { } } + public final FComboBoxPanel getCbpAutoUpdater() { + return cbpAutoUpdater; + } + /** @return {@link javax.swing.JCheckBox} */ public final JCheckBox getCbCompactMainMenu() { return cbCompactMainMenu; diff --git a/forge-gui-desktop/src/main/java/forge/view/Main.java b/forge-gui-desktop/src/main/java/forge/view/Main.java index 05675d2225d..de1bc65aafa 100644 --- a/forge-gui-desktop/src/main/java/forge/view/Main.java +++ b/forge-gui-desktop/src/main/java/forge/view/Main.java @@ -81,7 +81,7 @@ public final class Main { break; default: - System.out.println("Unknown mode.\nKnown mode is 'sim' "); + System.out.println("Unknown mode.\nKnown mode is 'sim', 'parse' "); break; } diff --git a/forge-gui-mobile/src/forge/assets/FSkin.java b/forge-gui-mobile/src/forge/assets/FSkin.java index 3eea1009c25..520c5e6a05c 100644 --- a/forge-gui-mobile/src/forge/assets/FSkin.java +++ b/forge-gui-mobile/src/forge/assets/FSkin.java @@ -209,7 +209,7 @@ public class FSkin { textures.put(f6.path(), textures.get(f3.path())); } if (f7.exists()){ - Texture t = new Texture(f7, false); + Texture t = new Texture(f7, true); //t.setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear); textures.put(f7.path(), t); } diff --git a/forge-gui-mobile/src/forge/assets/FSkinImage.java b/forge-gui-mobile/src/forge/assets/FSkinImage.java index 5ed5abe8b8f..38daeb2ced1 100644 --- a/forge-gui-mobile/src/forge/assets/FSkinImage.java +++ b/forge-gui-mobile/src/forge/assets/FSkinImage.java @@ -193,6 +193,15 @@ public enum FSkinImage implements FImage { QUEST_BIG_SWORD (FSkinProp.ICO_QUEST_BIG_SWORD, SourceFile.ICONS), QUEST_BIG_BAG (FSkinProp.ICO_QUEST_BIG_BAG, SourceFile.ICONS), + //menu icon + MENU_GALAXY (FSkinProp.ICO_MENU_GALAXY, SourceFile.ICONS), + MENU_STATS (FSkinProp.ICO_MENU_STATS, SourceFile.ICONS), + MENU_PUZZLE (FSkinProp.ICO_MENU_PUZZLE, SourceFile.ICONS), + MENU_GAUNTLET (FSkinProp.ICO_MENU_GAUNTLET, SourceFile.ICONS), + MENU_SEALED (FSkinProp.ICO_MENU_SEALED, SourceFile.ICONS), + MENU_DRAFT (FSkinProp.ICO_MENU_DRAFT, SourceFile.ICONS), + MENU_CONSTRUCTED (FSkinProp.ICO_MENU_CONSTRUCTED, SourceFile.ICONS), + //Interface icons QUESTION (FSkinProp.ICO_QUESTION, SourceFile.ICONS), INFORMATION (FSkinProp.ICO_INFORMATION, SourceFile.ICONS), diff --git a/forge-gui-mobile/src/forge/card/CardImageRenderer.java b/forge-gui-mobile/src/forge/card/CardImageRenderer.java index b2094fbaa15..8bedd01ae42 100644 --- a/forge-gui-mobile/src/forge/card/CardImageRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardImageRenderer.java @@ -35,6 +35,9 @@ import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.List; +import static forge.card.CardRenderer.CROP_MULTIPLIER; +import static forge.card.CardRenderer.isModernFrame; + public class CardImageRenderer { private static final float BASE_IMAGE_WIDTH = 360; private static final float BASE_IMAGE_HEIGHT = 504; @@ -357,13 +360,19 @@ public class CardImageRenderer { float new_yRotate = (dispH - new_w) /2; boolean rotateSplit = FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ROTATE_SPLIT_CARDS); boolean rotatePlane = FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ROTATE_PLANE_OR_PHENOMENON); + float croppedArea = isModernFrame(card) ? CROP_MULTIPLIER : 0.97f; + float minusxy = isModernFrame(card) ? 0.0f : 0.13f*radius; + if (card.getCurrentState().getSetCode().equals("LEA")||card.getCurrentState().getSetCode().equals("LEB")) { + croppedArea = 0.975f; + minusxy = 0.135f*radius; + } if (rotatePlane && (card.getCurrentState().isPhenomenon() || card.getCurrentState().isPlane())) { if (Forge.enableUIMask){ if (ImageCache.isExtendedArt(card)) g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90); else { g.drawRotatedImage(FSkin.getBorders().get(0), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90); - g.drawRotatedImage(ImageCache.croppedBorderImage(image, fullborder), new_x+radius/2, new_y+radius/2, new_w*0.96f, new_h*0.96f, (new_x+radius/2) + (new_w*0.96f) / 2, (new_y+radius/2) + (new_h*0.96f) / 2, -90); + g.drawRotatedImage(ImageCache.croppedBorderImage(image, fullborder), new_x+radius/2-minusxy, new_y+radius/2-minusxy, new_w*croppedArea, new_h*croppedArea, (new_x+radius/2-minusxy) + (new_w*croppedArea) / 2, (new_y+radius/2-minusxy) + (new_h*croppedArea) / 2, -90); } } else g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90); @@ -374,7 +383,7 @@ public class CardImageRenderer { g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); else { g.drawRotatedImage(FSkin.getBorders().get(ImageCache.getFSkinBorders(card)), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); - g.drawRotatedImage(ImageCache.croppedBorderImage(image, fullborder), new_x + radius / 2, new_y + radius / 2, new_w * 0.96f, new_h * 0.96f, (new_x + radius / 2) + (new_w * 0.96f) / 2, (new_y + radius / 2) + (new_h * 0.96f) / 2, isAftermath ? 90 : -90); + g.drawRotatedImage(ImageCache.croppedBorderImage(image, fullborder), new_x + radius / 2-minusxy, new_y + radius / 2-minusxy, new_w * croppedArea, new_h * croppedArea, (new_x + radius / 2-minusxy) + (new_w * croppedArea) / 2, (new_y + radius / 2-minusxy) + (new_h * croppedArea) / 2, isAftermath ? 90 : -90); } } else g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); @@ -384,7 +393,7 @@ public class CardImageRenderer { g.drawImage(image, x, y, w, h); else { g.drawImage(ImageCache.getBorderImage(card, canshow), x, y, w, h); - g.drawImage(ImageCache.croppedBorderImage(image, fullborder), x + radius / 2.4f, y + radius / 2, w * 0.96f, h * 0.96f); + g.drawImage(ImageCache.croppedBorderImage(image, fullborder), x + radius / 2.4f-minusxy, y + radius / 2-minusxy, w * croppedArea, h * croppedArea); } } else { if (canshow && !ImageKeys.getTokenKey(ImageKeys.MORPH_IMAGE).equals(card.getState(altState).getImageKey())) diff --git a/forge-gui-mobile/src/forge/card/CardRenderer.java b/forge-gui-mobile/src/forge/card/CardRenderer.java index 6dee11cb8cc..6dcc0c48681 100644 --- a/forge-gui-mobile/src/forge/card/CardRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardRenderer.java @@ -105,6 +105,7 @@ public class CardRenderer { private static final float NAME_COST_THRESHOLD = Utils.scale(200); private static final float BORDER_THICKNESS = Utils.scale(1); public static final float PADDING_MULTIPLIER = 0.021f; + public static final float CROP_MULTIPLIER = 0.96f; private static Map counterFonts = new HashMap<>(); private static final Color counterBackgroundColor = new Color(0f, 0f, 0f, 0.9f); @@ -142,6 +143,49 @@ public class CardRenderer { } } + public static boolean isModernFrame(IPaperCard c) { + if (c == null) + return false; + + CardEdition ed = FModel.getMagicDb().getEditions().get(c.getEdition()); + if (ed != null) { + switch (ed.getCode()) { + case "MED": + case "ME2": + case "ME3": + case "ME4": + case "TSB": + return false; + default: + return ed.isModern(); + } + } + + return false; + } + + public static boolean isModernFrame(CardView c) { + if (c == null) + return false; + + CardView.CardStateView state = c.getCurrentState(); + CardEdition ed = FModel.getMagicDb().getEditions().get(state.getSetCode()); + if (ed != null) { + switch (ed.getCode()) { + case "MED": + case "ME2": + case "ME3": + case "ME4": + case "TSB": + return false; + default: + return ed.isModern(); + } + } + + return false; + } + public static float getCardListItemHeight(boolean compactMode) { if (compactMode) { return MANA_SYMBOL_SIZE + 2 * FList.PADDING; @@ -402,7 +446,12 @@ public class CardRenderer { public static void drawCard(Graphics g, IPaperCard pc, float x, float y, float w, float h, CardStackPosition pos) { Texture image = new RendererCachedCardImage(pc, false).getImage(); float radius = (h - w)/8; - + float croppedArea = isModernFrame(pc) ? CROP_MULTIPLIER : 0.97f; + float minusxy = isModernFrame(pc) ? 0.0f : 0.13f*radius; + if (pc.getEdition().equals("LEA")||pc.getEdition().equals("LEB")) { + croppedArea = 0.975f; + minusxy = 0.135f*radius; + } if (image != null) { if (image == ImageCache.defaultImage) { CardImageRenderer.drawCardImage(g, CardView.getCardForUi(pc), false, x, y, w, h, pos); @@ -413,7 +462,7 @@ public class CardRenderer { g.drawImage(image, x, y, w, h); else { g.drawImage(ImageCache.getBorderImage(pc), x, y, w, h); - g.drawImage(ImageCache.croppedBorderImage(image, fullborder), x + radius / 2.4f, y + radius / 2, w * 0.96f, h * 0.96f); + g.drawImage(ImageCache.croppedBorderImage(image, fullborder), x + radius / 2.4f-minusxy, y + radius / 2-minusxy, w * croppedArea, h * croppedArea); } } else g.drawImage(image, x, y, w, h); @@ -437,7 +486,12 @@ public class CardRenderer { Texture image = new RendererCachedCardImage(card, false).getImage(); FImage sleeves = MatchController.getPlayerSleeve(card.getOwner()); float radius = (h - w)/8; - + float croppedArea = isModernFrame(card) ? CROP_MULTIPLIER : 0.97f; + float minusxy = isModernFrame(card) ? 0.0f : 0.13f*radius; + if (card.getCurrentState().getSetCode().equals("LEA")||card.getCurrentState().getSetCode().equals("LEB")) { + croppedArea = 0.975f; + minusxy = 0.135f*radius; + } if (image != null) { if (image == ImageCache.defaultImage) { CardImageRenderer.drawCardImage(g, card, false, x, y, w, h, pos); @@ -450,7 +504,7 @@ public class CardRenderer { g.drawRotatedImage(image, x, y, w, h, x + w / 2, y + h / 2, -90); else { g.drawRotatedImage(FSkin.getBorders().get(0), x, y, w, h, x + w / 2, y + h / 2, -90); - g.drawRotatedImage(ImageCache.croppedBorderImage(image, fullborder), x+radius/2.3f, y+radius/2, w*0.96f, h*0.96f, (x+radius/2.3f) + (w*0.96f) / 2, (y+radius/2) + (h*0.96f) / 2, -90); + g.drawRotatedImage(ImageCache.croppedBorderImage(image, fullborder), x+radius/2.3f-minusxy, y+radius/2-minusxy, w*croppedArea, h*croppedArea, (x+radius/2.3f-minusxy) + (w*croppedArea) / 2, (y+radius/2-minusxy) + (h*croppedArea) / 2, -90); } } else g.drawRotatedImage(image, x, y, w, h, x + w / 2, y + h / 2, -90); @@ -461,7 +515,7 @@ public class CardRenderer { else { boolean t = (card.getCurrentState().getOriginalColors() != card.getCurrentState().getColors()) || card.getCurrentState().hasChangeColors(); g.drawBorderImage(ImageCache.getBorderImage(card, canshow), ImageCache.getTint(card), x, y, w, h, t); //tint check for changed colors - g.drawImage(ImageCache.croppedBorderImage(image, fullborder), x + radius / 2.4f, y + radius / 2, w * 0.96f, h * 0.96f); + g.drawImage(ImageCache.croppedBorderImage(image, fullborder), x + radius / 2.4f-minusxy, y + radius / 2-minusxy, w * croppedArea, h * croppedArea); } } else { if (canshow) @@ -1119,8 +1173,14 @@ public class CardRenderer { public static void drawFoilEffect(Graphics g, CardView card, float x, float y, float w, float h, boolean inZoomer) { float new_x = x; float new_y = y; float new_w = w; float new_h = h; float radius = (h - w)/8; + float croppedArea = isModernFrame(card) ? CROP_MULTIPLIER : 0.97f; + float minusxy = isModernFrame(card) ? 0.0f : 0.13f*radius; + if (card.getCurrentState().getSetCode().equals("LEA")||card.getCurrentState().getSetCode().equals("LEB")) { + croppedArea = 0.975f; + minusxy = 0.135f*radius; + } if (Forge.enableUIMask) { - new_x += radius/2.4f; new_y += radius/2; new_w = w * 0.96f; new_h = h * 0.96f; + new_x += radius/2.4f-minusxy; new_y += radius/2-minusxy; new_w = w * croppedArea; new_h = h * croppedArea; } if (isPreferenceEnabled(FPref.UI_OVERLAY_FOIL_EFFECT) && MatchController.instance.mayView(card)) { boolean rotateSplit = isPreferenceEnabled(FPref.UI_ROTATE_SPLIT_CARDS) && card.isSplitCard() && inZoomer; diff --git a/forge-gui-mobile/src/forge/card/CardZoom.java b/forge-gui-mobile/src/forge/card/CardZoom.java index 8608cbbc82f..72d7d7c978f 100644 --- a/forge-gui-mobile/src/forge/card/CardZoom.java +++ b/forge-gui-mobile/src/forge/card/CardZoom.java @@ -219,7 +219,22 @@ public class CardZoom extends FOverlay { float w = getWidth(); float h = getHeight(); float messageHeight = FDialog.MSG_HEIGHT; - float maxCardHeight = h - 2 * messageHeight; + float AspectRatioMultiplier = 2; + switch (Forge.extrawide) { + case "default": + AspectRatioMultiplier = 3; //good for tablets with 16:10 or similar + break; + case "wide": + AspectRatioMultiplier = 2.5f; + break; + case "extrawide": + AspectRatioMultiplier = 2; //good for tall phones with 21:9 or similar + break; + default: + AspectRatioMultiplier = 3; + break; + } + float maxCardHeight = h - AspectRatioMultiplier * messageHeight; //maxheight of currently zoomed card float cardWidth, cardHeight, y; diff --git a/forge-gui-mobile/src/forge/deck/FDeckEditor.java b/forge-gui-mobile/src/forge/deck/FDeckEditor.java index 2f74d266722..ac553fb40ab 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckEditor.java +++ b/forge-gui-mobile/src/forge/deck/FDeckEditor.java @@ -856,6 +856,9 @@ public class FDeckEditor extends TabPageScreen { case Brawl: isLegalCommander = card.getRules().canBeBrawlCommander(); break; + case TinyLeaders: + isLegalCommander = card.getRules().canBeTinyLeadersCommander(); + break; case Oathbreaker: isLegalCommander = card.getRules().canBeOathbreaker(); captionSuffix = localizer.getMessage("lblOathbreaker"); diff --git a/forge-gui-mobile/src/forge/screens/home/LoadGameMenu.java b/forge-gui-mobile/src/forge/screens/home/LoadGameMenu.java index 47f4707f310..a875ea6c3ec 100644 --- a/forge-gui-mobile/src/forge/screens/home/LoadGameMenu.java +++ b/forge-gui-mobile/src/forge/screens/home/LoadGameMenu.java @@ -20,11 +20,11 @@ import forge.util.Localizer; public class LoadGameMenu extends FPopupMenu { public enum LoadGameScreen { - BoosterDraft("lblBoosterDraft", FSkinImage.HAND, LoadDraftScreen.class), - SealedDeck("lblSealedDeck", FSkinImage.PACK, LoadSealedScreen.class), + BoosterDraft("lblBoosterDraft", FSkinImage.MENU_DRAFT, LoadDraftScreen.class), + SealedDeck("lblSealedDeck", FSkinImage.MENU_SEALED, LoadSealedScreen.class), QuestMode("lblQuestMode", FSkinImage.QUEST_ZEP, LoadQuestScreen.class), - PlanarConquest("lblPlanarConquest", FSkinImage.MULTIVERSE, LoadConquestScreen.class), - Gauntlet("lblGauntlet", FSkinImage.ALPHASTRIKE, LoadGauntletScreen.class); + PlanarConquest("lblPlanarConquest", FSkinImage.MENU_GALAXY, LoadConquestScreen.class), + Gauntlet("lblGauntlet", FSkinImage.MENU_GAUNTLET, LoadGauntletScreen.class); private final FMenuItem item; private final Class screenClass; diff --git a/forge-gui-mobile/src/forge/screens/home/NewGameMenu.java b/forge-gui-mobile/src/forge/screens/home/NewGameMenu.java index 0bd6829888b..af3cb2e1b74 100644 --- a/forge-gui-mobile/src/forge/screens/home/NewGameMenu.java +++ b/forge-gui-mobile/src/forge/screens/home/NewGameMenu.java @@ -24,13 +24,13 @@ public class NewGameMenu extends FPopupMenu { final static Localizer localizer = Localizer.getInstance(); public enum NewGameScreen { - Constructed(localizer.getMessage("lblConstructed"), FSkinImage.DECKLIST, ConstructedScreen.class), - BoosterDraft(localizer.getMessage("lblBoosterDraft"), FSkinImage.HAND, NewDraftScreen.class), - SealedDeck(localizer.getMessage("lblSealedDeck"), FSkinImage.PACK, NewSealedScreen.class), + Constructed(localizer.getMessage("lblConstructed"), FSkinImage.MENU_CONSTRUCTED, ConstructedScreen.class), + BoosterDraft(localizer.getMessage("lblBoosterDraft"), FSkinImage.MENU_DRAFT, NewDraftScreen.class), + SealedDeck(localizer.getMessage("lblSealedDeck"), FSkinImage.MENU_SEALED, NewSealedScreen.class), QuestMode(localizer.getMessage("lblQuestMode"), FSkinImage.QUEST_ZEP, NewQuestScreen.class), - PuzzleMode(localizer.getMessage("lblPuzzleMode"), FSkinImage.QUEST_BOOK, PuzzleScreen.class), - PlanarConquest(localizer.getMessage("lblPlanarConquest"), FSkinImage.MULTIVERSE, NewConquestScreen.class), - Gauntlet(localizer.getMessage("lblGauntlet"), FSkinImage.ALPHASTRIKE, NewGauntletScreen.class); + PuzzleMode(localizer.getMessage("lblPuzzleMode"), FSkinImage.MENU_PUZZLE, PuzzleScreen.class), + PlanarConquest(localizer.getMessage("lblPlanarConquest"), FSkinImage.MENU_GALAXY, NewConquestScreen.class), + Gauntlet(localizer.getMessage("lblGauntlet"), FSkinImage.MENU_GAUNTLET, NewGauntletScreen.class); private final FMenuItem item; private final Class screenClass; diff --git a/forge-gui-mobile/src/forge/screens/home/puzzle/PuzzleScreen.java b/forge-gui-mobile/src/forge/screens/home/puzzle/PuzzleScreen.java index a740859f49b..0011ed4a6dc 100644 --- a/forge-gui-mobile/src/forge/screens/home/puzzle/PuzzleScreen.java +++ b/forge-gui-mobile/src/forge/screens/home/puzzle/PuzzleScreen.java @@ -54,36 +54,45 @@ public class PuzzleScreen extends LaunchScreen { final ArrayList puzzles = PuzzleIO.loadPuzzles(); Collections.sort(puzzles); - GuiChoose.one(Localizer.getInstance().getMessage("lblChooseAPuzzle"), puzzles, new Callback() { + GuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblChooseAPuzzle"), puzzles, new Callback() { @Override public void run(final Puzzle chosen) { - LoadingOverlay.show(Localizer.getInstance().getMessage("lblLoadingThePuzzle"), new Runnable() { - @Override - public void run() { - // Load selected puzzle - final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch(); - hostedMatch.setStartGameHook(new Runnable() { - @Override - public final void run() { - chosen.applyToGame(hostedMatch.getGame()); - } - }); + if (chosen != null) { + LoadingOverlay.show(Localizer.getInstance().getMessage("lblLoadingThePuzzle"), new Runnable() { + @Override + public void run() { + // Load selected puzzle + final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch(); + hostedMatch.setStartGameHook(new Runnable() { + @Override + public final void run() { + chosen.applyToGame(hostedMatch.getGame()); + } + }); - final List players = new ArrayList<>(); - final RegisteredPlayer human = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.getGuiPlayer()); - human.setStartingHand(0); - players.add(human); + hostedMatch.setEndGameHook((new Runnable() { + @Override + public void run() { + chosen.savePuzzleSolve(hostedMatch.getGame().getOutcome().isWinner(GamePlayerUtil.getGuiPlayer())); + } + })); - final RegisteredPlayer ai = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.createAiPlayer()); - ai.setStartingHand(0); - players.add(ai); + final List players = new ArrayList<>(); + final RegisteredPlayer human = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.getGuiPlayer()); + human.setStartingHand(0); + players.add(human); - GameRules rules = new GameRules(GameType.Puzzle); - rules.setGamesPerMatch(1); - hostedMatch.startMatch(rules, null, players, human, GuiBase.getInterface().getNewGuiGame()); - FOptionPane.showMessageDialog(chosen.getGoalDescription(), chosen.getName()); - } - }); + final RegisteredPlayer ai = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.createAiPlayer()); + ai.setStartingHand(0); + players.add(ai); + + GameRules rules = new GameRules(GameType.Puzzle); + rules.setGamesPerMatch(1); + hostedMatch.startMatch(rules, null, players, human, GuiBase.getInterface().getNewGuiGame()); + FOptionPane.showMessageDialog(chosen.getGoalDescription(), chosen.getName()); + } + }); + } } }); diff --git a/forge-gui-mobile/src/forge/screens/planarconquest/ConquestMenu.java b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestMenu.java index cffbd132a52..80ee1a8ff28 100644 --- a/forge-gui-mobile/src/forge/screens/planarconquest/ConquestMenu.java +++ b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestMenu.java @@ -56,7 +56,7 @@ public class ConquestMenu extends FPopupMenu { setCurrentScreen(collectionScreen); } }); - private static final FMenuItem statsItem = new FMenuItem(Localizer.getInstance().getMessage("lblStatistics"), FSkinImage.HDMULTI, new FEventHandler() { + private static final FMenuItem statsItem = new FMenuItem(Localizer.getInstance().getMessage("lblStatistics"), FSkinImage.MENU_STATS, new FEventHandler() { @Override public void handleEvent(FEvent e) { setCurrentScreen(statsScreen); diff --git a/forge-gui-mobile/src/forge/screens/planarconquest/ConquestRewardDialog.java b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestRewardDialog.java index e5086c2138c..239baa355d3 100644 --- a/forge-gui-mobile/src/forge/screens/planarconquest/ConquestRewardDialog.java +++ b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestRewardDialog.java @@ -244,10 +244,7 @@ public class ConquestRewardDialog extends FScrollPane { //ensure current card in view if (getScrollHeight() > getHeight() && index < cardCount) { CardRevealer currentCard = cardRevealers.get(index); - if (!Forge.extrawide.equals("default")) - scrollIntoView(currentCard, currentCard.getHeight() / (columnCount * PADDING) / 2); - else - scrollIntoView(currentCard, currentCard.getHeight() / 2 + PADDING); //show half of the card below + scrollIntoView(currentCard, currentCard.getHeight() / (columnCount * PADDING) / 2); } } diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestMenu.java b/forge-gui-mobile/src/forge/screens/quest/QuestMenu.java index 401852ee2e6..3cff3b41e84 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestMenu.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestMenu.java @@ -79,7 +79,7 @@ public class QuestMenu extends FPopupMenu implements IVQuestStats { setCurrentScreen(bazaarScreen); } }); - private static final FMenuItem statsItem = new FMenuItem(Localizer.getInstance().getMessage("lblStatistics"), FSkinImage.HDMULTI, new FEventHandler() { + private static final FMenuItem statsItem = new FMenuItem(Localizer.getInstance().getMessage("lblStatistics"), FSkinImage.MENU_STATS, new FEventHandler() { @Override public void handleEvent(FEvent e) { setCurrentScreen(statsScreen); diff --git a/forge-gui/res/blockdata/blocks.txt b/forge-gui/res/blockdata/blocks.txt index 3db02878fcb..67d158df0af 100644 --- a/forge-gui/res/blockdata/blocks.txt +++ b/forge-gui/res/blockdata/blocks.txt @@ -83,4 +83,5 @@ War of the Spark, 3/6/WAR, WAR Modern Horizons, 3/6/WAR, MH1 Core Set 2020, 3/6/M20, M20 Throne of Eldraine, 3/6/ELD, ELD -Theros Beyond Death, 3/6/THB, THB \ No newline at end of file +Theros Beyond Death, 3/6/THB, THB +Mystery Booster, 3/6/THB, MB1 \ No newline at end of file diff --git a/forge-gui/res/blockdata/printsheets.txt b/forge-gui/res/blockdata/printsheets.txt index fbb6d083c2b..3dc9401f5dd 100644 --- a/forge-gui/res/blockdata/printsheets.txt +++ b/forge-gui/res/blockdata/printsheets.txt @@ -1657,7 +1657,7 @@ Torbran, Thane of Red Fell|ELD|2 Feasting Troll King|ELD|2 Gilded Goose|ELD|2 The Great Henge|ELD|2 -Once Upon A Time|ELD|2 +Once Upon a Time|ELD|2 Questing Beast|ELD|2 Return of the Wildspeaker|ELD|2 Wicked Wolf|ELD|2 @@ -1778,4 +1778,1857 @@ Alseid of Life's Bounty|THB|2 Thirst for Meaning|THB|2 Gray Merchant of Asphodel|THB|2 Thrill of Possibility|THB|2 -Wolfwillow Haven|THB|2 \ No newline at end of file +Wolfwillow Haven|THB|2 + +[MB1 White CommonUncommon] +Abzan Falconer +Abzan Runemark +Acrobatic Maneuver +Adanto Vanguard +Affa Protector +Ainok Bond-Kin +Ajani's Pridemate +Alley Evasion +Angelic Gift +Angelic Purge +Angel of Mercy +Angel of Renewal +Angelsong +Apostle's Blessing +Arrest +Arrester's Zeal +Artful Maneuver +Aura of Silence +Aven Battle Priest +Aven Sentry +Ballynock Cohort +Bartered Cow +Battle Mastery +Benevolent Ancestor +Blade Instructor +Blessed Spirits +Bonds of Faith +Borrowed Grace +Built to Last +Bulwark Giant +Candlelight Vigil +Caravan Escort +Cartouche of Solidarity +Cast Out +Cathar's Companion +Caught in the Brights +Celestial Crusader +Celestial Flare +Center Soul +Champion of Arashin +Charge +Cliffside Lookout +Cloudshift +#Coalition Honor Guard +Collar the Culprit +Congregate +Conviction +Countless Gears Renegade +Court Homunculus +Court Street Denizen +Crib Swap +Danitha Capashen, Paragon +Daring Skyjek +Darksteel Mutation +Dauntless Cathar +Dawnglare Invoker +Decommission +Defiant Strike +Desperate Sentry +Devilthorn Fox +Disenchant +Dismantling Blow +Disposal Mummy +Divine Favor +Djeru's Renunciation +Djeru's Resolve +Doomed Traveler +Dragon Bell Monk +Dragon's Eye Sentry +Dragon's Presence +Eddytrail Hawk +Emerge Unscathed +Encampment Keeper +Encircling Fissure +Enduring Victory +Enlightened Ascetic +Ephemeral Shields +Ephemerate +Excavation Elephant +Excoriate +Expedition Raptor +Expose Evil +Exultant Skymarcher +Eyes in the Skies +Faithbearer Paladin +Faith's Fetters +Feat of Resistance +Felidar Guardian +Felidar Umbra +Fencing Ace +Fiend Hunter +Firehoof Cavalry +Forsake the Worldly +Fortify +Fragmentize +Geist of the Moors +Ghostblade Eidolon +Gideon's Lawkeeper +Gift of Estates +Glaring Aegis +Gleam of Resistance +Glint-Sleeve Artisan +God-Pharaoh's Faithful +Gods Willing +Grasp of the Hieromancer +Great-Horn Krushok +Guided Strike +Gustcloak Skirmisher +Gust Walker +Healer's Hawk +Healing Grace +Healing Hands +Heavy Infantry +Humble +Hyena Umbra +Infantry Veteran +Inquisitor's Ox +Inspired Charge +Intrusive Packbeast +Iona's Judgment +Isolation Zone +Jubilant Mascot +Knight of Cliffhaven +Knight of Old Benalia +Knight of Sorrows +Knight of the Skyward Eye +Knight of the Tusk +Kor Bladewhirl +Kor Firewalker +Kor Hookmaster +Kor Sky Climber +Kor Skyfisher +Leonin Relic-Warder +Lieutenants of the Guard +Lightform +Lightwalker +Lingering Souls +Lone Missionary +Lonesome Unicorn +Looming Altisaur +Lotus-Eye Mystics +Loxodon Partisan +Loyal Sentry +Lunarch Mantle +Mardu Hordechief +Marked by Honor +Meditation Puzzle +Midnight Guard +Momentary Blink +Moonlit Strider +Mortal's Ardor +Mother of Runes +Ninth Bridge Patrol +Nyx-Fleece Ram +Ondu Greathorn +Ondu War Cleric +Oreskos Swiftclaw +Oust +Pacifism +Palace Jailer +Palace Sentinels +Paladin of the Bloodstained +Path of Peace +Path to Exile +Peace of Mind +Pegasus Courser +Pentarch Ward +Pitfall Trap +Pressure Point +Promise of Bunrei +Prowling Caracal +Rally the Peasants +Raptor Companion +Refurbish +Renewed Faith +Resurrection +Retreat to Emeria +Reviving Dose +Rhet-Crop Spearmaster +Righteous Cause +Rootborn Defenses +Sacred Cat +Sanctum Gargoyle +Sandstorm Charger +Savannah Lions +Seal of Cleansing +Searing Light +Seeker of the Way +Sensor Splicer +Seraph of the Suns +Serra Disciple +Serra's Embrace +Sheer Drop +Shining Aerosaur +Shining Armor +Shoulder to Shoulder +Siegecraft +Silverchase Fox +Skyhunter Skirmisher +Skymarcher Aspirant +Skyspear Cavalry +Slash of Talons +Snubhorn Sentry +Soulmender +Soul Parry +Soul-Strike Technique +Soul Summons +Soul Warden +Sparring Mummy +Spectral Gateguards +Stalwart Aven +Star-Crowned Stag +Stave Off +Steadfast Sentinel +Stone Haven Medic +Sunlance +Sunrise Seeker +Suppression Bonds +Survive the Night +Swords to Plowshares +Take Vengeance +Tandem Tactics +Terashi's Grasp +Territorial Hammerskull +Thraben Inspector +Thraben Standard Bearer +Topan Freeblade +Unwavering Initiate +Veteran Swordsmith +Village Bell-Ringer +Voice of the Provinces +Wake the Reflections +Wall of Omens +Wall of One Thousand Cuts +Wandering Champion +War Behemoth +Wild Griffin +Windborne Charge +Winged Shepherd +Wing Shards +Youthful Knight +Zealous Strike + +[MB1 Blue CommonUncommon] +Academy Journeymage +Aethersnipe +Aether Spellbomb +Aether Tradewinds +Amass the Components +Amphin Pathmage +Anticipate +Arcane Denial +Archaeomancer +Archetype of Imagination +Artificer's Assistant +Augur of Bolas +Augury Owl +Bastion Inventor +Befuddle +Benthic Giant +Bewilder +Blue Elemental Blast +Borrowing 100,000 Arrows +Brainstorm +Brilliant Spectrum +Brine Elemental +Calculated Dismissal +Caller of Gales +Call to Heel +Cancel +Capture Sphere +Cartouche of Knowledge +Castaway's Despair +Catalog +Chart a Course +Chillbringer +Choking Tethers +Chronostutter +Circular Logic +Citywatch Sphinx +Claustrophobia +Clear the Mind +Cloak of Mists +Cloud Elemental +Cloudkin Seer +Cloudreader Sphinx +Clutch of Currents +Compelling Argument +Concentrate +Condescend +Containment Membrane +Contingency Plan +Contradict +Convolute +Coralhelm Guide +Coral Trickster +Counterspell +Court Hussar +Crashing Tide +Crush Dissent +Curiosity +Curio Vendor +Daze +Dazzling Lights +Decision Paralysis +Deep Analysis +Deep Freeze +Diminish +Dirgur Nemesis +Dispel +Displace +Distortion Strike +Divination +Doorkeeper +Dragon's Eye Savants +Drag Under +Dreadwaters +Dream Cache +Dream Twist +Eel Umbra +Embodiment of Spring +Enlightened Maniac +Ensoul Artifact +Errant Ephemeron +Essence Scatter +Everdream +Exclude +Fact or Fiction +Faerie Invaders +Faerie Mechanist +Failed Inspection +Fascination +Fathom Seer +Flashfreeze +Fledgling Mawcor +Fleeting Distraction +Fog Bank +Fogwalker +Foil +Forbidden Alchemy +Frantic Search +Frilled Sea Serpent +Frost Lynx +Gaseous Form +Ghost Ship +Glacial Crasher +Glint +Gone Missing +Grasp of Phantoms +Guard Gomazoa +Gurmag Drowner +Gush +Hieroglyphic Illumination +Hightide Hermit +Hinterland Drake +Horseshoe Crab +Humongulus +Impulse +Inkfathom Divers +Invisibility +Ior Ruin Expedition +Jace's Phantasm +Jeering Homunculus +Jeskai Sage +Jwar Isle Avenger +Kiora's Dambreaker +Laboratory Brute +Laboratory Maniac +Labyrinth Guardian +Lay Claim +Leapfrog +Mahamoti Djinn +Mana Leak +Man-o'-War +Maximize Altitude +Memory Lapse +Merfolk Looter +Messenger Jays +Metallic Rebuke +Mind Sculpt +Mist Raven +Mnemonic Wall +Monastery Loremaster +Mulldrifter +Murder of Crows +Mystical Teachings +Mystic of the Hidden Way +Nagging Thoughts +Negate +Niblis of Dusk +Nine-Tail White Fox +Ninja of the Deep Hours +Ojutai Interceptor +Ojutai's Breath +Omenspeaker +Opportunity +Opt +Peel from Reality +Phantasmal Bear +Phyrexian Ingester +Pondering Mage +Portent +Predict +Preordain +Prodigal Sorcerer +Propaganda +Prosperous Pirates +Purple-Crystal Crab +Refocus +Repulse +Retraction Helix +Riftwing Cloudskate +Ringwarden Owl +River Darter +River Serpent +Riverwheel Aerialists +Sage of Lat-Nam +Sailor of Means +Scroll Thief +Sea Gate Oracle +Sealock Monster +Secrets of the Golden City +Send to Sleep +Shaper Parasite +Shimmerscale Drake +Shipwreck Looter +Sigiled Starfish +Silent Observer +Silvergill Adept +Singing Bell Strike +Skaab Goliath +Skitter Eel +Skittering Crustacean +Sleep +Slipstream Eel +Slither Blade +Snap +Snapping Drake +Somber Hoverguard +Sphinx's Tutelage +Spire Monitor +Steady Progress +Stitched Drake +Storm Sculptor +Strategic Planning +Stream of Thought +Surrakar Banisher +Syncopate +Syr Elenora, the Discerning +Tandem Lookout +Temporal Fissure +Thornwind Faeries +Thoughtcast +Thought Collapse +Thought Scour +Thrummingbird +Thunder Drake +Tidal Warrior +Tidal Wave +Totally Lost +Trail of Evidence +Treasure Cruise +Treasure Hunt +Treasure Mage +Trinket Mage +Triton Tactics +Turn Aside +Uncomfortable Chill +Vapor Snag +Vigean Graftmage +Wall of Frost +Warden of Evos Isle +Watercourser +Wave-Wing Elemental +Weldfast Wingsmith +Welkin Tern +Whiplash Trap +Windcaller Aven +Wind Drake +Wind-Kin Raiders +Windrider Eel +Wind Strider +Wishcoin Crab +Wishful Merfolk +Write into Being +Youthful Scholar + +[MB1 Black CommonUncommon] +Absorb Vis +Accursed Spirit +Aid the Fallen +Alesha's Vanguard +Alley Strangler +Altar's Reap +Ambitious Aetherborn +Ancestral Vengeance +Animate Dead +Annihilate +Bala Ged Scorpion +Baleful Ammit +Balustrade Spy +Bartizan Bats +Bitter Revelation +Black Cat +Bladebrand +Blessing of Belzenlok +Blighted Bat +Blightsoil Druid +Blistergrub +Blood Artist +Bloodrite Invoker +Bone Splinters +Boon of Emrakul +Breeding Pit +Butcher's Glee +Cabal Therapy +Cackling Imp +Cadaver Imp +Caligo Skin-Witch +Carrion Feeder +Carrion Imp +Catacomb Crocodile +Catacomb Slug +Caustic Tar +Certain Death +Child of Night +Coat with Venom +Corpsehatch +Costly Plunder +Covenant of Blood +Cower in Fear +Crippling Blight +Crow of Dark Tidings +Cursed Minotaur +Daring Demolition +Darkblast +Dark Dabbling +Dark Ritual +Dark Withering +Deadbridge Shaman +Deadeye Tormentor +Dead Reveler +Death Denied +Defeat +Demonic Tutor +Demonic Vigor +Demon's Grasp +Desperate Castaways +Diabolic Edict +Die Young +Dinosaur Hunter +Dirge of Dread +Dismember +Disowned Ancestor +Doomed Dissenter +Douse in Gloom +Dreadbringer Lampads +Dread Drone +Dread Return +Dregscape Zombie +Driver of the Dead +Drudge Sentinel +Dukhara Scavenger +Dune Beetle +Duress +Dusk Charger +Dusk Legion Zealot +Epicure of Blood +Erg Raiders +Eternal Thirst +Evincar's Justice +Executioner's Capsule +Eyeblight's Ending +Fallen Angel +Farbog Revenant +Fatal Push +Fen Hauler +Feral Abomination +Festercreep +Festering Newt +Fetid Imp +Fill with Fright +First-Sphere Gargantua +Flesh to Dust +Fretwork Colony +Fungal Infection +Genju of the Fens +Ghostly Changeling +Ghoulcaller's Accomplice +Gifted Aetherborn +Go for the Throat +Grasping Scoundrel +Gravedigger +Gravepurge +Gray Merchant of Asphodel +Grim Affliction +Grim Discovery +Grixis Slavedriver +Grotesque Mutation +Gruesome Fate +Gurmag Angler +Hideous End +Hired Blade +Hound of the Farbogs +Induce Despair +Infernal Scarring +Infest +Innocent Blood +Inquisition of Kozilek +Instill Infection +Kalastria Nightwatch +Krumar Bond-Kin +Lawless Broker +Lazotep Behemoth +Lethal Sting +Lord of the Accursed +Macabre Waltz +Marauding Boneslasher +March of the Drowned +Mark of the Vampire +Marsh Hulk +Mephitic Vapors +Merciless Resolve +Miasmic Mummy +Mind Rake +Mind Rot +Mire's Malice +Moment of Craving +Murder +Murderous Compulsion +Nameless Inversion +Nantuko Husk +Never Happened +Night's Whisper +Nirkana Assassin +Noxious Dragon +Okiba-Gang Shinobi +Painful Lesson +Phyrexian Rager +Phyrexian Reclamation +Pit Keeper +Plaguecrafter +Plagued Rusalka +Plague Wight +Prakhata Club Security +Prowling Pangolin +Queen's Agent +Quest for the Gravelord +Rabid Bloodsucker +Rakdos Drake +Rakshasa's Secret +Ravenous Chupacabra +Read the Bones +Reaper of Night +Reassembling Skeleton +Reckless Imp +Reckless Spite +Recover +Renegade Demon +Renegade's Getaway +Returned Centaur +Revenant +Rite of the Serpent +Rotfeaster Maggot +Ruin Rat +Scarab Feast +Scrounger of Souls +Scuttling Death +Seal of Doom +Sengir Vampire +Shadowcloak Vampire +Shambling Attendants +Shambling Goblin +Shriekmaw +Silumgar Butcher +Skeletal Scrying +Skeleton Archer +Skulking Ghost +Smiting Helix +Spreading Rot +Stab Wound +Stallion of Ashmouth +Stinkweed Imp +Street Wraith +Stromkirk Patrol +Subtle Strike +Sultai Runemark +Tar Snare +Tavern Swindler +Tendrils of Corruption +Thallid Omnivore +The Eldest Reborn +Thornbow Archer +Thorn of the Black Rose +Thraben Foulbloods +Tidy Conclusion +Torment of Venom +Touch of Moonglove +Tragic Slip +Trespasser's Curse +Trial of Ambition +Twins of Maurer Estate +Typhoid Rats +Unburden +Undercity's Embrace +Untamed Hunger +Unyielding Krumar +Urborg Uprising +Vampire Champion +Vampire Envoy +Vampire Hexmage +Vampire Lacerator +Vampire Nighthawk +Vessel of Malignity +Virulent Swipe +Voracious Null +Vraska's Finisher +Wake of Vultures +Walking Corpse +Walk the Plank +Wander in Death +Warteye Witch +Weight of the Underworld +Weirded Vampire +Wight of Precinct Six +Will-o'-the-Wisp +Windgrace Acolyte +Wrench Mind +Yargle, Glutton of Urborg +Zulaport Chainmage + +[MB1 Red CommonUncommon] +Act of Treason +Act on Impulse +Ahn-Crop Crasher +Ainok Tracker +Akroan Sergeant +Alchemist's Greeting +Ancient Grudge +Anger +Arc Trail +Arrow Storm +Atarka Efreet +Avarax +Azra Bladeseeker +Balduvian Horde +Barging Sergeant +Barrage of Boulders +Battle Rampart +Battle-Rattle Shaman +Beetleback Chief +Bellows Lizard +Blades of Velis Vel +Blastfire Bolt +Blazing Volley +Blindblast +Bloodfire Expert +Bloodlust Inciter +Bloodmad Vampire +Blood Ogre +Bloodstone Goblin +Blow Your House Down +Blur of Blades +Boggart Brute +Boiling Earth +Bombard +Bomber Corps +Borrowed Hostility +Boulder Salvo +Brazen Buccaneers +Brazen Wolves +Bring Low +Browbeat +Brute Strength +Built to Smash +Burst Lightning +Canyon Lurkers +Cartouche of Zeal +Cathartic Reunion +Chandra's Pyrohelix +Chandra's Revolution +Charging Monstrosaur +Chartooth Cougar +Cinder Hellion +Cleansing Screech +Cobblebrute +Cosmotronic Wave +Crash Through +Crowd's Favor +Crown-Hunter Hireling +Curse of Opulence +Curse of the Nightly Hunt +Death by Dragons +Defiant Ogre +Demolish +Desert Cerodon +Desperate Ravings +Destructive Tampering +Direct Current +Distemper of the Blood +Dragon Breath +Dragon Egg +Dragon Fodder +Dragonsoul Knight +Dragon Whelp +Dual Shot +Dynacharge +Earth Elemental +Emrakul's Hatcher +Enthralling Victor +Erratic Explosion +Expedite +Faithless Looting +Falkenrath Reaver +Fall of the Hammer +Fervent Strike +Fierce Invocation +Fiery Hellhound +Fiery Temper +Fireball +Firebolt +Firebrand Archer +Fire Elemental +Flame Jab +Flametongue Kavu +Flamewave Invoker +Fling +Forge Devil +Foundry Street Denizen +Frenzied Raptor +Frilled Deathspitter +Frontline Devastator +Frontline Rebel +Furnace Whelp +Fury Charm +Galvanic Blast +Generator Servant +Genju of the Spires +Geomancer's Gambit +Ghitu Lavarunner +Giant Spectacle +Goblin Assault +Goblin Balloon Brigade +Goblin Bombardment +Goblin Fireslinger +Goblin Locksmith +Goblin Matron +Goblin Motivator +Goblin Oriflamme +Goblin Roughrider +Goblin Warchief +Goblin War Paint +Gorehorn Minotaurs +Gore Swine +Granitic Titan +Grapeshot +Gravitic Punch +Gut Shot +Guttersnipe +Hammerhand +Hanweir Lancer +Hardened Berserker +Hijack +Hulking Devil +Hyena Pack +Ill-Tempered Cyclops +Impact Tremors +Incorrigible Youths +Inferno Fist +Inferno Jet +Ingot Chewer +Insolent Neonate +Jackal Pup +Keldon Halberdier +Keldon Overseer +Khenra Scrapper +Kiln Fiend +Kird Ape +Kolaghan Stormsinger +Krenko's Command +Krenko's Enforcer +Leaping Master +Leopard-Spotted Jiao +Lightning Bolt +Lightning Javelin +Lightning Shrieker +Lightning Talons +Madcap Skills +Magma Spray +Makindi Sliderunner +Mardu Warshrieker +Mark of Mutiny +Maximize Velocity +Miner's Bane +Mogg Fanatic +Mogg Flunkies +Mogg War Marshal +Molten Rain +Monastery Swiftspear +Mutiny +Nimble-Blade Khenra +Ondu Champion +Orcish Cannonade +Orcish Oriflamme +Outnumber +Pillage +Price of Progress +Prickleboar +Prophetic Ravings +Pyrotechnics +Quakefoot Cyclops +Rampaging Cyclops +Reckless Fireweaver +Reckless Wurm +Renegade Tactics +Rivals' Duel +Roast +Rolling Thunder +Rubblebelt Maaka +Ruinous Gremlin +Rummaging Goblin +Run Amok +Rush of Adrenaline +Salivating Gremlins +Samut's Sprint +Sarkhan's Rage +Screamreach Brawler +Seismic Shift +Seismic Stomp +Shatter +Shattering Spree +Shenanigans +Shock +Skirk Commando +Skirk Prospector +Smash to Smithereens +Smelt +Sparkmage Apprentice +Sparkspitter +Sparktongue Dragon +Spikeshot Goblin +Staggershock +Stormblood Berserker +Sulfurous Blast +Summit Prowler +Sun-Crowned Hunters +Swashbuckling +Sweatworks Brawler +Swift Kick +Tarfire +Tectonic Rift +Temur Battle Rage +Thresher Lizard +Thrill of Possibility +Tibalt's Rager +Torch Courier +Uncaged Fury +Undying Rage +Valakut Invoker +Valakut Predator +Valley Dasher +Vandalize +Vent Sentinel +Vessel of Volatility +Volcanic Dragon +Volcanic Rush +Voldaren Duelist +Wall of Fire +Wayward Giant +Wildfire Emissary +Wojek Bodyguard +Young Pyromancer +Zada's Commando +Zealot of the God-Pharaoh + +[MB1 Green CommonUncommon] +Abundant Growth +Acidic Slime +Adventurous Impulse +Aerie Bowmasters +Affectionate Indrik +Aggressive Instinct +Aggressive Urge +Ainok Survivalist +Alpine Grizzly +Ambassador Oak +Ancestral Mask +Ancient Brontodon +Ancient Stirrings +Arachnus Web +Arbor Armament +Arbor Elf +Aura Gnarlid +Avacyn's Pilgrim +Backwoods Survivalists +Baloth Gorger +Basking Rootwalla +Beastbreaker of Bala Ged +Beast Within +Become Immense +Beneath the Sands +Bestial Menace +Bitterblade Warrior +Bitterbow Sharpshooters +Blanchwood Armor +Blastoderm +Blossom Dryad +Borderland Explorer +Borderland Ranger +Briarhorn +Bristling Boar +Broken Bond +Broodhunter Wurm +Byway Courier +Canopy Spider +Carnivorous Moss-Beast +Caustic Caterpillar +Centaur Courser +Charging Rhino +Citanul Woodreaders +Clip Wings +Colossal Dreadmaw +Combo Attack +Commune with Nature +Commune with the Gods +Conifer Strider +Creeping Mold +Crop Rotation +Crossroads Consecrator +Crowned Ceratok +Crushing Canopy +Cultivate +Daggerback Basilisk +Dawn's Reflection +Death-Hood Cobra +Desert Twister +Destructor Dragon +Dissenter's Deliverance +Domesticated Hydra +Dragonscale Boon +Dragon-Scarred Bear +Durkwood Baloth +Earthen Arms +Elemental Uprising +Elephant Guide +Elves of Deep Shadow +Elvish Fury +Elvish Visionary +Elvish Warrior +Ember Weaver +Epic Confrontation +Essence Warden +Eternal Witness +Experiment One +Explore +Explosive Vegetation +Ezuri's Archers +Fade into Antiquity +Farseek +Feed the Clan +Feral Krushok +Feral Prowler +Ferocious Zheng +Fertile Ground +Fierce Empath +Fog +Formless Nurturing +Frontier Mastodon +Gaea's Blessing +Gaea's Protector +Giant Growth +Giant Spider +Gift of Growth +Gift of Paradise +Glade Watcher +Gnarlid Pack +Grapple with the Past +Grazing Gladehart +Greater Basilisk +Greater Sandwurm +Greenwood Sentinel +Groundswell +Guardian Shield-Bearer +Hamlet Captain +Hardy Veteran +Harmonize +Harrow +Hooded Brawler +Hooting Mandrills +Hunter's Ambush +Hunt the Weak +Imperious Perfect +Invigorate +Ivy Lane Denizen +Jungle Delver +Jungle Wayfinder +Kavu Climber +Kavu Primarch +Khalni Heart Expedition +Kin-Tree Warden +Kozilek's Predator +Kraul Foragers +Kraul Warrior +Krosan Druid +Krosan Tusker +Larger Than Life +Lay of the Land +Lead by Example +Lead the Stampede +Lifespring Druid +Lignify +Llanowar Elves +Llanowar Empath +Longshot Squad +Lure +Manglehorn +Mantle of Webs +Map the Wastes +Might of the Masses +Mulch +Natural Connection +Naturalize +Nature's Claim +Nature's Lore +Nest Invader +Nettle Sentinel +New Horizons +Nimble Mongoose +Oakgnarl Warrior +Ondu Giant +Oran-Rief Invoker +Overgrown Armasaur +Overgrown Battlement +Overrun +Pack's Favor +Peema Outrider +Pelakka Wurm +Penumbra Spider +Pierce the Sky +Pinion Feast +Plummet +Pouncing Cheetah +Prey's Vengeance +Prey Upon +Priest of Titania +Pulse of Murasa +Quiet Disrepair +Rain of Thorns +Rampant Growth +Rancor +Ranger's Guile +Ravenous Leucrocota +Reclaim +Reclaiming Vines +Regrowth +Relic Crush +Return to the Earth +Revive +Rhox Maulers +Riparian Tiger +Roar of the Wurm +Root Out +Roots +Rosethorn Halberd +Runeclaw Bear +Sagu Archer +Sakura-Tribe Elder +Saproling Migration +Savage Punch +Scatter the Seeds +Seal of Strength +Search for Tomorrow +Seek the Horizon +Seek the Wilds +Shape the Sands +Siege Wurm +Silhana Ledgewalker +Silkweaver Elite +Snake Umbra +Snapping Sailback +Spider Spawning +Stalking Tiger +Stoic Builder +Strength in Numbers +Sylvan Bounty +Sylvan Scrying +Tajuru Pathwarden +Tajuru Warcaller +Take Down +Talons of Wildwood +Terrain Elemental +Territorial Baloth +#The Crowd Goes Wild +Thornhide Wolves +Thornscape Battlemage +Thornweald Archer +Thrashing Brontodon +Thrive +Timberwatch Elf +Time to Feed +Titanic Growth +Tukatongue Thallid +Turntimber Basilisk +Vastwood Gorger +Venom Sliver +Watcher in the Web +Wellwisher +Wild Growth +Wild Mongrel +Wildsize +Wolfkin Bond +Woodborn Behemoth +Woolly Loxodon +Wren's Run Vanquisher +Yavimaya Elder +Yavimaya Sapherd +Yeva's Forcemage +Zendikar's Roil + +[MB1 Multi CommonUncommon] +Azorius Charm +Cunning Breezedancer +Ethercaste Knight +Kiss of the Amesha +Lawmage's Binding +Migratory Route +Mistmeadow Witch +Raff Capashen, Ship's Mage +Reflector Mage +Riptide Crab +Agony Warp +Baleful Strix +Call of the Nightwing +Contraband Kingpin +Deny Reality +Extract from Darkness +Kathari Remnant +Shipwreck Singer +Soul Manipulation +Thought Erasure +Azra Oddsmaker +Bituminous Blast +Bladewing the Risen +Blightning +Cauldron Dance +Claim // Fame +Goblin Deathraiders +Shambling Remains +Terminate +Unlicensed Disintegration +Bloodbraid Elf +Draconic Disciple +Fires of Yavimaya +Ghor-Clan Rampager +Giantbaiting +Raging Swordtooth +Rosheen Meanderer +Savage Twister +Treacherous Terrain +Vengeful Rebirth +Zhur-Taa Druid +Armadillo Cloak +Belligerent Brontodon +Citadel Castellan +Engineered Might +Join Shields +Pollenbright Wings +Qasali Pridemage +Rosemane Centaur +Satyr Enchanter +Selesnya Guildmage +Unflinching Courage +Wayfaring Temple +Campaign of Vengeance +Drana's Emissary +Gift of Orzhova +Gwyllion Hedge-Mage +Hidden Stockpile +Mortify +Pillory of the Sleepless +Tithe Drinker +Underworld Coinsmith +Zealous Persecution +Fire // Ice +Gelectrode +Hypothesizzle +Maverick Thopterist +Mercurial Geists +Nucklavee +Reclusive Artificer +Shrewd Hatchling +Stormchaser Chimera +Wee Dragonauts +Baloth Null +Corpsejack Menace +Deathreap Ritual +Grim Contest +Kin-Tree Invocation +Obelisk Spider +Ochran Assassin +Putrefy +Winding Constrictor +Akroan Hoplite +Boros Challenger +Flame-Kin Zealot +Hammer Dropper +Highspire Mantis +Iroas's Champion +Lightning Helix +Martial Glory +Weapons Trainer +Bounding Krasis +Coiling Oracle +Ethereal Ambush +Jungle Barrier +Kiora's Follower +Plaxcaster Frogling +River Hoopoe +Shardless Agent +Tatyova, Benthic Druid +Urban Evolution +Esper Charm +Thopter Foundry +Tower Gargoyle +Crosis's Charm +Sedraxis Specter +Slave of Bolas +Sprouting Thrinax +Naya Charm +Woolly Thoctar +Rhox War Monk +Skyward Eye Prophets +Mardu Roughrider +Bear's Companion +Abzan Charm +Abzan Guide +Armament Corps +Warden of the Eye +Sultai Charm +Sultai Soothsayer +Fusion Elemental + +[MB1 Artifact Land CommonUncommon] +Blinding Souleater +Benthic Infiltrator +Wretched Gryff +Implement of Malice +Call the Scions +Gruul Signet +Simic Locket +Alchemist's Vial +Alloy Myr +Armillary Sphere +Artisan of Kozilek +Ashnod's Altar +Bomat Bazaar Barge +Bone Saw +Bottle Gnomes +Breaker of Armies +Burnished Hart +Cathodion +Coldsteel Heart +Consulate Dreadnought +Copper Carapace +Crystal Ball +Crystal Chimes +Diamond Mare +Eldrazi Devastator +Emmessi Tome +Etched Oracle +Farmstead Gleaner +Filigree Familiar +Flayer Husk +Foundry Inspector +Fountain of Renewal +Frogmite +Guardians of Meletis +Heavy Arbalest +Herald's Horn +Hexplate Golem +Hot Soup +Icy Manipulator +Irontread Crusher +Juggernaut +Lightning Greaves +Loxodon Warhammer +Mask of Memory +Meteorite +Millikin +Millstone +Mind Stone +Mishra's Bauble +Moonglove Extract +Mortarpod +Myr Retriever +Myr Sire +Ornithopter +Palladium Myr +Peace Strider +Perilous Myr +Pilgrim's Eye +Prophetic Prism +Renegade Map +Rhonas's Monument +Sandstone Oracle +Serrated Arrows +Short Sword +Sigil of Valor +Skullclamp +Skyscanner +Sol Ring +Sorcerer's Broom +Spy Kit +Sunset Pyramid +Suspicious Bookcase +Thought Vessel +Thran Dynamo +Thran Golem +Tormod's Crypt +Trepanation Blade +Universal Automaton +Universal Solvent +Whispersilk Cloak +New Benalia +Faerie Conclave +Blighted Fen +Bojuka Bog +Forgotten Cave +Goblin Burrows +Great Furnace +Wirewood Lodge +Sejiri Refuge +Dismal Backwater +Dreadship Reef +Akoum Refuge +Kazandu Refuge +Skarrg, the Rage Pits +Blossoming Sands +Graypelt Refuge +Orzhov Basilica +Scoured Barrens +Swiftwater Cliffs +Jungle Hollow +Thornwood Falls +Arcane Sanctum +Crumbling Necropolis +Jungle Shrine +Frontier Bivouac +Sandsteppe Citadel +Aether Hub +Ash Barrens +Blasted Landscape +Darksteel Citadel +Evolving Wilds +Field of Ruin +Gateway Plaza +Ghost Quarter +Krosan Verge +Mishra's Factory +Reliquary Tower +Rogue's Passage +Tectonic Edge +Temple of the False God +Unclaimed Territory + +[MB1 Pre M15] +Ana Sanctuary +Ancient Den +Ancient Ziggurat +Angelic Destiny +Archangel +Asceticism +Assemble the Legion +Athreos, God of Passage +Aura Shards +Avalanche Riders +Bear Cub +Belbe's Portal +Black Knight +Bloom Tender +Bonesplitter +Bow of Nylea +Brimstone Dragon +Brimstone Mage +Cairn Wanderer +Carpet of Flowers +Centaur Glade +Chancellor of the Annex +Chatter of the Squirrel +Chromatic Star +Contagion Clasp +Corrupted Conscience +Cragganwick Cremator +Crenellated Wall +Crystal Shard +Darksteel Garrison +Dauthi Mindripper +Defense of the Heart +Dictate of Erebos +Dolmen Gate +Dominus of Fealty +Doomgape +Draco +Dragon Broodmother +Dragon Mask +Dungrove Elder +Eater of Days +Elixir of Immortality +Empyrial Armor +Enchanted Evening +Energy Field +Exsanguinate +Flameshot +Floodgate +Font of Mythos +Ghitu War Cry +Gilt-Leaf Palace +Goblin Game +Greater Gargadon +Guided Passage +Haakon, Stromgald Scourge +Hedron Crab +Helm of Awakening +Hunter of Eyeblights +Hurricane +Hypnotic Specter +Impending Disaster +Jushi Apprentice +Kaervek's Torch +Kargan Dragonlord +Knight of Dawn +Knollspine Dragon +Kor Chant +Kruphix, God of Horizons +Lashknife Barrier +Lotus Petal +Maelstrom Archangel +Magus of the Moat +Mana Tithe +Manamorphose +Martyr's Bond +Martyr's Cause +Master Transmuter +Meddling Mage +Mistform Shrieker +Nemesis of Reason +Oracle of Nectars +Pathrazer of Ulamog +Perish +Pestilence +Phantasmal Dragon +Phantom Centaur +Phyrexian Metamorph +Phyrexian Soulgorger +Purphoros, God of the Forge +Questing Phelddagrif +Rage Reflection +Recoup +Release the Ants +Rhys the Redeemed +Rhystic Study +Rishadan Footpad +Rith, the Awakener +River Boa +Sadistic Hypnotist +Sakashima the Impostor +Sapphire Charm +Shrouded Lore +Soothsaying +Sorin Markov +Squirrel Wrangler +Thieving Magpie +Thrun, the Last Troll +Time Sieve +Timely Reinforcements +Tinker +Tower of Eons +Toxin Sliver +Triumph of the Hordes +Umbral Mantle +Viashino Sandstalker +Violent Ultimatum +Volunteer Reserves +Wargate +Weathered Wayfarer +Wild Nacatl +Yavimaya's Embrace + +[MB1 Post M15 RareMythic] +Adorned Pouncer +Aetherflux Reservoir +Akroan Horse +Alesha, Who Smiles at Death +Alhammarret's Archive +All Is Dust +Aminatou's Augury +Angel of the Dire Hour +Anger of the Gods +Animar, Soul of Elements +Approach of the Second Sun +Arch of Orazca +Basilisk Collar +Beacon of Immortality +Beastmaster Ascension +Birds of Paradise +Black Market +Boompile +Boros Reckoner +Caged Sun +Cauldron of Souls +Champion of the Parish +Chaos Warp +Chasm Skulker +Chromatic Lantern +Coat of Arms +Collective Brutality +Commit // Memory +Courser of Kruphix +Coveted Jewel +Daretti, Scrap Savant +Deadly Tempest +Debtors' Knell +Decree of Justice +Deepglow Skate +Desolation Twin +Dictate of Heliod +Djinn of Wishes +Dragonlord Ojutai +Drana, Kalastria Bloodchief +Eldrazi Monument +Eldritch Evolution +Elesh Norn, Grand Cenobite +Evra, Halcyon Witness +#Expropriate +Fblthp, the Lost +Felidar Sovereign +Gideon Jura +Goblin Charbelcher +Goblin Piledriver +Gonti, Lord of Luxury +Grasp of Fate +Grave Titan +Gravecrawler +Greenbelt Rampager +Hornet Nest +Kiki-Jiki, Mirror Breaker +Kolaghan's Command +Krenko, Mob Boss +Liliana, Death's Majesty +Living Death +Mana Crypt +Meandering Towershell +Memory Erosion +Meren of Clan Nel Toth +Mimic Vat +Mind Shatter +Mind Spring +Mirran Crusader +Mirror Entity +Misdirection +Mizzix's Mastery +Mycoloth +Mystic Confluence +Nighthowler +Nin, the Pain Artist +Nissa, Voice of Zendikar +Odric, Lunarch Marshal +Phyrexian Arena +Phyrexian Plaguelord +Precursor Golem +Preyseizer Dragon +Queen Marchesa +Reality Scramble +Recruiter of the Guard +Release the Gremlins +Revel in Riches +Rune-Scarred Demon +Savage Knuckleblade +Selvala, Heart of the Wilds +Serendib Efreet +Sewer Nemesis +Shamanic Revelation +Sliver Hivelord +Solemn Simulacrum +Spawning Grounds +Star of Extinction +Steamflogger Boss +Stunt Double +Sudden Demise +Supreme Verdict +Sword of the Animist +Talrand, Sky Summoner +Taurean Mauler +Teferi's Protection +Teferi, Temporal Archmage +Temporal Mastery +Tempt with Discovery +Thalia's Lancers +The Gitrog Monster +The Mirari Conjecture +Tireless Tracker +Torment of Hailfire +Trading Post +Two-Headed Giant +Urza's Rage +Vigor +Wheel of Fate +Whelming Wave +Whir of Invention +Yuriko, the Tiger's Shadow + +[FMB1 Foils] +Not of This World+|FMB1 +Celestial Dawn+|FMB1 +Celestial Kirin+|FMB1 +Changeling Hero+|FMB1 +Council Guardian+|FMB1 +Eidolon of Rhetoric+|FMB1 +Isamaru, Hound of Konda+|FMB1 +Lapse of Certainty+|FMB1 +Lumithread Field+|FMB1 +Norn's Annex+|FMB1 +Proclamation of Rebirth+|FMB1 +Pull from Eternity+|FMB1 +Rune-Tail, Kitsune Ascendant+|FMB1 +Sinew Sliver+|FMB1 +Soul's Attendant+|FMB1 +Spelltithe Enforcer+|FMB1 +Springjack Shepherd+|FMB1 +Wall of Shards+|FMB1 +White Knight+|FMB1 +Blighted Agent+|FMB1 +Delay+|FMB1 +Fatespinner+|FMB1 +Frozen Aether+|FMB1 +Grand Architect+|FMB1 +Intruder Alarm+|FMB1 +Misthollow Griffin+|FMB1 +Paradox Haze+|FMB1 +Patron of the Moon+|FMB1 +Puca's Mischief+|FMB1 +Spellweaver Volute+|FMB1 +Storm Crow+|FMB1 +Zur's Weirding+|FMB1 +Bringer of the Black Dawn+|FMB1 +Chimney Imp+|FMB1 +Conspiracy+|FMB1 +Echoing Decay+|FMB1 +Funeral Charm+|FMB1 +Herald of Leshrac+|FMB1 +Marrow-Gnawer+|FMB1 +Nezumi Shortfang+|FMB1 +One with Nothing+|FMB1 +Ravenous Trap+|FMB1 +Rescue from the Underworld+|FMB1 +Undead Warchief+|FMB1 +Viscera Seer+|FMB1 +Balduvian Rage+|FMB1 +Braid of Fire+|FMB1 +Burning Inquiry+|FMB1 +Fiery Gambit+|FMB1 +Flamekin Harbinger+|FMB1 +Form of the Dragon+|FMB1 +Goblin Bushwhacker+|FMB1 +Guerrilla Tactics+|FMB1 +Lightning Storm+|FMB1 +Norin the Wary+|FMB1 +Ogre Gatecrasher+|FMB1 +Pyretic Ritual+|FMB1 +Scourge of the Throne+|FMB1 +Stigma Lasher+|FMB1 +Treasonous Ogre+|FMB1 +Allosaurus Rider+|FMB1 +Archetype of Endurance+|FMB1 +Boreal Druid+|FMB1 +Boundless Realms+|FMB1 +Bramblewood Paragon+|FMB1 +Fungusaur+|FMB1 +Game-Trail Changeling+|FMB1 +Gleeful Sabotage+|FMB1 +Greater Mossdog+|FMB1 +Helix Pinnacle+|FMB1 +Hornet Sting+|FMB1 +Manaweft Sliver+|FMB1 +Maro+|FMB1 +Myojin of Life's Web+|FMB1 +Panglacial Wurm+|FMB1 +Reki, the History of Kamigawa+|FMB1 +Rhox+|FMB1 +Sakura-Tribe Scout+|FMB1 +Scryb Ranger+|FMB1 +Sheltering Ancient+|FMB1 +Sosuke, Son of Seshiro+|FMB1 +Spike Feeder+|FMB1 +Aurelia's Fury+|FMB1 +Drogskol Captain+|FMB1 +Glittering Wish+|FMB1 +Harmonic Sliver+|FMB1 +Karrthus, Tyrant of Jund+|FMB1 +Maelstrom Nexus+|FMB1 +Mind Funeral+|FMB1 +Sarkhan the Mad+|FMB1 +Sen Triplets+|FMB1 +Yore-Tiller Nephilim+|FMB1 +Balefire Liege+|FMB1 +Gilder Bairn+|FMB1 +Kulrath Knight+|FMB1 +Noggle Bandit+|FMB1 +Wear // Tear+|FMB1 +Amulet of Vigor+|FMB1 +Blasting Station+|FMB1 +Codex Shredder+|FMB1 +Geth's Grimoire+|FMB1 +Iron Myr+|FMB1 +Knowledge Pool+|FMB1 +Lantern of Insight+|FMB1 +Leveler+|FMB1 +Lich's Mirror+|FMB1 +Magewright's Stone+|FMB1 +Memnite+|FMB1 +Mindslaver+|FMB1 +Pili-Pala+|FMB1 +Reaper King+|FMB1 +Sundial of the Infinite+|FMB1 +Teferi's Puzzle Box+|FMB1 +Trailblazer's Boots+|FMB1 +Triskelion+|FMB1 +Witchbane Orb+|FMB1 +Alchemist's Refuge+|FMB1 +Minamo, School at Water's Edge+|FMB1 +Mirrodin's Core+|FMB1 +Shizo, Death's Storehouse+|FMB1 +Stalking Stones+|FMB1 + +[CN2 Not In Normal Slots] +Adriana's Valor +#Assemble the Rank and Vile +Echoing Boon +#Emissary's Ploy +Hired Heist +#Hold the Permiter +Hymn of the Wilds +Incendiary Dissent +Natural Unity +#Sovereign's Realm +#Summoner's Bond +Weight Advantage +Kaya, Ghost Assassin|CN2|2 + +[CN2 Foil Kaya] +Kaya, Ghost Assassin|CN2|2 diff --git a/forge-gui/res/cardsfolder/c/cavalier_of_dawn.txt b/forge-gui/res/cardsfolder/c/cavalier_of_dawn.txt index 513fd7f037c..601d7d96ee4 100644 --- a/forge-gui/res/cardsfolder/c/cavalier_of_dawn.txt +++ b/forge-gui/res/cardsfolder/c/cavalier_of_dawn.txt @@ -4,8 +4,9 @@ Types:Creature Elemental Knight PT:4/6 K:Vigilance T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDestroy | TriggerDescription$ When CARDNAME enters the battlefield, destroy up to one target nonland permanent. Its controller creates a 3/3 colorless Golem artifact creature token. -SVar:TrigDestroy:DB$ Destroy | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | SubAbility$ DBToken -SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_3_3_a_golem | TokenOwner$ TargetedController | LegacyImage$ c 3 3 a golem m20 +SVar:TrigDestroy:DB$ Destroy | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | RememberLKI$ True | SubAbility$ DBToken +SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_3_3_a_golem | TokenOwner$ RememberedController | LegacyImage$ c 3 3 a golem m20 | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigChangeZone | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, return target artifact or enchantment card from your graveyard to your hand. SVar:TrigChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | ValidTgts$ Artifact.YouCtrl,Enchantment.YouCtrl Oracle:Vigilance\nWhen Cavalier of Dawn enters the battlefield, destroy up to one target nonland permanent. Its controller creates a 3/3 colorless Golem artifact creature token.\nWhen Cavalier of Dawn dies, return target artifact or enchantment card from your graveyard to your hand. diff --git a/forge-gui/res/cardsfolder/d/dissenters_delivery.txt b/forge-gui/res/cardsfolder/d/dissenters_deliverance.txt similarity index 100% rename from forge-gui/res/cardsfolder/d/dissenters_delivery.txt rename to forge-gui/res/cardsfolder/d/dissenters_deliverance.txt diff --git a/forge-gui/res/cardsfolder/g/ghastly_demise.txt b/forge-gui/res/cardsfolder/g/ghastly_demise.txt index 78ced7746b3..f04b0f2ac15 100644 --- a/forge-gui/res/cardsfolder/g/ghastly_demise.txt +++ b/forge-gui/res/cardsfolder/g/ghastly_demise.txt @@ -1,7 +1,7 @@ Name:Ghastly Demise ManaCost:B Types:Instant -A:SP$ Destroy | Cost$ B | ValidTgts$ Creature.nonBlack+toughnessLEX | TgtPrompt$ Select target nonblack creature with toughness less than or equal to the number of cards in your graveyard. | References$ X | SpellDescription$ Destroy target nonblack creature if its toughness is less than or equal to the number of cards in your graveyard. +A:SP$ Destroy | Cost$ B | ValidTgts$ Creature.nonBlack | TgtPrompt$ Select target nonblack creature | ConditionCheckSVar$ Y | ConditionSVarCompare$ LEX | References$ X,Y | StackDescription$ SpellDescription | SpellDescription$ Destroy target nonblack creature if its toughness is less than or equal to the number of cards in your graveyard. +SVar:Y:Targeted$CardToughness SVar:X:Count$InYourYard -SVar:Picture:http://www.wizards.com/global/images/magic/general/ghastly_demise.jpg Oracle:Destroy target nonblack creature if its toughness is less than or equal to the number of cards in your graveyard. diff --git a/forge-gui/res/cardsfolder/j/joust.txt b/forge-gui/res/cardsfolder/j/joust.txt index 9d4c5ba84f4..d68d4eeb6f6 100644 --- a/forge-gui/res/cardsfolder/j/joust.txt +++ b/forge-gui/res/cardsfolder/j/joust.txt @@ -1,7 +1,7 @@ Name:Joust ManaCost:1 R Types:Sorcery -A:SP$ Pump | Cost$ 1 R | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | NumAtt$ +2 | NumDef$ +1 | ConditionDefined$ ThisTargetedCard | ConditionPresent$ Knight | SubAbility$ DBFight | SpellDescription$ Choose target creature you control and target creature you don't control. The creature you control gets +2/+1 until end of turn if it's a Knight. Then those creatures fight each other. (Each deals damage equal to its power to the other.) +A:SP$ Pump | Cost$ 1 R | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | NumAtt$ +2 | NumDef$ +1 | AILogic$ Fight | ConditionDefined$ ThisTargetedCard | ConditionPresent$ Knight | SubAbility$ DBFight | SpellDescription$ Choose target creature you control and target creature you don't control. The creature you control gets +2/+1 until end of turn if it's a Knight. Then those creatures fight each other. (Each deals damage equal to its power to the other.) SVar:DBFight:DB$ Fight | Defined$ ParentTarget | ValidTgts$ Creature.YouDontCtrl | AILogic$ Always | TgtPrompt$ Choose target creature you don't control DeckHints:Type$Knight Oracle:Choose target creature you control and target creature you don't control. The creature you control gets +2/+1 until end of turn if it's a Knight. Then those creatures fight each other. (Each deals damage equal to its power to the other.) diff --git a/forge-gui/res/cardsfolder/n/nissas_pilgrimage.txt b/forge-gui/res/cardsfolder/n/nissas_pilgrimage.txt index 3ad0c877919..f89143a06a0 100644 --- a/forge-gui/res/cardsfolder/n/nissas_pilgrimage.txt +++ b/forge-gui/res/cardsfolder/n/nissas_pilgrimage.txt @@ -1,9 +1,10 @@ Name:Nissa's Pilgrimage ManaCost:2 G Types:Sorcery -A:SP$ ChangeZone | Cost$ 2 G | Origin$ Library | Destination$ Battlefield | Tapped$ True | ChangeType$ Land.Basic+Forest | ChangeNum$ 1 | SubAbility$ DBChangeZone1 | NoShuffle$ True | SpellDescription$ Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle your library. Spell mastery — If there are two or more instant or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two. -SVar:DBChangeZone1:DB$ChangeZone | Origin$ Library | Destination$ Hand | SubAbility$ DBChangeZone2 | ChangeType$ Land.Basic+Forest | ChangeNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ LT2 | References$ X -SVar:DBChangeZone2:DB$ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Land.Basic+Forest | ChangeNum$ 2 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE2 | References$ X -SVar:X:Count$ValidGraveyard Instant.YouOwn,Sorcery.YouOwn -SVar:Picture:http://www.wizards.com/global/images/magic/general/nissas_pilgrimage.jpg +A:SP$ ChangeZone | Cost$ 2 G | Origin$ Library | Destination$ Library | ChangeType$ Land.Basic+Forest | ChangeNum$ X | References$ X,Y | RememberChanged$ True | SubAbility$ DBBattlefield | Shuffle$ False | StackDescription$ SpellDescription | SpellDescription$ Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle your library. Spell mastery — If there are two or more instant or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two. +SVar:DBBattlefield:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | Tapped$ True | SubAbility$ DBHand | ChangeType$ Card.IsRemembered | ChangeNum$ 1 | Mandatory$ True | NoLooking$ True | SelectPrompt$ Select a card to go to the battlefield | Shuffle$ False | StackDescription$ None +SVar:DBHand:DB$ ChangeZone | Origin$ Library | Destination$ Hand | Defined$ Remembered | NoLooking$ True | StackDescription$ None | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:X:Count$Compare Y GE2.3.2 +SVar:Y:Count$ValidGraveyard Instant.YouOwn,Sorcery.YouOwn Oracle:Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle your library.\nSpell mastery — If there are two or more instant or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two. diff --git a/forge-gui/res/cardsfolder/s/settle_the_wreckage.txt b/forge-gui/res/cardsfolder/s/settle_the_wreckage.txt index 521f24cb11c..c136b03296f 100644 --- a/forge-gui/res/cardsfolder/s/settle_the_wreckage.txt +++ b/forge-gui/res/cardsfolder/s/settle_the_wreckage.txt @@ -2,7 +2,7 @@ Name:Settle the Wreckage ManaCost:2 W W Types:Instant A:SP$ ChangeZoneAll | Cost$ 2 W W | ValidTgts$ Player | ChangeType$ Creature.attacking | TgtPrompt$ Select target player | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DBGetLands | SpellDescription$ Exile all attacking creatures target player controls. That player may search their library for that many basic lands, put those cards onto the battlefield tapped, then shuffle their library. -SVar:DBGetLands:DB$ ChangeZone | Optional$ True | Origin$ Library | Destination$ Battlefield | Tapped$ True | ChangeType$ Land.Basic | ChangeNum$ X | References$ X | DefinedPlayer$ RememberedController | ShuffleNonMandatory$ True | SubAbility$ DBCleanup +SVar:DBGetLands:DB$ ChangeZone | Optional$ True | Origin$ Library | Destination$ Battlefield | Tapped$ True | ChangeType$ Land.Basic | ChangeNum$ X | References$ X | DefinedPlayer$ TargetedPlayer | ShuffleNonMandatory$ True | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:Count$RememberedSize SVar:Picture:http://www.wizards.com/global/images/magic/general/settle_the_wreckage.jpg diff --git a/forge-gui/res/cardsfolder/t/the_birth_of_meletis.txt b/forge-gui/res/cardsfolder/t/the_birth_of_meletis.txt index 349f1e790d9..27021aac864 100644 --- a/forge-gui/res/cardsfolder/t/the_birth_of_meletis.txt +++ b/forge-gui/res/cardsfolder/t/the_birth_of_meletis.txt @@ -3,7 +3,7 @@ ManaCost:1 W Types:Enchantment Saga K:Saga:3:TrigChange,TrigToken,TrigGainLife SVar:TrigChange:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Land.Plains+Basic | ChangeNum$ 1 | SpellDescription$ Search your library for a basic Plains card, reveal it, put it into your hand, then shuffle your library. -SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_0_4_wall_defender | TokenOwner$ You | LegacyImage$ c 0 4 wall defender thb | SpellDescription$ Create a 0/4 colorless Wall artifact creature token with defender. +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_0_4_a_wall_defender | TokenOwner$ You | LegacyImage$ c 0 4 wall defender thb | SpellDescription$ Create a 0/4 colorless Wall artifact creature token with defender. SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 2 | SpellDescription$ You gain 2 life. DeckHas:Ability$LifeGain & Ability$Token Oracle:(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)\nI - Search your library for a basic Plains card, reveal it, put it into your hand, then shuffle your library.\nII - Create a 0/4 colorless Wall artifact creature token with defender.\nIII - You gain 2 life. diff --git a/forge-gui/res/cardsfolder/t/the_triumph_of_anax.txt b/forge-gui/res/cardsfolder/t/the_triumph_of_anax.txt index a7aacb3fd3c..6a6b9d25af5 100755 --- a/forge-gui/res/cardsfolder/t/the_triumph_of_anax.txt +++ b/forge-gui/res/cardsfolder/t/the_triumph_of_anax.txt @@ -1,7 +1,7 @@ Name:The Triumph of Anax ManaCost:2 R Types:Enchantment Saga -K:Saga:3:DBPump,DBPump,DBPump,DBPick +K:Saga:4:DBPump,DBPump,DBPump,DBPick SVar:DBPump:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +X | References$ X | KW$ Trample | SpellDescription$ Until end of turn, target creature gains trample and gets +X/+0, where X is the number of lore counters on CARDNAME. SVar:X:Count$CardCounters.LORE SVar:PlayMain1:TRUE diff --git a/forge-gui/res/editions/Aether Revolt.txt b/forge-gui/res/editions/Aether Revolt.txt index e2fcffcce5c..8f3e2c7cfd7 100644 --- a/forge-gui/res/editions/Aether Revolt.txt +++ b/forge-gui/res/editions/Aether Revolt.txt @@ -195,15 +195,15 @@ AdditionalSetUnlockedInQuest=MPS_KLD 182 C Watchful Automaton 183 C Welder Automaton 184 R Spire of Industry -185 M Ajani, Valiant Protector -186 R Ajani's Aid +185 M Ajani, Valiant Protector +186 C Inspiring Roar 187 U Ajani's Comrade -188 C Inspiring Roar +188 R Ajani's Aid 189 C Tranquil Expanse 190 M Tezzeret, Master of Metal 191 R Tezzeret's Betrayal -192 U Tezzeret's Simulacrum -193 C Pendulum of Patterns +192 C Pendulum of Patterns +193 U Tezzeret's Simulacrum 194 C Submerged Boneyard [tokens] diff --git a/forge-gui/res/editions/Battle Royale.txt b/forge-gui/res/editions/Battle Royale.txt index 76831b31973..13417672427 100644 --- a/forge-gui/res/editions/Battle Royale.txt +++ b/forge-gui/res/editions/Battle Royale.txt @@ -27,10 +27,10 @@ Foil=NotSupported 17 C Curfew 18 C Dark Ritual 19 R Dirtcowl Wurm -20 U Disenchant +20 C Disenchant 21 C Disruptive Student 22 C Drifting Meadow -23 C Elvish Lyrist +23 U Elvish Lyrist 24 C Exhume 25 U Fecundity 26 C Fertile Ground @@ -40,16 +40,16 @@ Foil=NotSupported 30 C Gorilla Warrior 31 C Healing Salve 32 C Heat Ray -33 R Hurricane +33 U Hurricane 34 C Infantry Veteran -35 R Land Tax +35 U Land Tax 36 R Lhurgoyf 37 C Lightning Elemental 38 R Living Death 39 C Llanowar Elves 40 C Man-o'-War 41 C Mana Leak -42 U Maniacal Rage +42 C Maniacal Rage 43 C Manta Riders 44 C Master Decoy 45 U Mogg Hollows @@ -59,7 +59,7 @@ Foil=NotSupported 49 U Pestilence 50 C Phyrexian Ghoul 51 C Pincher Beetles -52 U Plated Rootwalla +52 C Plated Rootwalla 53 C Polluted Mire 54 C Prodigal Sorcerer 55 C Raging Goblin @@ -72,7 +72,7 @@ Foil=NotSupported 62 C Sanctum Custodian 63 U Sanctum Guardian 64 C Sandstorm -65 U Scaled Wurm +65 C Scaled Wurm 66 C Scryb Sprites 67 U Seasoned Marshal 68 C Seeker of Skybreak @@ -83,7 +83,7 @@ Foil=NotSupported 73 C Slippery Karst 74 C Soltari Foot Soldier 75 U Songstitcher -76 U Soul Warden +76 C Soul Warden 77 C Spike Colony 78 U Spike Feeder 79 R Spike Weaver diff --git a/forge-gui/res/editions/Battlebond.txt b/forge-gui/res/editions/Battlebond.txt index 18524d0e6c0..83e830766f5 100644 --- a/forge-gui/res/editions/Battlebond.txt +++ b/forge-gui/res/editions/Battlebond.txt @@ -135,7 +135,7 @@ Booster=10 Common, 3 Uncommon, 1 fromSheet("BBD RareMythic"), 1 BasicLand 125 C Omenspeaker 126 U Opportunity 127 U Oracle's Insight -128 C Peregrine Drake +128 U Peregrine Drake 129 U Phantom Warrior 130 U Reckless Scholar 131 R Sower of Temptation @@ -203,7 +203,7 @@ Booster=10 Common, 3 Uncommon, 1 fromSheet("BBD RareMythic"), 1 BasicLand 193 C Cowl Prowler 194 C Daggerback Basilisk 195 M Doubling Season -196 U Elvish Visionary +196 C Elvish Visionary 197 U Feral Hydra 198 C Fertile Ground 199 U Fertilid diff --git a/forge-gui/res/editions/Beatdown.txt b/forge-gui/res/editions/Beatdown.txt index b8244084ac0..1c32e2b20ee 100644 --- a/forge-gui/res/editions/Beatdown.txt +++ b/forge-gui/res/editions/Beatdown.txt @@ -76,7 +76,7 @@ Foil=NotSupported 66 C Yavimaya Wurm 67 U Diabolic Vision 68 U Segmented Wurm -69 C Clockwork Avian +69 R Clockwork Avian 70 R Clockwork Beast 71 U Dwarven Ruins 72 U Ebon Stronghold @@ -97,4 +97,4 @@ Foil=NotSupported 87 L Mountain 88 L Forest 89 L Forest -90 L Forest +90 L Forest \ No newline at end of file diff --git a/forge-gui/res/editions/Conspiracy Take the Crown.txt b/forge-gui/res/editions/Conspiracy Take the Crown.txt index c82c56ae90e..7d2d59cfc7d 100644 --- a/forge-gui/res/editions/Conspiracy Take the Crown.txt +++ b/forge-gui/res/editions/Conspiracy Take the Crown.txt @@ -6,7 +6,8 @@ Code2=CN2 MciCode=cn2 Type=Other BoosterCovers=3 -Booster=10 Common:!fromSheet("CN2 Draft Matters"), 3 Uncommon:!fromSheet("CN2 Draft Matters"), 1 RareMythic:!fromSheet("CN2 Draft Matters"), 1 fromSheet("CN2 Draft Matters") +Booster=10 Common:!fromSheet("CN2 Not In Normal Slots"), 3 Uncommon:!fromSheet("CN2 Not In Normal Slots"), 1 RareMythic:!fromSheet("CN2 Not In Normal Slots"), 1 fromSheet("CN2 Draft Matters") +AdditionalSheetForFoils=fromSheet("CN2 Foil Kaya") [cards] 1 C Adriana's Valor @@ -230,6 +231,7 @@ Booster=10 Common:!fromSheet("CN2 Draft Matters"), 3 Uncommon:!fromSheet("CN2 Dr 219 R Exotic Orchard 220 U Rogue's Passage 221 U Shimmering Grotto +222 M Kaya, Ghost Assassin [tokens] w_1_1_soldier @@ -242,4 +244,4 @@ r_1_1_goblin_noblock r_8_8_lizard g_3_3_beast g_1_1_insect -c_1_1_a_construct_defender \ No newline at end of file +c_1_1_a_construct_defender diff --git a/forge-gui/res/editions/Fate Reforged.txt b/forge-gui/res/editions/Fate Reforged.txt index 02752ed7073..e3810f09b24 100644 --- a/forge-gui/res/editions/Fate Reforged.txt +++ b/forge-gui/res/editions/Fate Reforged.txt @@ -184,14 +184,14 @@ Booster=10 Common:!land, 3 Uncommon, 1 RareMythic, 1 fromSheet("FRF Lands"), 0 f 174 C Tranquil Cove 175 C Wind-Scarred Crag 176 L Plains -176 L Plains -179 L Island +177 L Plains +178 L Island 179 L Island +180 L Swamp 181 L Swamp -181 L Swamp +182 L Mountain 183 L Mountain -183 L Mountain -185 L Forest +184 L Forest 185 L Forest [tokens] diff --git a/forge-gui/res/editions/Khans of Tarkir.txt b/forge-gui/res/editions/Khans of Tarkir.txt index eb1ab10a7df..b1b96ce023e 100644 --- a/forge-gui/res/editions/Khans of Tarkir.txt +++ b/forge-gui/res/editions/Khans of Tarkir.txt @@ -258,26 +258,26 @@ Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand KTK 247 C Wind-Scarred Crag 248 R Windswept Heath 249 R Wooded Foothills -269 L Forest -269 L Forest -269 L Forest -269 L Forest -257 L Island -257 L Island -257 L Island -257 L Island -263 L Mountain -263 L Mountain -263 L Mountain -263 L Mountain -250 L Plains -250 L Plains -250 L Plains 250 L Plains +251 L Plains +252 L Plains +253 L Plains +254 L Island +255 L Island +256 L Island +257 L Island 258 L Swamp -258 L Swamp -258 L Swamp -258 L Swamp +259 L Swamp +260 L Swamp +261 L Swamp +262 L Mountain +263 L Mountain +264 L Mountain +265 L Mountain +266 L Forest +267 L Forest +268 L Forest +269 L Forest [tokens] w_3_4_bird_flying diff --git a/forge-gui/res/editions/Magic 2014.txt b/forge-gui/res/editions/Magic 2014.txt index d4daec8d83b..0934c02e1ef 100644 --- a/forge-gui/res/editions/Magic 2014.txt +++ b/forge-gui/res/editions/Magic 2014.txt @@ -238,26 +238,26 @@ Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand 227 U Encroaching Wastes 228 R Mutavault 229 U Shimmering Grotto +230 L Plains 231 L Plains -231 L Plains -231 L Plains -231 L Plains -234 L Island -234 L Island -234 L Island +232 L Plains +233 L Plains 234 L Island +235 L Island +236 L Island +237 L Island +238 L Swamp +239 L Swamp +240 L Swamp 241 L Swamp -241 L Swamp -241 L Swamp -241 L Swamp -244 L Mountain -244 L Mountain -244 L Mountain +242 L Mountain +243 L Mountain 244 L Mountain +245 L Mountain 246 L Forest -246 L Forest -246 L Forest -246 L Forest +247 L Forest +248 L Forest +249 L Forest [tokens] c_1_1_sliver diff --git a/forge-gui/res/editions/Magic 2015.txt b/forge-gui/res/editions/Magic 2015.txt index 53ada72d465..8d560ecd154 100644 --- a/forge-gui/res/editions/Magic 2015.txt +++ b/forge-gui/res/editions/Magic 2015.txt @@ -258,26 +258,26 @@ Booster=10 Common:!fromSheet("M15 Sample Cards"), 3 Uncommon:!fromSheet("M15 Sam 247 R Sliver Hive 248 R Urborg, Tomb of Yawgmoth 249 R Yavimaya Coast +250 L Plains 251 L Plains -251 L Plains -251 L Plains -251 L Plains -255 L Island -255 L Island -255 L Island +252 L Plains +253 L Plains +254 L Island 255 L Island +256 L Island +257 L Island 258 L Swamp -258 L Swamp -258 L Swamp -258 L Swamp -263 L Mountain -263 L Mountain -263 L Mountain +259 L Swamp +260 L Swamp +261 L Swamp +262 L Mountain 263 L Mountain +264 L Mountain +265 L Mountain 266 L Forest -266 L Forest -266 L Forest -266 L Forest +267 L Forest +268 L Forest +269 L Forest 270 R Aegis Angel 271 C Divine Verdict 272 C Inspired Charge diff --git a/forge-gui/res/editions/Mystery Booster Retail Edition Foils.txt b/forge-gui/res/editions/Mystery Booster Retail Edition Foils.txt new file mode 100644 index 00000000000..86da737ae2b --- /dev/null +++ b/forge-gui/res/editions/Mystery Booster Retail Edition Foils.txt @@ -0,0 +1,128 @@ +[metadata] +Code=FMB1 +Date=2020-03-08 +Name=Mystery Booster Retail Edition Foils +Type=Other + +[cards] +1 U Not of This World +2 R Celestial Dawn +3 R Celestial Kirin +4 U Changeling Hero +5 U Council Guardian +6 U Eidolon of Rhetoric +7 R Isamaru, Hound of Konda +8 C Lapse of Certainty +9 C Lumithread Field +10 R Norn's Annex +11 R Proclamation of Rebirth +12 U Pull from Eternity +13 R Rune-Tail, Kitsune Ascendant +14 C Sinew Sliver +15 C Soul's Attendant +16 R Spelltithe Enforcer +17 U Springjack Shepherd +18 U Wall of Shards +19 U White Knight +20 C Blighted Agent +21 U Delay +22 R Fatespinner +23 U Frozen Aether +24 R Grand Architect +25 R Intruder Alarm +26 M Misthollow Griffin +27 U Paradox Haze +28 R Patron of the Moon +29 R Puca's Mischief +30 R Spellweaver Volute +31 C Storm Crow +32 R Zur's Weirding +33 R Bringer of the Black Dawn +34 C Chimney Imp +35 R Conspiracy +36 C Echoing Decay +37 R Funeral Charm +38 R Herald of Leshrac +39 R Marrow-Gnawer +40 R Nezumi Shortfang +41 R One with Nothing +42 U Ravenous Trap +43 U Rescue from the Underworld +44 R Undead Warchief +45 C Viscera Seer +46 U Balduvian Rage +47 R Braid of Fire +48 C Burning Inquiry +49 R Fiery Gambit +50 U Flamekin Harbinger +51 R Form of the Dragon +52 C Goblin Bushwhacker +53 U Guerrilla Tactics +54 U Lightning Storm +55 R Norin the Wary +56 C Ogre Gatecrasher +57 C Pyretic Ritual +58 M Scourge of the Throne +59 R Stigma Lasher +60 U Treasonous Ogre +61 R Allosaurus Rider +62 U Archetype of Endurance +63 C Boreal Druid +64 R Boundless Realms +65 U Bramblewood Paragon +66 R Fungusaur +67 C Game-Trail Changeling +68 C Gleeful Sabotage +69 C Greater Mossdog +70 R Helix Pinnacle +71 C Hornet Sting +72 U Manaweft Sliver +73 R Maro +74 R Myojin of Life's Web +75 R Panglacial Wurm +76 R Reki, the History of Kamigawa +77 R Rhox +78 C Sakura-Tribe Scout +79 U Scryb Ranger +80 U Sheltering Ancient +81 U Sosuke, Son of Seshiro +82 R Spike Feeder +83 M Aurelia's Fury +84 U Drogskol Captain +85 R Glittering Wish +86 U Harmonic Sliver +87 M Karrthus, Tyrant of Jund +88 M Maelstrom Nexus +89 U Mind Funeral +90 M Sarkhan the Mad +91 M Sen Triplets +92 R Yore-Tiller Nephilim +93 R Balefire Liege +94 U Gilder Bairn +95 U Kulrath Knight +96 C Noggle Bandit +97 U Wear // Tear +98 R Amulet of Vigor +99 U Blasting Station +100 U Codex Shredder +101 U Geth's Grimoire +102 C Iron Myr +103 R Knowledge Pool +104 U Lantern of Insight +105 R Leveler +106 M Lich's Mirror +107 U Magewright's Stone +108 U Memnite +109 R Mindslaver +110 C Pili-Pala +111 R Reaper King +112 R Sundial of the Infinite +113 R Teferi's Puzzle Box +114 U Trailblazer's Boots +115 R Triskelion +116 R Witchbane Orb +117 R Alchemist's Refuge +118 R Minamo, School at Water's Edge +119 U Mirrodin's Core +120 R Shizo, Death's Storehouse +121 U Stalking Stones diff --git a/forge-gui/res/editions/Mystery Booster.txt b/forge-gui/res/editions/Mystery Booster.txt new file mode 100644 index 00000000000..4ca8e07217f --- /dev/null +++ b/forge-gui/res/editions/Mystery Booster.txt @@ -0,0 +1,1704 @@ +[metadata] +Code=MB1 +Date=2019-11-07 +Name=Mystery Booster +Type=Reprint +BoosterCovers=1 +Booster=2 fromSheet("MB1 White CommonUncommon"), 2 fromSheet("MB1 Blue CommonUncommon"), 2 fromSheet("MB1 Black CommonUncommon"), 2 fromSheet("MB1 Green CommonUncommon"), 2 fromSheet("MB1 Red CommonUncommon"), 1 fromSheet("MB1 Multi CommonUncommon"), 1 fromSheet("MB1 Artifact Land CommonUncommon"), 1 fromSheet("MB1 Pre M15"), 1 fromSheet("MB1 Post M15 RareMythic"), 1 fromSheet("FMB1 Foils") +Foil=NotSupported + +[cards] +1 R All Is Dust +2 U Artisan of Kozilek +3 U Breaker of Armies +4 R Desolation Twin +5 C Eldrazi Devastator +6 U Pathrazer of Ulamog +7 U Abzan Falconer +8 C Abzan Runemark +9 C Acrobatic Maneuver +10 U Adanto Vanguard +11 R Adorned Pouncer +12 C Affa Protector +13 C Ainok Bond-Kin +14 U Ajani's Pridemate +15 C Alley Evasion +16 M Angelic Destiny +17 C Angelic Gift +18 C Angelic Purge +19 C Angel of Mercy +20 U Angel of Renewal +21 R Angel of the Dire Hour +22 C Angelsong +23 C Apostle's Blessing +24 R Approach of the Second Sun +25 U Archangel +26 C Arrest +27 C Arrester's Zeal +28 C Artful Maneuver +29 U Aura of Silence +30 C Aven Battle Priest +31 C Aven Sentry +32 C Ballynock Cohort +33 C Bartered Cow +34 U Battle Mastery +35 R Beacon of Immortality +36 C Benevolent Ancestor +37 C Blade Instructor +38 U Blessed Spirits +39 C Bonds of Faith +40 C Borrowed Grace +41 C Built to Last +42 C Bulwark Giant +43 C Candlelight Vigil +44 C Caravan Escort +45 C Cartouche of Solidarity +46 U Cast Out +47 C Cathar's Companion +48 C Caught in the Brights +49 U Celestial Crusader +50 C Celestial Flare +51 C Center Soul +52 C Champion of Arashin +53 R Champion of the Parish +54 R Chancellor of the Annex +55 C Charge +56 C Cliffside Lookout +57 C Cloudshift +58 C Coalition Honor Guard +59 C Collar the Culprit +60 U Congregate +61 C Conviction +62 C Countless Gears Renegade +63 C Court Homunculus +64 C Court Street Denizen +65 U Crib Swap +66 U Danitha Capashen, Paragon +67 C Daring Skyjek +68 U Darksteel Mutation +69 C Dauntless Cathar +70 C Dawnglare Invoker +71 C Decommission +72 R Decree of Justice +73 C Defiant Strike +74 C Desperate Sentry +75 C Devilthorn Fox +76 R Dictate of Heliod +77 C Disenchant +78 U Dismantling Blow +79 C Disposal Mummy +80 C Divine Favor +81 C Djeru's Renunciation +82 C Djeru's Resolve +83 C Doomed Traveler +84 C Dragon Bell Monk +85 C Dragon's Eye Sentry +86 C Dragon's Presence +87 C Eddytrail Hawk +88 M Elesh Norn, Grand Cenobite +89 C Emerge Unscathed +90 C Empyrial Armor +91 C Encampment Keeper +92 U Encircling Fissure +93 C Enduring Victory +94 C Enlightened Ascetic +95 C Ephemeral Shields +96 C Ephemerate +97 R Evra, Halcyon Witness +98 C Excavation Elephant +99 C Excoriate +100 C Expedition Raptor +101 C Expose Evil +102 C Exultant Skymarcher +103 C Eyes in the Skies +104 C Faithbearer Paladin +105 C Faith's Fetters +106 C Feat of Resistance +107 U Felidar Guardian +108 R Felidar Sovereign +109 U Felidar Umbra +110 C Fencing Ace +111 U Fiend Hunter +112 C Firehoof Cavalry +113 C Forsake the Worldly +114 C Fortify +115 C Fragmentize +116 C Geist of the Moors +117 U Ghostblade Eidolon +118 M Gideon Jura +119 C Gideon's Lawkeeper +120 U Gift of Estates +121 C Glaring Aegis +122 C Gleam of Resistance +123 C Glint-Sleeve Artisan +124 C God-Pharaoh's Faithful +125 C Gods Willing +126 R Grasp of Fate +127 C Grasp of the Hieromancer +128 C Great-Horn Krushok +129 C Guided Strike +130 U Gustcloak Skirmisher +131 C Gust Walker +132 C Healer's Hawk +133 C Healing Grace +134 C Healing Hands +135 C Heavy Infantry +136 C Humble +137 C Hyena Umbra +138 C Infantry Veteran +139 C Inquisitor's Ox +140 C Inspired Charge +141 C Intrusive Packbeast +142 C Iona's Judgment +143 C Isolation Zone +144 U Jubilant Mascot +145 C Knight of Cliffhaven +146 U Knight of Dawn +147 C Knight of Old Benalia +148 C Knight of Sorrows +149 C Knight of the Skyward Eye +150 C Knight of the Tusk +151 U Kor Bladewhirl +152 C Kor Chant +153 U Kor Firewalker +154 C Kor Hookmaster +155 C Kor Sky Climber +156 C Kor Skyfisher +157 U Lashknife Barrier +158 U Leonin Relic-Warder +159 C Lieutenants of the Guard +160 U Lightform +161 C Lightwalker +162 U Lingering Souls +163 C Lone Missionary +164 C Lonesome Unicorn +165 C Looming Altisaur +166 C Lotus-Eye Mystics +167 C Loxodon Partisan +168 C Loyal Sentry +169 C Lunarch Mantle +170 R Magus of the Moat +171 C Mana Tithe +172 C Mardu Hordechief +173 C Marked by Honor +174 R Martyr's Bond +175 U Martyr's Cause +176 C Meditation Puzzle +177 C Midnight Guard +178 R Mirran Crusader +179 R Mirror Entity +180 C Momentary Blink +181 C Moonlit Strider +182 C Mortal's Ardor +183 U Mother of Runes +184 C Ninth Bridge Patrol +185 U Nyx-Fleece Ram +186 R Odric, Lunarch Marshal +187 C Ondu Greathorn +188 C Ondu War Cleric +189 C Oreskos Swiftclaw +190 U Oust +191 C Pacifism +192 U Palace Jailer +193 C Palace Sentinels +194 C Paladin of the Bloodstained +195 C Path of Peace +196 U Path to Exile +197 U Peace of Mind +198 C Pegasus Courser +199 C Pentarch Ward +200 C Pitfall Trap +201 C Pressure Point +202 U Promise of Bunrei +203 C Prowling Caracal +204 C Rally the Peasants +205 C Raptor Companion +206 R Recruiter of the Guard +207 U Refurbish +208 C Renewed Faith +209 C Resurrection +210 U Retreat to Emeria +211 C Reviving Dose +212 C Rhet-Crop Spearmaster +213 U Righteous Cause +214 C Rootborn Defenses +215 C Sacred Cat +216 C Sanctum Gargoyle +217 C Sandstorm Charger +218 C Savannah Lions +219 C Seal of Cleansing +220 C Searing Light +221 U Seeker of the Way +222 C Sensor Splicer +223 U Seraph of the Suns +224 C Serra Disciple +225 U Serra's Embrace +226 C Sheer Drop +227 C Shining Aerosaur +228 C Shining Armor +229 C Shoulder to Shoulder +230 C Siegecraft +231 C Silverchase Fox +232 C Skyhunter Skirmisher +233 U Skymarcher Aspirant +234 C Skyspear Cavalry +235 C Slash of Talons +236 C Snubhorn Sentry +237 C Soulmender +238 C Soul Parry +239 C Soul-Strike Technique +240 C Soul Summons +241 C Soul Warden +242 C Sparring Mummy +243 C Spectral Gateguards +244 C Stalwart Aven +245 C Star-Crowned Stag +246 C Stave Off +247 C Steadfast Sentinel +248 C Stone Haven Medic +249 C Sunlance +250 C Sunrise Seeker +251 C Suppression Bonds +252 C Survive the Night +253 U Swords to Plowshares +254 C Take Vengeance +255 C Tandem Tactics +256 R Teferi's Protection +257 C Terashi's Grasp +258 C Territorial Hammerskull +259 R Thalia's Lancers +260 C Thraben Inspector +261 C Thraben Standard Bearer +262 U Timely Reinforcements +263 C Topan Freeblade +264 C Unwavering Initiate +265 C Veteran Swordsmith +266 C Village Bell-Ringer +267 C Voice of the Provinces +268 U Volunteer Reserves +269 C Wake the Reflections +270 U Wall of Omens +271 C Wall of One Thousand Cuts +272 C Wandering Champion +273 C War Behemoth +274 R Weathered Wayfarer +275 C Wild Griffin +276 U Windborne Charge +277 C Winged Shepherd +278 U Wing Shards +279 C Youthful Knight +280 C Zealous Strike +281 C Academy Journeymage +282 C Aethersnipe +283 C Aether Tradewinds +284 C Amass the Components +285 R Aminatou's Augury +286 C Amphin Pathmage +287 C Anticipate +288 C Arcane Denial +289 C Archaeomancer +290 U Archetype of Imagination +291 C Artificer's Assistant +292 C Augur of Bolas +293 C Augury Owl +294 C Bastion Inventor +295 C Befuddle +296 C Benthic Giant +297 C Benthic Infiltrator +298 C Bewilder +299 U Blue Elemental Blast +300 C Borrowing 100,000 Arrows +301 C Brainstorm +302 C Brilliant Spectrum +303 U Brine Elemental +304 C Calculated Dismissal +305 C Caller of Gales +306 C Call to Heel +307 C Cancel +308 C Capture Sphere +309 C Cartouche of Knowledge +310 C Castaway's Despair +311 C Catalog +312 U Chart a Course +313 R Chasm Skulker +314 C Chillbringer +315 C Choking Tethers +316 C Chronostutter +317 U Circular Logic +318 U Citywatch Sphinx +319 C Claustrophobia +320 C Clear the Mind +321 C Cloak of Mists +322 C Cloud Elemental +323 C Cloudkin Seer +324 C Cloudreader Sphinx +325 C Clutch of Currents +326 C Compelling Argument +327 U Concentrate +328 U Condescend +329 C Containment Membrane +330 C Contingency Plan +331 C Contradict +332 C Convolute +333 C Coralhelm Guide +334 C Coral Trickster +335 U Corrupted Conscience +336 C Counterspell +337 C Court Hussar +338 C Crashing Tide +339 C Crush Dissent +340 U Curiosity +341 C Curio Vendor +342 C Daze +343 C Dazzling Lights +344 C Decision Paralysis +345 C Deep Analysis +346 C Deep Freeze +347 R Deepglow Skate +348 C Diminish +349 C Dirgur Nemesis +350 C Dispel +351 C Displace +352 U Distortion Strike +353 C Divination +354 R Djinn of Wishes +355 C Doorkeeper +356 U Dragon's Eye Savants +357 C Drag Under +358 C Dreadwaters +359 C Dream Cache +360 C Dream Twist +361 C Eel Umbra +362 C Embodiment of Spring +363 R Energy Field +364 C Enlightened Maniac +365 U Ensoul Artifact +366 C Errant Ephemeron +367 C Essence Scatter +368 U Everdream +369 U Exclude +370 M Expropriate +371 U Fact or Fiction +372 C Faerie Invaders +373 C Faerie Mechanist +374 C Failed Inspection +375 U Fascination +376 C Fathom Seer +377 R Fblthp, the Lost +378 U Flashfreeze +379 U Fledgling Mawcor +380 C Fleeting Distraction +381 U Floodgate +382 U Fog Bank +383 C Fogwalker +384 C Foil +385 C Forbidden Alchemy +386 C Frantic Search +387 C Frilled Sea Serpent +388 C Frost Lynx +389 C Gaseous Form +390 C Ghost Ship +391 C Glacial Crasher +392 C Glint +393 C Gone Missing +394 C Grasp of Phantoms +395 U Guard Gomazoa +396 C Gurmag Drowner +397 C Gush +398 U Hedron Crab +399 C Hieroglyphic Illumination +400 C Hightide Hermit +401 C Hinterland Drake +402 C Horseshoe Crab +403 C Humongulus +404 C Impulse +405 C Inkfathom Divers +406 C Invisibility +407 C Ior Ruin Expedition +408 C Jace's Phantasm +409 C Jeering Homunculus +410 C Jeskai Sage +411 R Jushi Apprentice // Tomoya the Revealer +412 C Jwar Isle Avenger +413 C Kiora's Dambreaker +414 C Laboratory Brute +415 U Laboratory Maniac +416 U Labyrinth Guardian +417 U Lay Claim +418 C Leapfrog +419 U Mahamoti Djinn +420 C Mana Leak +421 C Man-o'-War +422 R Master Transmuter +423 C Maximize Altitude +424 R Memory Erosion +425 C Memory Lapse +426 U Merfolk Looter +427 C Messenger Jays +428 C Metallic Rebuke +429 C Mind Sculpt +430 R Mind Spring +431 R The Mirari Conjecture +432 R Misdirection +433 U Mistform Shrieker +434 C Mist Raven +435 C Mnemonic Wall +436 C Monastery Loremaster +437 C Mulldrifter +438 U Murder of Crows +439 C Mystical Teachings +440 R Mystic Confluence +441 C Mystic of the Hidden Way +442 C Nagging Thoughts +443 C Negate +444 C Niblis of Dusk +445 C Nine-Tail White Fox +446 C Ninja of the Deep Hours +447 C Ojutai Interceptor +448 C Ojutai's Breath +449 C Omenspeaker +450 U Opportunity +451 C Opt +452 C Peel from Reality +453 C Phantasmal Bear +454 U Phantasmal Dragon +455 U Phyrexian Ingester +456 R Phyrexian Metamorph +457 C Pondering Mage +458 C Portent +459 U Predict +460 C Preordain +461 U Prodigal Sorcerer +462 U Propaganda +463 C Prosperous Pirates +464 C Purple-Crystal Crab +465 C Refocus +466 C Repulse +467 C Retraction Helix +468 C Rhystic Study +469 U Riftwing Cloudskate +470 C Ringwarden Owl +471 U Rishadan Footpad +472 C River Darter +473 C River Serpent +474 C Riverwheel Aerialists +475 U Sage of Lat-Nam +476 C Sailor of Means +477 R Sakashima the Impostor +478 C Sapphire Charm +479 C Scroll Thief +480 C Sea Gate Oracle +481 U Sealock Monster +482 C Secrets of the Golden City +483 C Send to Sleep +484 R Serendib Efreet +485 C Shaper Parasite +486 C Shimmerscale Drake +487 C Shipwreck Looter +488 U Sigiled Starfish +489 C Silent Observer +490 U Silvergill Adept +491 C Singing Bell Strike +492 U Skaab Goliath +493 C Skitter Eel +494 C Skittering Crustacean +495 U Sleep +496 C Slipstream Eel +497 C Slither Blade +498 C Snap +499 C Snapping Drake +500 C Somber Hoverguard +501 U Soothsaying +502 U Sphinx's Tutelage +503 C Spire Monitor +504 C Steady Progress +505 C Stitched Drake +506 C Storm Sculptor +507 C Strategic Planning +508 C Stream of Thought +509 R Stunt Double +510 C Surrakar Banisher +511 C Syncopate +512 U Syr Elenora, the Discerning +513 R Talrand, Sky Summoner +514 C Tandem Lookout +515 M Teferi, Temporal Archmage +516 C Temporal Fissure +517 M Temporal Mastery +518 U Thieving Magpie +519 C Thornwind Faeries +520 C Thoughtcast +521 C Thought Collapse +522 C Thought Scour +523 U Thrummingbird +524 C Thunder Drake +525 C Tidal Warrior +526 C Tidal Wave +527 U Tinker +528 C Totally Lost +529 U Trail of Evidence +530 C Treasure Cruise +531 C Treasure Hunt +532 U Treasure Mage +533 C Trinket Mage +534 U Triton Tactics +535 C Turn Aside +536 C Uncomfortable Chill +537 C Vapor Snag +538 C Vigean Graftmage +539 U Wall of Frost +540 C Warden of Evos Isle +541 C Watercourser +542 C Wave-Wing Elemental +543 C Weldfast Wingsmith +544 C Welkin Tern +545 R Whelming Wave +546 C Whiplash Trap +547 R Whir of Invention +548 C Windcaller Aven +549 C Wind Drake +550 U Wind-Kin Raiders +551 C Windrider Eel +552 C Wind Strider +553 C Wishcoin Crab +554 C Wishful Merfolk +555 C Wretched Gryff +556 C Write into Being +557 U Youthful Scholar +558 C Absorb Vis +559 C Accursed Spirit +560 C Aid the Fallen +561 C Alesha's Vanguard +562 C Alley Strangler +563 C Altar's Reap +564 C Ambitious Aetherborn +565 C Ancestral Vengeance +566 U Animate Dead +567 U Annihilate +568 C Bala Ged Scorpion +569 U Baleful Ammit +570 C Balustrade Spy +571 C Bartizan Bats +572 C Bitter Revelation +573 C Black Cat +574 U Black Knight +575 R Black Market +576 C Bladebrand +577 C Blessing of Belzenlok +578 C Blighted Bat +579 C Blightsoil Druid +580 C Blistergrub +581 U Blood Artist +582 C Bloodrite Invoker +583 C Bone Splinters +584 C Boon of Emrakul +585 U Breeding Pit +586 C Butcher's Glee +587 U Cabal Therapy +588 C Cackling Imp +589 C Cadaver Imp +590 R Cairn Wanderer +591 C Caligo Skin-Witch +592 U Carrion Feeder +593 C Carrion Imp +594 C Catacomb Crocodile +595 C Catacomb Slug +596 U Caustic Tar +597 C Certain Death +598 C Child of Night +599 C Coat with Venom +600 R Collective Brutality +601 U Corpsehatch +602 C Costly Plunder +603 C Covenant of Blood +604 C Cower in Fear +605 C Crippling Blight +606 C Crow of Dark Tidings +607 C Cursed Minotaur +608 C Daring Demolition +609 U Darkblast +610 C Dark Dabbling +611 C Dark Ritual +612 C Dark Withering +613 U Dauthi Mindripper +614 C Deadbridge Shaman +615 C Deadeye Tormentor +616 R Deadly Tempest +617 C Dead Reveler +618 C Death Denied +619 C Defeat +620 U Demonic Tutor +621 C Demonic Vigor +622 C Demon's Grasp +623 C Desperate Castaways +624 C Diabolic Edict +625 R Dictate of Erebos +626 C Die Young +627 C Dinosaur Hunter +628 C Dirge of Dread +629 U Dismember +630 C Disowned Ancestor +631 C Doomed Dissenter +632 C Douse in Gloom +633 R Drana, Kalastria Bloodchief +634 C Dreadbringer Lampads +635 C Dread Drone +636 U Dread Return +637 C Dregscape Zombie +638 C Driver of the Dead +639 C Drudge Sentinel +640 C Dukhara Scavenger +641 C Dune Beetle +642 C Duress +643 C Dusk Charger +644 C Dusk Legion Zealot +645 U The Eldest Reborn +646 C Epicure of Blood +647 C Erg Raiders +648 C Eternal Thirst +649 C Evincar's Justice +650 C Executioner's Capsule +651 U Exsanguinate +652 C Eyeblight's Ending +653 U Fallen Angel +654 C Farbog Revenant +655 U Fatal Push +656 C Fen Hauler +657 C Feral Abomination +658 C Festercreep +659 C Festering Newt +660 C Fetid Imp +661 C Fill with Fright +662 C First-Sphere Gargantua +663 C Flesh to Dust +664 U Fretwork Colony +665 C Fungal Infection +666 U Genju of the Fens +667 C Ghostly Changeling +668 C Ghoulcaller's Accomplice +669 U Gifted Aetherborn +670 U Go for the Throat +671 R Gonti, Lord of Luxury +672 C Grasping Scoundrel +673 R Gravecrawler +674 C Gravedigger +675 C Gravepurge +676 M Grave Titan +677 C Gray Merchant of Asphodel +678 C Grim Affliction +679 C Grim Discovery +680 C Grixis Slavedriver +681 C Grotesque Mutation +682 C Gruesome Fate +683 C Gurmag Angler +684 R Haakon, Stromgald Scourge +685 C Hideous End +686 C Hired Blade +687 C Hound of the Farbogs +688 U Hunter of Eyeblights +689 R Hypnotic Specter +690 C Induce Despair +691 C Infernal Scarring +692 U Infest +693 C Innocent Blood +694 U Inquisition of Kozilek +695 C Instill Infection +696 C Kalastria Nightwatch +697 C Krumar Bond-Kin +698 C Lawless Broker +699 C Lazotep Behemoth +700 C Lethal Sting +701 M Liliana, Death's Majesty +702 R Living Death +703 U Lord of the Accursed +704 C Macabre Waltz +705 C Marauding Boneslasher +706 C March of the Drowned +707 C Mark of the Vampire +708 C Marsh Hulk +709 C Mephitic Vapors +710 C Merciless Resolve +711 C Miasmic Mummy +712 C Mind Rake +713 C Mind Rot +714 R Mind Shatter +715 C Mire's Malice +716 C Moment of Craving +717 C Murder +718 C Murderous Compulsion +719 C Nameless Inversion +720 C Nantuko Husk +721 C Never Happened +722 R Nighthowler +723 C Night's Whisper +724 C Nirkana Assassin +725 U Noxious Dragon +726 C Okiba-Gang Shinobi +727 C Painful Lesson +728 U Perish +729 C Pestilence +730 R Phyrexian Arena +731 R Phyrexian Plaguelord +732 C Phyrexian Rager +733 U Phyrexian Reclamation +734 C Pit Keeper +735 U Plaguecrafter +736 C Plagued Rusalka +737 C Plague Wight +738 C Prakhata Club Security +739 C Prowling Pangolin +740 C Queen's Agent +741 U Quest for the Gravelord +742 C Rabid Bloodsucker +743 C Rakdos Drake +744 C Rakshasa's Secret +745 U Ravenous Chupacabra +746 C Read the Bones +747 C Reaper of Night // Harvest Fear +748 U Reassembling Skeleton +749 C Reckless Imp +750 U Reckless Spite +751 C Recover +752 C Renegade Demon +753 C Renegade's Getaway +754 C Returned Centaur +755 R Revel in Riches +756 U Revenant +757 C Rite of the Serpent +758 C Rotfeaster Maggot +759 C Ruin Rat +760 R Rune-Scarred Demon +761 U Sadistic Hypnotist +762 C Scarab Feast +763 C Scrounger of Souls +764 C Scuttling Death +765 C Seal of Doom +766 U Sengir Vampire +767 R Sewer Nemesis +768 C Shadowcloak Vampire +769 C Shambling Attendants +770 C Shambling Goblin +771 U Shriekmaw +772 U Shrouded Lore +773 C Silumgar Butcher +774 U Skeletal Scrying +775 C Skeleton Archer +776 C Skulking Ghost +777 U Smiting Helix +778 M Sorin Markov +779 C Spreading Rot +780 U Stab Wound +781 C Stallion of Ashmouth +782 C Stinkweed Imp +783 U Street Wraith +784 C Stromkirk Patrol +785 C Subtle Strike +786 C Sultai Runemark +787 C Tar Snare +788 U Tavern Swindler +789 C Tendrils of Corruption +790 C Thallid Omnivore +791 C Thornbow Archer +792 C Thorn of the Black Rose +793 C Thraben Foulbloods +794 C Tidy Conclusion +795 R Torment of Hailfire +796 C Torment of Venom +797 C Touch of Moonglove +798 R Toxin Sliver +799 C Tragic Slip +800 C Trespasser's Curse +801 U Trial of Ambition +802 C Twins of Maurer Estate +803 C Typhoid Rats +804 C Unburden +805 C Undercity's Embrace +806 C Untamed Hunger +807 C Unyielding Krumar +808 C Urborg Uprising +809 C Vampire Champion +810 C Vampire Envoy +811 U Vampire Hexmage +812 C Vampire Lacerator +813 U Vampire Nighthawk +814 C Vessel of Malignity +815 C Virulent Swipe +816 C Voracious Null +817 C Vraska's Finisher +818 C Wake of Vultures +819 C Walking Corpse +820 U Walk the Plank +821 C Wander in Death +822 C Warteye Witch +823 C Weight of the Underworld +824 C Weirded Vampire +825 U Wight of Precinct Six +826 U Will-o'-the-Wisp +827 C Windgrace Acolyte +828 C Wrench Mind +829 U Yargle, Glutton of Urborg +830 C Zulaport Chainmage +831 C Act of Treason +832 U Act on Impulse +833 U Ahn-Crop Crasher +834 C Ainok Tracker +835 C Akroan Sergeant +836 C Alchemist's Greeting +837 R Alesha, Who Smiles at Death +838 U Ancient Grudge +839 U Anger +840 R Anger of the Gods +841 U Arc Trail +842 C Arrow Storm +843 C Atarka Efreet +844 U Avalanche Riders +845 C Avarax +846 C Azra Bladeseeker +847 C Balduvian Horde +848 C Barging Sergeant +849 C Barrage of Boulders +850 C Battle Rampart +851 C Battle-Rattle Shaman +852 U Beetleback Chief +853 C Bellows Lizard +854 C Blades of Velis Vel +855 C Blastfire Bolt +856 C Blazing Volley +857 C Blindblast +858 C Bloodfire Expert +859 C Bloodlust Inciter +860 C Bloodmad Vampire +861 C Blood Ogre +862 C Bloodstone Goblin +863 C Blow Your House Down +864 C Blur of Blades +865 C Boggart Brute +866 C Boiling Earth +867 C Bombard +868 C Bomber Corps +869 C Borrowed Hostility +870 C Boulder Salvo +871 C Brazen Buccaneers +872 C Brazen Wolves +873 R Brimstone Dragon +874 U Brimstone Mage +875 C Bring Low +876 U Browbeat +877 C Brute Strength +878 C Built to Smash +879 C Burst Lightning +880 C Canyon Lurkers +881 C Cartouche of Zeal +882 C Cathartic Reunion +883 C Chandra's Pyrohelix +884 C Chandra's Revolution +885 R Chaos Warp +886 U Charging Monstrosaur +887 C Chartooth Cougar +888 C Cinder Hellion +889 C Cleansing Screech +890 C Cobblebrute +891 C Cosmotronic Wave +892 R Cragganwick Cremator +893 C Crash Through +894 C Crowd's Favor +895 C Crown-Hunter Hireling +896 U Curse of Opulence +897 U Curse of the Nightly Hunt +898 M Daretti, Scrap Savant +899 U Death by Dragons +900 C Defiant Ogre +901 C Demolish +902 C Desert Cerodon +903 U Desperate Ravings +904 C Destructive Tampering +905 C Direct Current +906 C Distemper of the Blood +907 U Dragon Breath +908 C Dragon Egg +909 C Dragon Fodder +910 C Dragonsoul Knight +911 U Dragon Whelp +912 C Dual Shot +913 C Dynacharge +914 C Earth Elemental +915 C Emrakul's Hatcher +916 U Enthralling Victor +917 C Erratic Explosion +918 C Expedite +919 C Faithless Looting +920 C Falkenrath Reaver +921 C Fall of the Hammer +922 C Fervent Strike +923 C Fierce Invocation +924 C Fiery Hellhound +925 C Fiery Temper +926 U Fireball +927 C Firebolt +928 C Firebrand Archer +929 C Fire Elemental +930 U Flame Jab +931 U Flameshot +932 U Flametongue Kavu +933 U Flamewave Invoker +934 C Fling +935 C Forge Devil +936 C Foundry Street Denizen +937 C Frenzied Raptor +938 C Frilled Deathspitter +939 C Frontline Devastator +940 C Frontline Rebel +941 C Furnace Whelp +942 C Fury Charm +943 C Galvanic Blast +944 C Generator Servant +945 U Genju of the Spires +946 C Geomancer's Gambit +947 C Ghitu Lavarunner +948 U Ghitu War Cry +949 C Giant Spectacle +950 U Goblin Assault +951 C Goblin Balloon Brigade +952 U Goblin Bombardment +953 C Goblin Fireslinger +954 R Goblin Game +955 C Goblin Locksmith +956 U Goblin Matron +957 C Goblin Motivator +958 U Goblin Oriflamme +959 R Goblin Piledriver +960 C Goblin Roughrider +961 U Goblin Warchief +962 C Goblin War Paint +963 C Gorehorn Minotaurs +964 C Gore Swine +965 C Granitic Titan +966 C Grapeshot +967 C Gravitic Punch +968 R Greater Gargadon +969 C Gut Shot +970 U Guttersnipe +971 C Hammerhand +972 C Hanweir Lancer +973 C Hardened Berserker +974 C Hijack +975 C Hulking Devil +976 C Hyena Pack +977 C Ill-Tempered Cyclops +978 C Impact Tremors +979 R Impending Disaster +980 U Incorrigible Youths +981 C Inferno Fist +982 U Inferno Jet +983 C Ingot Chewer +984 C Insolent Neonate +985 C Jackal Pup +986 C Kaervek's Torch +987 M Kargan Dragonlord +988 C Keldon Halberdier +989 C Keldon Overseer +990 C Khenra Scrapper +991 M Kiki-Jiki, Mirror Breaker +992 C Kiln Fiend +993 C Kird Ape +994 R Knollspine Dragon +995 C Kolaghan Stormsinger +996 R Krenko, Mob Boss +997 C Krenko's Command +998 C Krenko's Enforcer +999 C Leaping Master +1000 C Leopard-Spotted Jiao +1001 U Lightning Bolt +1002 C Lightning Javelin +1003 C Lightning Shrieker +1004 C Lightning Talons +1005 C Madcap Skills +1006 C Magma Spray +1007 C Makindi Sliderunner +1008 C Mardu Warshrieker +1009 U Mark of Mutiny +1010 C Maximize Velocity +1011 C Miner's Bane +1012 R Mizzix's Mastery +1013 U Mogg Fanatic +1014 C Mogg Flunkies +1015 C Mogg War Marshal +1016 U Molten Rain +1017 U Monastery Swiftspear +1018 C Mutiny +1019 C Nimble-Blade Khenra +1020 C Ondu Champion +1021 C Orcish Cannonade +1022 C Orcish Oriflamme +1023 C Outnumber +1024 C Pillage +1025 R Preyseizer Dragon +1026 U Price of Progress +1027 C Prickleboar +1028 C Prophetic Ravings +1029 M Purphoros, God of the Forge +1030 U Pyrotechnics +1031 C Quakefoot Cyclops +1032 R Rage Reflection +1033 C Rampaging Cyclops +1034 R Reality Scramble +1035 C Reckless Fireweaver +1036 C Reckless Wurm +1037 U Recoup +1038 U Release the Ants +1039 R Release the Gremlins +1040 C Renegade Tactics +1041 U Rivals' Duel +1042 U Roast +1043 U Rolling Thunder +1044 C Rubblebelt Maaka +1045 C Ruinous Gremlin +1046 C Rummaging Goblin +1047 C Run Amok +1048 C Rush of Adrenaline +1049 C Salivating Gremlins +1050 C Samut's Sprint +1051 C Sarkhan's Rage +1052 C Screamreach Brawler +1053 C Seismic Shift +1054 C Seismic Stomp +1055 C Shatter +1056 U Shattering Spree +1057 C Shenanigans +1058 C Shock +1059 C Skirk Commando +1060 C Skirk Prospector +1061 C Smash to Smithereens +1062 C Smelt +1063 C Sparkmage Apprentice +1064 C Sparkspitter +1065 C Sparktongue Dragon +1066 U Spikeshot Goblin +1067 U Staggershock +1068 M Star of Extinction +1069 R Steamflogger Boss +1070 U Stormblood Berserker +1071 R Sudden Demise +1072 U Sulfurous Blast +1073 C Summit Prowler +1074 C Sun-Crowned Hunters +1075 C Swashbuckling +1076 C Sweatworks Brawler +1077 C Swift Kick +1078 C Tarfire +1079 R Taurean Mauler +1080 U Tectonic Rift +1081 C Temur Battle Rage +1082 C Thresher Lizard +1083 C Thrill of Possibility +1084 U Tibalt's Rager +1085 C Torch Courier +1086 R Two-Headed Giant +1087 C Uncaged Fury +1088 C Undying Rage +1089 R Urza's Rage +1090 C Valakut Invoker +1091 C Valakut Predator +1092 C Valley Dasher +1093 C Vandalize +1094 C Vent Sentinel +1095 C Vessel of Volatility +1096 U Viashino Sandstalker +1097 U Volcanic Dragon +1098 C Volcanic Rush +1099 C Voldaren Duelist +1100 C Wall of Fire +1101 C Wayward Giant +1102 R Wheel of Fate +1103 C Wildfire Emissary +1104 C Wojek Bodyguard +1105 U Young Pyromancer +1106 C Zada's Commando +1107 C Zealot of the God-Pharaoh +1108 C Abundant Growth +1109 U Acidic Slime +1110 C Adventurous Impulse +1111 C Aerie Bowmasters +1112 U Affectionate Indrik +1113 C Aggressive Instinct +1114 C Aggressive Urge +1115 U Ainok Survivalist +1116 C Alpine Grizzly +1117 C Ambassador Oak +1118 U Ana Sanctuary +1119 U Ancestral Mask +1120 C Ancient Brontodon +1121 U Ancient Stirrings +1122 C Arachnus Web +1123 C Arbor Armament +1124 C Arbor Elf +1125 R Asceticism +1126 C Aura Gnarlid +1127 C Avacyn's Pilgrim +1128 C Backwoods Survivalists +1129 C Baloth Gorger +1130 C Basking Rootwalla +1131 C Bear Cub +1132 U Beastbreaker of Bala Ged +1133 R Beastmaster Ascension +1134 U Beast Within +1135 U Become Immense +1136 C Beneath the Sands +1137 U Bestial Menace +1138 R Birds of Paradise +1139 C Bitterblade Warrior +1140 C Bitterbow Sharpshooters +1141 U Blanchwood Armor +1142 C Blastoderm +1143 R Bloom Tender +1144 C Blossom Dryad +1145 C Borderland Explorer +1146 C Borderland Ranger +1147 R Bow of Nylea +1148 U Briarhorn +1149 C Bristling Boar +1150 C Broken Bond +1151 C Broodhunter Wurm +1152 C Byway Courier +1153 C Call the Scions +1154 C Canopy Spider +1155 C Carnivorous Moss-Beast +1156 U Carpet of Flowers +1157 C Caustic Caterpillar +1158 C Centaur Courser +1159 U Centaur Glade +1160 C Charging Rhino +1161 C Chatter of the Squirrel +1162 C Citanul Woodreaders +1163 C Clip Wings +1164 C Colossal Dreadmaw +1165 C Combo Attack +1166 C Commune with Nature +1167 C Commune with the Gods +1168 C Conifer Strider +1169 R Courser of Kruphix +1170 U Creeping Mold +1171 C Crop Rotation +1172 C Crossroads Consecrator +1173 U The Crowd Goes Wild +1174 C Crowned Ceratok +1175 C Crushing Canopy +1176 C Cultivate +1177 C Daggerback Basilisk +1178 C Dawn's Reflection +1179 C Death-Hood Cobra +1180 R Defense of the Heart +1181 U Desert Twister +1182 U Destructor Dragon +1183 C Dissenter's Deliverance +1184 U Domesticated Hydra +1185 C Dragonscale Boon +1186 C Dragon-Scarred Bear +1187 R Dungrove Elder +1188 C Durkwood Baloth +1189 C Earthen Arms +1190 R Eldritch Evolution +1191 C Elemental Uprising +1192 C Elephant Guide +1193 C Elves of Deep Shadow +1194 C Elvish Fury +1195 C Elvish Visionary +1196 C Elvish Warrior +1197 C Ember Weaver +1198 C Epic Confrontation +1199 C Essence Warden +1200 U Eternal Witness +1201 U Experiment One +1202 C Explore +1203 U Explosive Vegetation +1204 C Ezuri's Archers +1205 C Fade into Antiquity +1206 C Farseek +1207 C Feed the Clan +1208 C Feral Krushok +1209 C Feral Prowler +1210 C Ferocious Zheng +1211 C Fertile Ground +1212 C Fierce Empath +1213 C Fog +1214 C Formless Nurturing +1215 C Frontier Mastodon +1216 U Gaea's Blessing +1217 C Gaea's Protector +1218 C Giant Growth +1219 C Giant Spider +1220 C Gift of Growth +1221 C Gift of Paradise +1222 C Glade Watcher +1223 C Gnarlid Pack +1224 C Grapple with the Past +1225 C Grazing Gladehart +1226 C Greater Basilisk +1227 C Greater Sandwurm +1228 R Greenbelt Rampager +1229 C Greenwood Sentinel +1230 C Groundswell +1231 C Guardian Shield-Bearer +1232 U Hamlet Captain +1233 C Hardy Veteran +1234 U Harmonize +1235 C Harrow +1236 C Hooded Brawler +1237 C Hooting Mandrills +1238 R Hornet Nest +1239 C Hunter's Ambush +1240 C Hunt the Weak +1241 R Hurricane +1242 U Imperious Perfect +1243 U Invigorate +1244 C Ivy Lane Denizen +1245 C Jungle Delver +1246 C Jungle Wayfinder +1247 C Kavu Climber +1248 C Kavu Primarch +1249 C Khalni Heart Expedition +1250 C Kin-Tree Warden +1251 C Kozilek's Predator +1252 C Kraul Foragers +1253 C Kraul Warrior +1254 C Krosan Druid +1255 C Krosan Tusker +1256 C Larger Than Life +1257 C Lay of the Land +1258 C Lead by Example +1259 C Lead the Stampede +1260 C Lifespring Druid +1261 C Lignify +1262 C Llanowar Elves +1263 C Llanowar Empath +1264 C Longshot Squad +1265 U Lure +1266 U Manglehorn +1267 C Mantle of Webs +1268 C Map the Wastes +1269 R Meandering Towershell +1270 C Might of the Masses +1271 C Mulch +1272 R Mycoloth +1273 C Natural Connection +1274 C Naturalize +1275 C Nature's Claim +1276 C Nature's Lore +1277 C Nest Invader +1278 C Nettle Sentinel +1279 C New Horizons +1280 C Nimble Mongoose +1281 M Nissa, Voice of Zendikar +1282 C Oakgnarl Warrior +1283 C Ondu Giant +1284 C Oran-Rief Invoker +1285 C Overgrown Armasaur +1286 U Overgrown Battlement +1287 U Overrun +1288 C Pack's Favor +1289 C Peema Outrider +1290 U Pelakka Wurm +1291 C Penumbra Spider +1292 U Phantom Centaur +1293 C Pierce the Sky +1294 C Pinion Feast +1295 C Plummet +1296 C Pouncing Cheetah +1297 C Prey's Vengeance +1298 C Prey Upon +1299 C Priest of Titania +1300 C Pulse of Murasa +1301 C Quiet Disrepair +1302 U Rain of Thorns +1303 C Rampant Growth +1304 U Rancor +1305 C Ranger's Guile +1306 C Ravenous Leucrocota +1307 C Reclaim +1308 C Reclaiming Vines +1309 U Regrowth +1310 C Relic Crush +1311 C Return to the Earth +1312 C Revive +1313 C Rhox Maulers +1314 C Riparian Tiger +1315 U River Boa +1316 U Roar of the Wurm +1317 C Root Out +1318 C Roots +1319 C Rosethorn Halberd +1320 C Runeclaw Bear +1321 C Sagu Archer +1322 C Sakura-Tribe Elder +1323 C Saproling Migration +1324 C Savage Punch +1325 C Scatter the Seeds +1326 C Seal of Strength +1327 C Search for Tomorrow +1328 U Seek the Horizon +1329 C Seek the Wilds +1330 M Selvala, Heart of the Wilds +1331 R Shamanic Revelation +1332 C Shape the Sands +1333 C Siege Wurm +1334 C Silhana Ledgewalker +1335 C Silkweaver Elite +1336 C Snake Umbra +1337 U Snapping Sailback +1338 R Spawning Grounds +1339 U Spider Spawning +1340 R Squirrel Wrangler +1341 C Stalking Tiger +1342 C Stoic Builder +1343 C Strength in Numbers +1344 C Sylvan Bounty +1345 U Sylvan Scrying +1346 C Tajuru Pathwarden +1347 U Tajuru Warcaller +1348 C Take Down +1349 C Talons of Wildwood +1350 R Tempt with Discovery +1351 C Terrain Elemental +1352 C Territorial Baloth +1353 C Thornhide Wolves +1354 U Thornscape Battlemage +1355 C Thornweald Archer +1356 U Thrashing Brontodon +1357 C Thrive +1358 M Thrun, the Last Troll +1359 U Timberwatch Elf +1360 C Time to Feed +1361 R Tireless Tracker +1362 C Titanic Growth +1363 U Triumph of the Hordes +1364 C Tukatongue Thallid +1365 U Turntimber Basilisk +1366 C Vastwood Gorger +1367 U Venom Sliver +1368 R Vigor +1369 C Watcher in the Web +1370 C Wellwisher +1371 C Wild Growth +1372 C Wild Mongrel +1373 C Wild Nacatl +1374 C Wildsize +1375 C Wolfkin Bond +1376 U Woodborn Behemoth +1377 C Woolly Loxodon +1378 U Wren's Run Vanquisher +1379 C Yavimaya Elder +1380 C Yavimaya Sapherd +1381 C Yeva's Forcemage +1382 U Zendikar's Roil +1383 U Abzan Charm +1384 C Abzan Guide +1385 C Agony Warp +1386 U Akroan Hoplite +1387 M Animar, Soul of Elements +1388 U Armadillo Cloak +1389 U Armament Corps +1390 R Assemble the Legion +1391 M Athreos, God of Passage +1392 U Aura Shards +1393 U Azorius Charm +1394 U Azra Oddsmaker +1395 U Baleful Strix +1396 U Baloth Null +1397 U Bear's Companion +1398 U Belligerent Brontodon +1399 U Bituminous Blast +1400 U Bladewing the Risen +1401 U Blightning +1402 U Bloodbraid Elf +1403 U Boros Challenger +1404 U Bounding Krasis +1405 U Call of the Nightwing +1406 U Campaign of Vengeance +1407 U Cauldron Dance +1408 U Citadel Castellan +1409 C Coiling Oracle +1410 U Contraband Kingpin +1411 U Corpsejack Menace +1412 U Crosis's Charm +1413 U Cunning Breezedancer +1414 U Deathreap Ritual +1415 C Deny Reality +1416 U Draconic Disciple +1417 M Dragon Broodmother +1418 M Dragonlord Ojutai +1419 U Drana's Emissary +1420 U Engineered Might +1421 U Esper Charm +1422 U Ethercaste Knight +1423 C Ethereal Ambush +1424 U Extract from Darkness +1425 U Fires of Yavimaya +1426 U Flame-Kin Zealot +1427 U Fusion Elemental +1428 U Gelectrode +1429 U Ghor-Clan Rampager +1430 M The Gitrog Monster +1431 C Goblin Deathraiders +1432 C Grim Contest +1433 R Guided Passage +1434 C Hammer Dropper +1435 U Hidden Stockpile +1436 U Highspire Mantis +1437 C Hypothesizzle +1438 U Iroas's Champion +1439 U Join Shields +1440 U Jungle Barrier +1441 U Kathari Remnant +1442 U Kin-Tree Invocation +1443 U Kiora's Follower +1444 U Kiss of the Amesha +1445 R Kolaghan's Command +1446 M Kruphix, God of Horizons +1447 C Lawmage's Binding +1448 U Lightning Helix +1449 M Maelstrom Archangel +1450 U Mardu Roughrider +1451 C Martial Glory +1452 U Maverick Thopterist +1453 R Meddling Mage +1454 U Mercurial Geists +1455 M Meren of Clan Nel Toth +1456 U Migratory Route +1457 U Mortify +1458 U Naya Charm +1459 R Nemesis of Reason +1460 R Nin, the Pain Artist +1461 U Obelisk Spider +1462 U Ochran Assassin +1463 U Pillory of the Sleepless +1464 U Plaxcaster Frogling +1465 U Pollenbright Wings +1466 U Putrefy +1467 C Qasali Pridemage +1468 M Queen Marchesa +1469 R Questing Phelddagrif +1470 U Raff Capashen, Ship's Mage +1471 U Raging Swordtooth +1472 U Reclusive Artificer +1473 U Reflector Mage +1474 U Rhox War Monk +1475 C Riptide Crab +1476 R Rith, the Awakener +1477 U River Hoopoe +1478 C Rosemane Centaur +1479 U Satyr Enchanter +1480 R Savage Knuckleblade +1481 U Savage Twister +1482 U Sedraxis Specter +1483 U Shambling Remains +1484 U Shardless Agent +1485 U Shipwreck Singer +1486 U Skyward Eye Prophets +1487 M Sliver Hivelord +1488 U Soul Manipulation +1489 U Sprouting Thrinax +1490 U Stormchaser Chimera +1491 U Sultai Charm +1492 U Sultai Soothsayer +1493 R Supreme Verdict +1494 U Tatyova, Benthic Druid +1495 C Terminate +1496 U Thought Erasure +1497 R Time Sieve +1498 C Tithe Drinker +1499 U Tower Gargoyle +1500 U Treacherous Terrain +1501 U Underworld Coinsmith +1502 U Unflinching Courage +1503 U Unlicensed Disintegration +1504 U Urban Evolution +1505 U Vengeful Rebirth +1506 R Violent Ultimatum +1507 U Warden of the Eye +1508 R Wargate +1509 U Wayfaring Temple +1510 U Weapons Trainer +1511 U Wee Dragonauts +1512 U Winding Constrictor +1513 U Woolly Thoctar +1514 R Yavimaya's Embrace +1515 R Yuriko, the Tiger's Shadow +1516 U Zealous Persecution +1517 C Zhur-Taa Druid +1518 R Boros Reckoner +1519 R Debtors' Knell +1520 R Dominus of Fealty +1521 R Doomgape +1522 R Enchanted Evening +1523 C Giantbaiting +1524 C Gift of Orzhova +1525 U Gwyllion Hedge-Mage +1526 C Manamorphose +1527 U Mistmeadow Witch +1528 U Nucklavee +1529 R Oracle of Nectars +1530 R Rhys the Redeemed +1531 U Rosheen Meanderer +1532 U Selesnya Guildmage +1533 U Shrewd Hatchling +1534 U Slave of Bolas +1535 U Thopter Foundry +1536 U Claim // Fame +1537 R Commit // Memory +1538 C Fire // Ice +1539 R Aetherflux Reservoir +1540 C Aether Spellbomb +1541 R Akroan Horse +1542 C Alchemist's Vial +1543 M Alhammarret's Archive +1544 C Alloy Myr +1545 C Armillary Sphere +1546 U Ashnod's Altar +1547 R Basilisk Collar +1548 R Belbe's Portal +1549 C Blinding Souleater +1550 U Bomat Bazaar Barge +1551 C Bone Saw +1552 C Bonesplitter +1553 R Boompile +1554 U Bottle Gnomes +1555 U Burnished Hart +1556 R Caged Sun +1557 U Cathodion +1558 R Cauldron of Souls +1559 R Chromatic Lantern +1560 C Chromatic Star +1561 R Coat of Arms +1562 U Coldsteel Heart +1563 U Consulate Dreadnought +1564 U Contagion Clasp +1565 C Copper Carapace +1566 R Coveted Jewel +1567 U Crenellated Wall +1568 U Crystal Ball +1569 U Crystal Chimes +1570 U Crystal Shard +1571 R Darksteel Garrison +1572 U Diamond Mare +1573 R Dolmen Gate +1574 R Draco +1575 U Dragon Mask +1576 R Eater of Days +1577 M Eldrazi Monument +1578 U Elixir of Immortality +1579 U Emmessi Tome +1580 U Etched Oracle +1581 U Farmstead Gleaner +1582 U Filigree Familiar +1583 C Flayer Husk +1584 R Font of Mythos +1585 U Foundry Inspector +1586 U Fountain of Renewal +1587 C Frogmite +1588 R Goblin Charbelcher +1589 C Gruul Signet +1590 C Guardians of Meletis +1591 U Heavy Arbalest +1592 U Helm of Awakening +1593 U Herald's Horn +1594 C Hexplate Golem +1595 U Hot Soup +1596 U Icy Manipulator +1597 C Implement of Malice +1598 C Irontread Crusher +1599 U Juggernaut +1600 U Lightning Greaves +1601 C Lotus Petal +1602 U Loxodon Warhammer +1603 M Mana Crypt +1604 U Mask of Memory +1605 U Meteorite +1606 U Millikin +1607 U Millstone +1608 R Mimic Vat +1609 C Mind Stone +1610 U Mishra's Bauble +1611 C Moonglove Extract +1612 U Mortarpod +1613 U Myr Retriever +1614 C Myr Sire +1615 C Ornithopter +1616 U Palladium Myr +1617 C Peace Strider +1618 U Perilous Myr +1619 R Phyrexian Soulgorger +1620 U Pilgrim's Eye +1621 R Precursor Golem +1622 C Prophetic Prism +1623 C Renegade Map +1624 U Rhonas's Monument +1625 U Sandstone Oracle +1626 C Serrated Arrows +1627 C Short Sword +1628 U Sigil of Valor +1629 C Simic Locket +1630 U Skullclamp +1631 C Skyscanner +1632 R Solemn Simulacrum +1633 U Sol Ring +1634 U Sorcerer's Broom +1635 U Spy Kit +1636 U Sunset Pyramid +1637 U Suspicious Bookcase +1638 R Sword of the Animist +1639 C Thought Vessel +1640 U Thran Dynamo +1641 U Thran Golem +1642 U Tormod's Crypt +1643 R Tower of Eons +1644 R Trading Post +1645 U Trepanation Blade +1646 U Umbral Mantle +1647 C Universal Automaton +1648 C Universal Solvent +1649 U Whispersilk Cloak +1650 U Aether Hub +1651 U Akoum Refuge +1652 C Ancient Den +1653 U Ancient Ziggurat +1654 U Arcane Sanctum +1655 R Arch of Orazca +1656 C Ash Barrens +1657 U Blasted Landscape +1658 U Blighted Fen +1659 C Blossoming Sands +1660 C Bojuka Bog +1661 U Crumbling Necropolis +1662 C Darksteel Citadel +1663 C Dismal Backwater +1664 U Dreadship Reef +1665 C Evolving Wilds +1666 U Faerie Conclave +1667 U Field of Ruin +1668 C Forgotten Cave +1669 U Frontier Bivouac +1670 C Gateway Plaza +1671 U Ghost Quarter +1672 R Gilt-Leaf Palace +1673 U Goblin Burrows +1674 U Graypelt Refuge +1675 C Great Furnace +1676 C Jungle Hollow +1677 U Jungle Shrine +1678 U Kazandu Refuge +1679 U Krosan Verge +1680 U Mishra's Factory +1681 U New Benalia +1682 C Orzhov Basilica +1683 U Reliquary Tower +1684 U Rogue's Passage +1685 U Sandsteppe Citadel +1686 C Scoured Barrens +1687 U Sejiri Refuge +1688 U Skarrg, the Rage Pits +1689 C Swiftwater Cliffs +1690 U Tectonic Edge +1691 U Temple of the False God +1692 C Thornwood Falls +1693 U Unclaimed Territory +1694 U Wirewood Lodge diff --git a/forge-gui/res/editions/Theros Beyond Death.txt b/forge-gui/res/editions/Theros Beyond Death.txt index 65fd9f6ae80..6d8b9f91a2d 100644 --- a/forge-gui/res/editions/Theros Beyond Death.txt +++ b/forge-gui/res/editions/Theros Beyond Death.txt @@ -367,17 +367,17 @@ Prerelease=6 Boosters, 1 RareMythic+ 350 R Temple of Malice 351 R Temple of Plenty #Bundle promo -R Arasta of the Endless Web +352 R Arasta of the Endless Web #Promo Pack -U Alseid of Life's Bounty -C Thirst for Meaning -U Gray Merchant of Asphodel -C Thrill of Possibility -U Wolfwillow Haven +353 U Alseid of Life's Bounty +354 C Thirst for Meaning +355 U Gray Merchant of Asphodel +356 C Thrill of Possibility +357 U Wolfwillow Haven [tokens] b_2_2_zombie -c_0_4_wall_defender +c_0_4_a_wall_defender g_1_2_spider_reach g_2_2_wolf r_x_1_elemental_trample_haste diff --git a/forge-gui/res/editions/Throne of Eldraine.txt b/forge-gui/res/editions/Throne of Eldraine.txt index 1c567deab3e..b08eab5cb35 100644 --- a/forge-gui/res/editions/Throne of Eldraine.txt +++ b/forge-gui/res/editions/Throne of Eldraine.txt @@ -284,36 +284,36 @@ Prerelease=6 Boosters, 1 RareMythic+ 271 M Oko, Thief of Crowns 272 M The Royal Scions #Storybook Frames -C Ardenvale Tactician -C Faerie Guidemother -R Giant Killer -C Lonesome Unicorn -M Realm-Cloaked Giant -U Shepherd of the Flock -C Silverflame Squire -U Animating Faerie -M Brazen Borrower -R Fae of Wishes -U Hypnotic Sprite -C Merfolk Secretkeeper -C Queen of Ice -U Foulmire Knight -R Murderous Rider -U Order of Midnight -C Reaper of Night -C Smitten Swordmaster -R Bonecrusher Giant -U Embereth Shieldbreaker -C Merchant of the Vale -C Rimrock Knight -U Beanstalk Giant -C Curious Pair -U Flaxen Intruder -C Garenbrig Carver -R Lovestruck Beast -C Rosethorn Acolyte -C Tuinvale Treefolk -U Oakhame Ranger +273 C Ardenvale Tactician +274 C Faerie Guidemother +275 R Giant Killer +276 C Lonesome Unicorn +277 M Realm-Cloaked Giant +278 U Shepherd of the Flock +279 C Silverflame Squire +280 U Animating Faerie +281 M Brazen Borrower +282 R Fae of Wishes +283 U Hypnotic Sprite +284 C Merfolk Secretkeeper +285 C Queen of Ice +286 U Foulmire Knight +287 R Murderous Rider +288 U Order of Midnight +289 C Reaper of Night +290 C Smitten Swordmaster +291 R Bonecrusher Giant +292 U Embereth Shieldbreaker +293 C Merchant of the Vale +294 C Rimrock Knight +295 U Beanstalk Giant +296 C Curious Pair +297 U Flaxen Intruder +298 C Garenbrig Carver +299 R Lovestruck Beast +300 C Rosethorn Acolyte +301 C Tuinvale Treefolk +302 U Oakhame Ranger #Buy-A-Box Promo 303 M Kenrith, the Returned King #Planeswalker Deck Cards @@ -348,72 +348,72 @@ U Oakhame Ranger 332 R Tome of Legends 333 C Command Tower #Borderless art rares and mythics -R Acclaimed Contender -R Charming Prince -M The Circle of Loyalty -R Happily Ever After -M Harmonious Archon -R Hushbringer -R Linden, the Steadfast Queen -R Worthy Knight -R Emry, Lurker of the Loch -R Folio of Fancies -R Gadwick, the Wizened -M The Magic Mirror -R Midnight Clock -R Mirrormade -R Stolen by the Fae -R Vantress Gargoyle -R Ayara, First of Locthwain -R Blacklance Paragon -M The Cauldron of Eternity -R Clackbridge Troll -R Oathsworn Knight -R Piper of the Swarm -M Rankle, Master of Pranks -R Wishclaw Talisman -R Witch's Vengeance -M Embercleave -R Fervent Champion -R Fires of Invention -R Irencrag Feat -R Irencrag Pyromancer -R Opportunistic Dragon -M Robber of the Rich -R Sundering Stroke -R Torbran, Thane of Red Fell -R Feasting Troll King -R Gilded Goose -M The Great Henge -R Once Upon A Time -M Questing Beast -R Return of the Wildspeaker -R Wicked Wolf -R Wildborn Preserver -R Yorvo, Lord of Garenbrig -R Dance of the Manse -R Doom Foretold -R Escape to the Wilds -R Faeburrow Elder -R Lochmere Serpent -M Outlaws' Merriment -R Stormfist Crusader -R Sorcerous Spyglass -R Stonecoil Serpent -R Castle Ardenvale -R Castle Embereth -R Castle Garenbrig -R Castle Locthwain -R Castle Vantress -R Fabled Passage +334 R Acclaimed Contender +335 R Charming Prince +336 M The Circle of Loyalty +337 R Happily Ever After +338 M Harmonious Archon +339 R Hushbringer +340 R Linden, the Steadfast Queen +341 R Worthy Knight +342 R Emry, Lurker of the Loch +343 R Folio of Fancies +344 R Gadwick, the Wizened +345 M The Magic Mirror +346 R Midnight Clock +347 R Mirrormade +348 R Stolen by the Fae +349 R Vantress Gargoyle +350 R Ayara, First of Locthwain +351 R Blacklance Paragon +352 M The Cauldron of Eternity +353 R Clackbridge Troll +354 R Oathsworn Knight +355 R Piper of the Swarm +356 M Rankle, Master of Pranks +357 R Wishclaw Talisman +358 R Witch's Vengeance +359 M Embercleave +360 R Fervent Champion +361 R Fires of Invention +362 R Irencrag Feat +363 R Irencrag Pyromancer +364 R Opportunistic Dragon +365 M Robber of the Rich +366 R Sundering Stroke +367 R Torbran, Thane of Red Fell +368 R Feasting Troll King +369 R Gilded Goose +370 M The Great Henge +371 R Once Upon a Time +372 M Questing Beast +373 R Return of the Wildspeaker +374 R Wicked Wolf +375 R Wildborn Preserver +376 R Yorvo, Lord of Garenbrig +377 R Dance of the Manse +378 R Doom Foretold +379 R Escape to the Wilds +380 R Faeburrow Elder +381 R Lochmere Serpent +382 M Outlaws' Merriment +383 R Stormfist Crusader +384 R Sorcerous Spyglass +385 R Stonecoil Serpent +386 R Castle Ardenvale +387 R Castle Embereth +388 R Castle Garenbrig +389 R Castle Locthwain +390 R Castle Vantress +391 R Fabled Passage #Bundle promo -R Piper of the Swarm +392 R Piper of the Swarm #Promo Pack -U Glass Casket -U Slaying Fire -U Kenrith's Transformation -U Improbable Alliance -U Inspiring Veteran +393 U Glass Casket +394 U Slaying Fire +395 U Kenrith's Transformation +396 U Improbable Alliance +397 U Inspiring Veteran [tokens] w_0_1_goat diff --git a/forge-gui/res/editions/Weatherlight.txt b/forge-gui/res/editions/Weatherlight.txt index 3689f4a2a66..1ef49097fbf 100644 --- a/forge-gui/res/editions/Weatherlight.txt +++ b/forge-gui/res/editions/Weatherlight.txt @@ -178,5 +178,5 @@ R Winding Canyons R Xanthic Statue C Zombie Scavengers -[token] +[tokens] g_1_1_squirrel \ No newline at end of file diff --git a/forge-gui/res/formats/Casual/Brawl.txt b/forge-gui/res/formats/Casual/Brawl.txt index 804db4799d5..63db92dec93 100644 --- a/forge-gui/res/formats/Casual/Brawl.txt +++ b/forge-gui/res/formats/Casual/Brawl.txt @@ -4,4 +4,4 @@ Order:101 Type:Casual Subtype:Commander Sets:GRN, RNA, WAR, M20, ELD, THB -Banned:Sorcerous Spyglass;Oko, Thief of Crowns +Banned:Golos, Tireless Pilgrim; Oko, Thief of Crowns; Sorcerous Spyglass diff --git a/forge-gui/res/formats/Sanctioned/Legacy.txt b/forge-gui/res/formats/Sanctioned/Legacy.txt index 404a575f8cd..5d6162ad978 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; 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; Wrenn and Six; 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; Underworld Breach; 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; Wrenn and Six; 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 5f00bc45197..78faab16590 100644 --- a/forge-gui/res/formats/Sanctioned/Modern.txt +++ b/forge-gui/res/formats/Sanctioned/Modern.txt @@ -4,4 +4,4 @@ Order:103 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, G18, GRN, RNA, WAR, MH1, M20, ELD, THB -Banned:Ancient Den; Birthing Pod; Blazing Shoal; Bridge from Below; Chrome Mox; Cloudpost; Dark Depths; Deathrite Shaman; Dig Through Time; Dread Return; Eye of Ugin; Faithless Looting; Gitaxian Probe; Glimpse of Nature; Golgari Grave-Troll; Great Furnace; Green Sun's Zenith; Hogaak, Arisen Necropolis; Hypergenesis; Krark-Clan Ironworks; Mental Misstep; Mox Opal; Mycosynth Lattice; Oko, Thief of Crowns; Ponder; Preordain; Punishing Fire; Rite of Flame; Seat of the Synod; Second Sunrise; Seething Song; Sensei's Divining Top; Skullclamp; Splinter Twin; Summer Bloom; Treasure Cruise; Tree of Tales; Umezawa's Jitte; Vault of Whispers +Banned:Ancient Den; Birthing Pod; Blazing Shoal; Bridge from Below; Chrome Mox; Cloudpost; Dark Depths; Deathrite Shaman; Dig Through Time; Dread Return; Eye of Ugin; Faithless Looting; Gitaxian Probe; Glimpse of Nature; Golgari Grave-Troll; Great Furnace; Green Sun's Zenith; Hogaak, Arisen Necropolis; Hypergenesis; Krark-Clan Ironworks; Mental Misstep; Mox Opal; Mycosynth Lattice; Oko, Thief of Crowns; Once Upon A Time; Ponder; Preordain; Punishing Fire; Rite of Flame; Seat of the Synod; Second Sunrise; Seething Song; Sensei's Divining Top; Skullclamp; Splinter Twin; Summer Bloom; Treasure Cruise; Tree of Tales; Umezawa's Jitte; Vault of Whispers diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 48007ba7e84..c336f991d72 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -50,6 +50,8 @@ btnResetJavaFutureCompatibilityWarnings=Java-Kompatibilitätswarnung zurücksetz btnClearImageCache=Leere Bildspeicher btnTokenPreviewer=Spielstein-Vorschau btnCopyToClipboard=In Zwischenablage kopieren +cbpAutoUpdater=Auto updater +nlAutoUpdater=Select the release channel to use for updating Forge cbpSelectLanguage=Sprache nlSelectLanguage=Wähle Sprache (Ist noch in Arbeit und nur teilweise umgesetzt.) (Neustart ist erforderlich.) cbRemoveSmall=Entferne kleine Kreaturen @@ -180,6 +182,7 @@ KeyboardShortcuts=Tastenkombinationen #VSubmenuAchievements.java lblAchievements=Errungenschaften #VSubmenuDownloaders.java +btnCheckForUpdates=Check for Updates btnDownloadSetPics=Bilder(LQ) Sets herunterladen btnDownloadPicsHQ=Bilder(HQ) Karten herunterladen (Sehr langsam!) btnDownloadPics=Bilder(LQ) Karten herunterladen @@ -192,6 +195,7 @@ btnImportPictures=Daten importieren btnHowToPlay=Wie man spielt btnDownloadPrices=Kartenpreise herunterladen btnLicensing=Lizenzhinweis +lblCheckForUpdates=Check Forge server to see if there's a more recent release lblDownloadPics=Lädt ein Standardbild pro Karte. lblDownloadPicsHQ=Lädt ein HQ-Standardbild pro Karte. lblDownloadSetPics=Lädt alle Bilder pro Karte. Eines für jedes Set, in welchem die Karte auftauchte. diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 503298d25a2..7b149832456 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -50,6 +50,8 @@ btnResetJavaFutureCompatibilityWarnings=Reset Java Compatibility Warnings btnClearImageCache=Clear Image Cache btnTokenPreviewer=Token Previewer btnCopyToClipboard=Copy to Clipboard +cbpAutoUpdater=Auto updater +nlAutoUpdater=Select the release channel to use for updating Forge cbpSelectLanguage=Language nlSelectLanguage=Select Language (Excluded Game part. Still a work in progress) (RESTART REQUIRED) cbRemoveSmall=Remove Small Creatures @@ -180,6 +182,7 @@ KeyboardShortcuts=Keyboard Shortcuts #VSubmenuAchievements.java lblAchievements=Achievements #VSubmenuDownloaders.java +btnCheckForUpdates=Check for Updates btnDownloadSetPics=Download LQ Set Pictures btnDownloadPicsHQ=Download HQ Card Pictures (Very Slow!) btnDownloadPics=Download LQ Card Pictures @@ -192,6 +195,7 @@ btnImportPictures=Import Data btnHowToPlay=How To Play btnDownloadPrices=Download Card Prices btnLicensing=License Details +lblCheckForUpdates=Check Forge server to see if there's a more recent release lblDownloadPics=Download default card picture for each card. lblDownloadPicsHQ=Download default card HQ picture for each card. lblDownloadSetPics=Download all pictures of each card (one for each set the card appeared in) diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 9c4ddf6ed92..29524d91269 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -50,6 +50,8 @@ btnResetJavaFutureCompatibilityWarnings=Restablecer las advertencias de compatib btnClearImageCache=Limpiar Caché de Imágenes btnTokenPreviewer=Previsualizador de Fichas (Token) btnCopyToClipboard=Copiar al portapapeles +cbpAutoUpdater=Actualizar Forge +nlAutoUpdater=Selecciona la versión a utilizar para actualizar Forge cbpSelectLanguage=Idioma nlSelectLanguage=Seleccionar idioma (excepto partida). Todavía un trabajo en progreso) (Es necesario reiniciar Forge) cbRemoveSmall=Eliminar Pequeñas Criaturas @@ -180,6 +182,7 @@ KeyboardShortcuts=Atajos de teclado #VSubmenuAchievements.java lblAchievements=Logros #VSubmenuDownloaders.java +btnCheckForUpdates=Comprobar Actualizaciones btnDownloadSetPics=Descargar todas las Ediciones de Cartas btnDownloadPics=Descargar todas las Cartas btnDownloadPicsHQ=Descargar todas las Cartas en calidad alta (Muy lento!) @@ -192,6 +195,7 @@ btnImportPictures=Importar Datos btnHowToPlay=Cómo jugar (Inglés) btnDownloadPrices=Descargar los precios de las cartas btnLicensing=Detalles de la licencia +lblCheckForUpdates=Comprueba si en el servidor de Forge existe alguna versión más reciente lblDownloadPics=Descargar la imagen de la carta por defecto para cada carta. lblDownloadPicsHQ=Descargar la imagen en calidad alta de la carta por defecto para cada carta. lblDownloadSetPics=Descargue todas las imágenes de cada carta (una por cada edición donde apareció la carta) diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 5b059135cd4..c260b57b87c 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -50,6 +50,8 @@ btnResetJavaFutureCompatibilityWarnings=Ripristina avvisi di compatibilità Java btnClearImageCache=Cancella cache immagini btnTokenPreviewer=Anteprima token btnCopyToClipboard=Copia negli appunti +cbpAutoUpdater=Auto updater +nlAutoUpdater=Select the release channel to use for updating Forge cbpSelectLanguage=Lingua nlSelectLanguage=Seleziona la lingua (parte di gioco esclusa. Ancora in fase di sviluppo) (RIAVVIO NECESSARIO) cbRemoveSmall=Rimuovi le piccole creature @@ -180,6 +182,7 @@ KeyboardShortcuts=Tasti rapidi #VSubmenuAchievements.java lblAchievements=realizzazioni #VSubmenuDownloaders.java +btnCheckForUpdates=Check for Updates btnDownloadSetPics=Scarica LQ Set Pictures btnDownloadPicsHQ=Scarica le immagini della scheda HQ (molto lento!) btnDownloadPics=Scarica LQ Card Pictures @@ -192,6 +195,7 @@ btnImportPictures=Importa dati btnHowToPlay=Come giocare btnDownloadPrices=Scarica i prezzi delle carte btnLicensing=Dettagli della licenza +lblCheckForUpdates=Check Forge server to see if there's a more recent release lblDownloadPics=Scarica l''immagine della carta predefinita per ogni carta. lblDownloadPicsHQ=Scarica l''immagine HQ della scheda predefinita per ogni scheda. lblDownloadSetPics=Scarica tutte le immagini di ogni carta (una per ogni set in cui è apparso la carta) diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index 409c129d0e7..c72c559cbac 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -50,6 +50,8 @@ btnResetJavaFutureCompatibilityWarnings=重置Java兼容性警告 btnClearImageCache=清除图片缓存 btnTokenPreviewer=衍生物预览器 btnCopyToClipboard=复制到剪切板 +cbpAutoUpdater=Auto updater +nlAutoUpdater=Select the release channel to use for updating Forge cbpSelectLanguage=语言 nlSelectLanguage=选择语言(除了正在进行中的游戏)(需要重新启动) cbRemoveSmall=删除小生物 @@ -180,6 +182,7 @@ KeyboardShortcuts=键盘快捷键 #VSubmenuAchievements.java lblAchievements=成就 #VSubmenuDownloaders.java +btnCheckForUpdates=Check for Updates btnDownloadSetPics=下载低清系列图 btnDownloadPicsHQ=下载高清卡图(这很慢!) btnDownloadPics=下载低清卡图 @@ -192,6 +195,7 @@ btnImportPictures=导入数据 btnHowToPlay=如何玩 btnDownloadPrices=下载卡牌价格 btnLicensing=许可证详情 +lblCheckForUpdates=Check Forge server to see if there's a more recent release lblDownloadPics=下载缺省牌的图片 lblDownloadPicsHQ=下载缺省牌的高清图片 lblDownloadSetPics=下载每张牌的图片(每张牌出现一次) diff --git a/forge-gui/res/puzzle/PS_THB6.pzl b/forge-gui/res/puzzle/PS_THB6.pzl new file mode 100644 index 00000000000..0fb3f36c66e --- /dev/null +++ b/forge-gui/res/puzzle/PS_THB6.pzl @@ -0,0 +1,18 @@ +[metadata] +Name:Possibility Storm - Theros Beyond Death #06 +URL:https://i0.wp.com/www.possibilitystorm.com/wp-content/uploads/2020/02/149.-THB6-1-scaled.jpg +Goal:Win +Turns:1 +Difficulty:Uncommon +Description:Win this turn. Assume any unknown cards drawn by either player are not relevant to solving the puzzle. Your opponent starts with 13 cards in their library. Your opponent has a Pollenbright Druid on top of their library, and twelve other unknown cards in it. +[state] +humanlife=20 +ailife=18 +turn=1 +activeplayer=human +activephase=MAIN1 +humanhand=Assassin's Trophy;Unmoored Ego;Applied Biomancy;Underworld Dreams;Tyrant's Scorn +humanlibrary=Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt +humanbattlefield=Ob Nixilis, the Hate-Twisted|Counters:LOYALTY=2;Nessian Boar;Thief of Sanity;Thief of Sanity;Watery Grave|NoETBTrigs;Watery Grave|NoETBTrigs;Watery Grave|NoETBTrigs;Watery Grave|NoETBTrigs;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs +ailibrary=Pollenbright Druid;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt +aibattlefield=Silhana Wayfinder;Silhana Wayfinder;Blightbeetle;Wavebreak Hippocamp diff --git a/forge-gui/res/puzzle/PS_THB7.pzl b/forge-gui/res/puzzle/PS_THB7.pzl new file mode 100644 index 00000000000..bd9f0a62678 --- /dev/null +++ b/forge-gui/res/puzzle/PS_THB7.pzl @@ -0,0 +1,16 @@ +[metadata] +Name:Possibility Storm - Theros Beyond Death #07 +URL:https://i2.wp.com/www.possibilitystorm.com/wp-content/uploads/2020/03/150.-THB7-scaled.jpg +Goal:Win +Turns:100 +Difficulty:Mythic +Description:It's your OPPONENT'S turn (first main phase), and you need to win before you lose. Can you do it? Your opponent has no cards in hand and no available mana (assume they just tapped out to cast Goblin Assault Team). You control your opponent's Dreadhorde Butcher with The Akroan War's first chapter ability. Assume the puzzle starts with no cards in either player's graveyard. +[state] +humanlife=3 +ailife=11 +turn=1 +activeplayer=ai +activephase=MAIN1 +humanhand=Lazotep Plating;Slaying Fire;So Tiny;Shock;Gideon's Triumph;Aspect of Manticore +humanbattlefield=The Akroan War|Counters:LORE=2|ExecuteScript:DBGainControl->1;Blood Aspirant;Flux Channeler;Naiad of Hidden Coves;Temple of Enlightenment|NoETBTrigs;Temple of Enlightenment|NoETBTrigs;Sacred Foundry|NoETBTrigs;Sacred Foundry|NoETBTrigs +aibattlefield=Underworld Dreams;Underworld Dreams;Underworld Dreams;Ferocity of the Wilds;Goblin Assault Team;Temple Thief;Mire Triton;Dreadhorde Butcher|Id:1 diff --git a/forge-gui/res/skins/darkred/bg_match.jpg b/forge-gui/res/skins/darkred/bg_match.jpg index f926fee0812..fb7c0298072 100644 Binary files a/forge-gui/res/skins/darkred/bg_match.jpg and b/forge-gui/res/skins/darkred/bg_match.jpg differ diff --git a/forge-gui/res/skins/default/font1.ttf b/forge-gui/res/skins/default/font1.ttf index 4b4ecc66671..8723f9e2252 100644 Binary files a/forge-gui/res/skins/default/font1.ttf and b/forge-gui/res/skins/default/font1.ttf differ diff --git a/forge-gui/res/skins/default/sprite_border.png b/forge-gui/res/skins/default/sprite_border.png index c6be80f099a..4fe259b55c7 100644 Binary files a/forge-gui/res/skins/default/sprite_border.png and b/forge-gui/res/skins/default/sprite_border.png differ diff --git a/forge-gui/res/skins/default/sprite_icons.png b/forge-gui/res/skins/default/sprite_icons.png index 7cff5a518d1..384ae908ccf 100644 Binary files a/forge-gui/res/skins/default/sprite_icons.png and b/forge-gui/res/skins/default/sprite_icons.png differ diff --git a/forge-gui/res/skins/default/sprite_manaicons.png b/forge-gui/res/skins/default/sprite_manaicons.png index 3b8f734e939..8cbbda13212 100644 Binary files a/forge-gui/res/skins/default/sprite_manaicons.png and b/forge-gui/res/skins/default/sprite_manaicons.png differ diff --git a/forge-gui/res/tokenscripts/c_0_4_wall_defender.txt b/forge-gui/res/tokenscripts/c_0_4_a_wall_defender.txt similarity index 67% rename from forge-gui/res/tokenscripts/c_0_4_wall_defender.txt rename to forge-gui/res/tokenscripts/c_0_4_a_wall_defender.txt index 03a29952252..2b5be99e3e2 100644 --- a/forge-gui/res/tokenscripts/c_0_4_wall_defender.txt +++ b/forge-gui/res/tokenscripts/c_0_4_a_wall_defender.txt @@ -1,6 +1,6 @@ Name:Wall ManaCost:no cost -Types:Creature Wall +Types:Artifact Creature Wall PT:0/4 K:Defender Oracle:Defender diff --git a/forge-gui/src/main/java/forge/assets/FSkinProp.java b/forge-gui/src/main/java/forge/assets/FSkinProp.java index 5468c1e2914..38edff0ea32 100644 --- a/forge-gui/src/main/java/forge/assets/FSkinProp.java +++ b/forge-gui/src/main/java/forge/assets/FSkinProp.java @@ -230,6 +230,15 @@ public enum FSkinProp { ICO_QUEST_BIG_SWORD (new int[] {320, 1360, 160, 160}, PropType.ICON), ICO_QUEST_BIG_BAG (new int[] {480, 1360, 160, 160}, PropType.ICON), + //menu icon + ICO_MENU_GALAXY (new int[] {0, 1520, 80, 80}, PropType.ICON), + ICO_MENU_STATS (new int[] {80, 1520, 80, 80}, PropType.ICON), + ICO_MENU_PUZZLE (new int[] {160, 1520, 80, 80}, PropType.ICON), + ICO_MENU_GAUNTLET (new int[] {240, 1520, 80, 80}, PropType.ICON), + ICO_MENU_SEALED (new int[] {320, 1520, 80, 80}, PropType.ICON), + ICO_MENU_DRAFT (new int[] {400, 1520, 80, 80}, PropType.ICON), + ICO_MENU_CONSTRUCTED (new int[] {480, 1520, 80, 80}, PropType.ICON), + //interface icons ICO_QUESTION (new int[] {560, 800, 32, 32}, PropType.ICON), ICO_INFORMATION (new int[] {592, 800, 32, 32}, PropType.ICON), diff --git a/forge-gui/src/main/java/forge/download/AutoUpdater.java b/forge-gui/src/main/java/forge/download/AutoUpdater.java new file mode 100644 index 00000000000..8d050efecef --- /dev/null +++ b/forge-gui/src/main/java/forge/download/AutoUpdater.java @@ -0,0 +1,247 @@ +package forge.download; + +import com.google.common.collect.ImmutableList; +import forge.GuiBase; +import forge.model.FModel; +import forge.properties.ForgePreferences; +import forge.util.BuildInfo; +import forge.util.FileUtil; +import forge.util.WaitCallback; +import forge.util.gui.SOptionPane; +import org.apache.commons.lang3.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.net.*; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class AutoUpdater { + private final String SNAPSHOT_VERSION_INDEX = "https://snapshots.cardforge.org/"; + private final String SNAPSHOT_VERSION_URL = "https://snapshots.cardforge.org/version.txt"; + private final String SNAPSHOT_PACKAGE = "https://snapshots.cardforge.org/latest/"; + private final String RELEASE_VERSION_URL = "https://releases.cardforge.org/forge/forge-gui-desktop/version.txt"; + private final String RELEASE_PACKAGE = "https://releases.cardforge.org/latest/"; + private final String RELEASE_MAVEN_METADATA = "https://releases.cardforge.org/forge/forge-gui-desktop/maven-metadata.xml"; + private static final boolean VERSION_FROM_METADATA = true; + private static final String TMP_DIR = "tmp/"; + + public static String[] updateChannels = new String[]{ "none", "snapshot", "release"}; + + private boolean isLoading; + private String updateChannel; + private String version; + private String buildVersion; + private String versionUrlString; + private String packageUrl; + private String packagePath; + + public AutoUpdater(boolean loading) { + // What do I need? Preferences? Splashscreen? UI? Skins? + isLoading = loading; + updateChannel = FModel.getPreferences().getPref(ForgePreferences.FPref.AUTO_UPDATE); + buildVersion = BuildInfo.getVersionString(); + } + + public boolean attemptToUpdate() { + if (!verifyUpdateable()) { + return false; + } + try { + if (downloadUpdate()) { + extractAndRestart(); + } + } catch(IOException | URISyntaxException e) { + return false; + } + return true; + } + + private void extractAndRestart() { + extractUpdate(); + restartForge(); + } + + private boolean verifyUpdateable() { + if (buildVersion.contains("GIT")) { + //return false; + } + + if (isLoading) { + // TODO This doesn't work yet, because FSkin isn't loaded at the time. + return false; + } else if (updateChannel.equals("none")) { + String message = "You haven't set an update channel. Do you want to check a channel now?"; + List options = ImmutableList.of("Cancel", "release", "snapshot"); + int option = SOptionPane.showOptionDialog(message, "Manual Check", null, options, 0); + if (option == 0) { + return false; + } else { + updateChannel = options.get(option); + } + } + + if (buildVersion.contains("SNAPSHOT")) { + if (!updateChannel.equals("snapshot")) { + System.out.println("Snapshot build versions must use snapshot update channel to work"); + return false; + } + + versionUrlString = SNAPSHOT_VERSION_URL; + packageUrl = SNAPSHOT_PACKAGE; + } else { + versionUrlString = RELEASE_VERSION_URL; + packageUrl = RELEASE_PACKAGE; + } + + // Check the internet connection + if (!testNetConnection()) { + return false; + } + + // Download appropriate version file + return compareBuildWithLatestChannelVersion(); + } + + private boolean testNetConnection() { + try (Socket socket = new Socket()) { + InetSocketAddress address = new InetSocketAddress("releases.cardforge.org", 443); + socket.connect(address, 1000); + return true; + } catch (IOException e) { + return false; // Either timeout or unreachable or failed DNS lookup. + } + } + + private boolean compareBuildWithLatestChannelVersion() { + try { + retrieveVersion(); + + if (StringUtils.isEmpty(version) ) { + return false; + } + + if (buildVersion.equals(version)) { + return false; + } + } + catch (Exception e) { + e.printStackTrace(); + return false; + } + // If version doesn't match, it's assummably newer. + return true; + } + + private void retrieveVersion() throws MalformedURLException { + if (VERSION_FROM_METADATA) { + if (updateChannel.equals("release")) { + extractVersionFromMavenRelease(); + } else { + extractVersionFromSnapshotIndex(); + } + } else { + URL versionUrl = new URL(versionUrlString); + version = FileUtil.readFileToString(versionUrl); + } + } + + private void extractVersionFromSnapshotIndex() throws MalformedURLException { + URL metadataUrl = new URL(SNAPSHOT_VERSION_INDEX); + String index = FileUtil.readFileToString(metadataUrl); + + System.out.println(index); + Pattern p = Pattern.compile(">forge-(.*SNAPSHOT)"); + Matcher m = p.matcher(index); + while(m.find()){ + version = m.group(1); + } + } + + private void extractVersionFromMavenRelease() throws MalformedURLException { + URL metadataUrl = new URL(RELEASE_MAVEN_METADATA); + String xml = FileUtil.readFileToString(metadataUrl); + + Pattern p = Pattern.compile("(.*)"); + Matcher m = p.matcher(xml); + while(m.find()){ + version = m.group(1); + } + } + + private boolean downloadUpdate() throws URISyntaxException, IOException { + // TODO Change the "auto" to be more auto. + if (isLoading) { + // We need to preload enough of a Skins to show a dialog and a button if we're in loading + // splashScreen.prepareForDialogs(); + return downloadFromBrowser(); + } + + String message = "A new version of Forge is available (" + version + ").\n" + + "You are currently on version (" + buildVersion + ").\n\n" + + "Would you like to update to the new version now?"; + + final List options = ImmutableList.of("Update Now", "Update Later"); + if (SOptionPane.showOptionDialog(message, "New Version Available", null, options, 0) == 0) { + return downloadFromForge(); + } + + return false; + } + + private boolean downloadFromBrowser() throws URISyntaxException, IOException { + final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null; + if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) { + // Linking directly there will auto download, but won't auto-update + desktop.browse(new URI(packageUrl)); + return true; + } else { + System.out.println("Download latest version: " + packageUrl); + return false; + } + } + + private boolean downloadFromForge() { + WaitCallback callback = new WaitCallback() { + @Override + public void run() { + GuiBase.getInterface().download(new GuiDownloadZipService("Auto Updater", "Download the new version..", packageUrl, "tmp/", null, null) { + @Override + public void downloadAndUnzip() { + packagePath = download(version + "-upgrade.tar.bz2"); + if (packagePath != null) { + extractAndRestart(); + } + } + }, this); + } + }; + + SwingUtilities.invokeLater(callback); + // + return false; + } + + private void extractUpdate() { + // TODOD Something like https://stackoverflow.com/questions/315618/how-do-i-extract-a-tar-file-in-java + final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null; + if (desktop != null) { + try { + desktop.open(new File(packagePath).getParentFile()); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + System.out.println(packagePath); + } + } + + private void restartForge() { + if (isLoading || SOptionPane.showConfirmDialog("Forge has been downloaded. You should extract the package and restart Forge for the new version.", "Exit now?")) { + System.exit(0); + } + } +} diff --git a/forge-gui/src/main/java/forge/download/GuiDownloadZipService.java b/forge-gui/src/main/java/forge/download/GuiDownloadZipService.java index f1d1dc9b8d4..dd142b04cf4 100644 --- a/forge-gui/src/main/java/forge/download/GuiDownloadZipService.java +++ b/forge-gui/src/main/java/forge/download/GuiDownloadZipService.java @@ -73,72 +73,7 @@ public class GuiDownloadZipService extends GuiDownloadService { String zipFilename = download("temp.zip"); if (zipFilename == null) { return; } - //if assets.zip downloaded successfully, unzip into destination folder - try { - GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while unzipping - - if (deleteFolder != null) { - final File deleteDir = new File(deleteFolder); - if (deleteDir.exists()) { - //attempt to delete previous res directory if to be rebuilt - progressBar.reset(); - progressBar.setDescription("Deleting old " + desc + "..."); - if (deleteFolder.equals(destFolder)) { //move zip file to prevent deleting it - final String oldZipFilename = zipFilename; - zipFilename = deleteDir.getParentFile().getAbsolutePath() + File.separator + "temp.zip"; - Files.move(new File(oldZipFilename), new File(zipFilename)); - } - FileUtil.deleteDirectory(deleteDir); - } - } - - final ZipFile zipFile = new ZipFile(zipFilename); - final Enumeration entries = zipFile.entries(); - - progressBar.reset(); - progressBar.setPercentMode(true); - progressBar.setDescription("Extracting " + desc); - progressBar.setMaximum(zipFile.size()); - - FileUtil.ensureDirectoryExists(destFolder); - - int count = 0; - int failedCount = 0; - while (entries.hasMoreElements()) { - if (cancel) { break; } - - try { - final ZipEntry entry = entries.nextElement(); - - final String path = destFolder + File.separator + entry.getName(); - if (entry.isDirectory()) { - new File(path).mkdir(); - progressBar.setValue(++count); - continue; - } - copyInputStream(zipFile.getInputStream(entry), path); - progressBar.setValue(++count); - filesExtracted++; - } - catch (final Exception e) { //don't quit out completely if an entry is not UTF-8 - progressBar.setValue(++count); - failedCount++; - } - } - - if (failedCount > 0) { - Log.error("Downloading " + desc, failedCount + " " + desc + " could not be extracted"); - } - - zipFile.close(); - new File(zipFilename).delete(); - } - catch (final Exception e) { - e.printStackTrace(); - } - finally { - GuiBase.getInterface().preventSystemSleep(false); - } + extract(zipFilename); } public String download(final String filename) { @@ -211,6 +146,75 @@ public class GuiDownloadZipService extends GuiDownloadService { } } + public void extract(String zipFilename) { + //if assets.zip downloaded successfully, unzip into destination folder + try { + GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while unzipping + + if (deleteFolder != null) { + final File deleteDir = new File(deleteFolder); + if (deleteDir.exists()) { + //attempt to delete previous res directory if to be rebuilt + progressBar.reset(); + progressBar.setDescription("Deleting old " + desc + "..."); + if (deleteFolder.equals(destFolder)) { //move zip file to prevent deleting it + final String oldZipFilename = zipFilename; + zipFilename = deleteDir.getParentFile().getAbsolutePath() + File.separator + "temp.zip"; + Files.move(new File(oldZipFilename), new File(zipFilename)); + } + FileUtil.deleteDirectory(deleteDir); + } + } + + final ZipFile zipFile = new ZipFile(zipFilename); + final Enumeration entries = zipFile.entries(); + + progressBar.reset(); + progressBar.setPercentMode(true); + progressBar.setDescription("Extracting " + desc); + progressBar.setMaximum(zipFile.size()); + + FileUtil.ensureDirectoryExists(destFolder); + + int count = 0; + int failedCount = 0; + while (entries.hasMoreElements()) { + if (cancel) { break; } + + try { + final ZipEntry entry = entries.nextElement(); + + final String path = destFolder + File.separator + entry.getName(); + if (entry.isDirectory()) { + new File(path).mkdir(); + progressBar.setValue(++count); + continue; + } + copyInputStream(zipFile.getInputStream(entry), path); + progressBar.setValue(++count); + filesExtracted++; + } + catch (final Exception e) { //don't quit out completely if an entry is not UTF-8 + progressBar.setValue(++count); + failedCount++; + } + } + + if (failedCount > 0) { + Log.error("Downloading " + desc, failedCount + " " + desc + " could not be extracted"); + } + + zipFile.close(); + new File(zipFilename).delete(); + } + catch (final Exception e) { + e.printStackTrace(); + } + finally { + GuiBase.getInterface().preventSystemSleep(false); + } + } + protected void copyInputStream(final InputStream in, final String outPath) throws IOException { final byte[] buffer = new byte[1024]; int len; diff --git a/forge-gui/src/main/java/forge/model/FModel.java b/forge-gui/src/main/java/forge/model/FModel.java index d0c182e890c..a574d3cd493 100644 --- a/forge-gui/src/main/java/forge/model/FModel.java +++ b/forge-gui/src/main/java/forge/model/FModel.java @@ -28,6 +28,7 @@ import forge.card.CardType; import forge.deck.CardArchetypeLDAGenerator; import forge.deck.CardRelationMatrixGenerator; import forge.deck.io.DeckPreferences; +import forge.download.AutoUpdater; import forge.game.GameFormat; import forge.game.GameType; import forge.game.card.CardUtil; @@ -117,7 +118,6 @@ public final class FModel { Localizer.getInstance().initialize(FModel.getPreferences().getPref(FPref.UI_LANGUAGE), ForgeConstants.LANG_DIR); - //load card database final ProgressObserver progressBarBridge = (progressBar == null) ? ProgressObserver.emptyObserver : new ProgressObserver() { @Override @@ -143,6 +143,11 @@ public final class FModel { } }; + if (new AutoUpdater(true).attemptToUpdate()) { + // + } + + //load card database final CardStorageReader reader = new CardStorageReader(ForgeConstants.CARD_DATA_DIR, progressBarBridge, FModel.getPreferences().getPrefBoolean(FPref.LOAD_CARD_SCRIPTS_LAZILY)); final CardStorageReader tokenReader = new CardStorageReader(ForgeConstants.TOKEN_DATA_DIR, progressBarBridge, @@ -220,8 +225,6 @@ public final class FModel { achievements.put(GameType.Quest, new QuestAchievements()); achievements.put(GameType.PlanarConquest, new PlanarConquestAchievements()); achievements.put(GameType.Puzzle, new PuzzleAchievements()); - - //preload AI profiles AiProfileUtil.loadAllProfiles(ForgeConstants.AI_PROFILE_DIR); diff --git a/forge-gui/src/main/java/forge/net/ProtocolMethod.java b/forge-gui/src/main/java/forge/net/ProtocolMethod.java index 4497b5cf0f9..642e79dec5c 100644 --- a/forge-gui/src/main/java/forge/net/ProtocolMethod.java +++ b/forge-gui/src/main/java/forge/net/ProtocolMethod.java @@ -75,7 +75,7 @@ public enum ProtocolMethod { clearSelectables (Mode.SERVER), refreshField (Mode.SERVER), // TODO case "setPlayerAvatar": - openZones (Mode.SERVER, PlayerZoneUpdates.class, Collection/*ZoneType*/.class, Map/*PlayerView,Object*/.class), + openZones (Mode.SERVER, PlayerZoneUpdates.class, PlayerView.class, Collection/*ZoneType*/.class, Map/*PlayerView,Object*/.class), restoreOldZones (Mode.SERVER, Void.TYPE, PlayerView.class, PlayerZoneUpdates.class), isUiSetToSkipPhase (Mode.SERVER, Boolean.TYPE, PlayerView.class, PhaseType.class), setRememberedActions(Mode.SERVER, Void.TYPE), diff --git a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java index a337db37099..36f124105a3 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java +++ b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java @@ -105,10 +105,7 @@ public class HumanPlaySpellAbility { if (ability.isSpell() && !ability.isCastFaceDown() && fromState == CardStateName.FaceDown) { c.turnFaceUp(); } - c.setCastSA(ability); - ability.setLastStateBattlefield(game.getLastStateBattlefield()); - ability.setLastStateGraveyard(game.getLastStateGraveyard()); - ability.setHostCard(game.getAction().moveToStack(c, null)); + ability.setHostCard(game.getAction().moveToStack(c, ability)); } if (!ability.isCopied()) { diff --git a/forge-gui/src/main/java/forge/properties/ForgePreferences.java b/forge-gui/src/main/java/forge/properties/ForgePreferences.java index f9b7c3329a4..c3001f43e0a 100644 --- a/forge-gui/src/main/java/forge/properties/ForgePreferences.java +++ b/forge-gui/src/main/java/forge/properties/ForgePreferences.java @@ -153,6 +153,7 @@ public class ForgePreferences extends PreferencesStore { //TODO This should be removed after the update that requires Java 8. DISABLE_DISPLAY_JAVA_8_UPDATE_WARNING("false"), + AUTO_UPDATE("none"), USE_SENTRY("false"), // this controls whether automated bug reporting is done or not MATCH_HOT_SEAT_MODE("false"), //this only applies to mobile game diff --git a/forge-gui/src/main/java/forge/util/ImageFetcher.java b/forge-gui/src/main/java/forge/util/ImageFetcher.java index cf219331dc8..ef83a64f414 100644 --- a/forge-gui/src/main/java/forge/util/ImageFetcher.java +++ b/forge-gui/src/main/java/forge/util/ImageFetcher.java @@ -6,6 +6,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import forge.FThreads; import forge.ImageKeys; @@ -45,21 +47,28 @@ public abstract class ImageFetcher { final String filename = ImageUtil.getImageKey(paperCard, backFace, true); destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR + "/" + filename + ".jpg"); - // First try to download the LQ Set URL, then fetch from scryfall/magiccards.info + // First try to download the LQ Set URL, then fetch from scryfall StringBuilder setDownload = new StringBuilder(ForgeConstants.URL_PIC_DOWNLOAD); setDownload.append(ImageUtil.getDownloadUrl(paperCard, backFace)); downloadUrls.add(setDownload.toString()); + int artIndex = 1; + final Pattern pattern = Pattern.compile( + "^.:([^|]*\\|){2}(\\d+).*$" + ); + Matcher matcher = pattern.matcher(imageKey); + if (matcher.matches()) { + artIndex = Integer.parseInt(matcher.group(2)); + } final StaticData data = StaticData.instance(); - final int cardNum = data.getCommonCards().getCardCollectorNumber(paperCard.getName(), paperCard.getEdition()); - if (cardNum != -1) { + final String cardNum = data.getCommonCards().getCardCollectorNumber(paperCard.getName(), paperCard.getEdition(), artIndex); + if (cardNum != null) { String suffix = ""; if (paperCard.getRules().getOtherPart() != null) { suffix = (backFace ? "b" : "a"); } final String editionMciCode = data.getEditions().getMciCodeByCode(paperCard.getEdition()); - downloadUrls.add(String.format("https://img.scryfall.com/cards/normal/en/%s/%d%s.jpg", editionMciCode, cardNum, suffix)); - downloadUrls.add(String.format("https://magiccards.info/scans/en/%s/%d%s.jpg", editionMciCode, cardNum, suffix)); + downloadUrls.add(String.format("https://img.scryfall.com/cards/normal/en/%s/%s%s.jpg", editionMciCode, cardNum, suffix)); } } else if (prefix.equals(ImageKeys.TOKEN_PREFIX)) { if (tokenImages == null) {