From 6db188406ad68f4919abed0dda6f1efff13ebc8a Mon Sep 17 00:00:00 2001 From: TabletopGeneral <56438137+jjayers99@users.noreply.github.com> Date: Sun, 7 Jan 2024 23:10:54 -0500 Subject: [PATCH 1/4] Adventure - Quest fixes (#4490) Correction for empty dialog textboxes displaying on what should be silent quest triggers Bugfixes within Library Of Varsil dungeon --- .../util/AdventureQuestController.java | 7 ++++ .../res/adventure/Shandalar/world/quests.json | 2 +- .../library_of_varsil_3.tmx | 35 +++++++++++-------- .../library_of_varsil_4.tmx | 12 +++---- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/forge-gui-mobile/src/forge/adventure/util/AdventureQuestController.java b/forge-gui-mobile/src/forge/adventure/util/AdventureQuestController.java index 7d66efaff13..aa1138b687f 100644 --- a/forge-gui-mobile/src/forge/adventure/util/AdventureQuestController.java +++ b/forge-gui-mobile/src/forge/adventure/util/AdventureQuestController.java @@ -226,6 +226,13 @@ public void displayNextDialog(MapStage stage){ DialogData data = dialogQueue.remove(); MapDialog dialog = new MapDialog(data, stage, -1, null); + + if (data.options == null || data.options.length == 0) { + dialog.setEffects(data.action); + displayNextDialog(stage); + return; + } + stage.showDialog(); dialog.activate(); ChangeListener listen = new ChangeListener() { diff --git a/forge-gui/res/adventure/Shandalar/world/quests.json b/forge-gui/res/adventure/Shandalar/world/quests.json index c496670d4b9..af6d58bcd5a 100644 --- a/forge-gui/res/adventure/Shandalar/world/quests.json +++ b/forge-gui/res/adventure/Shandalar/world/quests.json @@ -10033,8 +10033,8 @@ "name": "Locate The Research", "description": "Search $(poi_1) for research about the mechanics of summoning spells", "mapFlag": "foundLibraryOfVarsilResearch", + "anyPOI": true, "mapFlagValue": 1, - "here": true, "objective": "QuestFlag", "prologue": { "text": "The structure before you is enormous, looking more like an ancient fortress than a library.", diff --git a/forge-gui/res/adventure/common/maps/map/main_story_explore/library_of_varsil_3.tmx b/forge-gui/res/adventure/common/maps/map/main_story_explore/library_of_varsil_3.tmx index 593b271535e..27a3d85c4db 100644 --- a/forge-gui/res/adventure/common/maps/map/main_story_explore/library_of_varsil_3.tmx +++ b/forge-gui/res/adventure/common/maps/map/main_story_explore/library_of_varsil_3.tmx @@ -93,19 +93,26 @@ [ -{ - "text": "'Shandalaar’s Most Burnable Cities'. Well, this one sounds like light reading...", - "options": [{ - "name": "(Continue)", "action": [{"deleteMapObject":-1}, - "action": [{ - "grantRewards": [{ - "type": "card", - "count": 1, - "cardName": "Fireball" - }] - }] - }] -} + { + "text": "'Shandalaar’s Most Burnable Cities'. Well, this one sounds like light reading...", + "options": [ + { + "name": "(Continue)", + "action": [ + { + "deleteMapObject": -1, + "grantRewards": [ + { + "type": "card", + "count": 1, + "cardName": "Fireball" + } + ] + } + ] + } + ] + } ] @@ -275,7 +282,7 @@ "getQuestFlag": { "key": "exploreShand1", "op": "=", - "val": 5 + "val": 4 } }, { diff --git a/forge-gui/res/adventure/common/maps/map/main_story_explore/library_of_varsil_4.tmx b/forge-gui/res/adventure/common/maps/map/main_story_explore/library_of_varsil_4.tmx index accd596fe68..da733b53679 100644 --- a/forge-gui/res/adventure/common/maps/map/main_story_explore/library_of_varsil_4.tmx +++ b/forge-gui/res/adventure/common/maps/map/main_story_explore/library_of_varsil_4.tmx @@ -40,14 +40,14 @@ [{ - "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 5}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch", "not": true}], + "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 4}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch", "not": true}], "text": "With this monstrous machine out of action, defeating its (relatively) smaller companions could be left to lesser adventurers, but you still haven't found the documents Sir Donovan wanted. They must be somewhere downstairs.", "options": [{ "name": "(Continue)", "action": [{"setQuestFlag": {"key":"defeatedLibraryOfVarsilBoss", "val": 1} }, {"deleteMapObject": -1}] }] },{ - "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 5}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch"}], + "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 4}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch"}], "text": "With this monstrous machine out of action, defeating its (relatively) smaller companions could be left to lesser adventurers. You've already found the documents Sir Donovan wanted and can report back to him now or go back down and explore further first.", "options": [{ "name": "(Continue)", @@ -64,14 +64,14 @@ [{ - "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 5}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch", "not": true}], + "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 4}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch", "not": true}], "text": "With this monstrous machine out of action, defeating its (relatively) smaller companions could be left to lesser adventurers, but you still haven't found the documents Sir Donovan wanted. They must be somewhere downstairs.", "options": [{ "name": "(Continue)", "action": [{"setQuestFlag": {"key":"defeatedLibraryOfVarsilBoss", "val": 1} }, {"deleteMapObject": -1}] }] },{ - "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 5}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch"}], + "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 4}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch"}], "text": "With this monstrous machine out of action, defeating its (relatively) smaller companions could be left to lesser adventurers. You've already found the documents Sir Donovan wanted and can report back to him now or go back down and explore further first.", "options": [{ "name": "(Continue)", @@ -90,14 +90,14 @@ [{ - "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 5}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch", "not": true}], + "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 4}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch", "not": true}], "text": "With this monstrous machine out of action, defeating its (relatively) smaller companions could be left to lesser adventurers, but you still haven't found the documents Sir Donovan wanted. They must be somewhere downstairs.", "options": [{ "name": "(Continue)", "action": [{"setQuestFlag": {"key":"defeatedLibraryOfVarsilBoss", "val": 1} }, {"deleteMapObject": -1}] }] },{ - "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 5}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch"}], + "condition": [{"getQuestFlag": {"key": "exploreShand1", "op":"=", "val": 4}}, {"checkQuestFlag": "foundLibraryOfVarsilResearch"}], "text": "With this monstrous machine out of action, defeating its (relatively) smaller companions could be left to lesser adventurers. You've already found the documents Sir Donovan wanted and can report back to him now or go back down and explore further first.", "options": [{ "name": "(Continue)", From 1a3a5cbf8c7aff8d6520c60dcaadc8e92b38f74c Mon Sep 17 00:00:00 2001 From: tool4ever Date: Mon, 8 Jan 2024 07:12:49 +0100 Subject: [PATCH 2/4] Fix Fatal Lore (#4488) Co-authored-by: tool4EvEr --- .../src/main/java/forge/ai/ability/CharmAi.java | 11 +++++------ .../src/main/java/forge/game/GameActionUtil.java | 1 + .../java/forge/game/ability/AbilityUtils.java | 15 +++++++++------ .../forge/game/ability/effects/CharmEffect.java | 2 +- .../main/java/forge/game/card/CardFactory.java | 6 +++--- .../forge/game/spellability/SpellAbility.java | 13 +++++++++++-- forge-gui/res/cardsfolder/f/fatal_lore.txt | 4 ++-- forge-gui/res/cardsfolder/m/misfortune.txt | 4 ++-- .../java/forge/player/HumanPlaySpellAbility.java | 2 ++ 9 files changed, 36 insertions(+), 22 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java index b1e981d9d6a..7a642b7a831 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java @@ -37,11 +37,6 @@ protected boolean checkApiLogic(Player ai, SpellAbility sa) { min = sa.hasParam("MinCharmNum") ? AbilityUtils.calculateAmount(source, sa.getParam("MinCharmNum"), sa) : num; } - // only randomize if not all possible together - if (num < choices.size() || source.hasKeyword(Keyword.ESCALATE)) { - Collections.shuffle(choices); - } - boolean timingRight = sa.isTrigger(); //is there a reason to play the charm now? // Reset the chosen list otherwise it will be locked in forever by earlier calls @@ -51,11 +46,15 @@ protected boolean checkApiLogic(Player ai, SpellAbility sa) { if (!ai.equals(sa.getActivatingPlayer())) { // This branch is for "An Opponent chooses" Charm spells from Alliances // Current just choose the first available spell, which seem generally less disastrous for the AI. - //return choices.subList(0, 1); chosenList = choices.subList(1, choices.size()); } else if ("Triskaidekaphobia".equals(ComputerUtilAbility.getAbilitySourceName(sa))) { chosenList = chooseTriskaidekaphobia(choices, ai); } else { + // only randomize if not all possible together + if (num < choices.size() || source.hasKeyword(Keyword.ESCALATE)) { + Collections.shuffle(choices); + } + /* * The generic chooseOptionsAi uses canPlayAi() to determine good choices * which means most "bonus" effects like life-gain and random pumps will diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index c52d4594cb4..ae6cf563e02 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -916,6 +916,7 @@ public static void rollbackAbility(SpellAbility ability, final Zone fromZone, fi if (ability.getApi() == ApiType.Charm) { // reset chain ability.setSubAbility(null); + ability.setChosenList(null); } ability.clearTargets(); 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 b14163f6a40..ebe8381ceaa 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -1050,7 +1050,7 @@ else if (defined.startsWith("Remembered")) { addPlayer(card.getRemembered(), defined, players); } else if (defined.startsWith("Imprinted")) { - addPlayer(Lists.newArrayList(card.getImprintedCards()), defined, players); + addPlayer(card.getImprintedCards(), defined, players); } else if (defined.startsWith("EffectSource")) { Card root = findEffectRoot(card); @@ -1093,9 +1093,9 @@ else if (defined.startsWith("Triggered") && sa instanceof SpellAbility) { o = ((SpellAbility) c).getActivatingPlayer(); } else if (c instanceof Iterable) { // For merged permanent if (orCont) { - addPlayer(ImmutableList.copyOf(Iterables.filter((Iterable)c, Player.class)), "", players); + addPlayer(Iterables.filter((Iterable)c, Player.class), "", players); } - addPlayer(ImmutableList.copyOf(Iterables.filter((Iterable)c, Card.class)), "Controller", players); + addPlayer(Iterables.filter((Iterable)c, Card.class), "Controller", players); } } else if (defParsed.endsWith("Opponent")) { @@ -1205,6 +1205,9 @@ else if (defined.equals("AttackingPlayer")) { else if (defined.equals("DefendingPlayer")) { players.add(game.getCombat().getDefendingPlayerRelatedTo(card)); } + else if (defined.equals("ChoosingPlayer")) { + players.add(((SpellAbility) sa).getRootAbility().getChoosingPlayer()); + } else if (defined.equals("ChosenPlayer")) { final Player p = card.getChosenPlayer(); if (p != null) { @@ -1212,7 +1215,7 @@ else if (defined.equals("ChosenPlayer")) { } } else if (defined.startsWith("ChosenCard")) { - addPlayer(Lists.newArrayList(card.getChosenCards()), defined, players); + addPlayer(card.getChosenCards(), defined, players); } else if (defined.equals("SourceController")) { players.add(sa.getHostCard().getController()); @@ -3053,11 +3056,11 @@ public static final String getSVar(final CardTraitBase ability, final String sVa return applyAbilityTextChangeEffects(val, ability); } - private static void addPlayer(Iterable objects, final String def, FCollection players) { + private static void addPlayer(Iterable objects, final String def, FCollection players) { addPlayer(objects, def, players, false); } - private static void addPlayer(Iterable objects, final String def, FCollection players, boolean skipRemembered) { + private static void addPlayer(Iterable objects, final String def, FCollection players, boolean skipRemembered) { for (Object o : objects) { if (o instanceof Player) { final Player p = (Player) o; diff --git a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java index 6fc489e3c64..20ab2ee1a5c 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java @@ -224,7 +224,7 @@ public static boolean makeChoices(SpellAbility sa) { //String choosers = sa.getParam("Chooser"); FCollection opponents = activator.getOpponents(); // all cards have Choser$ Opponent, so it's hardcoded here chooser = activator.getController().chooseSingleEntityForEffect(opponents, sa, "Choose an opponent", null); - source.setChosenPlayer(chooser); + sa.setChoosingPlayer(chooser); } List chosen = chooser.getController().chooseModeForAbility(sa, choices, min, num, canRepeat); 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 0624524101e..de875ee33a9 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -83,7 +83,7 @@ public final static Card copyCard(final Card in, boolean assignNewId) { out = assignNewId ? getCard(in.getPaperCard(), in.getOwner(), in.getGame()) : getCard(in.getPaperCard(), in.getOwner(), in.getId(), in.getGame()); } else { // token - out = CardFactory.copyStats(in, in.getController(), assignNewId); + out = copyStats(in, in.getController(), assignNewId); out.setToken(true); // need to copy this values for the tokens @@ -128,7 +128,7 @@ private final static Card copySpellHost(final SpellAbility sourceSA, final Spell int id = game.nextCardId(); // need to create a physical card first, i need the original card faces - final Card copy = CardFactory.getCard(original.getPaperCard(), controller, id, game); + final Card copy = getCard(original.getPaperCard(), controller, id, game); if (original.isTransformable()) { // 707.8a If an effect creates a token that is a copy of a transforming permanent or a transforming double-faced card not on the battlefield, @@ -530,7 +530,7 @@ public static Card copyStats(final Card in, final Player newOwner, boolean assig c.setSetCode(in.getSetCode()); for (final CardStateName state : in.getStates()) { - CardFactory.copyState(in, state, c, state); + copyState(in, state, c, state); } c.setState(in.getCurrentStateName(), false); 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 9363684128f..5ce952c8799 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -103,11 +103,14 @@ public static class EmptySa extends SpellAbility { // choices for constructor isPermanent argument private String originalDescription = "", description = ""; private String originalStackDescription = "", stackDescription = ""; - private ManaCost multiKickerManaCost; + private Player activatingPlayer; private Player targetingPlayer; + private Player choosingPlayer; private Pair controlledByPlayer; + private ManaCostBeingPaid manaCostBeingPaid; + private ManaCost multiKickerManaCost; private int spentPhyrexian = 0; private int paidLifeAmount = 0; @@ -147,7 +150,6 @@ public static class EmptySa extends SpellAbility { private TreeBasedTable paidLists = TreeBasedTable.create(); private EnumMap triggeringObjects = AbilityKey.newMap(); - private EnumMap replacingObjects = AbilityKey.newMap(); private final List pipsToReduce = new ArrayList<>(); @@ -481,6 +483,13 @@ public void setTargetingPlayer(Player targetingPlayer0) { targetingPlayer = targetingPlayer0; } + public Player getChoosingPlayer() { + return choosingPlayer; + } + public void setChoosingPlayer(Player choosingPlayer0) { + choosingPlayer = choosingPlayer0; + } + /** * @return returns who controls the controller of this sa when it is resolving (for Word of Command effect). Null means not being controlled by other */ diff --git a/forge-gui/res/cardsfolder/f/fatal_lore.txt b/forge-gui/res/cardsfolder/f/fatal_lore.txt index fd86a53e4d7..d50dc94130a 100644 --- a/forge-gui/res/cardsfolder/f/fatal_lore.txt +++ b/forge-gui/res/cardsfolder/f/fatal_lore.txt @@ -3,7 +3,7 @@ ManaCost:2 B B Types:Sorcery A:SP$ Charm | Cost$ 2 B B | Chooser$ Opponent | Choices$ DrawThree,DestroyAndDraw SVar:DrawThree:DB$ Draw | NumCards$ 3 | Defined$ You | SpellDescription$ You draw three cards. -SVar:DestroyAndDraw:DB$ Destroy | ValidTgts$ Creature.ChosenCtrl | TgtPrompt$ Select target creature | TargetMin$ 0 | TargetMax$ 2 | NoRegen$ True | SpellDescription$ You destroy up to two target creatures that opponent controls and that player draws up to three cards. Those creatures can't be regenerated. | SubAbility$ ChooserDraws -SVar:ChooserDraws:DB$ Draw | NumCards$ 3 | Defined$ ChosenPlayer | UpTo$ True +SVar:DestroyAndDraw:DB$ Destroy | ValidTgts$ Creature.ControlledBy ChoosingPlayer | TgtPrompt$ Select target creature | TargetMin$ 0 | TargetMax$ 2 | NoRegen$ True | SpellDescription$ You destroy up to two target creatures that opponent controls and that player draws up to three cards. Those creatures can't be regenerated. | SubAbility$ ChooserDraws +SVar:ChooserDraws:DB$ Draw | NumCards$ 3 | Defined$ ChoosingPlayer | UpTo$ True AI:RemoveDeck:All Oracle:An opponent chooses one —\n• You draw three cards.\n• You destroy up to two target creatures that player controls. They can't be regenerated. That player draws up to three cards. diff --git a/forge-gui/res/cardsfolder/m/misfortune.txt b/forge-gui/res/cardsfolder/m/misfortune.txt index e4d4f52eaee..bc08dfdc7a2 100644 --- a/forge-gui/res/cardsfolder/m/misfortune.txt +++ b/forge-gui/res/cardsfolder/m/misfortune.txt @@ -4,7 +4,7 @@ Types:Sorcery A:SP$ Charm | Cost$ 1 B R G | Chooser$ Opponent | Choices$ Fortune,Misfortune SVar:Fortune:DB$ PutCounterAll | ValidCards$ Creature.YouCtrl | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBGainLife | SpellDescription$ Put a +1/+1 counter on each creature you control. You gain 4 life. | SubAbility$ DBGainLife SVar:DBGainLife:DB$ GainLife | LifeAmount$ 4 -SVar:Misfortune:DB$ PutCounterAll | ValidCards$ Creature.ChosenCtrl | CounterType$ M1M1 | CounterNum$ 1 | SubAbility$ DBLoseLife | SpellDescription$ You put a -1/-1 counter on each creature that player controls and CARDNAME deals 4 damage to that player. | SubAbility$ DBDamage -SVar:DBDamage:DB$ DealDamage | Defined$ ChosenPlayer | NumDmg$ 4 +SVar:Misfortune:DB$ PutCounterAll | ValidCards$ Creature.ControlledBy ChoosingPlayer | CounterType$ M1M1 | CounterNum$ 1 | SubAbility$ DBLoseLife | SpellDescription$ You put a -1/-1 counter on each creature that player controls and CARDNAME deals 4 damage to that player. | SubAbility$ DBDamage +SVar:DBDamage:DB$ DealDamage | Defined$ ChoosingPlayer | NumDmg$ 4 SVar:ChooserDraws:DB$ Draw | NumCards$ 3 | Defined$ ChosenPlayer Oracle:An opponent chooses one —\n• You put a +1/+1 counter on each creature you control and gain 4 life.\n• You put a -1/-1 counter on each creature that player controls and Misfortune deals 4 damage to that player. diff --git a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java index 83d9918c5d4..2eded9202f1 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java +++ b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java @@ -74,11 +74,13 @@ public final boolean playAbility(final boolean mayChooseTargets, final boolean i if ("X".equals(ability.getParam("CharmNum"))) { // CR 601.4 if (!announceValuesLikeX()) { + game.clearTopLibsCast(ability); return false; } needX = false; } if (!CharmEffect.makeChoices(ability)) { + game.clearTopLibsCast(ability); // 603.3c If no mode is chosen, the ability is removed from the stack. return false; } From aa27ea8888a23efb017f3acdb41c11f2705c31b7 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Mon, 8 Jan 2024 07:13:03 +0100 Subject: [PATCH 3/4] alchemy draft (#4479) --- forge-gui/res/blockdata/blocks.txt | 4 +++- forge-gui/res/editions/Alchemy Eldraine.txt | 1 + forge-gui/res/editions/Alchemy Ixalan.txt | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/forge-gui/res/blockdata/blocks.txt b/forge-gui/res/blockdata/blocks.txt index 394c83ccc15..c5e127216d4 100644 --- a/forge-gui/res/blockdata/blocks.txt +++ b/forge-gui/res/blockdata/blocks.txt @@ -126,4 +126,6 @@ March of the Machine Jumpstart, -/2/MOM, Meta-Choose(S(MOM Brood 1)Brood 1;S(MOM The Lord of the Rings: Tales of Middle-earth, 3/6/LTR, LTR The Lord of the Rings: Tales of Middle-earth Jumpstart, -/2/LTR, Meta-Choose(S(LTR Courageous 1)Courageous 1;S(LTR Courageous 2)Courageous 2;S(LTR Tricksy 1)Tricksy 1;S(LTR Tricksy 2)Tricksy 2;S(LTR Mordor 1)Mordor 1;S(LTR Mordor 2)Mordor 1;S(LTR Marauders 1)Marauders 1;S(LTR Marauders 2)Marauders 1;S(LTR Journey 1)Journey 1;S(LTR Journey 2)Journey 2)Themes Wilds of Eldraine, 3/6/WOE, WOE -The Lost Caverns of Ixalan, 3/6/LCI, LCI \ No newline at end of file +Alchemy: Eldraine,3/6/WOE, YWOE +The Lost Caverns of Ixalan, 3/6/LCI, LCI +Alchemy: Ixalan,3/6/LCI, YLCI \ No newline at end of file diff --git a/forge-gui/res/editions/Alchemy Eldraine.txt b/forge-gui/res/editions/Alchemy Eldraine.txt index 4b096f5e46a..c54002b3cda 100644 --- a/forge-gui/res/editions/Alchemy Eldraine.txt +++ b/forge-gui/res/editions/Alchemy Eldraine.txt @@ -3,6 +3,7 @@ Code=YWOE Date=2023-10-10 Name=Alchemy: Eldraine Type=Online +Booster=1 UncommonRareMythic,8 Common:fromsheet("WOE cards"), 3 Uncommon:fromSheet("WOE cards"), 1 UncommonRareMythic:fromSheet("WOT cards"), 1 RareMythic:fromSheet("WOE cards"), 1 BasicLand:fromSheet("WOE cards") ScryfallCode=YWOE [cards] diff --git a/forge-gui/res/editions/Alchemy Ixalan.txt b/forge-gui/res/editions/Alchemy Ixalan.txt index 764b4a60d65..b36090a1315 100644 --- a/forge-gui/res/editions/Alchemy Ixalan.txt +++ b/forge-gui/res/editions/Alchemy Ixalan.txt @@ -3,6 +3,7 @@ Code=YLCI Date=2023-12-05 Name=Alchemy: Ixalan Type=Online +Booster=1 UncommonRareMythic,8 Common:!dfc:!fromSheet("LCI lands"):fromsheet("LCI cards"), 3 Uncommon:!dfc:!fromSheet("LCI lands"):fromSheet("LCI cards"), 1 fromSheet("LCI double-face"), 1 RareMythic:fromSheet("LCI cards"), 1 fromSheet("LCI lands") ScryfallCode=YLCI [cards] From dccfee646f04663f9c878b2cf70ca0a4d84cc7d0 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Mon, 8 Jan 2024 07:13:36 +0100 Subject: [PATCH 4/4] WHO 5 cards with Villainous Choice (#4450) * update * cleanup * improvements * update * update * Update genesis_of_the_daleks.txt * Update midnight_crusader_shuttle.txt --- .../res/cardsfolder/e/ensnared_by_the_mara.txt | 11 +++++++++++ .../res/cardsfolder/g/genesis_of_the_daleks.txt | 14 ++++++++++++++ .../res/cardsfolder/h/hunted_by_the_family.txt | 10 ++++++++++ .../cardsfolder/m/midnight_crusader_shuttle.txt | 15 +++++++++++++++ forge-gui/res/cardsfolder/m/missy.txt | 14 ++++++++++++++ 5 files changed, 64 insertions(+) create mode 100644 forge-gui/res/cardsfolder/e/ensnared_by_the_mara.txt create mode 100644 forge-gui/res/cardsfolder/g/genesis_of_the_daleks.txt create mode 100644 forge-gui/res/cardsfolder/h/hunted_by_the_family.txt create mode 100644 forge-gui/res/cardsfolder/m/midnight_crusader_shuttle.txt create mode 100644 forge-gui/res/cardsfolder/m/missy.txt diff --git a/forge-gui/res/cardsfolder/e/ensnared_by_the_mara.txt b/forge-gui/res/cardsfolder/e/ensnared_by_the_mara.txt new file mode 100644 index 00000000000..cadb07851df --- /dev/null +++ b/forge-gui/res/cardsfolder/e/ensnared_by_the_mara.txt @@ -0,0 +1,11 @@ +Name:Ensnared by the Mara +ManaCost:2 R R +Types:Sorcery +A:SP$ VillainousChoice | Defined$ Opponent | Choices$ DBDig,DBDamage | SpellDescription$ Each opponent faces a villainous choice — They exile cards from the top of their library until they exile a nonland card, then you may cast that card without paying its mana cost, or that player exiles the top four cards of their library and CARDNAME deals damage equal to the total mana value of those exiled cards to that player. +SVar:DBDig:DB$ DigUntil | Defined$ Remembered | Valid$ Card.nonLand | FoundDestination$ Exile | RevealedDestination$ Exile | RememberFound$ True | SubAbility$ DBPlay | SpellDescription$ They exile cards from the top of their library until they exile a nonland card, then you may cast that card without paying its mana cost. +SVar:DBPlay:DB$ Play | Controller$ You | Defined$ Remembered | WithoutManaCost$ True | ValidSA$ Spell | Optional$ True | Amount$ All | SubAbility$ DBCleanup +SVar:DBDamage:DB$ Dig | RememberChanged$ True | DestinationZone$ Exile | Defined$ Remembered | DigNum$ 4 | ChangeNum$ All | SubAbility$ DamageOpponent | SpellDescription$ That player exiles the top four cards of their library and CARDNAME deals damage equal to the total mana value of those exiled cards to that player. +SVar:DamageOpponent:DB$ DealDamage | Defined$ Remembered | NumDmg$ X | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:X:Remembered$SumCMC +Oracle:Each opponent faces a villainous choice — They exile cards from the top of their library until they exile a nonland card, then you may cast that card without paying its mana cost, or that player exiles the top four cards of their library and Ensnared by the Mara deals damage equal to the total mana value of those exiled cards to that player. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/g/genesis_of_the_daleks.txt b/forge-gui/res/cardsfolder/g/genesis_of_the_daleks.txt new file mode 100644 index 00000000000..381ad6c8814 --- /dev/null +++ b/forge-gui/res/cardsfolder/g/genesis_of_the_daleks.txt @@ -0,0 +1,14 @@ +Name:Genesis of the Daleks +ManaCost:4 B B +Types:Enchantment Saga +K:Chapter:4:DBToken,DBToken,DBToken,DBVillainous +SVar:DBToken:DB$ Token | TokenAmount$ X | TokenScript$ b_3_3_a_dalek_menace | SpellDescription$ Create a 3/3 black Dalek artifact creature token with menace for each lore counter on CARDNAME. +SVar:DBVillainous:DB$ VillainousChoice | Choices$ DBDestroyDalek,DBDestroyNonDalek | ValidTgts$ Opponent | SpellDescription$ Target opponent faces a villainous choice — Destroy all Dalek creatures and each of your opponents loses life equal to the total power of Daleks that died this turn, or destroy all non-Dalek creatures. +SVar:DBDestroyDalek:DB$ DestroyAll | ValidCards$ Creature.Dalek | SubAbility$ DBLoseLife | SpellDescription$ Destroy all Dalek creatures and each of your opponents loses life equal to the total power of Daleks that died this turn. +SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ Y | Defined$ Opponent +SVar:DBDestroyNonDalek:DB$ DestroyAll | ValidCards$ Creature.nonDalek | SpellDescription$ Destroy all non-Dalek creatures. +SVar:X:Count$CardCounters.LORE +SVar:Y:Count$ThisTurnEntered_Graveyard_from_Battlefield_Dalek$CardPower +DeckHas:Ability$Token & Type$Artifact|Dalek +DeckHints:Type$Dalek +Oracle:(As this Saga enters and after your draw step, add a lore counter. Sacrifice after IV.)\nI, II, III — Create a 3/3 black Dalek artifact creature token with menace for each lore counter on Genesis of the Daleks.\nIV — Target opponent faces a villainous choice — Destroy all Dalek creatures and each of your opponents loses life equal to the total power of Daleks that died this turn, or destroy all non-Dalek creatures. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/h/hunted_by_the_family.txt b/forge-gui/res/cardsfolder/h/hunted_by_the_family.txt new file mode 100644 index 00000000000..8378afd513c --- /dev/null +++ b/forge-gui/res/cardsfolder/h/hunted_by_the_family.txt @@ -0,0 +1,10 @@ +Name:Hunted by The Family +ManaCost:5 U U +Types:Sorcery +A:SP$ ChooseCard | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Select up to four target creatures you don't control | TargetMin$ 0 | TargetMax$ 4 | SubAbility$ DBRepeat | SpellDescription$ Choose up to four target creatures you don't control. For each of them, that creature's controller faces a villainous choice — That creature becomes a 1/1 white Human creature and loses all abilities, or you create a token that's a copy of it. +SVar:DBRepeat:DB$ RepeatEach | RepeatSubAbility$ DBChoice | DefinedCards$ Targeted +SVar:DBChoice:DB$ VillainousChoice | Defined$ RememberedController | Choices$ DBAnimate,DBCopy +SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Power$ 1 | Toughness$ 1 | Types$ Creature,Human | RemoveCreatureTypes$ True | RemoveCardTypes$ True | RemoveAllAbilities$ True | IsCurse$ True | Colors$ White | OverwriteColors$ True | Duration$ Permanent | SpellDescription$ That creature becomes a 1/1 white Human creature and loses all abilities. +SVar:DBCopy:DB$ CopyPermanent | Defined$ Remembered | SpellDescription$ You create a token that's a copy of it. +DeckHas:Ability$Token & Type$Human +Oracle:Choose up to four target creatures you don't control. For each of them, that creature's controller faces a villainous choice — That creature becomes a 1/1 white Human creature and loses all abilities, or you create a token that's a copy of it. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/m/midnight_crusader_shuttle.txt b/forge-gui/res/cardsfolder/m/midnight_crusader_shuttle.txt new file mode 100644 index 00000000000..75835494a1f --- /dev/null +++ b/forge-gui/res/cardsfolder/m/midnight_crusader_shuttle.txt @@ -0,0 +1,15 @@ +Name:Midnight Crusader Shuttle +ManaCost:4 +Types:Artifact Vehicle +PT:3/4 +T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigVillainousChoice | TriggerDescription$ Midnight Entity — Whenever CARDNAME attacks, defending player faces a villainous choice — That player sacrifices a creature, or you gain control of a creature of your choice that player controls until end of turn. If you gain control of a creature this way, tap it, and it's attacking that player. +SVar:TrigVillainousChoice:DB$ VillainousChoice | Defined$ TriggeredDefendingPlayer | Choices$ DBSacrifice,DBGainControl +SVar:DBSacrifice:DB$ Sacrifice | Amount$ 1 | SacValid$ Creature | Defined$ Remembered | SpellDescription$ That player sacrifices a creature. +SVar:DBGainControl:DB$ GainControl | Defined$ ChosenCard | Choices$ Creature.RememberedPlayerCtrl | ChoiceTitle$ Select a creature that player controls | NewController$ You | LoseControl$ EOT | RememberControlled$ True | SubAbility$ DBTap | SpellDescription$ You gain control of a creature of your choice that player controls until end of turn. If you gain control of a creature this way, tap it, and it's attacking that player. +SVar:DBTap:DB$ Tap | Defined$ Remembered | ConditionDefined$ Remembered | ConditionPresent$ Card.YouCtrl | SubAbility$ DBSetAttacking +SVar:DBSetAttacking:DB$ ChangeCombatants | Defined$ Remembered | ConditionDefined$ Remembered | ConditionPresent$ Card.YouCtrl | Attacking$ RememberedPlayer | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +K:Crew:2 +SVar:HasAttackEffect:True +DeckHas:Ability$Sacrifice +Oracle:Midnight Entity — Whenever Midnight Crusader Shuttle attacks, defending player faces a villainous choice — That player sacrifices a creature, or you gain control of a creature of your choice that player controls until end of turn. If you gain control of a creature this way, tap it, and it's attacking that player.\nCrew 2 \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/m/missy.txt b/forge-gui/res/cardsfolder/m/missy.txt new file mode 100644 index 00000000000..8df40209126 --- /dev/null +++ b/forge-gui/res/cardsfolder/m/missy.txt @@ -0,0 +1,14 @@ +Name:Missy +ManaCost:3 U B R +Types:Legendary Creature Time Lord Rogue +PT:4/5 +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.nonArtifact+Other | TriggerZones$ Battlefield | Execute$ TrigChangeZone | TriggerDescription$ Whenever another nonartifact creature dies, return it to the battlefield under your control face down and tapped. It's a 2/2 Cyberman artifact creature. +SVar:TrigChangeZone:DB$ ChangeZone | Defined$ TriggeredCard | GainControl$ True | FaceDown$ True | Origin$ Graveyard | Destination$ Battlefield | Tapped$ True | FaceDownSetType$ Artifact & Creature & Cyberman | FaceDownPower$ 2 | FaceDownToughness$ 2 +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ VillainousChoice | TriggerDescription$ At the beginning of your end step, each opponent faces a villainous choice — Each artifact creature you control deals 1 damage to that opponent, or you draw a card and chaos ensues. +SVar:VillainousChoice:DB$ VillainousChoice | Defined$ Opponent | Choices$ DBDamage,DBDraw +SVar:DBDamage:DB$ DealDamage | NumDmg$ 1 | DamageSource$ Valid Artifact.Creature+YouCtrl | Defined$ Remembered | SpellDescription$ Each artifact creature you control deals 1 damage to that opponent +SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 1 | SubAbility$ DBChaos | SpellDescription$ You draw a card and chaos ensues. +SVar:DBChaos:DB$ ChaosEnsues +DeckHints:Type$Artifact +DeckHas:Type$Cyberman +Oracle:Whenever another nonartifact creature dies, return it to the battlefield under your control face down and tapped. It's a 2/2 Cyberman artifact creature.\nAt the beginning of your end step, each opponent faces a villainous choice — Each artifact creature you control deals 1 damage to that opponent, or you draw a card and chaos ensues. \ No newline at end of file