diff --git a/forge-core/src/main/java/forge/card/MagicColor.java b/forge-core/src/main/java/forge/card/MagicColor.java index a3af1906781..0592b0a9d04 100644 --- a/forge-core/src/main/java/forge/card/MagicColor.java +++ b/forge-core/src/main/java/forge/card/MagicColor.java @@ -106,6 +106,14 @@ public final class MagicColor { } } + public static String toSymbol(final byte color) { + return MagicColor.Color.fromByte(color).getSymbol(); + } + + public static String toSymbol(final String color) { + return toSymbol(fromName(color)); + } + /** * The Interface Color. */ @@ -165,6 +173,17 @@ public final class MagicColor { symbol = symbol0; } + public static Color fromByte(final byte color) { + switch (color) { + case MagicColor.WHITE: return WHITE; + case MagicColor.BLUE: return BLUE; + case MagicColor.BLACK: return BLACK; + case MagicColor.RED: return RED; + case MagicColor.GREEN: return GREEN; + default: return COLORLESS; + } + } + public String getName() { return name; } diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index bc9209c2e0e..2de0c3815ee 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -3,7 +3,6 @@ package forge.game.ability; import com.google.common.base.Functions; import com.google.common.collect.*; import com.google.common.math.IntMath; - import forge.card.CardStateName; import forge.card.CardType; import forge.card.ColorSet; @@ -2510,6 +2509,19 @@ public class AbilityUtils { return doXMath(CardLists.getValidCardCount(game.getLeftGraveyardThisTurn(), validFilter, player, c, ctb), expr, c, ctb); } + // Count$UnlockedDoors + if (sq[0].startsWith("UnlockedDoors")) { + final String[] workingCopy = l[0].split(" ", 2); + final String validFilter = workingCopy[1]; + + int unlocked = 0; + for (Card doorCard : CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), validFilter, player, c, ctb)) { + unlocked += doorCard.getUnlockedRooms().size(); + } + + return doXMath(unlocked, expr, c, ctb); + } + // Manapool if (sq[0].startsWith("ManaPool")) { final String color = l[0].split(":")[1]; diff --git a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java index 45c4fe55e23..5d393c39783 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java @@ -55,11 +55,14 @@ public class ManaEffect extends SpellAbilityEffect { if (abMana.isComboMana()) { int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(card, sa.getParam("Amount"), sa) : 1; + if(amount <= 0) + continue; String express = abMana.getExpressChoice(); String[] colorsProduced = abMana.getComboColors(sa).split(" "); final StringBuilder choiceString = new StringBuilder(); + final StringBuilder choiceSymbols = new StringBuilder(); ColorSet colorOptions = ColorSet.fromNames(colorsProduced); String[] colorsNeeded = express.isEmpty() ? null : express.split(" "); boolean differentChoice = abMana.getOrigProduced().contains("Different"); @@ -70,12 +73,14 @@ public class ManaEffect extends SpellAbilityEffect { for (Map.Entry e : choices.entrySet()) { Byte chosenColor = e.getKey(); String choice = MagicColor.toShortString(chosenColor); + String symbol = MagicColor.toSymbol(chosenColor); Integer count = e.getValue(); while (count > 0) { if (choiceString.length() > 0) { choiceString.append(" "); } choiceString.append(choice); + choiceSymbols.append(symbol); --count; } } @@ -106,25 +111,26 @@ public class ManaEffect extends SpellAbilityEffect { choiceString.append(" "); } choiceString.append(choice); + choiceSymbols.append(MagicColor.toSymbol(choice)); if (sa.hasParam("TwoEach")) { choiceString.append(" ").append(choice); + choiceSymbols.append(MagicColor.toSymbol(choice)); } } } if (choiceString.toString().isEmpty() && "Combo ColorIdentity".equals(abMana.getOrigProduced())) { // No mana could be produced here (non-EDH match?), so cut short - return; + continue; } - game.getAction().notifyOfValue(sa, card, Localizer.getInstance().getMessage("lblPlayerPickedChosen", p.getName(), choiceString), p); + game.getAction().notifyOfValue(sa, p, choiceSymbols.toString(), p); abMana.setExpressChoice(choiceString.toString()); } else if (abMana.isAnyMana()) { // AI color choice is set in ComputerUtils so only human players need to make a choice String colorsNeeded = abMana.getExpressChoice(); - String choice = ""; ColorSet colorMenu = null; byte mask = 0; @@ -137,10 +143,9 @@ public class ManaEffect extends SpellAbilityEffect { if (0 == val) { throw new RuntimeException("ManaEffect::resolve() /*any mana*/ - " + p + " color mana choice is empty for " + card.getName()); } - choice = MagicColor.toShortString(val); - game.getAction().notifyOfValue(sa, card, Localizer.getInstance().getMessage("lblPlayerPickedChosen", p.getName(), choice), p); - abMana.setExpressChoice(choice); + game.getAction().notifyOfValue(sa, card, MagicColor.toSymbol(val), p); + abMana.setExpressChoice(MagicColor.toShortString(val)); } else if (abMana.isSpecialMana()) { String type = abMana.getOrigProduced().split("Special ")[1]; @@ -183,7 +188,7 @@ public class ManaEffect extends SpellAbilityEffect { int nMana = 0; for (Object o : card.getRemembered()) { if (o instanceof String) { - sb.append(o.toString()); + sb.append(o); nMana++; } } diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index 577fef1e184..6e218f09e25 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -33,6 +33,7 @@ import forge.game.cost.Cost; import forge.game.keyword.Keyword; import forge.game.keyword.KeywordInterface; import forge.game.player.Player; +import forge.game.replacement.ReplacementEffect; import forge.game.replacement.ReplacementHandler; import forge.game.spellability.*; import forge.game.staticability.StaticAbility; @@ -268,6 +269,11 @@ public class CardFactory { original.addStaticAbility(st.copy(card, false)); } } + for (ReplacementEffect re : card.getCurrentState().getReplacementEffects()) { + if (re.isIntrinsic()) { + original.addReplacementEffect(re.copy(card, false)); + } + } original.getSVars().putAll(card.getCurrentState().getSVars()); // Unfortunately need to copy these to (Effect looks for sVars on execute) } else if (state != CardStateName.Original) { CardFactoryUtil.setupKeywordedAbilities(card); diff --git a/forge-game/src/main/java/forge/util/MessageUtil.java b/forge-game/src/main/java/forge/util/MessageUtil.java index 69b00ec61d6..555803b66c1 100644 --- a/forge-game/src/main/java/forge/util/MessageUtil.java +++ b/forge-game/src/main/java/forge/util/MessageUtil.java @@ -41,6 +41,7 @@ public class MessageUtil { case Seek: return value; case ChooseColor: + case Mana: return sa.hasParam("Random") ? Localizer.getInstance().getMessage("lblRandomColorChosen", value) : Localizer.getInstance().getMessage("lblPlayerPickedChosen", choser, value); diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/FOptionPane.java b/forge-gui-desktop/src/main/java/forge/toolbox/FOptionPane.java index d5c381b8f65..8147ab6f4b8 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/FOptionPane.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/FOptionPane.java @@ -6,15 +6,15 @@ import java.awt.FontMetrics; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; -import javax.swing.JComponent; -import javax.swing.JOptionPane; -import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; +import javax.swing.*; import javax.swing.text.StyleConstants; import com.google.common.collect.ImmutableList; +import forge.gui.FThreads; import forge.localinstance.skin.FSkinProp; import forge.toolbox.FSkin.SkinImage; import forge.util.Localizer; @@ -87,20 +87,25 @@ public class FOptionPane extends FDialog { if (FView.SINGLETON_INSTANCE.getSplash() != null) { return 0; } - - final FOptionPane optionPane = new FOptionPane(message, title, icon, null, options, defaultOption); - optionPane.setVisible(true); - final int dialogResult = optionPane.result; - optionPane.dispose(); - return dialogResult; + return showOptionDialog(message, title, icon, null, options, defaultOption); } public static int showOptionDialog(final String message, final String title, final SkinImage icon, final Component comp, final List options, final int defaultOption) { - final FOptionPane optionPane = new FOptionPane(message, title, icon, comp, options, defaultOption); - optionPane.setVisible(true); - final int dialogResult = optionPane.result; - optionPane.dispose(); - return dialogResult; + final Callable showChoice = () -> { + final FOptionPane optionPane = new FOptionPane(message, title, icon, comp, options, defaultOption); + optionPane.setVisible(true); + final int dialogResult = optionPane.result; + optionPane.dispose(); + return dialogResult; + }; + final FutureTask future = new FutureTask<>(showChoice); + FThreads.invokeInEdtAndWait(future); + try { + return future.get(); + } catch (final Exception e) { // should be no exception here + e.printStackTrace(); + throw new RuntimeException(e); + } } public static String showInputDialog(final String message, final String title) { @@ -117,45 +122,56 @@ public class FOptionPane extends FDialog { @SuppressWarnings("unchecked") public static T showInputDialog(final String message, final String title, final SkinImage icon, final String initialInput, final List inputOptions) { - final JComponent inputField; - FTextField txtInput = null; - FComboBox cbInput = null; - if (inputOptions == null) { - txtInput = new FTextField.Builder().text(initialInput).build(); - inputField = txtInput; - } else { - cbInput = new FComboBox<>(inputOptions); - cbInput.setSelectedItem(initialInput); - inputField = cbInput; - } + final Callable showChoice = () -> { + final JComponent inputField; + FTextField txtInput = null; + FComboBox cbInput = null; + if (inputOptions == null) { + txtInput = new FTextField.Builder().text(initialInput).build(); + inputField = txtInput; + } else { + cbInput = new FComboBox<>(inputOptions); + cbInput.setSelectedItem(initialInput); + inputField = cbInput; + } - final FOptionPane optionPane = new FOptionPane(message, title, icon, inputField, ImmutableList.of(Localizer.getInstance().getMessage("lblOK"), Localizer.getInstance().getMessage("lblCancel")), -1); - optionPane.setDefaultFocus(inputField); - inputField.addKeyListener(new KeyAdapter() { //hook so pressing Enter on field accepts dialog - @Override - public void keyPressed(final KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - optionPane.setResult(0); + final FOptionPane optionPane = new FOptionPane(message, title, icon, inputField, ImmutableList.of(Localizer.getInstance().getMessage("lblOK"), Localizer.getInstance().getMessage("lblCancel")), -1); + optionPane.setDefaultFocus(inputField); + inputField.addKeyListener(new KeyAdapter() { //hook so pressing Enter on field accepts dialog + @Override + public void keyPressed(final KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + optionPane.setResult(0); + } + } + }); + optionPane.setVisible(true); + final int dialogResult = optionPane.result; + optionPane.dispose(); + if (dialogResult == 0) { + if (inputOptions == null) { + return (T)txtInput.getText(); + } else { + return cbInput.getSelectedItem(); } } - }); - optionPane.setVisible(true); - final int dialogResult = optionPane.result; - optionPane.dispose(); - if (dialogResult == 0) { - if (inputOptions == null) { - return (T)txtInput.getText(); - } else { - return cbInput.getSelectedItem(); - } + return null; + }; + final FutureTask future = new FutureTask<>(showChoice); + FThreads.invokeInEdtAndWait(future); + try { + return future.get(); + } catch (final Exception e) { // should be no exception here + e.printStackTrace(); + throw new RuntimeException(e); } - return null; } private int result = -1; //default result to -1, indicating dialog closed without choosing option private final FButton[] buttons; public FOptionPane(final String message, final String title, final SkinImage icon, final Component comp, final List options, final int defaultOption) { + FThreads.assertExecutedByEdt(true); this.setTitle(title); final int padding = 10; @@ -163,7 +179,7 @@ public class FOptionPane extends FDialog { final int gapAboveButtons = padding * 3 / 2; final int gapBottom = comp == null ? gapAboveButtons : padding; FLabel centeredLabel = null; - FTextPane centeredPrompt = null; + FTextPane prompt = null; if (icon != null) { if (icon.getWidth() < 100) { @@ -179,23 +195,16 @@ public class FOptionPane extends FDialog { } } if (message != null) { - if (centeredLabel == null) { - final FTextArea prompt = new FTextArea(message); - prompt.setFont(FSkin.getFont(14)); - prompt.setAutoSize(true); - final Dimension parentSize = JOptionPane.getRootFrame().getSize(); - prompt.setMaximumSize(new Dimension(parentSize.width / 2, parentSize.height - 100)); - this.add(prompt, "x " + x + ", ay top, wrap, gaptop " + (icon == null ? 0 : 7) + ", gapbottom " + gapBottom); - } - else { - final FTextPane prompt = new FTextPane(message); - prompt.setFont(FSkin.getFont(14)); + prompt = new FTextPane(); + prompt.setContentType("text/html"); + prompt.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); + prompt.setText(FSkin.encodeSymbols(message, false)); + prompt.setFont(FSkin.getFont(14)); + if(centeredLabel != null) prompt.setTextAlignment(StyleConstants.ALIGN_CENTER); - final Dimension parentSize = JOptionPane.getRootFrame().getSize(); - prompt.setMaximumSize(new Dimension(parentSize.width / 2, parentSize.height - 100)); - this.add(prompt, "x " + x + ", ay top, wrap, gapbottom " + gapBottom); - centeredPrompt = prompt; - } + final Dimension parentSize = JOptionPane.getRootFrame().getSize(); + prompt.setMaximumSize(new Dimension(parentSize.width / 2, parentSize.height - 100)); + this.add(prompt, "x " + x + ", ay top, wrap, gaptop " + (icon == null ? 0 : 7) + ", gapbottom " + gapBottom); x = padding; } if (comp != null) { @@ -277,7 +286,8 @@ public class FOptionPane extends FDialog { if (centeredLabel != null) { centeredLabel.setPreferredSize(new Dimension(width - 2 * padding, centeredLabel.getMinimumSize().height)); - centeredPrompt.setPreferredSize(new Dimension(width - 2 * padding, centeredPrompt.getPreferredSize().height)); + if(prompt != null) + prompt.setPreferredSize(new Dimension(width - 2 * padding, prompt.getPreferredSize().height)); } this.setSize(width, this.getHeight() + buttonHeight); //resize dialog again to account for buttons diff --git a/forge-gui-mobile/src/forge/adventure/scene/SpellSmithScene.java b/forge-gui-mobile/src/forge/adventure/scene/SpellSmithScene.java index fbcebe551ec..60a6892bc4a 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SpellSmithScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SpellSmithScene.java @@ -39,7 +39,7 @@ public class SpellSmithScene extends UIScene { private List cardPool = new ArrayList<>(); private TextraLabel playerGold, playerShards, poolSize; - private final TextraButton pullUsingGold, pullUsingShards; + private final TextraButton pullUsingGold, pullUsingShards, acceptReward, declineReward, exitSmith; private final ScrollPane rewardDummy; private RewardActor rewardActor; SelectBox editionList; @@ -47,6 +47,7 @@ public class SpellSmithScene extends UIScene { final private HashMap rarityButtons = new HashMap<>(); final private HashMap costButtons = new HashMap<>(); final private HashMap colorButtons = new HashMap<>(); + //Filter variables. private String edition = ""; private String rarity = ""; @@ -57,20 +58,28 @@ public class SpellSmithScene extends UIScene { private int currentPrice = 0; private int currentShardPrice = 0; private List editions = null; + private Reward currentReward = null; + private boolean paidInShards = false; private SpellSmithScene() { super(Forge.isLandscapeMode() ? "ui/spellsmith.json" : "ui/spellsmith_portrait.json"); - editionList = ui.findActor("BSelectPlane"); rewardDummy = ui.findActor("RewardDummy"); rewardDummy.setVisible(false); - pullUsingGold = ui.findActor("pullUsingGold"); pullUsingGold.setDisabled(true); pullUsingShards = ui.findActor("pullUsingShards"); pullUsingShards.setDisabled(true); + + exitSmith = ui.findActor("done"); + + acceptReward = ui.findActor("accept"); + acceptReward.setVisible(false); + declineReward = ui.findActor("decline"); + declineReward.setVisible(false); + playerGold = Controls.newAccountingLabel(ui.findActor("playerGold"), false); playerShards = Controls.newAccountingLabel(ui.findActor("playerShards"), true); poolSize = ui.findActor("poolSize"); @@ -114,6 +123,8 @@ public class SpellSmithScene extends UIScene { } } + ui.onButtonPress("accept", SpellSmithScene.this::acceptSmithing); + ui.onButtonPress("decline", SpellSmithScene.this::declineSmithing); ui.onButtonPress("done", SpellSmithScene.this::done); ui.onButtonPress("pullUsingGold", () -> SpellSmithScene.this.pullCard(false)); ui.onButtonPress("pullUsingShards", () -> SpellSmithScene.this.pullCard(true)); @@ -122,6 +133,7 @@ public class SpellSmithScene extends UIScene { filterResults(); }); } + private void reset() { edition = ""; cost_low = -1; @@ -160,6 +172,10 @@ public class SpellSmithScene extends UIScene { } public boolean done() { + if (currentReward != null) { + acceptSmithing(); + } + if (rewardActor != null) rewardActor.remove(); cardPool.clear(); //Get rid of cardPool, filtering is fast enough to justify keeping it cached. Forge.switchToLast(); @@ -380,29 +396,74 @@ public class SpellSmithScene extends UIScene { } public void pullCard(boolean usingShards) { + paidInShards = usingShards; PaperCard P = cardPool.get(MyRandom.getRandom().nextInt(cardPool.size())); //Don't use the standard RNG. - Reward R = null; + currentReward = null; if (Config.instance().getSettingData().useAllCardVariants) { if (!edition.isEmpty()) { - R = new Reward(CardUtil.getCardByNameAndEdition(P.getCardName(), edition)); + currentReward = new Reward(CardUtil.getCardByNameAndEdition(P.getCardName(), edition)); } else { - R = new Reward(CardUtil.getCardByName(P.getCardName())); // grab any random variant if no set preference is specified + currentReward = new Reward(CardUtil.getCardByName(P.getCardName())); // grab any random variant if no set preference is specified } } else { - R = new Reward(P); + currentReward = new Reward(P); } - Current.player().addReward(R); - if (usingShards) { + if (rewardActor != null) rewardActor.remove(); + rewardActor = new RewardActor(currentReward, true, null, true); + rewardActor.flip(); //Make it flip so it draws visual attention, why not. + rewardActor.setBounds(rewardDummy.getX(), rewardDummy.getY(), rewardDummy.getWidth(), rewardDummy.getHeight()); + stage.addActor(rewardActor); + + acceptReward.setVisible(true); + declineReward.setVisible(true); + exitSmith.setDisabled(true); + disablePullButtons(); + } + + private void acceptSmithing() { + if (paidInShards) { Current.player().takeShards(currentShardPrice); } else { Current.player().takeGold(currentPrice); } - if (Current.player().getGold() < currentPrice) pullUsingGold.setDisabled(true); - if (Current.player().getShards() < currentShardPrice) pullUsingShards.setDisabled(true); + + Current.player().addReward(currentReward); + + clearReward(); + updatePullButtons(); + } + + private void declineSmithing() { + // Decline the smith reward for 10% of original price + float priceAdjustment = .10f; + if (paidInShards) { + Current.player().takeShards((int)(currentShardPrice * priceAdjustment)); + } else { + Current.player().takeGold((int)(currentPrice * priceAdjustment)); + } + + clearReward(); + updatePullButtons(); + } + + private void clearReward() { if (rewardActor != null) rewardActor.remove(); - rewardActor = new RewardActor(R, true, null, true); - rewardActor.flip(); //Make it flip so it draws visual attention, why not. - rewardActor.setBounds(rewardDummy.getX(), rewardDummy.getY(), rewardDummy.getWidth(), rewardDummy.getHeight()); - stage.addActor(rewardActor); + currentReward = null; + } + + + private void updatePullButtons() { + pullUsingGold.setDisabled(Current.player().getGold() < currentPrice); + pullUsingShards.setDisabled(Current.player().getShards() < currentShardPrice); + + acceptReward.setVisible(false); + declineReward.setVisible(false); + + exitSmith.setDisabled(false); + } + + private void disablePullButtons() { + pullUsingGold.setDisabled(true); + pullUsingShards.setDisabled(true); } } diff --git a/forge-gui/res/adventure/common/maps/map/aerie/aerie_0.tmx b/forge-gui/res/adventure/common/maps/map/aerie/aerie_0.tmx index 08fba40b1ad..e8279474efd 100644 --- a/forge-gui/res/adventure/common/maps/map/aerie/aerie_0.tmx +++ b/forge-gui/res/adventure/common/maps/map/aerie/aerie_0.tmx @@ -67,7 +67,7 @@ "options": [ { "name": "Am I allowed to enter the aerie ?", - "text": "I'm afraid to say to you that you are not allowed to do that. Our guild is very protective of it's breeding practices, which have been developed over a span of more than thousands of years. Because of that, we don't want our competitors peeking into our business. If anyone without permission enters the aerie, that person will be repremanded by the various guards and even the birds, who have been trained to attack unwanted intruders.'", + "text": "I'm afraid to say to you that you are not allowed to do that. Our guild is very protective of it's breeding practices, which have been developed over a span of more than thousands of years. Because of that, we don't want our competitors peeking into our business. If anyone without permission enters the aerie, that person will be reprimanded by the various guards and even the birds, who have been trained to attack unwanted intruders.'", "options": [ { "name": "Thanks for the information, goodbye", diff --git a/forge-gui/res/adventure/common/ui/spellsmith.json b/forge-gui/res/adventure/common/ui/spellsmith.json index f831865f5fa..dc1e9f19aa7 100644 --- a/forge-gui/res/adventure/common/ui/spellsmith.json +++ b/forge-gui/res/adventure/common/ui/spellsmith.json @@ -169,12 +169,34 @@ "y": 5, "width": 90, "height": 20 + }, + { + "type": "TextButton", + "selectable": true, + "name": "accept", + "text": "tr(lblTake)", + "binding": "Use", + "x": 343, + "y": 173, + "width": 60, + "height": 20 + }, + { + "type": "TextButton", + "selectable": true, + "name": "decline", + "text": "tr(lblRefund)", + "binding": "Back", + "x": 405, + "y": 173, + "width": 60, + "height": 20 }, { "type": "Label", "name": "poolSize", "x": 360, - "y": 180, + "y": 192, "width": 90, "height": 20 }, diff --git a/forge-gui/res/adventure/common/ui/spellsmith_portrait.json b/forge-gui/res/adventure/common/ui/spellsmith_portrait.json index 47855ffcecf..89d252edc75 100644 --- a/forge-gui/res/adventure/common/ui/spellsmith_portrait.json +++ b/forge-gui/res/adventure/common/ui/spellsmith_portrait.json @@ -174,12 +174,34 @@ "y": 75, "width": 90, "height": 20 + }, + { + "type": "TextButton", + "selectable": true, + "name": "accept", + "text": "tr(lblTake)", + "binding": "Use", + "x": 2, + "y": 142, + "width": 60, + "height": 20 + }, + { + "type": "TextButton", + "selectable": true, + "name": "decline", + "text": "tr(lblRefund)", + "binding": "Back", + "x": 70, + "y": 142, + "width": 60, + "height": 20 }, { "type": "Label", "name": "poolSize", "x": 16, - "y": 150, + "y": 163, "width": 97, "height": 20 }, diff --git a/forge-gui/res/cardsfolder/d/demon_of_fates_design.txt b/forge-gui/res/cardsfolder/d/demon_of_fates_design.txt index 57d45fdee43..c17abe70b5b 100644 --- a/forge-gui/res/cardsfolder/d/demon_of_fates_design.txt +++ b/forge-gui/res/cardsfolder/d/demon_of_fates_design.txt @@ -4,7 +4,7 @@ Types:Enchantment Creature Demon PT:6/6 K:Flying K:Trample -S:Mode$ Continuous | Affected$ Card.Enchantment+YouCtrl+nonLand | MayPlayLimit$ 1 | MayPlay$ True | MayPlayAltManaCost$ PayLife | MayPlayDontGrantZonePermissions$ True | AffectedZone$ Hand,Graveyard,Exile,Library,Command | Description$ Once during each of your turns, you may cast an enchantment spell by paying life equal to its mana value rather than paying its mana cost. +S:Mode$ Continuous | Condition$ PlayerTurn | Affected$ Card.Enchantment+YouCtrl+nonLand | MayPlayLimit$ 1 | MayPlay$ True | MayPlayAltManaCost$ PayLife | MayPlayDontGrantZonePermissions$ True | AffectedZone$ Hand,Graveyard,Exile,Library,Command | Description$ Once during each of your turns, you may cast an enchantment spell by paying life equal to its mana value rather than paying its mana cost. A:AB$ Pump | Cost$ 2 B Sac<1/Enchantment.Other> | NumAtt$ X | SpellDescription$ CARDNAME gets +X/+0 until end of turn, where X is the sacrificed enchantment's mana value. SVar:X:Sacrificed$CardManaCost DeckHints:Type$Enchantment diff --git a/forge-gui/res/cardsfolder/s/snakeskin_veil.txt b/forge-gui/res/cardsfolder/s/snakeskin_veil.txt index 4c31fb3d03c..3e7c6c486fd 100644 --- a/forge-gui/res/cardsfolder/s/snakeskin_veil.txt +++ b/forge-gui/res/cardsfolder/s/snakeskin_veil.txt @@ -1,7 +1,7 @@ Name:Snakeskin Veil ManaCost:G Types:Instant -A:SP$ PutCounter | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBPump | SpellDescription$ Put a +1/+1 counter on target creature you control. +A:SP$ PutCounter | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBPump | SpellDescription$ Put a +1/+1 counter on target creature you control. It gains hexproof until end of turn. SVar:DBPump:DB$ Pump | Defined$ Targeted | KW$ Hexproof DeckHas:Ability$Counters Oracle:Put a +1/+1 counter on target creature you control. It gains hexproof until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/balemurk_leech.txt b/forge-gui/res/cardsfolder/upcoming/balemurk_leech.txt index 30f3e75c228..e16619ef189 100644 --- a/forge-gui/res/cardsfolder/upcoming/balemurk_leech.txt +++ b/forge-gui/res/cardsfolder/upcoming/balemurk_leech.txt @@ -3,7 +3,7 @@ ManaCost:1 B Types:Creature Leech PT:2/2 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, each opponent loses 1 life. -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigLoseLife| TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, each opponent loses 1 life. +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigLoseLife| TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, each opponent loses 1 life. SVar:TrigLoseLife:DB$ LoseLife | Defined$ Player.Opponent | LifeAmount$ 1 DeckNeeds:Type$Enchantment -Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, each opponent loses 1 life. \ No newline at end of file +Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, each opponent loses 1 life. diff --git a/forge-gui/res/cardsfolder/upcoming/cult_healer.txt b/forge-gui/res/cardsfolder/upcoming/cult_healer.txt index 70d35d3a0be..c18ef34c9ab 100644 --- a/forge-gui/res/cardsfolder/upcoming/cult_healer.txt +++ b/forge-gui/res/cardsfolder/upcoming/cult_healer.txt @@ -3,7 +3,7 @@ ManaCost:2 W Types:Creature Human Doctor PT:3/3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gains lifelink until end of turn. -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPump | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gains lifelink until end of turn. +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gains lifelink until end of turn. SVar:TrigPump:DB$ Pump | Defined$ Self | KW$ Lifelink DeckNeeds:Type$Enchantment -Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, Cult Healer gains lifelink until end of turn. \ No newline at end of file +Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, Cult Healer gains lifelink until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/dashing_bloodsucker.txt b/forge-gui/res/cardsfolder/upcoming/dashing_bloodsucker.txt index 58f513604b1..1c9410f3121 100644 --- a/forge-gui/res/cardsfolder/upcoming/dashing_bloodsucker.txt +++ b/forge-gui/res/cardsfolder/upcoming/dashing_bloodsucker.txt @@ -3,7 +3,7 @@ ManaCost:3 B Types:Creature Vampire Warrior PT:2/5 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gets +2/+0 and gains lifelink until end of turn. -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPump | TriggerDescription$ $ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gets +2/+0 and gains lifelink until end of turn. +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ $ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gets +2/+0 and gains lifelink until end of turn. SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ 2 | KW$ Lifelink DeckNeeds:Type$Enchantment -Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, Dashing Bloodsucker gets +2/+0 and gains lifelink until end of turn. \ No newline at end of file +Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, Dashing Bloodsucker gets +2/+0 and gains lifelink until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/disorienting_choice.txt b/forge-gui/res/cardsfolder/upcoming/disorienting_choice.txt new file mode 100644 index 00000000000..2749459bbc7 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/disorienting_choice.txt @@ -0,0 +1,14 @@ +Name:Disorienting Choice +ManaCost:3 G +Types:Sorcery +A:SP$ Pump | ValidTgts$ Artifact.OppCtrl,Enchantment.OppCtrl | TgtPrompt$ Choose up to one target artifact or enchantment each opponent controls | TargetMin$ 0 | TargetMax$ OneEach | TargetsForEachPlayer$ True | SubAbility$ DBRepeat | SpellDescription$ For each opponent, choose up to one target artifact or enchantment that player controls. For each permanent chosen this way, its controller may exile it. Then if one or more of the chosen permanents are still on the battlefield, you search your library for up to that many land cards, put them onto the battlefield tapped, then shuffle. +SVar:DBRepeat:DB$ RepeatEach | RepeatPlayers$ TargetedController | RepeatSubAbility$ DBChoice | SubAbility$ DBExile +SVar:DBChoice:DB$ GenericChoice | Choices$ DBDoNotKeep,DBIncrease | Defined$ Remembered | AILogic$ Random | ShowChoice$ ExceptSelf +SVar:DBDoNotKeep:DB$ Pump | Defined$ Targeted.RememberedPlayerCtrl | RememberPumped$ True | SpellDescription$ Exile targeted card +SVar:DBIncrease:DB$ StoreSVar | SVar$ X | Type$ CountSVar | Expression$ X/Plus.1 | SpellDescription$ Keep targeted card +SVar:DBExile:DB$ ChangeZoneAll | Origin$ Battlefield | Destination$ Exile | ChangeType$ Card.IsRemembered | SubAbility$ DBSearchLibrary +SVar:DBSearchLibrary:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Land | Tapped$ True | ChangeNum$ X | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:X:Number$0 +SVar:OneEach:PlayerCountOpponents$Amount +Oracle:For each opponent, choose up to one target artifact or enchantment that player controls. For each permanent chosen this way, its controller may exile it. Then if one or more of the chosen permanents are still on the battlefield, you search your library for up to that many land cards, put them onto the battlefield tapped, then shuffle. diff --git a/forge-gui/res/cardsfolder/upcoming/erratic_apparition.txt b/forge-gui/res/cardsfolder/upcoming/erratic_apparition.txt index b02ad568f74..e11a3c1d47f 100644 --- a/forge-gui/res/cardsfolder/upcoming/erratic_apparition.txt +++ b/forge-gui/res/cardsfolder/upcoming/erratic_apparition.txt @@ -5,7 +5,7 @@ PT:1/3 K:Flying K:Vigilance T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gets +1/+1 until end of turn. -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPump | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gets +1/+1 until end of turn. +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gets +1/+1 until end of turn. SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ 1 | NumDef$ 1 DeckNeeds:Type$Enchantment Oracle:Flying, vigilance\nEerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, Erratic Apparition gets +1/+1 until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/fear_my_authority.txt b/forge-gui/res/cardsfolder/upcoming/fear_my_authority.txt new file mode 100644 index 00000000000..26e971ab29a --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/fear_my_authority.txt @@ -0,0 +1,9 @@ +Name:Fear My Authority +ManaCost:no cost +Types:Ongoing Scheme +S:Mode$ Continuous | EffectZone$ Command | Affected$ Creature.YouCtrl | AddPower$ 2 | AddToughness$ 2 | AddKeyword$ Fear | Description$ Creatures you control get +2/+2 and have fear. +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ DBAbandonCheck | TriggerDescription$ At the beginning of your upkeep, abandon this scheme unless you discard a card or pay 3 life. +SVar:DBAbandonCheck:DB$ GenericChoice | Choices$ DBPayLife,DBDiscard +SVar:DBPayLife:DB$ Abandon | UnlessCost$ PayLife<3> | UnlessPayer$ You | SpellDescription$ Pay 3 life or abandon this scheme +SVar:DBDiscard:DB$ Abandon | UnlessCost$ Discard<1/Card> | UnlessPayer$ You | SpellDescription$ Discard a card or abandon this scheme +Oracle:(An ongoing scheme remains face up until it's abandoned.)\nCreatures you control get +2/+2 and have fear. (They can't be blocked except by artifact creatures and/or black creatures.)\nAt the beginning of your upkeep, abandon this scheme unless you discard a card or pay 3 life. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/fear_of_infinity.txt b/forge-gui/res/cardsfolder/upcoming/fear_of_infinity.txt index fb96df79c3b..680caea3554 100644 --- a/forge-gui/res/cardsfolder/upcoming/fear_of_infinity.txt +++ b/forge-gui/res/cardsfolder/upcoming/fear_of_infinity.txt @@ -6,6 +6,6 @@ K:Flying K:Lifelink K:CARDNAME can't block. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | OptionalDecider$ You | TriggerZones$ Graveyard | Execute$ TrigChange | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, you may return CARDNAME from your graveyard to your hand. -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | OptionalDecider$ You | TriggerZones$ Graveyard | Execute$ TrigChange | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, you may return CARDNAME from your graveyard to your hand. +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | OptionalDecider$ You | TriggerZones$ Graveyard | Execute$ TrigChange | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, you may return CARDNAME from your graveyard to your hand. SVar:TrigChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand Oracle:Flying, lifelink\nFear of Infinity can't block.\nEerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, you may return Fear of Infinity from your graveyard to your hand. diff --git a/forge-gui/res/cardsfolder/upcoming/gremlin_tamer.txt b/forge-gui/res/cardsfolder/upcoming/gremlin_tamer.txt index 0be3f288709..b506a000815 100644 --- a/forge-gui/res/cardsfolder/upcoming/gremlin_tamer.txt +++ b/forge-gui/res/cardsfolder/upcoming/gremlin_tamer.txt @@ -3,8 +3,8 @@ ManaCost:W U Types:Creature Human Scout PT:2/2 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, create a 1/1 red Gremlin creature token. -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigToken | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, create a 1/1 red Gremlin creature token. +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, create a 1/1 red Gremlin creature token. SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ r_1_1_gremlin | TokenOwner$ You DeckHas:Ability$Token DeckNeeds:Type$Enchantment -Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, create a 1/1 red Gremlin creature token. \ No newline at end of file +Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, create a 1/1 red Gremlin creature token. diff --git a/forge-gui/res/cardsfolder/upcoming/i_am_never_alone.txt b/forge-gui/res/cardsfolder/upcoming/i_am_never_alone.txt new file mode 100644 index 00000000000..b437d994887 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/i_am_never_alone.txt @@ -0,0 +1,6 @@ +Name:I Am Never Alone +ManaCost:no cost +Types:Scheme +T:Mode$ SetInMotion | ValidCard$ Card.Self | Execute$ DBCopyCommander | TriggerZones$ Command | TriggerDescription$ When you set this scheme in motion, create a token that's a copy of your commander, except it's not legendary. +SVar:DBCopyCommander:DB$ CopyPermanent | Choices$ Card.IsCommander+YouOwn | Defined$ ValidAll Card.IsCommander+YouOwn | ChoiceTitle$ Choose a commander you own | NonLegendary$ True +Oracle:When you set this scheme in motion, create a token that's a copy of your commander, except it's not legendary.\n"This is but a pale shadow of my true form. Cower before it, and despair." diff --git a/forge-gui/res/cardsfolder/upcoming/infernal_phantom.txt b/forge-gui/res/cardsfolder/upcoming/infernal_phantom.txt index 383a846673b..5bf2f757441 100644 --- a/forge-gui/res/cardsfolder/upcoming/infernal_phantom.txt +++ b/forge-gui/res/cardsfolder/upcoming/infernal_phantom.txt @@ -3,10 +3,10 @@ ManaCost:3 R Types:Creature Spirit PT:2/3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gets +2/+0 until end of turn. -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPump | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gets +2/+0 until end of turn. +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME gets +2/+0 until end of turn. SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ 2 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigDamage | TriggerDescription$ When CARDNAME dies, it deals damage equal to its power to any target. SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Any | NumDmg$ X SVar:X:TriggeredCard$CardPower DeckNeeds:Type$Enchantment -Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, Infernal Phantom gets +2/+0 until end of turn.\nWhen Infernal Phantom dies, it deals damage equal to its power to any target. \ No newline at end of file +Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, Infernal Phantom gets +2/+0 until end of turn.\nWhen Infernal Phantom dies, it deals damage equal to its power to any target. diff --git a/forge-gui/res/cardsfolder/upcoming/optimistic_scavenger.txt b/forge-gui/res/cardsfolder/upcoming/optimistic_scavenger.txt index 559180742ee..23ddae673a2 100644 --- a/forge-gui/res/cardsfolder/upcoming/optimistic_scavenger.txt +++ b/forge-gui/res/cardsfolder/upcoming/optimistic_scavenger.txt @@ -3,7 +3,7 @@ ManaCost:W Types:Creature Human Scout PT:1/1 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, put a +1/+1 counter on target creature. -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPutCounter | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, put a +1/+1 counter on target creature. +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, put a +1/+1 counter on target creature. SVar:TrigPutCounter:DB$ PutCounter | ValidTgts$ Creature | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ 1 DeckHas:Ability$Counters DeckNeeds:Type$Enchantment diff --git a/forge-gui/res/cardsfolder/upcoming/rampaging_soulrager.txt b/forge-gui/res/cardsfolder/upcoming/rampaging_soulrager.txt new file mode 100644 index 00000000000..af9fc947061 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/rampaging_soulrager.txt @@ -0,0 +1,7 @@ +Name:Rampaging Soulrager +ManaCost:2 R +Types:Creature Spirit +PT:1/4 +S:Mode$ Continuous | Affected$ Card.Self | AddPower$ 3 | CheckSVar$ X | SVarCompare$ GE2 | Description$ CARDNAME gets +3/+0 as long as there are two or more unlocked doors among Rooms you control. +SVar:X:Count$UnlockedDoors Card.Room+YouCtrl +Oracle:Rampaging Soulrager gets +3/+0 as long as there are two or more unlocked doors among Rooms you control. diff --git a/forge-gui/res/cardsfolder/upcoming/scrabbling_skullcrab.txt b/forge-gui/res/cardsfolder/upcoming/scrabbling_skullcrab.txt index c3eb6d6daf0..773e900cb6e 100644 --- a/forge-gui/res/cardsfolder/upcoming/scrabbling_skullcrab.txt +++ b/forge-gui/res/cardsfolder/upcoming/scrabbling_skullcrab.txt @@ -3,7 +3,7 @@ ManaCost:U Types:Creature Crab Skeleton PT:0/3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigMill | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, target player mills two cards. (They put the top two cards of their library into their graveyard.) -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigMill | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, target player mills two cards. (They put the top two cards of their library into their graveyard.) +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigMill | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, target player mills two cards. (They put the top two cards of their library into their graveyard.) SVar:TrigMill:DB$ Mill | NumCards$ 2 | ValidTgts$ Player | TgtPrompt$ Select target player DeckNeeds:Type$Enchantment -Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, target player mills two cards. (They put the top two cards of their library into their graveyard.) \ No newline at end of file +Oracle:Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, target player mills two cards. (They put the top two cards of their library into their graveyard.) diff --git a/forge-gui/res/cardsfolder/upcoming/skullsnap_nuisance.txt b/forge-gui/res/cardsfolder/upcoming/skullsnap_nuisance.txt index 073406f1f51..c24d715614f 100644 --- a/forge-gui/res/cardsfolder/upcoming/skullsnap_nuisance.txt +++ b/forge-gui/res/cardsfolder/upcoming/skullsnap_nuisance.txt @@ -4,7 +4,7 @@ Types:Creature Insect Skeleton PT:1/4 K:Flying T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigSurveil | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, surveil 1. (Look at the top card of your library. You may put it into your graveyard.) -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigSurveil | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, surveil 1. (Look at the top card of your library. You may put it into your graveyard.). +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigSurveil | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, surveil 1. (Look at the top card of your library. You may put it into your graveyard.). SVar:TrigSurveil:DB$ Surveil | Amount$ 1 DeckNeeds:Type$Enchantment -Oracle:Flying\nEerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, surveil 1. (Look at the top card of your library. You may put it into your graveyard.) \ No newline at end of file +Oracle:Flying\nEerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, surveil 1. (Look at the top card of your library. You may put it into your graveyard.) diff --git a/forge-gui/res/cardsfolder/upcoming/stalked_researcher.txt b/forge-gui/res/cardsfolder/upcoming/stalked_researcher.txt index c737d968208..30e6371f87d 100644 --- a/forge-gui/res/cardsfolder/upcoming/stalked_researcher.txt +++ b/forge-gui/res/cardsfolder/upcoming/stalked_researcher.txt @@ -4,7 +4,7 @@ Types:Creature Human Wizard PT:3/3 K:Defender T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigEffect | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME can attack this turn as though it didn't have defender. -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigEffect | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME can attack this turn as though it didn't have defender. +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigEffect | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, CARDNAME can attack this turn as though it didn't have defender. SVar:TrigEffect:DB$ Effect | StaticAbilities$ CanAttack | ForgetOnMoved$ Battlefield SVar:CanAttack:Mode$ CanAttackDefender | ValidCard$ Card.EffectSource | Description$ EFFECTSOURCE can attack this turn as though it didn't have defender. DeckNeeds:Type$Enchantment diff --git a/forge-gui/res/cardsfolder/upcoming/unwilling_vessel.txt b/forge-gui/res/cardsfolder/upcoming/unwilling_vessel.txt index e68418be225..e082b912a1b 100644 --- a/forge-gui/res/cardsfolder/upcoming/unwilling_vessel.txt +++ b/forge-gui/res/cardsfolder/upcoming/unwilling_vessel.txt @@ -4,11 +4,11 @@ Types:Creature Human Wizard PT:3/2 K:Vigilance T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, put a possession counter on CARDNAME. -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPutCounter | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, put a possession counter on CARDNAME. +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, put a possession counter on CARDNAME. SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ POSSESSION | CounterNum$ 1 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME dies, create an X/X blue Spirit creature token with flying, where X is the number of counters on CARDNAME. SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ u_x_x_spirit_flying | TokenPower$ X | TokenToughness$ X | TokenOwner$ You SVar:X:TriggeredCard$CardCounters.ALL DeckHas:Ability$Token & Type$Spirit DeckNeeds:Type$Enchantment -Oracle:Vigilance\nEerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, put a possession counter on Unwilling Vessel.\nWhen Unwilling Vessel dies, create an X/X blue Spirit creature token with flying, where X is the number of counters on Unwilling Vessel. \ No newline at end of file +Oracle:Vigilance\nEerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, put a possession counter on Unwilling Vessel.\nWhen Unwilling Vessel dies, create an X/X blue Spirit creature token with flying, where X is the number of counters on Unwilling Vessel. diff --git a/forge-gui/res/cardsfolder/upcoming/victor_valgavoths_seneschal.txt b/forge-gui/res/cardsfolder/upcoming/victor_valgavoths_seneschal.txt index 34cdc4540ab..fc5b61dd418 100644 --- a/forge-gui/res/cardsfolder/upcoming/victor_valgavoths_seneschal.txt +++ b/forge-gui/res/cardsfolder/upcoming/victor_valgavoths_seneschal.txt @@ -3,7 +3,7 @@ ManaCost:1 W B Types:Legendary Creature Human Warlock PT:3/3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigSurveil | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, surveil 2 if this is the first time this ability has resolved this turn. If it's the second time, each opponent discards a card. If it's the third time, put a creature card from a graveyard onto the battlefield under your control. -T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigSurveil | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, surveil 2 if this is the first time this ability has resolved this turn. If it's the second time, each opponent discards a card. If it's the third time, put a creature card from a graveyard onto the battlefield under your control. +T:Mode$ FullyUnlock | ValidCard$ Card.Room | ValidPlayer$ You | Secondary$ True | Execute$ TrigSurveil | TriggerZones$ Battlefield | TriggerDescription$ Eerie — Whenever an enchantment you control enters and whenever you fully unlock a Room, surveil 2 if this is the first time this ability has resolved this turn. If it's the second time, each opponent discards a card. If it's the third time, put a creature card from a graveyard onto the battlefield under your control. SVar:TrigSurveil:DB$ Surveil | Amount$ 2 | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ1 | SubAbility$ DBDiscard SVar:DBDiscard:DB$ Discard | Defined$ Player.Opponent | Mode$ TgtChoose | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ2 | SubAbility$ DBChangeZone SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature | ChangeNum$ 1 | Mandatory$ True | GainControl$ True | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ3 | SelectPrompt$ Select a creature card to return to the battlefield | Hidden$ True | SubAbility$ DBLog diff --git a/forge-gui/res/cardsfolder/upcoming/zimone_all_questioning.txt b/forge-gui/res/cardsfolder/upcoming/zimone_all_questioning.txt index aa8da24d713..2b03fb00fe7 100644 --- a/forge-gui/res/cardsfolder/upcoming/zimone_all_questioning.txt +++ b/forge-gui/res/cardsfolder/upcoming/zimone_all_questioning.txt @@ -3,7 +3,7 @@ ManaCost:1 G U Types:Legendary Creature Human Wizard PT:1/1 T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | Execute$ TrigToken | CheckSVar$ X | TriggerDescription$ At the beginning of your end step, if a land entered the battlefield under your control this turn and you control a prime number of lands, create Primo, the Indivisible, a legendary 0/0 green and blue Fractal creature token, then put that many +1/+1 counters on it. (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, and 31 are prime numbers.) -SVar:TrigToken:DB$ Token | TokenScript$ primo_the_invisible | RememberTokens$ True | SubAbility$ DBCounters +SVar:TrigToken:DB$ Token | TokenScript$ primo_the_indivisible | RememberTokens$ True | SubAbility$ DBCounters SVar:DBCounters:DB$ PutCounter | Defined$ Remembered | CounterNum$ Y | CounterType$ P1P1 | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:Count$IsPrime Y.Z.0 diff --git a/forge-gui/res/editions/Alchemy Duskmourn.txt b/forge-gui/res/editions/Alchemy Duskmourn.txt new file mode 100644 index 00000000000..761fe1255ee --- /dev/null +++ b/forge-gui/res/editions/Alchemy Duskmourn.txt @@ -0,0 +1,9 @@ +[metadata] +Code=YDSK +Date=2024-10-15 +Name=Alchemy: Duskmourn +Type=Online +ScryfallCode=YDSK + +[cards] +0 R Solitary Study // Endless Corridor @Leon Tukker diff --git a/forge-gui/res/editions/Secret Lair Drop Series.txt b/forge-gui/res/editions/Secret Lair Drop Series.txt index 88a0299e7a2..8de4bbbad21 100644 --- a/forge-gui/res/editions/Secret Lair Drop Series.txt +++ b/forge-gui/res/editions/Secret Lair Drop Series.txt @@ -796,6 +796,8 @@ F798 M Discord, Lord of Disharmony @Narendra Bintara Adi 827 R Norin the Wary @Jarel Threat 827b R Norin the Wary @Jarel Threat 828 R Keen Duelist @Thanh Tuấn +871 R Soul-Guide Lantern @ +872 R Yargle and Multani @Warren Mahy 873 R Dark Deal @Tyler Jacobson 874 R Archivist of Oghma @Cory Trego-Erdner 875 M Battle Angels of Tyr @Raymond Swanland @@ -803,6 +805,7 @@ F798 M Discord, Lord of Disharmony @Narendra Bintara Adi 877 R Druid of Purification @Alexander Mokhov 878 R Prosperous Innkeeper @Tyler Jacobson 879 M Minsc & Boo, Timeless Heroes @Justin Gerard +880 R Stuffy Doll @Robin Olausson 900 M The Scarab God @Barely Human 901 R Lightning Bolt @Christopher Rush 903 M The Locust God @See Machine diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 4d02b28a191..74042508522 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -3434,4 +3434,6 @@ lblShowNoSell=No-Sell Anzeigen lblShowAll=Alle Anzeigen lblHideCollection=Sammlung Ausblenden lblShowCollection=Sammlung Anzeigen -lblCracked=Geknackt! \ No newline at end of file +lblCracked=Geknackt! +lblTake=Nehmen +lblRefund=Erstattung \ No newline at end of file diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 80863cca86b..5f2ead89cf4 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -3167,4 +3167,6 @@ lblShowNoSell=Show No-Sell lblShowAll=Show All lblHideCollection=Hide Collection lblShowCollection=Show Collection -lblCracked=Cracked! \ No newline at end of file +lblCracked=Cracked! +lblTake=Take +lblRefund=Refund \ No newline at end of file diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 36ffbc1b600..258f1a5f6b8 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -3448,4 +3448,6 @@ lblShowNoSell=Mostrar No Vender lblShowAll=Mostrar Todo lblHideCollection=Ocultar Colección lblShowCollection=Mostrar Colección -lblCracked=¡Agrietado! \ No newline at end of file +lblCracked=¡Agrietado! +lblTake=Llevar +lblRefund=Reembolso \ No newline at end of file diff --git a/forge-gui/res/languages/fr-FR.properties b/forge-gui/res/languages/fr-FR.properties index 1941f39fa0e..76669bb1446 100644 --- a/forge-gui/res/languages/fr-FR.properties +++ b/forge-gui/res/languages/fr-FR.properties @@ -3442,4 +3442,6 @@ lblShowNoSell=Afficher Non-Vente lblShowAll=Afficher Tout lblHideCollection=Masquer la Collection lblShowCollection=Afficher la Collection -lblCracked=Fissuré! \ No newline at end of file +lblCracked=Fissuré! +lblTake=Prendre +lblRefund=Remboursement \ No newline at end of file diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index f44607dbc64..9d08f89df5b 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -3441,3 +3441,5 @@ lblShowAll=Mostra Tutto lblHideCollection=Nascondi Collezione lblShowCollection=Mostra Collezione lblCracked=Incrinato! +lblTake=Prendere +lblRefund=Rimborso \ No newline at end of file diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index e08a27e1a8a..11fb5ebdee6 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -3436,4 +3436,6 @@ lblShowNoSell=ノーセールを表示 lblShowAll=すべて表示 lblHideCollection=コレクションを非表示にする lblShowCollection=ショーコレクション -lblCracked=ひび割れた! \ No newline at end of file +lblCracked=ひび割れた! +lblTake=取る +lblRefund=返金 \ No newline at end of file diff --git a/forge-gui/res/languages/pt-BR.properties b/forge-gui/res/languages/pt-BR.properties index 3ff8bc9b44c..6e28dd5b91f 100644 --- a/forge-gui/res/languages/pt-BR.properties +++ b/forge-gui/res/languages/pt-BR.properties @@ -3526,4 +3526,6 @@ lblShowNoSell=Mostrar Não-Venda lblShowAll=Mostrar Tudo lblHideCollection=Ocultar Coleção lblShowCollection=Mostrar Coleção -lblCracked=Rachado! \ No newline at end of file +lblCracked=Rachado! +lblTake=Pegar +lblRefund=Reembolso \ No newline at end of file diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index b77274cf232..9b65d372bce 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -3427,4 +3427,6 @@ lblShowNoSell=显示不卖 lblShowAll=显示全部 lblHideCollection=隐藏收藏 lblShowCollection=展会系列 -lblCracked=破裂了! \ No newline at end of file +lblCracked=破裂了! +lblTake=拿 +lblRefund=退款 \ No newline at end of file diff --git a/forge-gui/res/tokenscripts/primo_the_invisible.txt b/forge-gui/res/tokenscripts/primo_the_indivisible.txt similarity index 75% rename from forge-gui/res/tokenscripts/primo_the_invisible.txt rename to forge-gui/res/tokenscripts/primo_the_indivisible.txt index 52f4b310f61..4189e6ef591 100644 --- a/forge-gui/res/tokenscripts/primo_the_invisible.txt +++ b/forge-gui/res/tokenscripts/primo_the_indivisible.txt @@ -1,4 +1,4 @@ -Name:Primo, the Invisible +Name:Primo, the Indivisible ManaCost:no cost Colors:green, blue Types:Legendary Creature Fractal