From cd3d7278182b2151b9d4fd651879f4dc0b4f6332 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 21 Jan 2025 21:43:26 +0100 Subject: [PATCH 01/17] AnimateSubAbility rework --- .../src/main/java/forge/game/GameAction.java | 37 +++++++++++++++++++ .../game/ability/SpellAbilityEffect.java | 10 +++-- .../ability/effects/ChangeZoneEffect.java | 12 ++++-- .../res/cardsfolder/d/dance_of_the_manse.txt | 4 +- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 2cb7b0196e1..f0e4e044418 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -29,6 +29,7 @@ import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; +import forge.game.ability.SpellAbilityEffect; import forge.game.card.*; import forge.game.event.*; import forge.game.extrahands.BackupPlanService; @@ -588,6 +589,8 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer } } + handleStaticEffect(copied, cause); + if (!table.isEmpty()) { // we don't want always trigger before counters are placed game.getTriggerHandler().suppressMode(TriggerType.Always); @@ -725,6 +728,40 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer return copied; } + private void handleStaticEffect(Card copied, SpellAbility cause) { + if (cause != null && cause.hasParam("StaticEffect") && copied.isPermanent()) { + final Card source = cause.getHostCard(); + if (cause.hasParam("StaticEffectCheckSVar")) { + String cmp = cause.getParamOrDefault("StaticEffectSVarCompare$", "GE1"); + int lhs = AbilityUtils.calculateAmount(source, cause.getParam("StaticEffectCheckSVar"), cause); + int rhs = AbilityUtils.calculateAmount(source, cmp.substring(2), cause); + if (!Expressions.compare(lhs, cmp, rhs)) { + return; + } + } + + Integer timestamp = cause.getSVarInt("StaticEffectTimestamp"); + String name = "Static Effect #" + timestamp; + // check if this isn't the first card being moved + Optional opt = IterableUtil.tryFind(cause.getActivatingPlayer().getZone(ZoneType.Command).getCards(), CardPredicates.nameEquals(name)); + + Card eff; + if (opt.isPresent()) { + eff = opt.get(); + } else { + // otherwise create effect first + eff = SpellAbilityEffect.createEffect(cause, cause.getActivatingPlayer(), name, source.getImageKey(), timestamp); + eff.setRenderForUI(false); + StaticAbility stAb = eff.addStaticAbility(AbilityUtils.getSVar(cause, cause.getParam("StaticEffect"))); + stAb.putParam("EffectZone", "Command"); + SpellAbilityEffect.addForgetOnMovedTrigger(copied, "Battlefield"); + game.getAction().moveToCommand(eff, cause); + } + + eff.addRemembered(copied); + } + } + private void storeChangesZoneAll(Card c, Zone zoneFrom, Zone zoneTo, Map params) { if (params != null && params.containsKey(AbilityKey.InternalTriggerTable)) { ((CardZoneTable) params.get(AbilityKey.InternalTriggerTable)).put(zoneFrom != null ? zoneFrom.getZoneType() : null, zoneTo.getZoneType(), c); diff --git a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java index 4eeaaca593e..4868d5ec6ac 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -585,14 +585,16 @@ protected static void addLeaveBattlefieldReplacement(final Card eff, final Strin eff.addReplacementEffect(re); } - // create a basic template for Effect to be used somewhere else - public static Card createEffect(final SpellAbility sa, final Player controller, final String name, - final String image) { + // create a basic template for Effect to be used somewhere els + public static Card createEffect(final SpellAbility sa, final Player controller, final String name, final String image) { + return createEffect(sa, controller, name, image, controller.getGame().getNextTimestamp()); + } + public static Card createEffect(final SpellAbility sa, final Player controller, final String name, final String image, final long timestamp) { final Card hostCard = sa.getHostCard(); final Game game = hostCard.getGame(); final Card eff = new Card(game.nextCardId(), game); - eff.setGameTimestamp(game.getNextTimestamp()); + eff.setGameTimestamp(timestamp); eff.setName(name); eff.setColor(hostCard.getColor().getColor()); // if name includes emblem then it should be one diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index 30b848d1d07..fc30eccc39b 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -521,14 +521,18 @@ private void changeKnownOriginResolve(final SpellAbility sa) { final CardCollection random = new CardCollection(tgtCards); CardLists.shuffle(random); tgtCards = random; + } else if (sa.hasParam("Chooser")) { + tgtCards = chooser.getController().orderMoveToZoneList(tgtCards, destination, sa); } else { - if (sa.hasParam("Chooser")) - tgtCards = chooser.getController().orderMoveToZoneList(tgtCards, destination, sa); - else - tgtCards = GameActionUtil.orderCardsByTheirOwners(game, tgtCards, destination, sa); + tgtCards = GameActionUtil.orderCardsByTheirOwners(game, tgtCards, destination, sa); } } + // if the player didn't order the effect above use default + if (sa.hasParam("StaticEffect") && !sa.hasSVar("StaticEffectTimestamp")) { + sa.setSVar("StaticEffectTimestamp", String.valueOf(game.getNextTimestamp())); + } + for (final Card tgtC : tgtCards) { final Card gameCard = game.getCardState(tgtC, null); // gameCard is LKI in that case, the card is not in game anymore diff --git a/forge-gui/res/cardsfolder/d/dance_of_the_manse.txt b/forge-gui/res/cardsfolder/d/dance_of_the_manse.txt index de6d1a84d25..827109bb9e4 100644 --- a/forge-gui/res/cardsfolder/d/dance_of_the_manse.txt +++ b/forge-gui/res/cardsfolder/d/dance_of_the_manse.txt @@ -1,8 +1,8 @@ Name:Dance of the Manse ManaCost:X W U Types:Sorcery -A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Artifact.cmcLEX+YouOwn,Enchantment.cmcLEX+YouOwn+nonAura | TgtPrompt$ Select target artifact or non-Aura enchantment in your graveyard | TargetMin$ 0 | TargetMax$ X | AnimateSubAbility$ DBAnimate | SpellDescription$ Return up to X target artifact and/or non-Aura enchantment cards with mana value X or less from your graveyard to the battlefield. If X is 6 or more, those permanents are 4/4 creatures in addition to their other types. -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Creature | Power$ 4 | Toughness$ 4 | Duration$ Permanent | ConditionCheckSVar$ X | ConditionSVarCompare$ GE6 +A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Artifact.cmcLEX+YouOwn,Enchantment.cmcLEX+YouOwn+nonAura | TgtPrompt$ Select target artifact or non-Aura enchantment in your graveyard | TargetMin$ 0 | TargetMax$ X | StaticEffect$ Animate | StaticEffectCheckSVar$ X | StaticEffectSVarCompare$ GE6 | SpellDescription$ Return up to X target artifact and/or non-Aura enchantment cards with mana value X or less from your graveyard to the battlefield. If X is 6 or more, those permanents are 4/4 creatures in addition to their other types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Creature | SetPower$ 4 | SetToughness$ 4 SVar:X:Count$xPaid AI:RemoveDeck:All Oracle:Return up to X target artifact and/or non-Aura enchantment cards each with mana value X or less from your graveyard to the battlefield. If X is 6 or more, those permanents are 4/4 creatures in addition to their other types. From 66028d39cb3b673d7481d65ea70aec0b0f432696 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 21 Jan 2025 21:49:05 +0100 Subject: [PATCH 02/17] Remove old fix code, it will no longer be needed --- .../src/main/java/forge/game/GameAction.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index f0e4e044418..df0a36eeaa7 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -150,7 +150,6 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer if (!found) { c.clearControllers(); if (cause != null) { - unanimateOnAbortedChange(cause, c); } return c; } @@ -362,7 +361,6 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer if (repres == ReplacementResult.Prevented) { c.clearControllers(); if (cause != null) { - unanimateOnAbortedChange(cause, c); if (cause.hasParam("Transformed") || cause.hasParam("FaceDown")) { c.setBackSide(false); c.changeToState(CardStateName.Original); @@ -2706,19 +2704,6 @@ public static boolean attachAuraOnIndirectEnterBattlefield(final Card source, Ma return false; } - private static void unanimateOnAbortedChange(final SpellAbility cause, final Card c) { - if (cause.hasParam("AnimateSubAbility")) { - long unanimateTimestamp = Long.parseLong(cause.getAdditionalAbility("AnimateSubAbility").getSVar("unanimateTimestamp")); - c.removeChangedCardKeywords(unanimateTimestamp, 0); - c.removeChangedCardTypes(unanimateTimestamp, 0); - c.removeChangedName(unanimateTimestamp, 0); - c.removeNewPT(unanimateTimestamp, 0); - if (c.removeChangedCardTraits(unanimateTimestamp, 0)) { - c.updateStateForView(); - } - } - } - public CardCollectionView getLastState(final AbilityKey key, final SpellAbility cause, final Map params, final boolean refreshIfEmpty) { CardCollectionView lastState = null; if (params != null) { From b0a6d2d6cb268019a3d6094aa6b6b8cf5536a5c3 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 21 Jan 2025 22:31:45 +0100 Subject: [PATCH 03/17] Add zone ordering --- .../main/java/forge/game/GameActionUtil.java | 22 ++++++++++++++++++- .../ability/effects/ChangeZoneEffect.java | 7 +++++- .../forge/game/player/PlayerController.java | 2 +- .../java/forge/screens/match/CMatchUI.java | 1 + .../forge/screens/match/MatchController.java | 1 + 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index 0873567a008..8863bcc4921 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -26,6 +26,7 @@ import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.ability.SpellAbilityEffect; +import forge.game.ability.effects.DetachedCardEffect; import forge.game.card.*; import forge.game.card.CardPlayOption.PayManaCost; import forge.game.cost.Cost; @@ -34,6 +35,7 @@ import forge.game.player.Player; import forge.game.player.PlayerCollection; import forge.game.player.PlayerController; +import forge.game.player.PlayerController.FullControlFlag; import forge.game.replacement.ReplacementEffect; import forge.game.replacement.ReplacementHandler; import forge.game.replacement.ReplacementLayer; @@ -835,9 +837,11 @@ public static String generatedMana(final SpellAbility sa) { } public static CardCollectionView orderCardsByTheirOwners(Game game, CardCollectionView list, ZoneType dest, SpellAbility sa) { - if (list.size() <= 1) { + if (list.size() <= 1 && + (sa == null || !sa.getActivatingPlayer().getController().isFullControl(FullControlFlag.LayerTimestampOrder))) { return list; } + Card eff = null; CardCollection completeList = new CardCollection(); // CR 613.7m use APNAP PlayerCollection players = game.getPlayersInTurnOrder(game.getPhaseHandler().getPlayerTurn()); @@ -853,12 +857,28 @@ public static CardCollectionView orderCardsByTheirOwners(Game game, CardCollecti subList.add(c); } } + if (sa.getActivatingPlayer() == p && sa.hasParam("StaticEffect")) { + String name = "Static Effect of " + sa.getHostCard(); + // create helper card for ordering + eff = new DetachedCardEffect(sa.getHostCard(), name); + subList.add(eff); + } CardCollectionView subListView = subList; if (subList.size() > 1) { subListView = p.getController().orderMoveToZoneList(subList, dest, sa); } completeList.addAll(subListView); } + if (eff != null) { + int idx = completeList.indexOf(eff); + // add generous buffer to timestamp, to ensure it applies last compared to cards that were ordered to ETB before it + sa.setSVar("StaticEffectTimestamp", String.valueOf(game.getTimestamp() + idx + 100)); + // effects with this param have the responsibility to realign it when later cards are reached + if (idx < completeList.size() - 1) { + sa.setSVar("StaticEffectUntilCardID", String.valueOf(completeList.get(idx + 1).getId())); + } + completeList.remove(eff); + } return completeList; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index fc30eccc39b..8cce4d5840a 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -13,6 +13,7 @@ import forge.game.event.GameEventCombatChanged; import forge.game.keyword.Keyword; import forge.game.player.*; +import forge.game.player.PlayerController.FullControlFlag; import forge.game.replacement.ReplacementEffect; import forge.game.replacement.ReplacementType; import forge.game.spellability.SpellAbility; @@ -516,7 +517,7 @@ private void changeKnownOriginResolve(final SpellAbility sa) { } // CR 401.4 - if (destination.isDeck() && !shuffle && tgtCards.size() > 1) { + if (((destination.isDeck() && tgtCards.size() > 1) || chooser.getController().isFullControl(FullControlFlag.LayerTimestampOrder)) && !shuffle) { if (sa.hasParam("RandomOrder")) { final CardCollection random = new CardCollection(tgtCards); CardLists.shuffle(random); @@ -534,6 +535,10 @@ private void changeKnownOriginResolve(final SpellAbility sa) { } for (final Card tgtC : tgtCards) { + if (sa.hasSVar("StaticEffectUntilCardID") && sa.getSVarInt("StaticEffectUntilCardID") == tgtC.getId()) { + sa.setSVar("StaticEffectTimestamp", String.valueOf(game.getNextTimestamp())); + } + final Card gameCard = game.getCardState(tgtC, null); // gameCard is LKI in that case, the card is not in game anymore // or the timestamp did change diff --git a/forge-game/src/main/java/forge/game/player/PlayerController.java b/forge-game/src/main/java/forge/game/player/PlayerController.java index 2d33809788c..1c14e10bae6 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -65,7 +65,7 @@ public enum FullControlFlag { NoPaymentFromManaAbility, NoFreeCombatCostHandling, AllowPaymentStartWithMissingResources, - //AdditionalLayerTimestampOrder // tokens etc. + LayerTimestampOrder // for StaticEffect$, tokens later etc. } private Set fullControls = EnumSet.noneOf(FullControlFlag.class); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java index b79a74e2469..92f77001077 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java @@ -1516,6 +1516,7 @@ public void showFullControl(PlayerView pv, MouseEvent e) { addFullControlEntry(menu, "lblNoPaymentFromManaAbility", FullControlFlag.NoPaymentFromManaAbility, controlFlags); addFullControlEntry(menu, "lblNoFreeCombatCostHandling", FullControlFlag.NoFreeCombatCostHandling, controlFlags); addFullControlEntry(menu, "lblAllowPaymentStartWithMissingResources", FullControlFlag.AllowPaymentStartWithMissingResources, controlFlags); + addFullControlEntry(menu, "lblLayerTimestampOrder", FullControlFlag.LayerTimestampOrder, controlFlags); menu.show(view.getControl().getFieldViewFor(pv).getAvatarArea(), e.getX(), e.getY()); } diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index 85e37268fd4..50f009d0608 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -757,6 +757,7 @@ protected void buildMenu() { addItem(getFullControlMenuEntry("lblNoPaymentFromManaAbility", FullControlFlag.NoPaymentFromManaAbility, controlFlags)); addItem(getFullControlMenuEntry("lblNoFreeCombatCostHandling", FullControlFlag.NoFreeCombatCostHandling, controlFlags)); addItem(getFullControlMenuEntry("lblAllowPaymentStartWithMissingResources", FullControlFlag.AllowPaymentStartWithMissingResources, controlFlags)); + addItem(getFullControlMenuEntry("lblLayerTimestampOrder", FullControlFlag.LayerTimestampOrder, controlFlags)); } }; From 278d72f8123a84b422204b8605ee16038a3f4b59 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 21 Jan 2025 22:37:49 +0100 Subject: [PATCH 04/17] Add labels --- forge-gui/res/languages/de-DE.properties | 1 + forge-gui/res/languages/en-US.properties | 1 + forge-gui/res/languages/es-ES.properties | 1 + forge-gui/res/languages/fr-FR.properties | 1 + forge-gui/res/languages/it-IT.properties | 1 + forge-gui/res/languages/ja-JP.properties | 1 + forge-gui/res/languages/pt-BR.properties | 1 + forge-gui/res/languages/zh-CN.properties | 1 + 8 files changed, 8 insertions(+) diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 98a7851dff6..0f46a6f71cd 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -1278,6 +1278,7 @@ lblChooseCostReductionOrder=Choose cost reduction order & amount lblNoPaymentFromManaAbility=Don\'t attempt paying when generating mana lblNoFreeCombatCostHandling=Don\'t accept attack/block costs of \{0\} lblAllowPaymentStartWithMissingResources=Allow payment start when cost seems unaffordable +lblLayerTimestampOrder=Finetune layer timestamp order lblOrderCosts=Order costs lblPayFirst=Pay first lblYouHaveWonTheCoinToss={0}, du hast den Münzwurf gewonnen. diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 70a8b9a7e21..69a0bba0633 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -1298,6 +1298,7 @@ lblChooseCostReductionOrder=Choose cost reduction order & amount lblNoPaymentFromManaAbility=Don\'t attempt paying when generating mana lblNoFreeCombatCostHandling=Don\'t accept attack/block costs of \{0\} lblAllowPaymentStartWithMissingResources=Allow payment start when cost seems unaffordable +lblLayerTimestampOrder=Finetune layer timestamp order lblOrderCosts=Order costs lblPayFirst=Pay first lblYouHaveWonTheCoinToss={0}, you have won the coin toss. diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index d95834d62a4..8b232fd6d05 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -1288,6 +1288,7 @@ lblChooseCostReductionOrder=Choose cost reduction order & amount lblNoPaymentFromManaAbility=Don\'t attempt paying when generating mana lblNoFreeCombatCostHandling=Don\'t accept attack/block costs of \{0\} lblAllowPaymentStartWithMissingResources=Allow payment start when cost seems unaffordable +lblLayerTimestampOrder=Finetune layer timestamp order lblOrderCosts=Order costs lblPayFirst=Pay first lblYouHaveWonTheCoinToss={0}, has ganado el lanzamiento de la moneda. diff --git a/forge-gui/res/languages/fr-FR.properties b/forge-gui/res/languages/fr-FR.properties index de2bba806bd..c4845bb341b 100644 --- a/forge-gui/res/languages/fr-FR.properties +++ b/forge-gui/res/languages/fr-FR.properties @@ -1282,6 +1282,7 @@ lblChooseCostReductionOrder=Choose cost reduction order & amount lblNoPaymentFromManaAbility=Don\'t attempt paying when generating mana lblNoFreeCombatCostHandling=Don\'t accept attack/block costs of \{0\} lblAllowPaymentStartWithMissingResources=Allow payment start when cost seems unaffordable +lblLayerTimestampOrder=Finetune layer timestamp order lblOrderCosts=Order costs lblPayFirst=Pay first lblYouHaveWonTheCoinToss={0}, vous avez gagné le tirage au sort. diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 094a3e8e48d..3cd6138d55b 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -1279,6 +1279,7 @@ lblChooseCostReductionOrder=Choose cost reduction order & amount lblNoPaymentFromManaAbility=Don\'t attempt paying when generating mana lblNoFreeCombatCostHandling=Don\'t accept attack/block costs of \{0\} lblAllowPaymentStartWithMissingResources=Allow payment start when cost seems unaffordable +lblLayerTimestampOrder=Finetune layer timestamp order lblOrderCosts=Order costs lblPayFirst=Pay first lblYouHaveWonTheCoinToss= %s, hai vinto il lancio della moneta. diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index a2de9e7aaf3..7a3d0ed01e5 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -1281,6 +1281,7 @@ lblChooseCostReductionOrder=Choose cost reduction order & amount lblNoPaymentFromManaAbility=Don\'t attempt paying when generating mana lblNoFreeCombatCostHandling=Don\'t accept attack/block costs of \{0\} lblAllowPaymentStartWithMissingResources=Allow payment start when cost seems unaffordable +lblLayerTimestampOrder=Finetune layer timestamp order lblOrderCosts=Order costs lblPayFirst=Pay first lblYouHaveWonTheCoinToss={0}、あなたはコイントスに勝ちました。 diff --git a/forge-gui/res/languages/pt-BR.properties b/forge-gui/res/languages/pt-BR.properties index b30effe0082..bb48930542a 100644 --- a/forge-gui/res/languages/pt-BR.properties +++ b/forge-gui/res/languages/pt-BR.properties @@ -1309,6 +1309,7 @@ lblChooseCostReductionOrder=Choose cost reduction order & amount lblNoPaymentFromManaAbility=Don\'t attempt paying when generating mana lblNoFreeCombatCostHandling=Don\'t accept attack/block costs of \{0\} lblAllowPaymentStartWithMissingResources=Allow payment start when cost seems unaffordable +lblLayerTimestampOrder=Finetune layer timestamp order lblOrderCosts=Order costs lblPayFirst=Pay first lblYouHaveWonTheCoinToss={0}, você ganhou na moeda. diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index d5b88a7c88f..da204ec94ac 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -1285,6 +1285,7 @@ lblChooseCostReductionOrder=Choose cost reduction order & amount lblNoPaymentFromManaAbility=Don\'t attempt paying when generating mana lblNoFreeCombatCostHandling=Don\'t accept attack/block costs of \{0\} lblAllowPaymentStartWithMissingResources=Allow payment start when cost seems unaffordable +lblLayerTimestampOrder=Finetune layer timestamp order lblOrderCosts=Order costs lblPayFirst=Pay first lblYouHaveWonTheCoinToss={0},你赢得了这次掷硬币。 From 2ef7d8955454e6c1255779c147749a98ec64aca6 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 21 Jan 2025 23:02:10 +0100 Subject: [PATCH 05/17] Clean up --- .../src/main/java/forge/game/GameAction.java | 14 +++++++-- .../main/java/forge/game/GameActionUtil.java | 9 +++--- .../ability/effects/ChangeZoneEffect.java | 30 +------------------ 3 files changed, 17 insertions(+), 36 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index df0a36eeaa7..cacae6bc4bb 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -738,14 +738,24 @@ private void handleStaticEffect(Card copied, SpellAbility cause) { } } - Integer timestamp = cause.getSVarInt("StaticEffectTimestamp"); - String name = "Static Effect #" + timestamp; + Long timestamp; + // check if player ordered it manually + if (cause.hasSVar("StaticEffectTimestamp")) { + timestamp = Long.parseLong(cause.getSVar("StaticEffectTimestamp")); + } else { + // else create default value (or realign) + timestamp = game.getNextTimestamp(); + cause.setSVar("StaticEffectTimestamp", String.valueOf(timestamp)); + } + String name = "Static Effect #" + source.getGameTimestamp(); // check if this isn't the first card being moved Optional opt = IterableUtil.tryFind(cause.getActivatingPlayer().getZone(ZoneType.Command).getCards(), CardPredicates.nameEquals(name)); Card eff; if (opt.isPresent()) { eff = opt.get(); + // update in case player manually ordered + eff.setLayerTimestamp(timestamp); } else { // otherwise create effect first eff = SpellAbilityEffect.createEffect(cause, cause.getActivatingPlayer(), name, source.getImageKey(), timestamp); diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index 8863bcc4921..cabd38eb56f 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -857,10 +857,9 @@ public static CardCollectionView orderCardsByTheirOwners(Game game, CardCollecti subList.add(c); } } - if (sa.getActivatingPlayer() == p && sa.hasParam("StaticEffect")) { - String name = "Static Effect of " + sa.getHostCard(); + if (sa != null && sa.getActivatingPlayer() == p && sa.hasParam("StaticEffect")) { // create helper card for ordering - eff = new DetachedCardEffect(sa.getHostCard(), name); + eff = new DetachedCardEffect(sa.getHostCard(), "Static Effect of " + sa.getHostCard()); subList.add(eff); } CardCollectionView subListView = subList; @@ -874,8 +873,8 @@ public static CardCollectionView orderCardsByTheirOwners(Game game, CardCollecti // add generous buffer to timestamp, to ensure it applies last compared to cards that were ordered to ETB before it sa.setSVar("StaticEffectTimestamp", String.valueOf(game.getTimestamp() + idx + 100)); // effects with this param have the responsibility to realign it when later cards are reached - if (idx < completeList.size() - 1) { - sa.setSVar("StaticEffectUntilCardID", String.valueOf(completeList.get(idx + 1).getId())); + if (idx > 0) { + sa.setSVar("StaticEffectUntilCardID", String.valueOf(completeList.get(idx - 1).getId())); } completeList.remove(eff); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index 8cce4d5840a..18669e277bc 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -529,14 +529,9 @@ private void changeKnownOriginResolve(final SpellAbility sa) { } } - // if the player didn't order the effect above use default - if (sa.hasParam("StaticEffect") && !sa.hasSVar("StaticEffectTimestamp")) { - sa.setSVar("StaticEffectTimestamp", String.valueOf(game.getNextTimestamp())); - } - for (final Card tgtC : tgtCards) { if (sa.hasSVar("StaticEffectUntilCardID") && sa.getSVarInt("StaticEffectUntilCardID") == tgtC.getId()) { - sa.setSVar("StaticEffectTimestamp", String.valueOf(game.getNextTimestamp())); + sa.removeSVar("StaticEffectTimestamp"); } final Card gameCard = game.getCardState(tgtC, null); @@ -661,19 +656,6 @@ private void changeKnownOriginResolve(final SpellAbility sa) { } } - if (sa.hasAdditionalAbility("AnimateSubAbility")) { - // need LKI before Animate does apply - if (!moveParams.containsKey(AbilityKey.CardLKI)) { - moveParams.put(AbilityKey.CardLKI, CardCopyService.getLKICopy(gameCard)); - } - - final SpellAbility animate = sa.getAdditionalAbility("AnimateSubAbility"); - hostCard.addRemembered(gameCard); - AbilityUtils.resolve(animate); - hostCard.removeRemembered(gameCard); - animate.setSVar("unanimateTimestamp", String.valueOf(game.getTimestamp())); - } - // need to be facedown before it hits the battlefield in case of Replacement Effects or Trigger if (sa.hasParam("FaceDown")) { gameCard.turnFaceDown(true); @@ -1286,16 +1268,6 @@ else if (destination.equals(ZoneType.Battlefield)) { if (sa.hasParam("Tapped")) { c.setTapped(true); } - if (sa.hasAdditionalAbility("AnimateSubAbility")) { - // need LKI before Animate does apply - moveParams.put(AbilityKey.CardLKI, CardCopyService.getLKICopy(c)); - - final SpellAbility animate = sa.getAdditionalAbility("AnimateSubAbility"); - source.addRemembered(c); - AbilityUtils.resolve(animate); - source.removeRemembered(c); - animate.setSVar("unanimateTimestamp", String.valueOf(game.getTimestamp())); - } if (sa.hasParam("GainControl")) { final String g = sa.getParam("GainControl"); Player newController = g.equals("True") ? sa.getActivatingPlayer() : From 58e5ee4f2d8d8e16e5db4484304a488bca2634fc Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 21 Jan 2025 23:55:22 +0100 Subject: [PATCH 06/17] Fix test --- forge-gui/res/cardsfolder/e/ever_after.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/e/ever_after.txt b/forge-gui/res/cardsfolder/e/ever_after.txt index 4c24a134eda..fb4c9476c4d 100644 --- a/forge-gui/res/cardsfolder/e/ever_after.txt +++ b/forge-gui/res/cardsfolder/e/ever_after.txt @@ -1,8 +1,8 @@ Name:Ever After ManaCost:4 B B Types:Sorcery -A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose target creature card in your graveyard | ValidTgts$ Creature.YouOwn | TargetMin$ 0 | TargetMax$ 2 | AnimateSubAbility$ Animate | SubAbility$ DBPut | SpellDescription$ Return up to two target creature cards from your graveyard onto the battlefield. -SVar:Animate:DB$ Animate | Defined$ Remembered | Types$ Zombie | Colors$ Black | Duration$ Permanent | SpellDescription$ Each of those creatures is a black Zombie in addition to its other colors and types. +A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose target creature card in your graveyard | ValidTgts$ Creature.YouOwn | TargetMin$ 0 | TargetMax$ 2 | StaticEffect$ Animate | SubAbility$ DBPut | SpellDescription$ Return up to two target creature cards from your graveyard onto the battlefield. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Zombie | AddColor$ Black SVar:DBPut:DB$ ChangeZone | Defined$ Parent | Origin$ Stack | Destination$ Library | LibraryPosition$ -1 | SpellDescription$ Put CARDNAME on the bottom of its owner's library. DeckHints:Ability$Graveyard|Discard & Type$Zombie Oracle:Return up to two target creature cards from your graveyard to the battlefield. Each of those creatures is a black Zombie in addition to its other colors and types. Put Ever After on the bottom of its owner's library. From 29a0c3dd99c7ae56cd4b8bec94879e02bbeb8283 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 22 Jan 2025 00:13:30 +0100 Subject: [PATCH 07/17] Tweak logic --- forge-game/src/main/java/forge/game/GameActionUtil.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index cabd38eb56f..89662c228ab 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -870,12 +870,13 @@ public static CardCollectionView orderCardsByTheirOwners(Game game, CardCollecti } if (eff != null) { int idx = completeList.indexOf(eff); - // add generous buffer to timestamp, to ensure it applies last compared to cards that were ordered to ETB before it - sa.setSVar("StaticEffectTimestamp", String.valueOf(game.getTimestamp() + idx + 100)); - // effects with this param have the responsibility to realign it when later cards are reached if (idx > 0) { + // effects with this param have the responsibility to realign it when later cards are reached sa.setSVar("StaticEffectUntilCardID", String.valueOf(completeList.get(idx - 1).getId())); + // add generous offset to timestamp, to ensure it applies last compared to cards that were ordered to ETB before it + idx += completeList.size() * 2; } + sa.setSVar("StaticEffectTimestamp", String.valueOf(game.getNextTimestamp() + idx)); completeList.remove(eff); } return completeList; From ab70ec0c86f9b5f1d24ec5f2f2134b536120802e Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 22 Jan 2025 00:54:44 +0100 Subject: [PATCH 08/17] Fix Gilraen --- .../game/ability/effects/ChangeZoneAllEffect.java | 10 ---------- .../forge/game/ability/effects/ChangeZoneEffect.java | 7 ++++--- .../java/forge/game/ability/effects/DigEffect.java | 10 ---------- .../res/cardsfolder/g/gilraen_dunedain_protector.txt | 7 ++----- 4 files changed, 6 insertions(+), 28 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java index 3de8a21609b..850dcb9b573 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java @@ -122,16 +122,6 @@ public void resolve(SpellAbility sa) { if (destination == ZoneType.Battlefield) { moveParams.put(AbilityKey.SimultaneousETB, cards); - if (sa.hasAdditionalAbility("AnimateSubAbility")) { - // need LKI before Animate does apply - moveParams.put(AbilityKey.CardLKI, CardCopyService.getLKICopy(c)); - - final SpellAbility animate = sa.getAdditionalAbility("AnimateSubAbility"); - source.addRemembered(c); - AbilityUtils.resolve(animate); - source.removeRemembered(c); - animate.setSVar("unanimateTimestamp", String.valueOf(game.getTimestamp())); - } if (sa.hasParam("Tapped")) { c.setTapped(true); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index 18669e277bc..406d18b1ae7 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -599,12 +599,13 @@ private void changeKnownOriginResolve(final SpellAbility sa) { } } if (sa.hasParam("WithCountersType")) { - CounterType cType = CounterType.getType(sa.getParam("WithCountersType")); int cAmount = AbilityUtils.calculateAmount(hostCard, sa.getParamOrDefault("WithCountersAmount", "1"), sa); - GameEntityCounterTable table = new GameEntityCounterTable(); - table.put(activator, gameCard, cType, cAmount); moveParams.put(AbilityKey.CounterTable, table); + for (String type : sa.getParam("WithCountersType").split(",")) { + CounterType cType = CounterType.getType(type); + table.put(activator, gameCard, cType, cAmount); + } } else if (sa.hasParam("WithNotedCounters")) { CountersNoteEffect.loadCounters(gameCard, hostCard, chooser, sa, moveParams); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java index 996a3fc998a..f74ff18fc18 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java @@ -399,16 +399,6 @@ else if (!sa.hasParam("NoLooking")) { moveParams.put(AbilityKey.CounterTable, table); } } - if (sa.hasAdditionalAbility("AnimateSubAbility")) { - // need LKI before Animate does apply - moveParams.put(AbilityKey.CardLKI, CardCopyService.getLKICopy(c)); - - final SpellAbility animate = sa.getAdditionalAbility("AnimateSubAbility"); - host.addRemembered(c); - AbilityUtils.resolve(animate); - host.removeRemembered(c); - animate.setSVar("unanimateTimestamp", String.valueOf(game.getTimestamp())); - } c = game.getAction().moveTo(c.getController().getZone(destZone1), c, sa, moveParams); if (destZone1.equals(ZoneType.Battlefield)) { if (addToCombat(c, sa, "Attacking", "Blocking")) { diff --git a/forge-gui/res/cardsfolder/g/gilraen_dunedain_protector.txt b/forge-gui/res/cardsfolder/g/gilraen_dunedain_protector.txt index 072aea31cda..54138d67220 100644 --- a/forge-gui/res/cardsfolder/g/gilraen_dunedain_protector.txt +++ b/forge-gui/res/cardsfolder/g/gilraen_dunedain_protector.txt @@ -2,13 +2,10 @@ Name:Gilraen, Dúnedain Protector ManaCost:2 W Types:Legendary Creature Human Noble PT:2/3 -A:AB$ ChangeZone | Cost$ 2 T | ValidTgts$ Creature.Other+YouCtrl | RememberChanged$ True | Origin$ Battlefield | Destination$ Exile | TgtPrompt$ Select another target creature you control | SubAbility$ DBReturn | SpellDescription$ Exile another target creature you control. You may return that card to the battlefield under its owner's control. If you don't, at the beginning of the next end step, return that card to the battlefield under its owner's control with a vigilance counter and a lifelink counter on it. +A:AB$ ChangeZone | Cost$ 2 T | ValidTgts$ Creature.Other+YouCtrl | RememberChanged$ True | Origin$ Battlefield | Destination$ Exile | TgtPrompt$ Select another target creature you control | SubAbility$ DBReturn | SpellDescription$ Exile another target creature you control. You may return that card to the battlefield under its owner's control. SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ All | Optional$ True | ForgetChanged$ True | Destination$ Battlefield | SubAbility$ DBDelayedTrigger SVar:DBDelayedTrigger:DB$ DelayedTrigger | RememberObjects$ Remembered | ConditionDefined$ Remembered | ConditionPresent$ Card | Mode$ Phase | Phase$ End Of Turn | Execute$ TrigReturn | SubAbility$ DBCleanup | SpellDescription$ If you don't, at the beginning of the next end step, return that card to the battlefield under its owner's control with a vigilance counter and a lifelink counter on it. -SVar:TrigReturn:DB$ ChangeZone | Defined$ DelayTriggerRemembered | Origin$ Exile | Destination$ Battlefield | AnimateSubAbility$ DBConditionEffect -SVar:DBConditionEffect:DB$ Effect | RememberObjects$ RememberedLKI | ReplacementEffects$ ETBCounters -SVar:ETBCounters:Event$ Moved | ReplacementResult$ Updated | Destination$ Battlefield | ValidCard$ Card.IsRemembered | ReplaceWith$ AddExtraCounter | Description$ return that card to the battlefield under its owner's control with a vigilance counter and a lifelink counter on it. -SVar:AddExtraCounter:DB$ PutCounter | ETB$ True | Defined$ ReplacedCard | CounterTypes$ Vigilance,Lifelink +SVar:TrigReturn:DB$ ChangeZone | Defined$ DelayTriggerRemembered | Origin$ Exile | Destination$ Battlefield | WithCountersType$ Vigilance,Lifelink SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True DeckHas:Ability$Counters|LifeGain Oracle:{2}, {T}: Exile another target creature you control. You may return that card to the battlefield under its owner's control. If you don't, at the beginning of the next end step, return that card to the battlefield under its owner's control with a vigilance counter and a lifelink counter on it. From 618279716951bc464cfe328ace05bf9354d6fe68 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 22 Jan 2025 09:34:21 +0100 Subject: [PATCH 09/17] Refactor with counter --- forge-game/src/main/java/forge/game/GameAction.java | 2 +- .../main/java/forge/game/ability/AbilityFactory.java | 1 - .../i/invasion_of_vryn_overloaded_mage_ring.txt | 4 ++-- .../res/cardsfolder/i/irenicuss_vile_duplication.txt | 4 ++-- forge-gui/res/cardsfolder/r/recommission.txt | 8 +++----- forge-gui/res/cardsfolder/s/semesters_end.txt | 9 ++++----- forge-gui/res/cardsfolder/t/teferis_time_twist.txt | 9 ++++----- forge-gui/res/cardsfolder/w/what_must_be_done.txt | 10 ++++------ 8 files changed, 20 insertions(+), 27 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index cacae6bc4bb..50fa73af573 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -730,7 +730,7 @@ private void handleStaticEffect(Card copied, SpellAbility cause) { if (cause != null && cause.hasParam("StaticEffect") && copied.isPermanent()) { final Card source = cause.getHostCard(); if (cause.hasParam("StaticEffectCheckSVar")) { - String cmp = cause.getParamOrDefault("StaticEffectSVarCompare$", "GE1"); + String cmp = cause.getParamOrDefault("StaticEffectSVarCompare", "GE1"); int lhs = AbilityUtils.calculateAmount(source, cause.getParam("StaticEffectCheckSVar"), cause); int rhs = AbilityUtils.calculateAmount(source, cmp.substring(2), cause); if (!Expressions.compare(lhs, cmp, rhs)) { diff --git a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java index 5bbc495d9dd..4c469019df2 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java @@ -61,7 +61,6 @@ public final class AbilityFactory { "FallbackAbility", // Complex Unless costs which can be unpayable "ChooseSubAbility", // Can choose a player via ChoosePlayer "CantChooseSubAbility", // Can't choose a player via ChoosePlayer - "AnimateSubAbility", // For ChangeZone Effects to Animate before ETB "RegenerationAbility", // for Regeneration Effect "ReturnAbility", // for Delayed Trigger on Magpie "GiftAbility" // for Promise Gift diff --git a/forge-gui/res/cardsfolder/i/invasion_of_vryn_overloaded_mage_ring.txt b/forge-gui/res/cardsfolder/i/invasion_of_vryn_overloaded_mage_ring.txt index 685e8d749e0..eda74c5901d 100644 --- a/forge-gui/res/cardsfolder/i/invasion_of_vryn_overloaded_mage_ring.txt +++ b/forge-gui/res/cardsfolder/i/invasion_of_vryn_overloaded_mage_ring.txt @@ -15,5 +15,5 @@ Name:Overloaded Mage-Ring ManaCost:no cost Colors:blue Types:Artifact -A:AB$ CopySpellAbility | Cost$ 1 T Sac<1/CARDNAME> | ValidTgts$ Card.YouCtrl | TargetType$ Spell | SpellDescription$ Copy target spell you control. (A copy of a permanent spell becomes a token.) -Oracle:{1}, {T}, Sacrifice Overloaded Mage-Ring: Copy target spell you control. (A copy of a permanent spell becomes a token.) +A:AB$ CopySpellAbility | Cost$ 1 T Sac<1/CARDNAME> | ValidTgts$ Card.YouCtrl | TargetType$ Spell | SpellDescription$ Copy target spell you control. You may choose new targets for the copy. (A copy of a permanent spell becomes a token.) +Oracle:{1}, {T}, Sacrifice Overloaded Mage-Ring: Copy target spell you control. You may choose new targets for the copy. (A copy of a permanent spell becomes a token.) diff --git a/forge-gui/res/cardsfolder/i/irenicuss_vile_duplication.txt b/forge-gui/res/cardsfolder/i/irenicuss_vile_duplication.txt index a234aa71ab9..a0da10ce99f 100644 --- a/forge-gui/res/cardsfolder/i/irenicuss_vile_duplication.txt +++ b/forge-gui/res/cardsfolder/i/irenicuss_vile_duplication.txt @@ -1,6 +1,6 @@ Name:Irenicus's Vile Duplication ManaCost:3 U Types:Sorcery -A:SP$ CopyPermanent | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | AddKeywords$ Flying | NonLegendary$ True | SpellDescription$ Create a token that's a copy of target creature you control, except the token has flying and isn't legendary if that creature is legendary. +A:SP$ CopyPermanent | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | AddKeywords$ Flying | NonLegendary$ True | SpellDescription$ Create a token that's a copy of target creature you control, except the token has flying and isn't legendary. DeckHas:Ability$Token -Oracle:Create a token that's a copy of target creature you control, except the token has flying and isn't legendary if that creature is legendary. +Oracle:Create a token that's a copy of target creature you control, except the token has flying and isn't legendary. diff --git a/forge-gui/res/cardsfolder/r/recommission.txt b/forge-gui/res/cardsfolder/r/recommission.txt index 5602b232e6c..159a88b4be9 100644 --- a/forge-gui/res/cardsfolder/r/recommission.txt +++ b/forge-gui/res/cardsfolder/r/recommission.txt @@ -1,11 +1,9 @@ Name:Recommission ManaCost:1 W Types:Sorcery -A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | AnimateSubAbility$ DBConditionEffect | ValidTgts$ Artifact.YouCtrl+cmcLE3,Creature.YouCtrl+cmcLE3 | TgtPrompt$ Select target artifact or creature card with mana value 3 from your graveyard | SpellDescription$ Return target artifact or creature card with mana value 3 or less from your graveyard to the battlefield. If a creature enters this way, it enters with an additional +1/+1 counter on it. -SVar:DBConditionEffect:DB$ Effect | RememberObjects$ Remembered | ReplacementEffects$ ETBCreat | SubAbility$ DBCleanup +A:SP$ Effect | RememberObjects$ Targeted | ReplacementEffects$ ETBCreat | ExileOnMoved$ Graveyard | SubAbility$ DBReturn | SpellDescription$ Return target artifact or creature card with mana value 3 or less from your graveyard to the battlefield. If a creature enters this way, it enters with an additional +1/+1 counter on it. +SVar:DBReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Artifact.YouCtrl+cmcLE3,Creature.YouCtrl+cmcLE3 | TgtPrompt$ Select target artifact or creature card with mana value 3 from your graveyard SVar:ETBCreat:Event$ Moved | ValidCard$ Creature.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | ReplacementResult$ Updated | Description$ If it's a creature, it enters with an additional +1/+1 counter on it. -SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ 1 | SubAbility$ DBExile -SVar:DBExile:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ 1 DeckHas:Ability$Graveyard|Counter Oracle:Return target artifact or creature card with mana value 3 or less from your graveyard to the battlefield. If a creature enters this way, it enters with an additional +1/+1 counter on it. diff --git a/forge-gui/res/cardsfolder/s/semesters_end.txt b/forge-gui/res/cardsfolder/s/semesters_end.txt index cdf5f5f4420..a40fcbc71f4 100644 --- a/forge-gui/res/cardsfolder/s/semesters_end.txt +++ b/forge-gui/res/cardsfolder/s/semesters_end.txt @@ -2,14 +2,13 @@ Name:Semester's End ManaCost:3 W Types:Instant A:SP$ ChangeZone | ValidTgts$ Creature.YouCtrl,Planeswalker.YouCtrl | TargetMin$ 0 | TargetMax$ X | Origin$ Battlefield | Destination$ Exile | TgtPrompt$ Select target creature you control | SubAbility$ DelTrig | RememberChanged$ True | SpellDescription$ Exile any number of target creatures and/or planeswalkers you control. At the beginning of the next end step, return each of them to the battlefield under its owner's control. Each of them enters with an additional +1/+1 counter on it if it's a creature and an additional loyalty counter on it if it's a planeswalker. -SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | RememberObjects$ RememberedLKI | TriggerDescription$ Return each of them to the battlefield under its owner's control. Each of them enters with an additional +1/+1 counter on it if it's a creature and an additional loyalty counter on it if it's a planeswalker. | SubAbility$ DBCleanup +SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigConditionEffect | RememberObjects$ RememberedLKI | TriggerDescription$ Return each of them to the battlefield under its owner's control. Each of them enters with an additional +1/+1 counter on it if it's a creature and an additional loyalty counter on it if it's a planeswalker. | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:TrigReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI | AnimateSubAbility$ DBConditionEffect -SVar:DBConditionEffect:DB$ Effect | RememberObjects$ Remembered | ReplacementEffects$ ETBCreatPlans +SVar:DBReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI +SVar:TrigConditionEffect:DB$ Effect | RememberObjects$ DelayTriggerRememberedLKI | ReplacementEffects$ ETBCreatPlans | ForgetOnMoved$ Exile | SubAbility$ DBReturn SVar:ETBCreatPlans:Event$ Moved | ValidCard$ Creature.IsRemembered,Planeswalker.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | ReplacementResult$ Updated | Description$ It enters with an additional +1/+1 counter on it if it's a creature, it enters with an additional loyalty counter on it if it's a planeswalker. SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedNewCard.Creature | CounterType$ P1P1 | ETB$ True | CounterNum$ 1 | SubAbility$ DBPutLOYALTY -SVar:DBPutLOYALTY:DB$ PutCounter | Defined$ ReplacedNewCard.Planeswalker | CounterType$ LOYALTY | ETB$ True | CounterNum$ 1 | SubAbility$ DBExile -SVar:DBExile:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile +SVar:DBPutLOYALTY:DB$ PutCounter | Defined$ ReplacedNewCard.Planeswalker | CounterType$ LOYALTY | ETB$ True | CounterNum$ 1 SVar:X:Count$Valid Permanent.YouCtrl DeckHas:Ability$Counters Oracle:Exile any number of target creatures and/or planeswalkers you control. At the beginning of the next end step, return each of them to the battlefield under its owner's control. Each of them enters with an additional +1/+1 counter on it if it's a creature and an additional loyalty counter on it if it's a planeswalker. diff --git a/forge-gui/res/cardsfolder/t/teferis_time_twist.txt b/forge-gui/res/cardsfolder/t/teferis_time_twist.txt index be795ddbad5..6cd8dd7af15 100644 --- a/forge-gui/res/cardsfolder/t/teferis_time_twist.txt +++ b/forge-gui/res/cardsfolder/t/teferis_time_twist.txt @@ -2,12 +2,11 @@ Name:Teferi's Time Twist ManaCost:1 U Types:Instant A:SP$ ChangeZone | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target permanent you control | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | AILogic$ DelayedBlink | SubAbility$ DBEffect | SpellDescription$ Exile target permanent you control. -SVar:DBEffect:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | RememberObjects$ RememberedLKI | SubAbility$ DBCleanup | SpellDescription$ Return that card to the battlefield under its owner's control at the beginning of the next end step. If it enters as a creature, it enters with an additional +1/+1 counter on it. -SVar:TrigReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI | AnimateSubAbility$ DBConditionEffect -SVar:DBConditionEffect:DB$ Effect | RememberObjects$ Remembered | ReplacementEffects$ EntersAsCreature +SVar:DBEffect:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigConditionEffect | RememberObjects$ RememberedLKI | SubAbility$ DBCleanup | SpellDescription$ Return that card to the battlefield under its owner's control at the beginning of the next end step. If it enters as a creature, it enters with an additional +1/+1 counter on it. +SVar:DBReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI +SVar:TrigConditionEffect:DB$ Effect | RememberObjects$ DelayTriggerRememberedLKI | ReplacementEffects$ EntersAsCreature | ExileOnMoved$ Exile | SubAbility$ DBReturn SVar:EntersAsCreature:Event$ Moved | ValidCard$ Creature.IsRemembered | Destination$ Battlefield | ReplaceWith$ PutP1P1 | Secondary$ True | ReplacementResult$ Updated | Description$ If it enters as a creature, it enters with an additional +1/+1 counter on it. -SVar:PutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | SubAbility$ DBExile -SVar:DBExile:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile +SVar:PutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True DeckHas:Ability$Counters Oracle:Exile target permanent you control. Return that card to the battlefield under its owner's control at the beginning of the next end step. If it enters as a creature, it enters with an additional +1/+1 counter on it. diff --git a/forge-gui/res/cardsfolder/w/what_must_be_done.txt b/forge-gui/res/cardsfolder/w/what_must_be_done.txt index f4914dfdee0..f7e88c91e62 100644 --- a/forge-gui/res/cardsfolder/w/what_must_be_done.txt +++ b/forge-gui/res/cardsfolder/w/what_must_be_done.txt @@ -1,13 +1,11 @@ Name:What Must Be Done ManaCost:3 W W Types:Sorcery -A:SP$ Charm | Choices$ DBDestroyAll,DBChangeZone +A:SP$ Charm | Choices$ DBDestroyAll,DBConditionEffect SVar:DBDestroyAll:DB$ DestroyAll | ValidCards$ Artifact,Creature | SpellDescription$ Let the World Burn — Destroy all artifacts and creatures. -SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Permanent.Historic+YouOwn | AnimateSubAbility$ DBConditionEffect | TgtPrompt$ Select target historic permanent card | SpellDescription$ Release Juno — Return target historic permanent card from your graveyard to the battlefield. It enters with two additional +1/+1 counters on it if it's a creature. (Artifacts, legendaries, and Sagas are historic.) -SVar:DBConditionEffect:DB$ Effect | RememberObjects$ Remembered | ReplacementEffects$ ETBCreat | SubAbility$ DBCleanup +SVar:DBConditionEffect:DB$ Effect | RememberObjects$ Targeted | ReplacementEffects$ ETBCreat | ExileOnMoved$ Graveyard | SubAbility$ DBChangeZone +SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Permanent.Historic+YouOwn | TgtPrompt$ Select target historic permanent card | SpellDescription$ Release Juno — Return target historic permanent card from your graveyard to the battlefield. It enters with two additional +1/+1 counters on it if it's a creature. (Artifacts, legendaries, and Sagas are historic.) SVar:ETBCreat:Event$ Moved | ValidCard$ Creature.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | ReplacementResult$ Updated | Description$ It enters with two additional +1/+1 counters on it if it's a creature. -SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ 2 | SubAbility$ DBExile -SVar:DBExile:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ 2 DeckHas:Ability$Graveyard|Counters Oracle:Choose one —\n• Let the World Burn — Destroy all artifacts and creatures.\n• Release Juno — Return target historic permanent card from your graveyard to the battlefield. It enters with two additional +1/+1 counters on it if it's a creature. (Artifacts, legendaries, and Sagas are historic.) From 870f0faab76063f2b6507f3e94495922a9c61797 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 22 Jan 2025 10:07:04 +0100 Subject: [PATCH 10/17] Clean up --- .../src/main/java/forge/game/GameAction.java | 76 ++++++++++--------- .../game/ability/SpellAbilityEffect.java | 11 ++- .../game/ability/effects/AmassEffect.java | 2 - .../game/ability/effects/EffectEffect.java | 7 -- .../game/ability/effects/HeistEffect.java | 2 - .../src/main/java/forge/game/card/Card.java | 2 - 6 files changed, 48 insertions(+), 52 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 50fa73af573..cdae25b60e4 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -727,47 +727,49 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer } private void handleStaticEffect(Card copied, SpellAbility cause) { - if (cause != null && cause.hasParam("StaticEffect") && copied.isPermanent()) { - final Card source = cause.getHostCard(); - if (cause.hasParam("StaticEffectCheckSVar")) { - String cmp = cause.getParamOrDefault("StaticEffectSVarCompare", "GE1"); - int lhs = AbilityUtils.calculateAmount(source, cause.getParam("StaticEffectCheckSVar"), cause); - int rhs = AbilityUtils.calculateAmount(source, cmp.substring(2), cause); - if (!Expressions.compare(lhs, cmp, rhs)) { - return; - } - } + if (cause == null || !cause.hasParam("StaticEffect") || !copied.isPermanent()) { + return; + } - Long timestamp; - // check if player ordered it manually - if (cause.hasSVar("StaticEffectTimestamp")) { - timestamp = Long.parseLong(cause.getSVar("StaticEffectTimestamp")); - } else { - // else create default value (or realign) - timestamp = game.getNextTimestamp(); - cause.setSVar("StaticEffectTimestamp", String.valueOf(timestamp)); - } - String name = "Static Effect #" + source.getGameTimestamp(); - // check if this isn't the first card being moved - Optional opt = IterableUtil.tryFind(cause.getActivatingPlayer().getZone(ZoneType.Command).getCards(), CardPredicates.nameEquals(name)); - - Card eff; - if (opt.isPresent()) { - eff = opt.get(); - // update in case player manually ordered - eff.setLayerTimestamp(timestamp); - } else { - // otherwise create effect first - eff = SpellAbilityEffect.createEffect(cause, cause.getActivatingPlayer(), name, source.getImageKey(), timestamp); - eff.setRenderForUI(false); - StaticAbility stAb = eff.addStaticAbility(AbilityUtils.getSVar(cause, cause.getParam("StaticEffect"))); - stAb.putParam("EffectZone", "Command"); - SpellAbilityEffect.addForgetOnMovedTrigger(copied, "Battlefield"); - game.getAction().moveToCommand(eff, cause); + final Card source = cause.getHostCard(); + if (cause.hasParam("StaticEffectCheckSVar")) { + String cmp = cause.getParamOrDefault("StaticEffectSVarCompare", "GE1"); + int lhs = AbilityUtils.calculateAmount(source, cause.getParam("StaticEffectCheckSVar"), cause); + int rhs = AbilityUtils.calculateAmount(source, cmp.substring(2), cause); + if (!Expressions.compare(lhs, cmp, rhs)) { + return; } + } - eff.addRemembered(copied); + Long timestamp; + // check if player ordered it manually + if (cause.hasSVar("StaticEffectTimestamp")) { + timestamp = Long.parseLong(cause.getSVar("StaticEffectTimestamp")); + } else { + // else create default value (or realign) + timestamp = game.getNextTimestamp(); + cause.setSVar("StaticEffectTimestamp", String.valueOf(timestamp)); + } + String name = "Static Effect #" + source.getGameTimestamp(); + // check if this isn't the first card being moved + Optional opt = IterableUtil.tryFind(cause.getActivatingPlayer().getZone(ZoneType.Command).getCards(), CardPredicates.nameEquals(name)); + + Card eff; + if (opt.isPresent()) { + eff = opt.get(); + // update in case player manually ordered + eff.setLayerTimestamp(timestamp); + } else { + // otherwise create effect first + eff = SpellAbilityEffect.createEffect(cause, cause.getActivatingPlayer(), name, source.getImageKey(), timestamp); + eff.setRenderForUI(false); + StaticAbility stAb = eff.addStaticAbility(AbilityUtils.getSVar(cause, cause.getParam("StaticEffect"))); + stAb.putParam("EffectZone", "Command"); + SpellAbilityEffect.addForgetOnMovedTrigger(copied, "Battlefield"); + game.getAction().moveToCommand(eff, cause); } + + eff.addRemembered(copied); } private void storeChangesZoneAll(Card c, Zone zoneFrom, Zone zoneTo, Map params) { diff --git a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java index 4868d5ec6ac..463b356ea0c 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -5,6 +5,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Table; import forge.GameCommand; +import forge.card.CardRarity; import forge.card.GamePieceType; import forge.card.MagicColor; import forge.game.Game; @@ -596,19 +597,25 @@ public static Card createEffect(final SpellAbility sa, final Player controller, eff.setGameTimestamp(timestamp); eff.setName(name); - eff.setColor(hostCard.getColor().getColor()); // if name includes emblem then it should be one if (name.startsWith("Emblem")) { eff.setEmblem(true); // Emblem needs to be colorless eff.setColor(MagicColor.COLORLESS); - } else if (sa.hasParam("Boon")) { + eff.setRarity(CardRarity.Common); + } else { + eff.setColor(hostCard.getColor().getColor()); + eff.setRarity(hostCard.getRarity()); + } + + if (sa.hasParam("Boon")) { eff.setBoon(true); } eff.setOwner(controller); eff.setSVars(sa.getSVars()); + eff.setSetCode(hostCard.getSetCode()); if (image != null) { eff.setImageKey(image); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/AmassEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AmassEffect.java index 75ff8519fba..848e5fb87ca 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AmassEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AmassEffect.java @@ -100,8 +100,6 @@ public void resolve(SpellAbility sa) { // 01.44a If it isn’t a [subtype], it becomes a [subtype] in addition to its other types. if (!tgt.getType().hasCreatureType(type)) { Card eff = createEffect(sa, activator, "Amass Effect", source.getImageKey()); - eff.setSetCode(source.getSetCode()); - eff.setRarity(source.getRarity()); eff.setRenderForUI(false); eff.addRemembered(tgt); diff --git a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java index 82a7dff7a91..6798276665f 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java @@ -8,7 +8,6 @@ import com.google.common.collect.Lists; import forge.ImageKeys; -import forge.card.CardRarity; import forge.game.Game; import forge.game.GameObject; import forge.game.ability.AbilityFactory; @@ -162,12 +161,6 @@ public void resolve(SpellAbility sa) { for (Player controller : effectOwner) { final Card eff = createEffect(sa, controller, name, image); - eff.setSetCode(hostCard.getSetCode()); - if (name.startsWith("Emblem")) { - eff.setRarity(CardRarity.Common); - } else { - eff.setRarity(hostCard.getRarity()); - } // Abilities and triggers work the same as they do for Token // Grant abilities diff --git a/forge-game/src/main/java/forge/game/ability/effects/HeistEffect.java b/forge-game/src/main/java/forge/game/ability/effects/HeistEffect.java index 3ae951016e8..876b80e465b 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/HeistEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/HeistEffect.java @@ -53,8 +53,6 @@ public void resolve(SpellAbility sa) { if (!heisted.isEmpty()) { final Card eff = createEffect(sa, player, source + "'s Heist Effect", source.getImageKey()); - eff.setSetCode(source.getSetCode()); - eff.setRarity(source.getRarity()); eff.addRemembered(heisted); String mayPlay = "Mode$ Continuous | MayPlay$ True | MayPlayIgnoreType$ True | EffectZone$ Command | " + "Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ You may play the heisted card for as " + diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index f2f0d0e0998..14cfeacd539 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -4098,8 +4098,6 @@ public final void attachToEntity(final GameEntity entity, SpellAbility sa, boole if (hasKeyword(Keyword.RECONFIGURE)) { Card eff = SpellAbilityEffect.createEffect(sa, sa.getActivatingPlayer(), "Reconfigure Effect", getImageKey()); - eff.setSetCode(getSetCode()); - eff.setRarity(getRarity()); eff.setRenderForUI(false); eff.addRemembered(this); From e5513d4b829d65a014c11abd6f4fc658ec31b3cd Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 22 Jan 2025 10:47:04 +0100 Subject: [PATCH 11/17] Cleanup effect if card can't ETB --- forge-gui/res/cardsfolder/r/recommission.txt | 2 +- forge-gui/res/cardsfolder/s/semesters_end.txt | 10 ++++++---- forge-gui/res/cardsfolder/t/teferis_time_twist.txt | 2 +- forge-gui/res/cardsfolder/w/what_must_be_done.txt | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/forge-gui/res/cardsfolder/r/recommission.txt b/forge-gui/res/cardsfolder/r/recommission.txt index 159a88b4be9..edef59930e7 100644 --- a/forge-gui/res/cardsfolder/r/recommission.txt +++ b/forge-gui/res/cardsfolder/r/recommission.txt @@ -1,7 +1,7 @@ Name:Recommission ManaCost:1 W Types:Sorcery -A:SP$ Effect | RememberObjects$ Targeted | ReplacementEffects$ ETBCreat | ExileOnMoved$ Graveyard | SubAbility$ DBReturn | SpellDescription$ Return target artifact or creature card with mana value 3 or less from your graveyard to the battlefield. If a creature enters this way, it enters with an additional +1/+1 counter on it. +A:SP$ Effect | RememberObjects$ Targeted,Self | ReplacementEffects$ ETBCreat | ExileOnMoved$ Graveyard,Stack | SubAbility$ DBReturn | SpellDescription$ Return target artifact or creature card with mana value 3 or less from your graveyard to the battlefield. If a creature enters this way, it enters with an additional +1/+1 counter on it. SVar:DBReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Artifact.YouCtrl+cmcLE3,Creature.YouCtrl+cmcLE3 | TgtPrompt$ Select target artifact or creature card with mana value 3 from your graveyard SVar:ETBCreat:Event$ Moved | ValidCard$ Creature.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | ReplacementResult$ Updated | Description$ If it's a creature, it enters with an additional +1/+1 counter on it. SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ 1 diff --git a/forge-gui/res/cardsfolder/s/semesters_end.txt b/forge-gui/res/cardsfolder/s/semesters_end.txt index a40fcbc71f4..2c6236506d9 100644 --- a/forge-gui/res/cardsfolder/s/semesters_end.txt +++ b/forge-gui/res/cardsfolder/s/semesters_end.txt @@ -2,10 +2,12 @@ Name:Semester's End ManaCost:3 W Types:Instant A:SP$ ChangeZone | ValidTgts$ Creature.YouCtrl,Planeswalker.YouCtrl | TargetMin$ 0 | TargetMax$ X | Origin$ Battlefield | Destination$ Exile | TgtPrompt$ Select target creature you control | SubAbility$ DelTrig | RememberChanged$ True | SpellDescription$ Exile any number of target creatures and/or planeswalkers you control. At the beginning of the next end step, return each of them to the battlefield under its owner's control. Each of them enters with an additional +1/+1 counter on it if it's a creature and an additional loyalty counter on it if it's a planeswalker. -SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigConditionEffect | RememberObjects$ RememberedLKI | TriggerDescription$ Return each of them to the battlefield under its owner's control. Each of them enters with an additional +1/+1 counter on it if it's a creature and an additional loyalty counter on it if it's a planeswalker. | SubAbility$ DBCleanup -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:DBReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI -SVar:TrigConditionEffect:DB$ Effect | RememberObjects$ DelayTriggerRememberedLKI | ReplacementEffects$ ETBCreatPlans | ForgetOnMoved$ Exile | SubAbility$ DBReturn +SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigConditionEffect | RememberObjects$ RememberedLKI | TriggerDescription$ Return each of them to the battlefield under its owner's control. Each of them enters with an additional +1/+1 counter on it if it's a creature and an additional loyalty counter on it if it's a planeswalker. | SubAbility$ DBCleanup1 +SVar:DBCleanup1:DB$ Cleanup | ClearRemembered$ True +SVar:DBReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI | SubAbility$ DBCleanEff +SVar:DBCleanEff:DB$ ChangeZone | Origin$ Command | Destination$ Exile | Defined$ Imprinted | SubAbility$ DBCleanup2 +SVar:DBCleanup2:DB$ Cleanup | ClearImprinted$ True +SVar:TrigConditionEffect:DB$ Effect | RememberObjects$ DelayTriggerRememberedLKI | ReplacementEffects$ ETBCreatPlans | ImprintOnHost$ True | ForgetOnMoved$ Exile | SubAbility$ DBReturn SVar:ETBCreatPlans:Event$ Moved | ValidCard$ Creature.IsRemembered,Planeswalker.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | ReplacementResult$ Updated | Description$ It enters with an additional +1/+1 counter on it if it's a creature, it enters with an additional loyalty counter on it if it's a planeswalker. SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedNewCard.Creature | CounterType$ P1P1 | ETB$ True | CounterNum$ 1 | SubAbility$ DBPutLOYALTY SVar:DBPutLOYALTY:DB$ PutCounter | Defined$ ReplacedNewCard.Planeswalker | CounterType$ LOYALTY | ETB$ True | CounterNum$ 1 diff --git a/forge-gui/res/cardsfolder/t/teferis_time_twist.txt b/forge-gui/res/cardsfolder/t/teferis_time_twist.txt index 6cd8dd7af15..1607acff035 100644 --- a/forge-gui/res/cardsfolder/t/teferis_time_twist.txt +++ b/forge-gui/res/cardsfolder/t/teferis_time_twist.txt @@ -4,7 +4,7 @@ Types:Instant A:SP$ ChangeZone | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target permanent you control | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | AILogic$ DelayedBlink | SubAbility$ DBEffect | SpellDescription$ Exile target permanent you control. SVar:DBEffect:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigConditionEffect | RememberObjects$ RememberedLKI | SubAbility$ DBCleanup | SpellDescription$ Return that card to the battlefield under its owner's control at the beginning of the next end step. If it enters as a creature, it enters with an additional +1/+1 counter on it. SVar:DBReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI -SVar:TrigConditionEffect:DB$ Effect | RememberObjects$ DelayTriggerRememberedLKI | ReplacementEffects$ EntersAsCreature | ExileOnMoved$ Exile | SubAbility$ DBReturn +SVar:TrigConditionEffect:DB$ Effect | RememberObjects$ DelayTriggerRememberedLKI,Self | ReplacementEffects$ EntersAsCreature | ExileOnMoved$ Exile,Stack | SubAbility$ DBReturn SVar:EntersAsCreature:Event$ Moved | ValidCard$ Creature.IsRemembered | Destination$ Battlefield | ReplaceWith$ PutP1P1 | Secondary$ True | ReplacementResult$ Updated | Description$ If it enters as a creature, it enters with an additional +1/+1 counter on it. SVar:PutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/cardsfolder/w/what_must_be_done.txt b/forge-gui/res/cardsfolder/w/what_must_be_done.txt index f7e88c91e62..c8a7cd75d14 100644 --- a/forge-gui/res/cardsfolder/w/what_must_be_done.txt +++ b/forge-gui/res/cardsfolder/w/what_must_be_done.txt @@ -3,7 +3,7 @@ ManaCost:3 W W Types:Sorcery A:SP$ Charm | Choices$ DBDestroyAll,DBConditionEffect SVar:DBDestroyAll:DB$ DestroyAll | ValidCards$ Artifact,Creature | SpellDescription$ Let the World Burn — Destroy all artifacts and creatures. -SVar:DBConditionEffect:DB$ Effect | RememberObjects$ Targeted | ReplacementEffects$ ETBCreat | ExileOnMoved$ Graveyard | SubAbility$ DBChangeZone +SVar:DBConditionEffect:DB$ Effect | RememberObjects$ Targeted,Self | ReplacementEffects$ ETBCreat | ExileOnMoved$ Graveyard,Stack | SubAbility$ DBChangeZone SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Permanent.Historic+YouOwn | TgtPrompt$ Select target historic permanent card | SpellDescription$ Release Juno — Return target historic permanent card from your graveyard to the battlefield. It enters with two additional +1/+1 counters on it if it's a creature. (Artifacts, legendaries, and Sagas are historic.) SVar:ETBCreat:Event$ Moved | ValidCard$ Creature.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | ReplacementResult$ Updated | Description$ It enters with two additional +1/+1 counters on it if it's a creature. SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ 2 From d5095a2f5bf130e0338bc67d11cd311aaecacde7 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Wed, 22 Jan 2025 10:55:04 +0100 Subject: [PATCH 12/17] Update semesters_end.txt Format abilities --- forge-gui/res/cardsfolder/s/semesters_end.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/forge-gui/res/cardsfolder/s/semesters_end.txt b/forge-gui/res/cardsfolder/s/semesters_end.txt index 2c6236506d9..eb9d18e75b8 100644 --- a/forge-gui/res/cardsfolder/s/semesters_end.txt +++ b/forge-gui/res/cardsfolder/s/semesters_end.txt @@ -2,15 +2,15 @@ Name:Semester's End ManaCost:3 W Types:Instant A:SP$ ChangeZone | ValidTgts$ Creature.YouCtrl,Planeswalker.YouCtrl | TargetMin$ 0 | TargetMax$ X | Origin$ Battlefield | Destination$ Exile | TgtPrompt$ Select target creature you control | SubAbility$ DelTrig | RememberChanged$ True | SpellDescription$ Exile any number of target creatures and/or planeswalkers you control. At the beginning of the next end step, return each of them to the battlefield under its owner's control. Each of them enters with an additional +1/+1 counter on it if it's a creature and an additional loyalty counter on it if it's a planeswalker. -SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigConditionEffect | RememberObjects$ RememberedLKI | TriggerDescription$ Return each of them to the battlefield under its owner's control. Each of them enters with an additional +1/+1 counter on it if it's a creature and an additional loyalty counter on it if it's a planeswalker. | SubAbility$ DBCleanup1 +SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigConditionEffect | RememberObjects$ RememberedLKI | SubAbility$ DBCleanup1 | TriggerDescription$ Return each of them to the battlefield under its owner's control. Each of them enters with an additional +1/+1 counter on it if it's a creature and an additional loyalty counter on it if it's a planeswalker. SVar:DBCleanup1:DB$ Cleanup | ClearRemembered$ True -SVar:DBReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI | SubAbility$ DBCleanEff -SVar:DBCleanEff:DB$ ChangeZone | Origin$ Command | Destination$ Exile | Defined$ Imprinted | SubAbility$ DBCleanup2 -SVar:DBCleanup2:DB$ Cleanup | ClearImprinted$ True SVar:TrigConditionEffect:DB$ Effect | RememberObjects$ DelayTriggerRememberedLKI | ReplacementEffects$ ETBCreatPlans | ImprintOnHost$ True | ForgetOnMoved$ Exile | SubAbility$ DBReturn SVar:ETBCreatPlans:Event$ Moved | ValidCard$ Creature.IsRemembered,Planeswalker.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | ReplacementResult$ Updated | Description$ It enters with an additional +1/+1 counter on it if it's a creature, it enters with an additional loyalty counter on it if it's a planeswalker. SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedNewCard.Creature | CounterType$ P1P1 | ETB$ True | CounterNum$ 1 | SubAbility$ DBPutLOYALTY SVar:DBPutLOYALTY:DB$ PutCounter | Defined$ ReplacedNewCard.Planeswalker | CounterType$ LOYALTY | ETB$ True | CounterNum$ 1 SVar:X:Count$Valid Permanent.YouCtrl +SVar:DBReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI | SubAbility$ DBCleanEff +SVar:DBCleanEff:DB$ ChangeZone | Origin$ Command | Destination$ Exile | Defined$ Imprinted | SubAbility$ DBCleanup2 +SVar:DBCleanup2:DB$ Cleanup | ClearImprinted$ True DeckHas:Ability$Counters Oracle:Exile any number of target creatures and/or planeswalkers you control. At the beginning of the next end step, return each of them to the battlefield under its owner's control. Each of them enters with an additional +1/+1 counter on it if it's a creature and an additional loyalty counter on it if it's a planeswalker. From 8ecb285f2fdcea0cdc8cecfb9b54ddb20c5ab956 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 22 Jan 2025 13:08:59 +0100 Subject: [PATCH 13/17] Return as Aura trickery --- .../src/main/java/forge/game/GameAction.java | 62 ++++++++++--------- .../StaticAbilityContinuous.java | 4 +- .../garruk_boss_effect_phasetwo.txt | 5 +- .../res/cardsfolder/a/abuelos_awakening.txt | 4 +- .../a/admiral_brass_unsinkable.txt | 4 +- .../cardsfolder/a/arbiter_of_the_ideal.txt | 4 +- .../cardsfolder/a/ascent_of_the_worthy.txt | 4 +- .../cardsfolder/a/ashiok_nightmare_weaver.txt | 4 +- .../res/cardsfolder/b/bronzehide_lion.txt | 4 +- 9 files changed, 48 insertions(+), 47 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index cdae25b60e4..57bc25b69d4 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -128,33 +128,6 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer CardCollectionView lastBattlefield = getLastState(AbilityKey.LastStateBattlefield, cause, params, false); CardCollectionView lastGraveyard = getLastState(AbilityKey.LastStateGraveyard, cause, params, false); - // Aura entering indirectly - // need to check before it enters - if (c.isAura() && !c.isAttachedToEntity() && toBattlefield && (zoneFrom == null || !zoneFrom.is(ZoneType.Stack))) { - boolean found = false; - if (game.getPlayers().stream().anyMatch(PlayerPredicates.canBeAttached(c, null))) { - found = true; - } - - if (!found) { - if (lastBattlefield.anyMatch(CardPredicates.canBeAttached(c, null))) { - found = true; - } - } - - if (!found) { - if (lastGraveyard.anyMatch(CardPredicates.canBeAttached(c, null))) { - found = true; - } - } - if (!found) { - c.clearControllers(); - if (cause != null) { - } - return c; - } - } - //717.6. If a card with an Astrotorium card back would be put into a zone other than the battlefield, exile, //or the command zone from anywhere, instead its owner puts it into the junkyard. if ((c.getGamePieceType() == GamePieceType.ATTRACTION || c.getGamePieceType() == GamePieceType.CONTRAPTION) @@ -393,6 +366,33 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer copied.getOwner().removeInboundToken(copied); + handleStaticEffect(copied, cause); + + // Aura entering indirectly + // need to check before it enters + if (copied.isAura() && !copied.isAttachedToEntity() && toBattlefield && (zoneFrom == null || !zoneFrom.is(ZoneType.Stack))) { + boolean found = false; + if (game.getPlayers().stream().anyMatch(PlayerPredicates.canBeAttached(copied, null))) { + found = true; + } + + if (!found) { + if (lastBattlefield.anyMatch(CardPredicates.canBeAttached(copied, null))) { + found = true; + } + } + + if (!found) { + if (lastGraveyard.anyMatch(CardPredicates.canBeAttached(copied, null))) { + found = true; + } + } + if (!found) { + c.clearControllers(); + return c; + } + } + // Aura entering as Copy from stack // without targets it is sent to graveyard if (copied.isAura() && !copied.isAttachedToEntity() && toBattlefield) { @@ -575,7 +575,6 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer copied.setChosenColorID(ImmutableSet.copyOf(c.getChosenColorID())); } - // update state for view copied.updateStateForView(); if (fromBattlefield) { @@ -587,8 +586,6 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer } } - handleStaticEffect(copied, cause); - if (!table.isEmpty()) { // we don't want always trigger before counters are placed game.getTriggerHandler().suppressMode(TriggerType.Always); @@ -727,6 +724,7 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer } private void handleStaticEffect(Card copied, SpellAbility cause) { + // CR 611.2e if (cause == null || !cause.hasParam("StaticEffect") || !copied.isPermanent()) { return; } @@ -765,11 +763,15 @@ private void handleStaticEffect(Card copied, SpellAbility cause) { eff.setRenderForUI(false); StaticAbility stAb = eff.addStaticAbility(AbilityUtils.getSVar(cause, cause.getParam("StaticEffect"))); stAb.putParam("EffectZone", "Command"); + stAb.putParam("AffectedZone", "Battlefield,Hand,Graveyard,Exile,Stack,Library,Command"); SpellAbilityEffect.addForgetOnMovedTrigger(copied, "Battlefield"); game.getAction().moveToCommand(eff, cause); } eff.addRemembered(copied); + + // refresh needed for effects like Bronzehide Lion + game.getAction().checkStaticAbilities(false, Sets.newHashSet(copied), new CardCollection(copied)); } private void storeChangesZoneAll(Card c, Zone zoneFrom, Zone zoneTo, Map params) { diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java index 11a1007f6ef..f1031c220b1 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -792,9 +792,7 @@ public static CardCollectionView applyContinuousAbility(final StaticAbility stAb final String costcmc = Integer.toString(affectedCard.getCMC()); ability = TextUtil.fastReplace(ability, "ConvertedManaCost", costcmc); } - if (ability.startsWith("AB") || ability.startsWith("ST")) { // grant the ability - addedAbilities.add(affectedCard.getSpellAbilityForStaticAbility(ability, stAb)); - } + addedAbilities.add(affectedCard.getSpellAbilityForStaticAbility(ability, stAb)); } } diff --git a/forge-gui/res/adventure/common/custom_cards/garruk_boss_effect_phasetwo.txt b/forge-gui/res/adventure/common/custom_cards/garruk_boss_effect_phasetwo.txt index 2a541a6a22f..8e97817c67a 100644 --- a/forge-gui/res/adventure/common/custom_cards/garruk_boss_effect_phasetwo.txt +++ b/forge-gui/res/adventure/common/custom_cards/garruk_boss_effect_phasetwo.txt @@ -9,8 +9,9 @@ SVar:TrigConjure:DB$ MakeCard | Conjure$ True | Zone$ Hand | AtRandom$ True | Sp T:Mode$ SpellCast | ValidCard$ Card.nonCreature | ValidActivatingPlayer$ Opponent | Execute$ DBPump | TriggerZones$ Command | TriggerDescription$ Whenever an opponent casts a noncreature spell, perpetually increase the power and toughness of creatures you control and creature cards in your hand, library, and graveyard by 1. SVar:DBPump:DB$ PumpAll | ValidCards$ Creature.YouCtrl | PumpZone$ Battlefield,Hand,Graveyard,Library | NumAtt$ 1 | NumDef$ 1 | Duration$ Perpetual T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Command | Execute$ TrigReanimate | TriggerDescription$ At the beginning of your end step, return a random creature card from your graveyard to the battlefield. It gains "If this creature would leave the battlefield, exile it instead." -SVar:TrigReanimate:DB$ ChangeZone | ChangeType$ Creature.YouOwn | ChangeNum$ 1 | Hidden$ True | Origin$ Graveyard | AtRandom$ True | Destination$ Battlefield | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Replacements$ ReplaceDies | Defined$ Remembered | Duration$ Permanent +SVar:TrigReanimate:DB$ ChangeZone | ChangeType$ Creature.YouOwn | ChangeNum$ 1 | Hidden$ True | Origin$ Graveyard | AtRandom$ True | Destination$ Battlefield | RememberChanged$ True | SubAbility$ DBAnimate +SVar:DBAnimate:DB$ Animate | Replacements$ ReplaceDies | Defined$ Remembered | Duration$ Permanent | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:ReplaceDies:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | ValidCard$ Card.Self | ReplaceWith$ Exile | Description$ If this creature would leave the battlefield, exile it instead. SVar:Exile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ ReplacedCard Oracle:Each Forest you control is a Swamp in addition to its other land types.\nBeast creatures you control get +3/+3 and have trample and deathtouch.\nAt the beginning of your upkeep, conjure a card from Garruk's Phase 2 spellbook into your hand.\nWhenever an opponent casts a noncreature spell, perpetually increase the power and toughness of creatures you control and creature cards in your hand, library, and graveyard by 1.\nAt the beginning of your end step, return a random creature card from your graveyard to the battlefield. That creature gains "If this creature would leave the battlefield, exile it instead." diff --git a/forge-gui/res/cardsfolder/a/abuelos_awakening.txt b/forge-gui/res/cardsfolder/a/abuelos_awakening.txt index 404744de6c8..8b72a8e4657 100644 --- a/forge-gui/res/cardsfolder/a/abuelos_awakening.txt +++ b/forge-gui/res/cardsfolder/a/abuelos_awakening.txt @@ -1,8 +1,8 @@ Name:Abuelo's Awakening ManaCost:X 3 W Types:Sorcery -A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Artifact.YouOwn,Enchantment.nonAura+YouOwn | TgtPrompt$ Select an Artifact or non-Aura enchantment | AnimateSubAbility$ DBAnimate | WithCountersType$ P1P1 | WithCountersAmount$ X | SpellDescription$ Return target artifact or non-Aura enchantment card from your graveyard to the battlefield with X additional +1/+1 counters on it. It's a 1/1 Spirit creature with flying in addition to its other types. -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Power$ 1 | Toughness$ 1 | Keywords$ Flying | Types$ Creature,Spirit | Duration$ Permanent +A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Artifact.YouOwn,Enchantment.nonAura+YouOwn | TgtPrompt$ Select an Artifact or non-Aura enchantment | StaticEffect$ Animate | WithCountersType$ P1P1 | WithCountersAmount$ X | SpellDescription$ Return target artifact or non-Aura enchantment card from your graveyard to the battlefield with X additional +1/+1 counters on it. It's a 1/1 Spirit creature with flying in addition to its other types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Creature & Spirit | SetPower$ 1 | SetToughness$ 1 | AddKeyword$ Flying SVar:X:Count$xPaid DeckHas:Ability$Graveyard|Counters & Type$Spirit DeckHints:Ability$Mill & Type$Artifact|Enchantment diff --git a/forge-gui/res/cardsfolder/a/admiral_brass_unsinkable.txt b/forge-gui/res/cardsfolder/a/admiral_brass_unsinkable.txt index 9db1a396c86..f011a9429e9 100644 --- a/forge-gui/res/cardsfolder/a/admiral_brass_unsinkable.txt +++ b/forge-gui/res/cardsfolder/a/admiral_brass_unsinkable.txt @@ -5,8 +5,8 @@ PT:3/3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigMill | TriggerDescription$ When CARDNAME enters, mill four cards. SVar:TrigMill:DB$ Mill | NumCards$ 4 | Defined$ You T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigReturn | TriggerDescription$ At the beginning of combat on your turn, you may return target Pirate creature card from your graveyard to the battlefield with a finality counter on it. It has base power and toughness 4/4. It gains haste until end of turn. (If a creature with a finality counter on it would die, exile it instead.) -SVar:TrigReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | WithCountersType$ FINALITY | ValidTgts$ Pirate.YouOwn | Optional$ True | TgtPrompt$ Select target pirate in your graveyard | SubAbility$ DBPump | RememberChanged$ True | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Power$ 4 | Toughness$ 4 | Duration$ Permanent | Defined$ Remembered +SVar:TrigReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | WithCountersType$ FINALITY | ValidTgts$ Pirate.YouOwn | Optional$ True | TgtPrompt$ Select target pirate in your graveyard | SubAbility$ DBPump | RememberChanged$ True | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | SetPower$ 4 | SetToughness$ 4 SVar:DBPump:DB$ Pump | KW$ Haste | Defined$ Remembered | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True DeckHas:Ability$Mill|Graveyard|Counters diff --git a/forge-gui/res/cardsfolder/a/arbiter_of_the_ideal.txt b/forge-gui/res/cardsfolder/a/arbiter_of_the_ideal.txt index 2b934ccf2ef..3d1c0bbaa56 100644 --- a/forge-gui/res/cardsfolder/a/arbiter_of_the_ideal.txt +++ b/forge-gui/res/cardsfolder/a/arbiter_of_the_ideal.txt @@ -4,6 +4,6 @@ Types:Creature Sphinx PT:4/5 K:Flying T:Mode$ Untaps | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigReveal | TriggerDescription$ Inspired — Whenever CARDNAME becomes untapped, reveal the top card of your library. If it's an artifact, creature, or land card, you may put it onto the battlefield with a manifestation counter on it. That permanent is an enchantment in addition to its other types. -SVar:TrigReveal:DB$ Dig | DigNum$ 1 | Reveal$ True | Optional$ True | ChangeValid$ Artifact,Creature,Land | DestinationZone$ Battlefield | LibraryPosition2$ 0 | WithCounters$ MANIFESTATION | AnimateSubAbility$ Enchantment -SVar:Enchantment:DB$ Animate | Defined$ Remembered | Types$ Enchantment | Duration$ Permanent +SVar:TrigReveal:DB$ Dig | DigNum$ 1 | Reveal$ True | Optional$ True | ChangeValid$ Artifact,Creature,Land | DestinationZone$ Battlefield | LibraryPosition2$ 0 | WithCounters$ MANIFESTATION | StaticEffect$ Enchantment +SVar:Enchantment:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Enchantment Oracle:Flying\nInspired — Whenever Arbiter of the Ideal becomes untapped, reveal the top card of your library. If it's an artifact, creature, or land card, you may put it onto the battlefield with a manifestation counter on it. That permanent is an enchantment in addition to its other types. diff --git a/forge-gui/res/cardsfolder/a/ascent_of_the_worthy.txt b/forge-gui/res/cardsfolder/a/ascent_of_the_worthy.txt index 7013982f9db..e2e657e1688 100644 --- a/forge-gui/res/cardsfolder/a/ascent_of_the_worthy.txt +++ b/forge-gui/res/cardsfolder/a/ascent_of_the_worthy.txt @@ -6,6 +6,6 @@ SVar:DBChoose:DB$ ChooseCard | Choices$ Creature.YouCtrl | Mandatory$ True | Sub SVar:DBEffect:DB$ Effect | ReplacementEffects$ DamageEvent | ExileOnMoved$ Battlefield | RememberObjects$ ChosenCard | Duration$ UntilYourNextTurn SVar:DamageEvent:Event$ DamageDone | ActiveZones$ Command | ValidTarget$ Creature.YouCtrl | ReplaceWith$ GideonSac | DamageTarget$ Remembered | Description$ All damage that would be dealt this turn to creatures you control is dealt to the chosen creature instead (if it's still on the battlefield). SVar:GideonSac:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Remembered | VarType$ Card -SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose target creature card in your graveyard | ValidTgts$ Creature.YouOwn | WithCountersType$ Flying | AnimateSubAbility$ Animate | SpellDescription$ Return target creature card from your graveyard to the battlefield with a flying counter on it. That creature is an Angel Warrior in addition to its other types. -SVar:Animate:DB$ Animate | Defined$ Remembered | Types$ Angel,Warrior | Duration$ Permanent +SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose target creature card in your graveyard | ValidTgts$ Creature.YouOwn | WithCountersType$ Flying | StaticEffect$ Animate | SpellDescription$ Return target creature card from your graveyard to the battlefield with a flying counter on it. That creature is an Angel Warrior in addition to its other types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Angel & Warrior Oracle:(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)\nI, II — Choose a creature you control. Until your next turn, all damage that would be dealt to creatures you control is dealt to that creature instead.\nIII — Return target creature card from your graveyard to the battlefield with a flying counter on it. That creature is an Angel Warrior in addition to its other types. diff --git a/forge-gui/res/cardsfolder/a/ashiok_nightmare_weaver.txt b/forge-gui/res/cardsfolder/a/ashiok_nightmare_weaver.txt index 24bbcfcddbc..5f0fb4b4a55 100644 --- a/forge-gui/res/cardsfolder/a/ashiok_nightmare_weaver.txt +++ b/forge-gui/res/cardsfolder/a/ashiok_nightmare_weaver.txt @@ -4,8 +4,8 @@ Types:Legendary Planeswalker Ashiok Loyalty:3 A:AB$ Dig | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | ValidTgts$ Opponent | DigNum$ 3 | ChangeNum$ All | DestinationZone$ Exile | SpellDescription$ Exile the top three cards of target opponent's library. A:AB$ ChooseCard | Cost$ SubCounter | Choices$ Creature.cmcEQX+ExiledWithSource | ChoiceZone$ Exile | Planeswalker$ True | SubAbility$ DBChangeZone | AILogic$ Ashiok | SpellDescription$ Put a creature card with mana value X exiled with CARDNAME onto the battlefield under your control. That creature is a Nightmare in addition to its other types. -SVar:DBChangeZone:DB$ ChangeZone | Defined$ ChosenCard | Origin$ Exile | Destination$ Battlefield | GainControl$ True | AnimateSubAbility$ DBAnimate | SubAbility$ DBCleanMinus -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Nightmare | Duration$ Permanent +SVar:DBChangeZone:DB$ ChangeZone | Defined$ ChosenCard | Origin$ Exile | Destination$ Battlefield | GainControl$ True | StaticEffect$ Animate | SubAbility$ DBCleanMinus +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Nightmare SVar:DBCleanMinus:DB$ Cleanup | ClearChosenCard$ True SVar:X:Count$xPaid A:AB$ ChangeZoneAll | Cost$ SubCounter<10/LOYALTY> | ChangeType$ Card.OppCtrl | Origin$ Graveyard,Hand | Destination$ Exile | RememberChanged$ True | Planeswalker$ True | Ultimate$ True | SpellDescription$ Exile all cards from all opponents' hands and graveyards. diff --git a/forge-gui/res/cardsfolder/b/bronzehide_lion.txt b/forge-gui/res/cardsfolder/b/bronzehide_lion.txt index b974475c340..41932122b90 100644 --- a/forge-gui/res/cardsfolder/b/bronzehide_lion.txt +++ b/forge-gui/res/cardsfolder/b/bronzehide_lion.txt @@ -4,8 +4,8 @@ Types:Creature Cat PT:3/3 A:AB$ Pump | Cost$ G W | KW$ Indestructible | Defined$ Self | SpellDescription$ CARDNAME gains indestructible until end of turn. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ DBReturn | TriggerDescription$ When CARDNAME dies, return it to the battlefield. It's an Aura enchantment with enchant creature you control and "{G}{W}: Enchanted creature gains indestructible until end of turn," and it loses all other abilities. -SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Enchantment,Aura | RemoveCardTypes$ True | RemoveAllAbilities$ True | Keywords$ Enchant creature you control | Abilities$ SPAttach,ABPump | Duration$ Permanent +SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Aura & Enchantment | RemoveCardTypes$ True | RemoveAllAbilities$ True | AddKeyword$ Enchant creature you control | AddAbility$ SPAttach & ABPump SVar:SPAttach:SP$ Attach | Cost$ 0 | ValidTgts$ Creature.YouCtrl | AILogic$ Pump SVar:ABPump:AB$ Pump | Cost$ G W | KW$ Indestructible | Defined$ Enchanted | SpellDescription$ Enchanted creature gains indestructible until end of turn. Oracle:{G}{W}: Bronzehide Lion gains indestructible until end of turn.\nWhen Bronzehide Lion dies, return it to the battlefield. It's an Aura enchantment with enchant creature you control and "{G}{W}: Enchanted creature gains indestructible until end of turn," and it loses all other abilities. From 93f2f841d176dffc5694d5fb3fa536cb74adc4d9 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Thu, 23 Jan 2025 20:14:42 +0100 Subject: [PATCH 14/17] Apply effect before RE --- .../src/main/java/forge/game/GameAction.java | 79 +++++++++++-------- .../res/cardsfolder/e/enduring_courage.txt | 4 +- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 57bc25b69d4..9abda7226e6 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -292,6 +292,34 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer table = new GameEntityCounterTable(); } + final Card staticEff = setupStaticEffect(copied, cause); + + // Aura entering indirectly + // need to check before it enters + if (copied.isAura() && !copied.isAttachedToEntity() && toBattlefield && (zoneFrom == null || !zoneFrom.is(ZoneType.Stack))) { + boolean found = false; + if (game.getPlayers().stream().anyMatch(PlayerPredicates.canBeAttached(copied, null))) { + found = true; + } + + if (!found) { + if (lastBattlefield.anyMatch(CardPredicates.canBeAttached(copied, null))) { + found = true; + } + } + + if (!found) { + if (lastGraveyard.anyMatch(CardPredicates.canBeAttached(copied, null))) { + found = true; + } + } + if (!found) { + c.clearControllers(); + cleanStaticEffect(staticEff, copied); + return c; + } + } + if (!suppress) { // Temporary disable commander replacement effect // 903.9a @@ -333,6 +361,7 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer if (repres == ReplacementResult.Prevented) { c.clearControllers(); + cleanStaticEffect(staticEff, copied); if (cause != null) { if (cause.hasParam("Transformed") || cause.hasParam("FaceDown")) { c.setBackSide(false); @@ -366,33 +395,6 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer copied.getOwner().removeInboundToken(copied); - handleStaticEffect(copied, cause); - - // Aura entering indirectly - // need to check before it enters - if (copied.isAura() && !copied.isAttachedToEntity() && toBattlefield && (zoneFrom == null || !zoneFrom.is(ZoneType.Stack))) { - boolean found = false; - if (game.getPlayers().stream().anyMatch(PlayerPredicates.canBeAttached(copied, null))) { - found = true; - } - - if (!found) { - if (lastBattlefield.anyMatch(CardPredicates.canBeAttached(copied, null))) { - found = true; - } - } - - if (!found) { - if (lastGraveyard.anyMatch(CardPredicates.canBeAttached(copied, null))) { - found = true; - } - } - if (!found) { - c.clearControllers(); - return c; - } - } - // Aura entering as Copy from stack // without targets it is sent to graveyard if (copied.isAura() && !copied.isAttachedToEntity() && toBattlefield) { @@ -723,10 +725,10 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer return copied; } - private void handleStaticEffect(Card copied, SpellAbility cause) { + private Card setupStaticEffect(Card copied, SpellAbility cause) { // CR 611.2e if (cause == null || !cause.hasParam("StaticEffect") || !copied.isPermanent()) { - return; + return null; } final Card source = cause.getHostCard(); @@ -735,13 +737,14 @@ private void handleStaticEffect(Card copied, SpellAbility cause) { int lhs = AbilityUtils.calculateAmount(source, cause.getParam("StaticEffectCheckSVar"), cause); int rhs = AbilityUtils.calculateAmount(source, cmp.substring(2), cause); if (!Expressions.compare(lhs, cmp, rhs)) { - return; + return null; } } Long timestamp; // check if player ordered it manually if (cause.hasSVar("StaticEffectTimestamp")) { + // TODO the copied card won't have new timestamp yet timestamp = Long.parseLong(cause.getSVar("StaticEffectTimestamp")); } else { // else create default value (or realign) @@ -763,16 +766,26 @@ private void handleStaticEffect(Card copied, SpellAbility cause) { eff.setRenderForUI(false); StaticAbility stAb = eff.addStaticAbility(AbilityUtils.getSVar(cause, cause.getParam("StaticEffect"))); stAb.putParam("EffectZone", "Command"); + // needed for ETB lookahead like Bronzehide Lion stAb.putParam("AffectedZone", "Battlefield,Hand,Graveyard,Exile,Stack,Library,Command"); - SpellAbilityEffect.addForgetOnMovedTrigger(copied, "Battlefield"); + SpellAbilityEffect.addForgetOnMovedTrigger(eff, "Battlefield"); game.getAction().moveToCommand(eff, cause); } eff.addRemembered(copied); - - // refresh needed for effects like Bronzehide Lion + // refresh needed for canEnchant checks game.getAction().checkStaticAbilities(false, Sets.newHashSet(copied), new CardCollection(copied)); + return eff; } + private void cleanStaticEffect(Card eff, Card copied) { + if (eff != null) { + eff.removeRemembered(copied); + if (!eff.hasRemembered()) { + exileEffect(eff); + } + } + } + private void storeChangesZoneAll(Card c, Zone zoneFrom, Zone zoneTo, Map params) { if (params != null && params.containsKey(AbilityKey.InternalTriggerTable)) { diff --git a/forge-gui/res/cardsfolder/e/enduring_courage.txt b/forge-gui/res/cardsfolder/e/enduring_courage.txt index 816e218e594..2f6756d04cf 100644 --- a/forge-gui/res/cardsfolder/e/enduring_courage.txt +++ b/forge-gui/res/cardsfolder/e/enduring_courage.txt @@ -5,6 +5,6 @@ PT:3/3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever another creature you control enters, it gets +2/+0 and gains haste until end of turn. SVar:TrigPump:DB$ Pump | Defined$ TriggeredCardLKICopy | NumAtt$ +2 | KW$ Haste T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self+Creature | Execute$ DBReturn | TriggerDescription$ When CARDNAME dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) -SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Enchantment | RemoveCardTypes$ True | Duration$ Permanent +SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Enchantment | RemoveCardTypes$ True Oracle:Whenever another creature you control enters, it gets +2/+0 and gains haste until end of turn.\nWhen Enduring Courage dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) From f74b4236fe48762ece3e0e23da868f9ebd3e521a Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Thu, 23 Jan 2025 21:27:23 +0100 Subject: [PATCH 15/17] Update scripts --- .../src/main/java/forge/game/GameAction.java | 14 +++++++------- .../staticability/StaticAbilityContinuous.java | 4 +--- .../res/cardsfolder/c/call_a_surprise_witness.txt | 4 ++-- .../res/cardsfolder/c/chainer_dementia_master.txt | 4 ++-- .../cardsfolder/d/drana_the_last_bloodchief.txt | 4 ++-- forge-gui/res/cardsfolder/d/dread_slaver.txt | 4 ++-- forge-gui/res/cardsfolder/e/enduring_curiosity.txt | 4 ++-- .../res/cardsfolder/e/enduring_friendship.txt | 4 ++-- forge-gui/res/cardsfolder/e/enduring_innocence.txt | 4 ++-- forge-gui/res/cardsfolder/e/enduring_tenacity.txt | 4 ++-- forge-gui/res/cardsfolder/e/enduring_vitality.txt | 4 ++-- forge-gui/res/cardsfolder/g/ghost_vacuum.txt | 4 ++-- forge-gui/res/cardsfolder/g/ghouls_night_out.txt | 7 ++++--- forge-gui/res/cardsfolder/g/grave_betrayal.txt | 4 ++-- .../res/cardsfolder/g/grimoire_of_the_dead.txt | 4 ++-- .../cardsfolder/h/harold_and_bob_first_numens.txt | 4 ++-- forge-gui/res/cardsfolder/i/infernal_vessel.txt | 4 ++-- .../res/cardsfolder/l/liliana_deaths_majesty.txt | 4 ++-- .../res/cardsfolder/l/lim_dul_the_necromancer.txt | 4 ++-- .../res/cardsfolder/l/lorcan_warlock_collector.txt | 4 ++-- .../cardsfolder/m/magar_of_the_magic_strings.txt | 6 ++++-- .../res/cardsfolder/n/necromantic_selection.txt | 10 ++++------ forge-gui/res/cardsfolder/o/old_growth_troll.txt | 4 ++-- .../res/cardsfolder/o/otherworldly_escort.txt | 4 ++-- .../res/cardsfolder/p/path_of_the_schemer.txt | 6 +++--- forge-gui/res/cardsfolder/p/portal_to_phyrexia.txt | 4 ++-- forge-gui/res/cardsfolder/r/relive_the_past.txt | 8 ++++---- .../res/cardsfolder/r/rise_from_the_grave.txt | 4 ++-- .../cardsfolder/s/shilgengar_sire_of_famine.txt | 4 ++-- .../res/cardsfolder/s/sorin_vengeful_bloodlord.txt | 4 ++-- forge-gui/res/cardsfolder/s/spawning_pod.txt | 4 ++-- forge-gui/res/cardsfolder/s/storm_of_souls.txt | 4 ++-- forge-gui/res/cardsfolder/t/terror_of_towashi.txt | 4 ++-- .../res/cardsfolder/t/the_master_transcendent.txt | 4 ++-- forge-gui/res/cardsfolder/t/the_war_in_heaven.txt | 4 ++-- forge-gui/res/cardsfolder/v/valkyries_call.txt | 4 ++-- .../res/cardsfolder/v/vraska_the_silencer.txt | 4 ++-- 37 files changed, 87 insertions(+), 88 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 9abda7226e6..29f4bbf5c2f 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -285,13 +285,6 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer // ensure that any leftover keyword/type changes are cleared in the state view copied.updateStateForView(); - GameEntityCounterTable table; - if (params != null && params.containsKey(AbilityKey.CounterTable)) { - table = (GameEntityCounterTable) params.get(AbilityKey.CounterTable); - } else { - table = new GameEntityCounterTable(); - } - final Card staticEff = setupStaticEffect(copied, cause); // Aura entering indirectly @@ -320,6 +313,13 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer } } + GameEntityCounterTable table; + if (params != null && params.containsKey(AbilityKey.CounterTable)) { + table = (GameEntityCounterTable) params.get(AbilityKey.CounterTable); + } else { + table = new GameEntityCounterTable(); + } + if (!suppress) { // Temporary disable commander replacement effect // 903.9a diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java index f1031c220b1..93ce5bea821 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -592,9 +592,7 @@ public static CardCollectionView applyContinuousAbility(final StaticAbility stAb } // start modifying the cards - for (int i = 0; i < affectedCards.size(); i++) { - final Card affectedCard = affectedCards.get(i); - + for (Card affectedCard : affectedCards) { // Gain control if (layer == StaticAbilityLayer.CONTROL && params.containsKey("GainControl")) { final PlayerCollection gain = AbilityUtils.getDefinedPlayers(hostCard, params.get("GainControl"), stAb); diff --git a/forge-gui/res/cardsfolder/c/call_a_surprise_witness.txt b/forge-gui/res/cardsfolder/c/call_a_surprise_witness.txt index 8b68815a23f..f83fe90706b 100644 --- a/forge-gui/res/cardsfolder/c/call_a_surprise_witness.txt +++ b/forge-gui/res/cardsfolder/c/call_a_surprise_witness.txt @@ -1,9 +1,9 @@ Name:Call a Surprise Witness ManaCost:1 W Types:Sorcery -A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouCtrl+cmcLE3 | AnimateSubAbility$ DBAnimate | RememberChanged$ True | SubAbility$ DBPutCounter | TgtPrompt$ Select target creature card with mana value 3 or less | StackDescription$ REP Return_{p:You} returns & target creature card with mana value 3 or less_{c:Targeted} & your_their & Put_{p:You} puts & on it_on {c:Targeted} | SpellDescription$ Return target creature card with mana value 3 or less from your graveyard to the battlefield. Put a flying counter on it. It's a Spirit in addition to its other types. +A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouCtrl+cmcLE3 | StaticEffect$ Animate | RememberChanged$ True | SubAbility$ DBPutCounter | TgtPrompt$ Select target creature card with mana value 3 or less | StackDescription$ REP Return_{p:You} returns & target creature card with mana value 3 or less_{c:Targeted} & your_their & Put_{p:You} puts & on it_on {c:Targeted} | SpellDescription$ Return target creature card with mana value 3 or less from your graveyard to the battlefield. Put a flying counter on it. It's a Spirit in addition to its other types. SVar:DBPutCounter:DB$ PutCounter | Defined$ Remembered | CounterType$ Flying | CounterNum$ 1 | SubAbility$ DBCleanup | StackDescription$ None -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Spirit | Duration$ Permanent +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Spirit SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True DeckHas:Ability$Graveyard & Type$Spirit Oracle:Return target creature card with mana value 3 or less from your graveyard to the battlefield. Put a flying counter on it. It's a Spirit in addition to its other types. diff --git a/forge-gui/res/cardsfolder/c/chainer_dementia_master.txt b/forge-gui/res/cardsfolder/c/chainer_dementia_master.txt index d824574d35a..15e143c3788 100644 --- a/forge-gui/res/cardsfolder/c/chainer_dementia_master.txt +++ b/forge-gui/res/cardsfolder/c/chainer_dementia_master.txt @@ -3,8 +3,8 @@ ManaCost:3 B B Types:Legendary Creature Human Minion PT:3/3 S:Mode$ Continuous | Affected$ Creature.Nightmare | AddPower$ 1 | AddToughness$ 1 | Description$ Nightmare creatures get +1/+1. -A:AB$ ChangeZone | Cost$ B B B PayLife<3> | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | TgtPrompt$ Select target creature card in a graveyard | ValidTgts$ Creature | ChangeNum$ 1 | AnimateSubAbility$ DBAnimate | SpellDescription$ Put target creature card from a graveyard onto the battlefield under your control. That creature is black and is a Nightmare in addition to its other creature types. -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Nightmare | Colors$ Black | Duration$ Permanent | OverwriteColors$ True +A:AB$ ChangeZone | Cost$ B B B PayLife<3> | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | TgtPrompt$ Select target creature card in a graveyard | ValidTgts$ Creature | ChangeNum$ 1 | StaticEffect$ Animate | SpellDescription$ Put target creature card from a graveyard onto the battlefield under your control. That creature is black and is a Nightmare in addition to its other creature types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Nightmare | SetColor$ Black T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME leaves the battlefield, exile all Nightmares. SVar:TrigExile:DB$ ChangeZoneAll | Origin$ Battlefield | Destination$ Exile | ChangeType$ Nightmare SVar:PlayMain1:TRUE diff --git a/forge-gui/res/cardsfolder/d/drana_the_last_bloodchief.txt b/forge-gui/res/cardsfolder/d/drana_the_last_bloodchief.txt index 603b2f4b0e4..3b7085b604a 100644 --- a/forge-gui/res/cardsfolder/d/drana_the_last_bloodchief.txt +++ b/forge-gui/res/cardsfolder/d/drana_the_last_bloodchief.txt @@ -5,8 +5,8 @@ PT:4/4 K:Flying T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigChoose | TriggerDescription$ Whenever CARDNAME attacks, defending player chooses a nonlegendary creature card in your graveyard. You return that card to the battlefield with an additional +1/+1 counter on it. The creature is a Vampire in addition to its other types. SVar:TrigChoose:DB$ ChooseCard | Defined$ TriggeredDefendingPlayer | Choices$ Creature.YouOwn+nonLegendary | Mandatory$ True | ChoiceZone$ Graveyard | AILogic$ WorstCard | SubAbility$ DBChangeZone -SVar:DBChangeZone:DB$ ChangeZone | Defined$ ChosenCard | Origin$ Graveyard | Destination$ Battlefield | WithCountersType$ P1P1 | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ ChosenCard | Types$ Vampire | Duration$ Permanent +SVar:DBChangeZone:DB$ ChangeZone | Defined$ ChosenCard | Origin$ Graveyard | Destination$ Battlefield | WithCountersType$ P1P1 | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Vampire DeckHas:Ability$Graveyard|Counters DeckHints:Type$Vampire Oracle:Flying\nWhenever Drana, the Last Bloodchief attacks, defending player chooses a nonlegendary creature card in your graveyard. You return that card to the battlefield with an additional +1/+1 counter on it. The creature is a Vampire in addition to its other types. diff --git a/forge-gui/res/cardsfolder/d/dread_slaver.txt b/forge-gui/res/cardsfolder/d/dread_slaver.txt index ce775d826ff..22123f224bc 100644 --- a/forge-gui/res/cardsfolder/d/dread_slaver.txt +++ b/forge-gui/res/cardsfolder/d/dread_slaver.txt @@ -3,6 +3,6 @@ ManaCost:3 B B Types:Creature Zombie Horror PT:3/5 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.DamagedBy | Execute$ TrigChange | TriggerDescription$ Whenever a creature dealt damage by CARDNAME this turn dies, return it to the battlefield under your control. That creature is a black Zombie in addition to its other colors and types. -SVar:TrigChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | Defined$ TriggeredNewCardLKICopy | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Zombie | Colors$ Black | Duration$ Permanent +SVar:TrigChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | Defined$ TriggeredNewCardLKICopy | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Zombie | AddColor$ Black Oracle:Whenever a creature dealt damage by Dread Slaver this turn dies, return it to the battlefield under your control. That creature is a black Zombie in addition to its other colors and types. diff --git a/forge-gui/res/cardsfolder/e/enduring_curiosity.txt b/forge-gui/res/cardsfolder/e/enduring_curiosity.txt index 0dfa2d3975f..5bd6723ed5d 100644 --- a/forge-gui/res/cardsfolder/e/enduring_curiosity.txt +++ b/forge-gui/res/cardsfolder/e/enduring_curiosity.txt @@ -6,6 +6,6 @@ K:Flash T:Mode$ DamageDone | ValidSource$ Creature.YouCtrl | ValidTarget$ Player | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever a creature you control deals combat damage to a player, draw a card. SVar:TrigDraw:DB$ Draw | NumCards$ 1 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self+Creature | Execute$ DBReturn | TriggerDescription$ When CARDNAME dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) -SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Enchantment | RemoveCardTypes$ True | Duration$ Permanent +SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Enchantment | RemoveCardTypes$ True Oracle:Flash\nWhenever a creature you control deals combat damage to a player, draw a card.\nWhen Enduring Curiosity dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) diff --git a/forge-gui/res/cardsfolder/e/enduring_friendship.txt b/forge-gui/res/cardsfolder/e/enduring_friendship.txt index cf941ad51e2..a8ab72288c5 100644 --- a/forge-gui/res/cardsfolder/e/enduring_friendship.txt +++ b/forge-gui/res/cardsfolder/e/enduring_friendship.txt @@ -6,6 +6,6 @@ K:Double team T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast an instant or sorcery spell, creatures you control that are Otters and/or enchantments get +1/+1 until end of turn. SVar:TrigPump:DB$ PumpAll | ValidCards$ Creature.Otter+YouCtrl,Creature.Enchantment+YouCtrl | NumAtt$ 1 | NumDef$ 1 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self+Creature | Execute$ DBReturn | TriggerDescription$ When CARDNAME dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) -SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Enchantment | RemoveCardTypes$ True | Duration$ Permanent +SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Enchantment | RemoveCardTypes$ True Oracle:Double team\nWhenever you cast an instant or sorcery spell, creatures you control that are Otters and/or enchantments get +1/+1 until end of turn. When Enduring Friendship dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) diff --git a/forge-gui/res/cardsfolder/e/enduring_innocence.txt b/forge-gui/res/cardsfolder/e/enduring_innocence.txt index 0d75dca8b87..4f86d17a3a3 100644 --- a/forge-gui/res/cardsfolder/e/enduring_innocence.txt +++ b/forge-gui/res/cardsfolder/e/enduring_innocence.txt @@ -6,7 +6,7 @@ K:Lifelink T:Mode$ ChangesZoneAll | ValidCards$ Creature.powerLE2+YouCtrl+Other | Destination$ Battlefield | TriggerZones$ Battlefield | ActivationLimit$ 1 | Execute$ TrigDraw | TriggerDescription$ Whenever one or more other creatures you control with power 2 or less enter, draw a card. This ability triggers only once each turn. SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self+Creature | Execute$ DBReturn | TriggerDescription$ When CARDNAME dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) -SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Enchantment | RemoveCardTypes$ True | Duration$ Permanent +SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Enchantment | RemoveCardTypes$ True SVar:BuffedBy:Creature.powerLE2 Oracle:Lifelink\nWhenever one or more other creatures you control with power 2 or less enter, draw a card. This ability triggers only once each turn.\nWhen Enduring Innocence dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) diff --git a/forge-gui/res/cardsfolder/e/enduring_tenacity.txt b/forge-gui/res/cardsfolder/e/enduring_tenacity.txt index f6b376db3ac..4a3ea4e8e41 100644 --- a/forge-gui/res/cardsfolder/e/enduring_tenacity.txt +++ b/forge-gui/res/cardsfolder/e/enduring_tenacity.txt @@ -6,7 +6,7 @@ T:Mode$ LifeGained | ValidPlayer$ You | Execute$ TrigLoseLife | TriggerZones$ Ba SVar:TrigLoseLife:DB$ LoseLife | ValidTgts$ Opponent | LifeAmount$ X SVar:X:TriggerCount$LifeAmount T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self+Creature | Execute$ DBReturn | TriggerDescription$ When CARDNAME dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) -SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Enchantment | RemoveCardTypes$ True | Duration$ Permanent +SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Enchantment | RemoveCardTypes$ True DeckHints:Ability$LifeGain Oracle:Whenever you gain life, target opponent loses that much life.\nWhen Enduring Tenacity dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) diff --git a/forge-gui/res/cardsfolder/e/enduring_vitality.txt b/forge-gui/res/cardsfolder/e/enduring_vitality.txt index b228b413acc..e91a2d0f3c0 100644 --- a/forge-gui/res/cardsfolder/e/enduring_vitality.txt +++ b/forge-gui/res/cardsfolder/e/enduring_vitality.txt @@ -6,6 +6,6 @@ K:Vigilance S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddAbility$ AnyMana | Description$ Creatures you control have "{T}: Add one mana of any color." SVar:AnyMana:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 1 | SpellDescription$ Add one mana of any color. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self+Creature | Execute$ DBReturn | TriggerDescription$ When CARDNAME dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) -SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Enchantment | RemoveCardTypes$ True | Duration$ Permanent +SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Enchantment | RemoveCardTypes$ True Oracle:Creatures you control have "{T}: Add one mana of any color."\nWhen Enduring Vitality dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. (It's not a creature.) diff --git a/forge-gui/res/cardsfolder/g/ghost_vacuum.txt b/forge-gui/res/cardsfolder/g/ghost_vacuum.txt index 8c179257936..37779ec0365 100644 --- a/forge-gui/res/cardsfolder/g/ghost_vacuum.txt +++ b/forge-gui/res/cardsfolder/g/ghost_vacuum.txt @@ -2,7 +2,7 @@ Name:Ghost Vacuum ManaCost:1 Types:Artifact A:AB$ ChangeZone | Cost$ T | Origin$ Graveyard | Destination$ Exile | TgtPrompt$ Choose target card in a graveyard | ValidTgts$ Card | SpellDescription$ Exile target card from a graveyard. -A:AB$ ChangeZoneAll | Cost$ 6 T Sac<1/CARDNAME> | ChangeType$ Creature.ExiledWithSource | Origin$ Exile | Destination$ Battlefield | GainControl$ True | SorcerySpeed$ True | WithCountersType$ Flying | AnimateSubAbility$ DBAnimate | SpellDescription$ Put each creature card exiled with CARDNAME onto the battlefield under your control with a flying counter on it. Each of them is a 1/1 Spirit in addition to its other types. Activate only as a sorcery. -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Power$ 1 | Toughness$ 1 | Types$ Spirit | Duration$ Permanent +A:AB$ ChangeZoneAll | Cost$ 6 T Sac<1/CARDNAME> | ChangeType$ Creature.ExiledWithSource | Origin$ Exile | Destination$ Battlefield | GainControl$ True | SorcerySpeed$ True | WithCountersType$ Flying | StaticEffect$ Animate | SpellDescription$ Put each creature card exiled with CARDNAME onto the battlefield under your control with a flying counter on it. Each of them is a 1/1 Spirit in addition to its other types. Activate only as a sorcery. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Spirit | SetPower$ 1 | SetToughness$ 1 DeckHas:Ability$Counters Oracle:{T}: Exile target card from a graveyard.\n{6}, {T}, Sacrifice Ghost Vacuum: Put each creature card exiled with Ghost Vacuum onto the battlefield under your control with a flying counter on it. Each of them is a 1/1 Spirit in addition to its other types. Activate only as a sorcery. diff --git a/forge-gui/res/cardsfolder/g/ghouls_night_out.txt b/forge-gui/res/cardsfolder/g/ghouls_night_out.txt index 72862d03dd1..56512b81c5f 100644 --- a/forge-gui/res/cardsfolder/g/ghouls_night_out.txt +++ b/forge-gui/res/cardsfolder/g/ghouls_night_out.txt @@ -3,8 +3,9 @@ ManaCost:3 B B Types:Sorcery A:SP$ RepeatEach | RepeatPlayers$ Player | RepeatSubAbility$ DBChoose | SubAbility$ DBChangeZone | StackDescription$ SpellDescription | SpellDescription$ For each player, choose a creature card in that player's graveyard. Put those cards onto the battlefield under your control. They're black Zombies in addition to their other colors and types and they gain decayed. (A creature with decayed can't block. When it attacks, sacrifice it at end of combat.) SVar:DBChoose:DB$ ChooseCard | Defined$ You | Choices$ Creature.RememberedPlayerCtrl | ChoiceZone$ Graveyard | Mandatory$ True | Amount$ 1 | ChoiceTitle$ Choose a creature card in this player's graveyard | ImprintChosen$ True -SVar:DBChangeZone:DB$ ChangeZone | Defined$ Imprinted | GainControl$ True | Origin$ Graveyard | Destination$ Battlefield | AnimateSubAbility$ DBAnimate | StackDescription$ None -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Zombie | Colors$ Black | Keywords$ Decayed | Duration$ Permanent | SubAbility$ DBCleanup -SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True | ClearImprinted$ True +SVar:DBChangeZone:DB$ ChangeZone | Defined$ Imprinted | RememberChanged$ True | GainControl$ True | Origin$ Graveyard | Destination$ Battlefield | StaticEffect$ Animate | SubAbility$ DBPump | StackDescription$ None +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Zombie | AddColor$ Black +SVar:DBPump:DB$ Pump | Defined$ Remembered | Keywords$ Decayed | Duration$ Permanent | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True | ClearImprinted$ True | ClearRemembered$ True DeckHas:Ability$Graveyard & Type$Zombie Oracle:For each player, choose a creature card in that player's graveyard. Put those cards onto the battlefield under your control. They're black Zombies in addition to their other colors and types and they gain decayed. (A creature with decayed can't block. When it attacks, sacrifice it at end of combat.) diff --git a/forge-gui/res/cardsfolder/g/grave_betrayal.txt b/forge-gui/res/cardsfolder/g/grave_betrayal.txt index 99f4495b0f5..896ba367c0a 100644 --- a/forge-gui/res/cardsfolder/g/grave_betrayal.txt +++ b/forge-gui/res/cardsfolder/g/grave_betrayal.txt @@ -3,6 +3,6 @@ ManaCost:5 B B Types:Enchantment T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouDontCtrl | TriggerZones$ Battlefield | Execute$ DelTrig | TriggerDescription$ Whenever a creature you don't control dies, return it to the battlefield under your control with an additional +1/+1 counter on it at the beginning of the next end step. That creature is a black Zombie in addition to its other colors and types. SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ GBReturn | RememberObjects$ TriggeredNewCardLKICopy | TriggerDescription$ Return creature to the battlefield under your control with an additional +1/+1 counter on it at the beginning of the next end step. It is a black Zombie in addition to its other colors and types. -SVar:GBReturn:DB$ ChangeZone | Defined$ DelayTriggerRememberedLKI | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | WithCountersType$ P1P1 | AnimateSubAbility$ GBZombify -SVar:GBZombify:DB$ Animate | Defined$ Remembered | Types$ Zombie | Colors$ Black | Duration$ Permanent +SVar:GBReturn:DB$ ChangeZone | Defined$ DelayTriggerRememberedLKI | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | WithCountersType$ P1P1 | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Zombie | AddColor$ Black Oracle:Whenever a creature you don't control dies, return it to the battlefield under your control with an additional +1/+1 counter on it at the beginning of the next end step. That creature is a black Zombie in addition to its other colors and types. diff --git a/forge-gui/res/cardsfolder/g/grimoire_of_the_dead.txt b/forge-gui/res/cardsfolder/g/grimoire_of_the_dead.txt index 40ccd0fc1bd..4bf0de37023 100644 --- a/forge-gui/res/cardsfolder/g/grimoire_of_the_dead.txt +++ b/forge-gui/res/cardsfolder/g/grimoire_of_the_dead.txt @@ -2,8 +2,8 @@ Name:Grimoire of the Dead ManaCost:4 Types:Legendary Artifact A:AB$ PutCounter | Cost$ 1 T Discard<1/Card> | Defined$ Self | CounterType$ STUDY | CounterNum$ 1 | SpellDescription$ Put a study counter on CARDNAME. -A:AB$ ChangeZoneAll | Cost$ T SubCounter<3/STUDY> Sac<1/CARDNAME> | ChangeType$ Creature | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | AnimateSubAbility$ DBAnimate | SpellDescription$ Put all creature cards in all graveyards onto the battlefield under your control. They are black Zombies in addition to their other colors and types. -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Colors$ Black | Types$ Zombie | Duration$ Permanent +A:AB$ ChangeZoneAll | Cost$ T SubCounter<3/STUDY> Sac<1/CARDNAME> | ChangeType$ Creature | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | StaticEffect$ Animate | SpellDescription$ Put all creature cards in all graveyards onto the battlefield under your control. They are black Zombies in addition to their other colors and types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Zombie | AddColor$ Black AI:RemoveDeck:All SVar:IsReanimatorCard:TRUE Oracle:{1}, {T}, Discard a card: Put a study counter on Grimoire of the Dead.\n{T}, Remove three study counters from Grimoire of the Dead and sacrifice it: Put all creature cards from all graveyards onto the battlefield under your control. They're black Zombies in addition to their other colors and types. diff --git a/forge-gui/res/cardsfolder/h/harold_and_bob_first_numens.txt b/forge-gui/res/cardsfolder/h/harold_and_bob_first_numens.txt index 5608714fe2d..6bf37a7d42f 100644 --- a/forge-gui/res/cardsfolder/h/harold_and_bob_first_numens.txt +++ b/forge-gui/res/cardsfolder/h/harold_and_bob_first_numens.txt @@ -5,8 +5,8 @@ PT:3/3 K:Vigilance K:Reach T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self+Creature | Execute$ DBReturn | TriggerDescription$ When CARDNAME dies, if it was a creature, return it to the battlefield. It's an Aura enchantment with enchant Forest you control and "Enchanted Forest has '{T}: Add three mana of any one color. You get two rad counters.'" NICKNAME loses all other abilities. -SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Enchantment,Aura | RemoveCardTypes$ True | RemoveAllAbilities$ True | Keywords$ Enchant Forest you control | Abilities$ SPAttach | staticAbilities$ STAura | Duration$ Permanent +SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Enchantment & Aura | RemoveCardTypes$ True | RemoveAllAbilities$ True | AddKeyword$ Enchant Forest you control | AddAbility$ SPAttach | AddStaticAbility$ STAura SVar:STAura:Mode$ Continuous | Affected$ Land.EnchantedBy | AddAbility$ ABMana | Description$ Enchanted Forest has "{T}: Add three mana of any one color. You get two rad counters." SVar:SPAttach:SP$ Attach | Cost$ 0 | ValidTgts$ Forest.YouCtrl | AILogic$ Pump SVar:ABMana:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 3 | SubAbility$ DBRadiation | SpellDescription$ Add three mana of any one color. You get two rad counters. diff --git a/forge-gui/res/cardsfolder/i/infernal_vessel.txt b/forge-gui/res/cardsfolder/i/infernal_vessel.txt index c129aef4a22..025edefdc4d 100644 --- a/forge-gui/res/cardsfolder/i/infernal_vessel.txt +++ b/forge-gui/res/cardsfolder/i/infernal_vessel.txt @@ -3,6 +3,6 @@ ManaCost:2 B Types:Creature Human Cleric PT:2/1 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self+nonDemon | Execute$ TrigReturn | TriggerDescription$ When this creature dies, if it wasn't a Demon, return it to the battlefield under its owner's control with two +1/+1 counters on it. It's a Demon in addition to its other types. -SVar:TrigReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ TriggeredNewCardLKICopy | WithCountersType$ P1P1 | WithCountersAmount$ 2 | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Demon | Duration$ Permanent +SVar:TrigReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ TriggeredNewCardLKICopy | WithCountersType$ P1P1 | WithCountersAmount$ 2 | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Demon Oracle:When this creature dies, if it wasn't a Demon, return it to the battlefield under its owner's control with two +1/+1 counters on it. It's a Demon in addition to its other types. diff --git a/forge-gui/res/cardsfolder/l/liliana_deaths_majesty.txt b/forge-gui/res/cardsfolder/l/liliana_deaths_majesty.txt index 542e9e2c337..1a8f7fd4f37 100644 --- a/forge-gui/res/cardsfolder/l/liliana_deaths_majesty.txt +++ b/forge-gui/res/cardsfolder/l/liliana_deaths_majesty.txt @@ -4,8 +4,8 @@ Types:Legendary Planeswalker Liliana Loyalty:5 A:AB$ Token | Cost$ AddCounter<1/LOYALTY> | TokenAmount$ 1 | TokenScript$ b_2_2_zombie | TokenOwner$ You | Planeswalker$ True | SubAbility$ DBMill | SpellDescription$ Create a 2/2 black Zombie creature token. Mill two cards. SVar:DBMill:DB$ Mill | Defined$ You | NumCards$ 2 -A:AB$ ChangeZone | Cost$ SubCounter<3/LOYALTY> | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouCtrl | AnimateSubAbility$ Animate | TgtPrompt$ Select target creature card from your graveyard | Planeswalker$ True | SpellDescription$ Return target creature card from your graveyard to the battlefield. That creature is a black Zombie in addition to its other colors and types. -SVar:Animate:DB$ Animate | Defined$ Remembered | Types$ Zombie | Colors$ Black | Duration$ Permanent +A:AB$ ChangeZone | Cost$ SubCounter<3/LOYALTY> | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouCtrl | StaticEffect$ Animate | TgtPrompt$ Select target creature card from your graveyard | Planeswalker$ True | SpellDescription$ Return target creature card from your graveyard to the battlefield. That creature is a black Zombie in addition to its other colors and types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Zombie | AddColor$ Black A:AB$ DestroyAll | Cost$ SubCounter<7/LOYALTY> | Ultimate$ True | ValidCards$ Creature.nonZombie | Planeswalker$ True | SpellDescription$ Destroy all non-Zombie creatures. DeckHas:Ability$Token|Graveyard DeckHints:Type$Zombie diff --git a/forge-gui/res/cardsfolder/l/lim_dul_the_necromancer.txt b/forge-gui/res/cardsfolder/l/lim_dul_the_necromancer.txt index eef17479a38..fac03cba645 100644 --- a/forge-gui/res/cardsfolder/l/lim_dul_the_necromancer.txt +++ b/forge-gui/res/cardsfolder/l/lim_dul_the_necromancer.txt @@ -3,7 +3,7 @@ ManaCost:5 B B Types:Legendary Creature Human Wizard PT:4/4 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.OppCtrl | TriggerZones$ Battlefield | Execute$ TrigReturn | OptionalDecider$ You | TriggerDescription$ Whenever a creature an opponent controls dies, you may pay {1}{B}. If you do, return that card to the battlefield under your control. If it's a creature, it's a Zombie in addition to its other creature types. -SVar:TrigReturn:AB$ ChangeZone | Cost$ 1 B | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | Defined$ TriggeredNewCardLKICopy | AnimateSubAbility$ Animate -SVar:Animate:DB$ Animate | Defined$ Remembered | Types$ Zombie | Duration$ Permanent | ConditionDefined$ Remembered | ConditionPresent$ Creature +SVar:TrigReturn:AB$ ChangeZone | Cost$ 1 B | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | Defined$ TriggeredNewCardLKICopy | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Creature.IsRemembered | AddType$ Zombie A:AB$ Regenerate | ValidTgts$ Zombie | TgtPrompt$ Select target Zombie | Cost$ 1 B | SpellDescription$ Regenerate target Zombie. Oracle:Whenever a creature an opponent controls dies, you may pay {1}{B}. If you do, return that card to the battlefield under your control. If it's a creature, it's a Zombie in addition to its other creature types.\n{1}{B}: Regenerate target Zombie. diff --git a/forge-gui/res/cardsfolder/l/lorcan_warlock_collector.txt b/forge-gui/res/cardsfolder/l/lorcan_warlock_collector.txt index 20113dc5336..917b8af3d90 100644 --- a/forge-gui/res/cardsfolder/l/lorcan_warlock_collector.txt +++ b/forge-gui/res/cardsfolder/l/lorcan_warlock_collector.txt @@ -4,8 +4,8 @@ Types:Legendary Creature Devil PT:6/6 K:Flying T:Mode$ ChangesZone | Origin$ Any | Destination$ Graveyard | ValidCard$ Creature.nonToken+OppOwn | TriggerZones$ Battlefield | Execute$ TrigReanimate | TriggerDescription$ Whenever a creature card is put into an opponent's graveyard from anywhere, you may pay life equal to its mana value. If you do, put it onto the battlefield under your control. It's a Warlock in addition to its other types. -SVar:TrigReanimate:AB$ ChangeZone | Cost$ PayLife | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | ChangeNum$ 1 | AnimateSubAbility$ Animate -SVar:Animate:DB$ Animate | Defined$ Remembered | Types$ Warlock | Duration$ Permanent +SVar:TrigReanimate:AB$ ChangeZone | Cost$ PayLife | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | ChangeNum$ 1 | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Warlock SVar:X:TriggeredCard$CardManaCost R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Warlock.YouCtrl | ReplaceWith$ Exile | Description$ If a Warlock you control would die, exile it instead. SVar:Exile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ ReplacedCard diff --git a/forge-gui/res/cardsfolder/m/magar_of_the_magic_strings.txt b/forge-gui/res/cardsfolder/m/magar_of_the_magic_strings.txt index bea857cd922..38ed89b4711 100644 --- a/forge-gui/res/cardsfolder/m/magar_of_the_magic_strings.txt +++ b/forge-gui/res/cardsfolder/m/magar_of_the_magic_strings.txt @@ -2,8 +2,10 @@ Name:Magar of the Magic Strings ManaCost:1 B R Types:Legendary Creature Minotaur Performer PT:3/3 -A:AB$ ChangeZone | Cost$ 1 B R | ValidTgts$ Instant.YouOwn,Sorcery.YouOwn | TgtPrompt$ Select target instant or sorcery card in your graveyard | Origin$ Graveyard | Destination$ Battlefield | RememberLKI$ True | FaceDown$ True | FaceDownPower$ 3 | FaceDownToughness$ 3 | FaceDownSetType$ Creature | AnimateSubAbility$ DBAnimate | StackDescription$ REP Note_{p:You} notes & target instant or sorcery card in your graveyard_{c:Targeted} & put_puts | SpellDescription$ Note the name of target instant or sorcery card in your graveyard and put it onto the battlefield face down. It's a 3/3 creature with "Whenever this creature deals combat damage to a player, you may create a copy of the card with the noted name. You may cast the copy without paying its mana cost" and "If this creature would leave the battlefield, exile it instead of putting it anywhere else." -SVar:DBAnimate:DB$ Animate | RememberObjects$ RememberedLKI | Defined$ Remembered | Triggers$ DealsCDTrig | Replacements$ ReplaceDies | Duration$ Permanent +A:AB$ ChangeZone | Cost$ 1 B R | ValidTgts$ Instant.YouOwn,Sorcery.YouOwn | TgtPrompt$ Select target instant or sorcery card in your graveyard | Origin$ Graveyard | Destination$ Battlefield | RememberLKI$ True | FaceDown$ True | FaceDownPower$ 3 | FaceDownToughness$ 3 | FaceDownSetType$ Creature | StaticEffect$ Animate | RememberChanged$ True | SubAbility$ RememberSpell | StackDescription$ REP Note_{p:You} notes & target instant or sorcery card in your graveyard_{c:Targeted} & put_puts | SpellDescription$ Note the name of target instant or sorcery card in your graveyard and put it onto the battlefield face down. It's a 3/3 creature with "Whenever this creature deals combat damage to a player, you may create a copy of the card with the noted name. You may cast the copy without paying its mana cost" and "If this creature would leave the battlefield, exile it instead of putting it anywhere else." +SVar:RememberSpell:DB$ Animate | RememberObjects$ RememberedLKI | Defined$ Remembered | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddTrigger$ DealsCDTrig | AddReplacementEffect$ ReplaceDies SVar:DealsCDTrig:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigPlay | TriggerZones$ Battlefield | TriggerDescription$ Whenever this creature deals combat damage to a player, you may create a copy of the card with the noted name. You may cast the copy without paying its mana cost. SVar:TrigPlay:DB$ Play | Defined$ RememberedLKI | ZoneRegardless$ True | CopyCard$ True | ValidSA$ Spell | WithoutManaCost$ True | Optional$ True SVar:ReplaceDies:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | ExcludeDestination$ Exile | ValidCard$ Card.Self | ReplaceWith$ Exile | Description$ If this creature would leave the battlefield, exile it instead of putting it anywhere else. diff --git a/forge-gui/res/cardsfolder/n/necromantic_selection.txt b/forge-gui/res/cardsfolder/n/necromantic_selection.txt index dee0fa45228..4679bd93397 100644 --- a/forge-gui/res/cardsfolder/n/necromantic_selection.txt +++ b/forge-gui/res/cardsfolder/n/necromantic_selection.txt @@ -1,11 +1,9 @@ Name:Necromantic Selection ManaCost:4 B B B Types:Sorcery -A:SP$ DestroyAll | ValidCards$ Creature | RememberDestroyed$ True | SubAbility$ TrigImprint | SpellDescription$ Destroy all creatures, then return a creature card put into a graveyard this way to the battlefield under your control. It's a black Zombie in addition to its other colors and types. Exile CARDNAME. -SVar:TrigImprint:DB$ Pump | ImprintCards$ Remembered | SubAbility$ DBClearRemember | StackDescription$ None -SVar:DBClearRemember:DB$ Cleanup | ClearRemembered$ True | SubAbility$ DBReturn -SVar:DBReturn:DB$ ChangeZone | ChangeType$ Creature.nonToken+IsImprinted | ChangeNum$ 1 | Hidden$ True | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | AnimateSubAbility$ DBZombify | SubAbility$ DBCleanup -SVar:DBZombify:DB$ Animate | Defined$ Remembered | Types$ Zombie | Colors$ Black | Duration$ Permanent -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True | SubAbility$ DBChange +A:SP$ DestroyAll | ValidCards$ Creature | RememberDestroyed$ True | SubAbility$ DBReturn | SpellDescription$ Destroy all creatures, then return a creature card put into a graveyard this way to the battlefield under your control. It's a black Zombie in addition to its other colors and types. Exile CARDNAME. +SVar:DBReturn:DB$ ChangeZone | ChangeType$ Creature.nonToken+IsRemembered | ChangeNum$ 1 | Hidden$ True | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | StaticEffect$ Animate | SubAbility$ DBCleanup +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Zombie | AddColor$ Black +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | SubAbility$ DBChange SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | StackDescription$ None Oracle:Destroy all creatures, then return a creature card put into a graveyard this way to the battlefield under your control. It's a black Zombie in addition to its other colors and types. Exile Necromantic Selection. diff --git a/forge-gui/res/cardsfolder/o/old_growth_troll.txt b/forge-gui/res/cardsfolder/o/old_growth_troll.txt index 7b2c5e61209..77a09693bc5 100644 --- a/forge-gui/res/cardsfolder/o/old_growth_troll.txt +++ b/forge-gui/res/cardsfolder/o/old_growth_troll.txt @@ -4,8 +4,8 @@ Types:Creature Troll Warrior PT:4/4 K:Trample T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self+Creature | Execute$ DBReturn | TriggerDescription$ When CARDNAME dies, if it was a creature, return it to the battlefield. It's an Aura enchantment with enchant Forest you control and "Enchanted Forest has '{T}: Add {G}{G}' and '{1}, {T}, Sacrifice this land: Create a tapped 4/4 green Troll Warrior creature token with trample.'" -SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Enchantment,Aura | RemoveCardTypes$ True | RemoveAllAbilities$ True | Keywords$ Enchant Forest you control | Abilities$ SPAttach | staticAbilities$ STAura | Duration$ Permanent +SVar:DBReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Enchantment & Aura | RemoveCardTypes$ True | RemoveAllAbilities$ True | AddKeyword$ Enchant Forest you control | AddAbility$ SPAttach | AddStaticAbility$ STAura SVar:STAura:Mode$ Continuous | Affected$ Land.EnchantedBy | AddAbility$ ABMana & ABToken | Description$ Enchanted Forest has "{T}: Add {G}{G}" and "{1}, {T}, Sacrifice this land: Create a tapped 4/4 green Troll Warrior creature token with trample." SVar:SPAttach:SP$ Attach | Cost$ 0 | ValidTgts$ Forest.YouCtrl | AILogic$ Pump SVar:ABMana:AB$ Mana | Cost$ T | Produced$ G | Amount$ 2 | SpellDescription$ Add {G}{G}. diff --git a/forge-gui/res/cardsfolder/o/otherworldly_escort.txt b/forge-gui/res/cardsfolder/o/otherworldly_escort.txt index 4acc635c0f0..55ba44baf54 100644 --- a/forge-gui/res/cardsfolder/o/otherworldly_escort.txt +++ b/forge-gui/res/cardsfolder/o/otherworldly_escort.txt @@ -5,8 +5,8 @@ PT:4/3 K:Flash Oracle:Flash T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self+nonSpirit | Execute$ TrigReturn | TriggerDescription$ Whenever CARDNAME dies, if it's not a Spirit, return it to the battlefield under its owner's control with four charge counters on it. It's a Spirit Detective. (It's no longer a Human.) -SVar:TrigReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | WithCountersType$ CHARGE | WithCountersAmount$ 4 | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | RemoveCreatureTypes$ True | Types$ Spirit,Detective | Duration$ Permanent +SVar:TrigReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | WithCountersType$ CHARGE | WithCountersAmount$ 4 | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Spirit & Detective | RemoveCreatureTypes$ True A:AB$ Destroy | Cost$ 1 W T SubCounter<1/CHARGE> | ValidTgts$ Creature.dealtDamageToYouThisTurn | TgtPrompt$ Select target creature that dealt damage to you this turn | SpellDescription$ Destroy target creature that dealt damage to you this turn. DeckHas:Type$Spirit & Ability$Counters Oracle:When Otherworldly Escort dies, if it's not a Spirit, return it to the battlefield under its owner's control with four charge counters on it. It's a Spirit Detective. (It's no longer a Human.)\n{1}{W}, {T}, Remove a charge counter from Otherworldly Escort: Destroy target creature that dealt damage to you this turn. diff --git a/forge-gui/res/cardsfolder/p/path_of_the_schemer.txt b/forge-gui/res/cardsfolder/p/path_of_the_schemer.txt index 302e644328b..3975407f4c4 100644 --- a/forge-gui/res/cardsfolder/p/path_of_the_schemer.txt +++ b/forge-gui/res/cardsfolder/p/path_of_the_schemer.txt @@ -1,9 +1,9 @@ Name:Path of the Schemer ManaCost:4 B Types:Sorcery -A:SP$ Mill | NumCards$ 2 | Defined$ Player | SubAbility$ DBChangeZone | SpellDescription$ Each player mills two cards. Then you put a creature card from a graveyard onto the battlefield under your control. -SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature | ChangeNum$ 1 | Mandatory$ True | GainControl$ True | AnimateSubAbility$ Animate | SubAbility$ DBSpace | SelectPrompt$ Select a creature card in a graveyard | Hidden$ True | StackDescription$ SpellDescription | SpellDescription$ Then you put a creature card from a graveyard onto the battlefield under your control. -SVar:Animate:DB$ Animate | Defined$ Remembered | Types$ Phyrexian | Duration$ Permanent +A:SP$ Mill | NumCards$ 2 | Defined$ Player | SubAbility$ DBChangeZone | SpellDescription$ Each player mills two cards. +SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature | ChangeNum$ 1 | Mandatory$ True | GainControl$ True | StaticEffect$ Animate | SubAbility$ DBSpace | SelectPrompt$ Select a creature card in a graveyard | Hidden$ True | StackDescription$ SpellDescription | SpellDescription$ Then you put a creature card from a graveyard onto the battlefield under your control. It's an artifact in addition to its other types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Artifact SVar:DBSpace:DB$ BlankLine | SubAbility$ DBVote | SpellDescription$ ,,,,,, SVar:DBVote:DB$ Vote | Defined$ Player | VoteType$ Planeswalk,Chaos | VotePlaneswalk$ DBPlaneswalk | VoteChaos$ DBChaos | Tied$ DBChaos | StackDescription$ SpellDescription | SpellDescription$ Will of the Planeswalkers — Starting with you, each player votes for planeswalk or chaos. If planeswalk gets more votes, planeswalk. If chaos gets more votes or the vote is tied, chaos ensues. SVar:DBPlaneswalk:DB$ Planeswalk diff --git a/forge-gui/res/cardsfolder/p/portal_to_phyrexia.txt b/forge-gui/res/cardsfolder/p/portal_to_phyrexia.txt index 526a57dcfc4..53a27206b97 100644 --- a/forge-gui/res/cardsfolder/p/portal_to_phyrexia.txt +++ b/forge-gui/res/cardsfolder/p/portal_to_phyrexia.txt @@ -4,8 +4,8 @@ Types:Artifact T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSac | TriggerDescription$ When CARDNAME enters, each opponent sacrifices three creatures. SVar:TrigSac:DB$ Sacrifice | Defined$ Opponent | SacValid$ Creature | Amount$ 3 T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigChange | TriggerDescription$ At the beginning of your upkeep, put target creature card from a graveyard onto the battlefield under your control. It's a Phyrexian in addition to its other types. -SVar:TrigChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature | GainControl$ True | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Phyrexian | Duration$ Permanent +SVar:TrigChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature | GainControl$ True | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Phyrexian DeckHas:Ability$Sacrifice|Graveyard DeckHints:Keyword$Mill|Dredge & Type$Phyrexian Oracle:When Portal to Phyrexia enters, each opponent sacrifices three creatures.\nAt the beginning of your upkeep, put target creature card from a graveyard onto the battlefield under your control. It's a Phyrexian in addition to its other types. diff --git a/forge-gui/res/cardsfolder/r/relive_the_past.txt b/forge-gui/res/cardsfolder/r/relive_the_past.txt index 284b5a3db31..348ffec69a1 100644 --- a/forge-gui/res/cardsfolder/r/relive_the_past.txt +++ b/forge-gui/res/cardsfolder/r/relive_the_past.txt @@ -1,11 +1,11 @@ Name:Relive the Past ManaCost:5 G W Types:Sorcery -A:SP$ Pump | TgtZone$ Graveyard | ValidTgts$ Artifact.YouOwn | TargetMin$ 0 | TargetMax$ 1 | SubAbility$ DBLand | TgtPrompt$ Select up to one target artifact from your graveyard | SpellDescription$ Return up to one target artifact card, up to one target land card, and up to one target non-Aura enchantment card from your graveyard to the battlefield. +A:SP$ Pump | TgtZone$ Graveyard | ValidTgts$ Artifact.YouOwn | TargetMin$ 0 | TargetMax$ 1 | SubAbility$ DBLand | TgtPrompt$ Select up to one target artifact from your graveyard | SpellDescription$ Return up to one target artifact card, up to one target land card, and up to one target non-Aura enchantment card from your graveyard to the battlefield. They are 5/5 Elemental creatures in addition to their other types. SVar:DBLand:DB$ Pump | TgtZone$ Graveyard | ValidTgts$ Land.YouOwn | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select up to one target land from your graveyard | SubAbility$ DBEnchantment SVar:DBEnchantment:DB$ Pump | TgtZone$ Graveyard | SubAbility$ DBChangeZoneAll | ValidTgts$ Enchantment.nonAura+YouOwn | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select up to one target non-aura enchantment from your graveyard -SVar:DBChangeZoneAll:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ Targeted | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Creature,Elemental | Power$ 5 | Toughness$ 5 | Duration$ Permanent | SpellDescription$ They are 5/5 Elemental creatures in addition to their other types. +SVar:DBChangeZoneAll:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ Targeted | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Creature & Elemental | SetPower$ 5 | SetToughness$ 5 DeckHas:Ability$Graveyard & Type$Elemental DeckHints:Ability$Graveyard|Mill & Type$Enchantment|Artifact -Oracle:Return up to one target artifact card, up to one target land card, and up to one target non-Aura enchantment card from your graveyard to the battlefield. They are 5/5 Elemental creatures in addition to their other types. +Oracle:Return up to one target artifact card, up to one target land card, and up to one target non-Aura enchantment card from your graveyard to the battlefield. diff --git a/forge-gui/res/cardsfolder/r/rise_from_the_grave.txt b/forge-gui/res/cardsfolder/r/rise_from_the_grave.txt index 78185b18931..e76dc34ea2e 100644 --- a/forge-gui/res/cardsfolder/r/rise_from_the_grave.txt +++ b/forge-gui/res/cardsfolder/r/rise_from_the_grave.txt @@ -1,6 +1,6 @@ Name:Rise from the Grave ManaCost:4 B Types:Sorcery -A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | TgtPrompt$ Choose target creature card in a graveyard | ValidTgts$ Creature | AnimateSubAbility$ Animate | SpellDescription$ Put target creature card from a graveyard onto the battlefield under your control. That creature is a black Zombie in addition to its other colors and types. -SVar:Animate:DB$ Animate | Defined$ Remembered | Types$ Zombie | Colors$ Black | Duration$ Permanent +A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | TgtPrompt$ Choose target creature card in a graveyard | ValidTgts$ Creature | StaticEffect$ Animate | SpellDescription$ Put target creature card from a graveyard onto the battlefield under your control. That creature is a black Zombie in addition to its other colors and types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Zombie | AddColor$ Black Oracle:Put target creature card from a graveyard onto the battlefield under your control. That creature is a black Zombie in addition to its other colors and types. diff --git a/forge-gui/res/cardsfolder/s/shilgengar_sire_of_famine.txt b/forge-gui/res/cardsfolder/s/shilgengar_sire_of_famine.txt index 684f9caa83c..860885f1e6d 100644 --- a/forge-gui/res/cardsfolder/s/shilgengar_sire_of_famine.txt +++ b/forge-gui/res/cardsfolder/s/shilgengar_sire_of_famine.txt @@ -7,8 +7,8 @@ A:AB$ Token | Cost$ Sac<1/Creature.Other/another creature> | TokenScript$ c_a_bl SVar:X:Count$Compare AngelSac EQ1.SacT.1 SVar:SacT:Sacrificed$CardToughness SVar:AngelSac:Sacrificed$Valid Card.Angel -A:AB$ ChangeZoneAll | Cost$ WB WB WB Sac<6/Blood.token/Blood token> | WithCountersType$ FINALITY | AnimateSubAbility$ DBAnimate | ChangeType$ Creature.YouOwn | Origin$ Graveyard | Destination$ Battlefield | SpellDescription$ Return each creature card from your graveyard to the battlefield with a finality counter on it. Those creatures are Vampires in addition to their other types. -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Vampire | Duration$ Permanent +A:AB$ ChangeZoneAll | Cost$ WB WB WB Sac<6/Blood.token/Blood token> | WithCountersType$ FINALITY | StaticEffect$ Animate | ChangeType$ Creature.YouOwn | Origin$ Graveyard | Destination$ Battlefield | SpellDescription$ Return each creature card from your graveyard to the battlefield with a finality counter on it. Those creatures are Vampires in addition to their other types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Vampire DeckHas:Ability$Sacrifice|Graveyard|Token & Type$Blood|Vampire DeckHints:Ability$Mill & Type$Angel Oracle:Flying\nSacrifice another creature: Create a Blood token. If you sacrificed an Angel this way, create a number of Blood tokens equal to its toughness instead.\n{W/B}{W/B}{W/B}, Sacrifice six Blood tokens: Return each creature card from your graveyard to the battlefield with a finality counter on it. Those creatures are Vampires in addition to their other types. diff --git a/forge-gui/res/cardsfolder/s/sorin_vengeful_bloodlord.txt b/forge-gui/res/cardsfolder/s/sorin_vengeful_bloodlord.txt index a72cf2803a0..505ceac4764 100644 --- a/forge-gui/res/cardsfolder/s/sorin_vengeful_bloodlord.txt +++ b/forge-gui/res/cardsfolder/s/sorin_vengeful_bloodlord.txt @@ -5,7 +5,7 @@ Loyalty:4 S:Mode$ Continuous | Affected$ Creature.YouCtrl,Planeswalker.YouCtrl | AddKeyword$ Lifelink | Condition$ PlayerTurn | Description$ As long as it's your turn, creatures and planeswalkers you control have lifelink. SVar:NonStackingEffect:True A:AB$ DealDamage | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | ValidTgts$ Player,Planeswalker | TgtPrompt$ Select target player or planeswalker | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to target player or planeswalker. -A:AB$ ChangeZone | Cost$ SubCounter | Planeswalker$ True | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn+cmcEQX | AILogic$ SorinVengefulBloodlord | TgtPrompt$ Select target creature with mana value X from your graveyard | AnimateSubAbility$ Animate | SpellDescription$ Return target creature card with mana value X from your graveyard to the battlefield. That creature is a Vampire in addition to its other types. -SVar:Animate:DB$ Animate | Defined$ Remembered | Types$ Vampire | Duration$ Permanent +A:AB$ ChangeZone | Cost$ SubCounter | Planeswalker$ True | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn+cmcEQX | AILogic$ SorinVengefulBloodlord | TgtPrompt$ Select target creature with mana value X from your graveyard | StaticEffect$ Animate | SpellDescription$ Return target creature card with mana value X from your graveyard to the battlefield. That creature is a Vampire in addition to its other types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Vampire SVar:X:Count$xPaid Oracle:As long as it's your turn, creatures and planeswalkers you control have lifelink.\n[+2]: Sorin, Vengeful Bloodlord deals 1 damage to target player or planeswalker.\n[-X]: Return target creature card with mana value X from your graveyard to the battlefield. That creature is a Vampire in addition to its other types. diff --git a/forge-gui/res/cardsfolder/s/spawning_pod.txt b/forge-gui/res/cardsfolder/s/spawning_pod.txt index 38a4add3702..f14d03b0eae 100644 --- a/forge-gui/res/cardsfolder/s/spawning_pod.txt +++ b/forge-gui/res/cardsfolder/s/spawning_pod.txt @@ -2,8 +2,8 @@ Name:Spawning Pod ManaCost:2 G Types:Artifact A:AB$ Seek | Cost$ 1 T Sac<1/Creature> | Type$ Creature.cmcEQX | SorcerySpeed$ True | AILogic$ SacAndUpgrade | ImprintFound$ True | SubAbility$ DBPut | SpellDescription$ Seek a creature card with mana value equal to 1 plus the sacrificed creature's mana value and put that card onto the battlefield. That creature is a Phyrexian in addition to its other types. Activate only as a sorcery. -SVar:DBPut:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | Defined$ Imprinted | AnimateSubAbility$ DBAnimate | SubAbility$ DBCleanup -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Phyrexian | Duration$ Permanent +SVar:DBPut:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | Defined$ Imprinted | StaticEffect$ Animate | SubAbility$ DBCleanup +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Phyrexian SVar:DBCleanup:DB$ Cleanup | ClearImprinted$ True SVar:X:Sacrificed$CardManaCost/Plus.1 SVar:AIPreference:SacCost$Creature.nonToken diff --git a/forge-gui/res/cardsfolder/s/storm_of_souls.txt b/forge-gui/res/cardsfolder/s/storm_of_souls.txt index b092c2373ee..d0edb76b402 100644 --- a/forge-gui/res/cardsfolder/s/storm_of_souls.txt +++ b/forge-gui/res/cardsfolder/s/storm_of_souls.txt @@ -1,8 +1,8 @@ Name:Storm of Souls ManaCost:4 W W Types:Sorcery -A:SP$ ChangeZoneAll | ChangeType$ Creature.YouOwn | Origin$ Graveyard | Destination$ Battlefield | AnimateSubAbility$ DBAnimate | SubAbility$ DBExile | SpellDescription$ Return all creature cards from your graveyard to the battlefield. Each of them is a 1/1 Spirit with flying in addition to its other types. -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Power$ 1 | Toughness$ 1 | Types$ Spirit | Duration$ Permanent | Keywords$ Flying +A:SP$ ChangeZoneAll | ChangeType$ Creature.YouOwn | Origin$ Graveyard | Destination$ Battlefield | StaticEffect$ Animate | SubAbility$ DBExile | SpellDescription$ Return all creature cards from your graveyard to the battlefield. Each of them is a 1/1 Spirit with flying in addition to its other types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | SetPower$ 1 | SetToughness$ 1 | AddType$ Spirit | AddKeyword$ Flying SVar:DBExile:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | SpellDescription$ Exile CARDNAME. SVar:X:Count$TypeInYourYard.Creature SVar:NeedsToPlayVar:X GE4 diff --git a/forge-gui/res/cardsfolder/t/terror_of_towashi.txt b/forge-gui/res/cardsfolder/t/terror_of_towashi.txt index 4c4931b016f..042070c506e 100644 --- a/forge-gui/res/cardsfolder/t/terror_of_towashi.txt +++ b/forge-gui/res/cardsfolder/t/terror_of_towashi.txt @@ -5,8 +5,8 @@ PT:4/3 K:Deathtouch T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigImmediateTrig | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, you may pay {3}{B}. When you do, return target creature card from your graveyard to the battlefield. It's a Phyrexian in addition to its other types. SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ 3 B | Execute$ TrigReturn | TriggerDescription$ When you do, return target creature card from your graveyard to the battlefield. It's a Phyrexian in addition to its other types. -SVar:TrigReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select target creature card in your graveyard | AnimateSubAbility$ Animate -SVar:Animate:DB$ Animate | Defined$ Remembered | Types$ Phyrexian | Duration$ Permanent +SVar:TrigReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select target creature card in your graveyard | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Phyrexian SVar:HasAttackEffect:TRUE DeckHas:Ability$Graveyard Oracle:Deathtouch\nWhenever Terror of Towashi attacks, you may pay {3}{B}. When you do, return target creature card from your graveyard to the battlefield. It's a Phyrexian in addition to its other types. diff --git a/forge-gui/res/cardsfolder/t/the_master_transcendent.txt b/forge-gui/res/cardsfolder/t/the_master_transcendent.txt index e56a9fdbc78..f1d8ed6e0fb 100644 --- a/forge-gui/res/cardsfolder/t/the_master_transcendent.txt +++ b/forge-gui/res/cardsfolder/t/the_master_transcendent.txt @@ -4,8 +4,8 @@ Types:Legendary Artifact Creature Mutant PT:2/4 T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRadiation | TriggerDescription$ When CARDNAME enters, target player gets two rad counters. SVar:TrigRadiation:DB$ Radiation | ValidTgts$ Player | Num$ 2 -A:AB$ ChangeZone | Cost$ T | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | ValidTgts$ Creature.milledThisTurn | TgtPrompt$ Select target creature in a graveyard that was milled this turn | AnimateSubAbility$ Animate | SpellDescription$ Put target creature card in a graveyard that was milled this turn onto the battlefield under your control. It's a green Mutant with base power and toughness 3/3. (It loses its other colors and creature types.) -SVar:Animate:DB$ Animate | Defined$ Remembered | Types$ Mutant | Colors$ Green | OverwriteColors$ True | Power$ 3 | Toughness$ 3 | RemoveCreatureTypes$ True | Duration$ Permanent +A:AB$ ChangeZone | Cost$ T | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | ValidTgts$ Creature.milledThisTurn | TgtPrompt$ Select target creature in a graveyard that was milled this turn | StaticEffect$ Animate | SpellDescription$ Put target creature card in a graveyard that was milled this turn onto the battlefield under your control. It's a green Mutant with base power and toughness 3/3. (It loses its other colors and creature types.) +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Mutant | SetColor$ Green | SetPower$ 3 | SetToughness$ 3 | RemoveCreatureTypes$ True DeckHas:Ability$Mill DeckHints:Ability$Mill Oracle:When The Master, Transcendent enters, target player gets two rad counters.\n{T}: Put target creature card in a graveyard that was milled this turn onto the battlefield under your control. It's a green Mutant with base power and toughness 3/3. (It loses its other colors and creature types.) diff --git a/forge-gui/res/cardsfolder/t/the_war_in_heaven.txt b/forge-gui/res/cardsfolder/t/the_war_in_heaven.txt index 1f4784cbbde..536463378a9 100644 --- a/forge-gui/res/cardsfolder/t/the_war_in_heaven.txt +++ b/forge-gui/res/cardsfolder/t/the_war_in_heaven.txt @@ -5,7 +5,7 @@ K:Chapter:3:DBDraw,DBMill,DBChoose SVar:DBDraw:DB$ Draw | NumCards$ 3 | SubAbility$ DBLoseLife | SpellDescription$ You draw three cards and you lose 3 life. SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ 3 SVar:DBMill:DB$ Mill | NumCards$ 3 | SpellDescription$ Mill three cards. -SVar:DBChoose:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Select up to three target creature cards with total mana value 8 or less | TargetMin$ 0 | TargetMax$ 3 | MaxTotalTargetCMC$ 8 | ValidTgts$ Creature.YouOwn | WithCountersType$ NECRODERMIS | AnimateSubAbility$ Animate | SpellDescription$ Choose up to three target creature cards with total mana value 8 or less in your graveyard. Return each of them to the battlefield with a necrodermis counter on it. They're artifacts in addition to their other types. -SVar:Animate:DB$ Animate | Defined$ Remembered | Types$ Artifact | Duration$ Permanent +SVar:DBChoose:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Select up to three target creature cards with total mana value 8 or less | TargetMin$ 0 | TargetMax$ 3 | MaxTotalTargetCMC$ 8 | ValidTgts$ Creature.YouOwn | WithCountersType$ NECRODERMIS | StaticEffect$ Animate | SpellDescription$ Choose up to three target creature cards with total mana value 8 or less in your graveyard. Return each of them to the battlefield with a necrodermis counter on it. They're artifacts in addition to their other types. +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Artifact DeckHas:Ability$Graveyard|Mill|Counters & Type$Artifact Oracle:(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)\nI — You draw three cards and you lose 3 life.\nII — Mill three cards.\nIII — Choose up to three target creature cards with total mana value 8 or less in your graveyard. Return each of them to the battlefield with a necrodermis counter on it. They're artifacts in addition to their other types. diff --git a/forge-gui/res/cardsfolder/v/valkyries_call.txt b/forge-gui/res/cardsfolder/v/valkyries_call.txt index e2ac0eb9dd8..52d36c7f925 100644 --- a/forge-gui/res/cardsfolder/v/valkyries_call.txt +++ b/forge-gui/res/cardsfolder/v/valkyries_call.txt @@ -2,6 +2,6 @@ Name:Valkyrie's Call ManaCost:3 W W Types:Enchantment T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.nonToken+nonAngel+YouCtrl | TriggerZones$ Battlefield | Execute$ DBChangeZone | TriggerDescription$ Whenever a nontoken, non-Angel creature you control dies, return that card to the battlefield under its owner's control with a +1/+1 counter on it. It has flying and is an Angel in addition to its other types. -SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ TriggeredCard | WithCountersType$ P1P1 | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Keywords$ Flying | Types$ Angel | Duration$ Permanent +SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ TriggeredCard | WithCountersType$ P1P1 | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Angel | AddKeyword$ Flying Oracle:Whenever a nontoken, non-Angel creature you control dies, return that card to the battlefield under its owner's control with a +1/+1 counter on it. It has flying and is an Angel in addition to its other types. diff --git a/forge-gui/res/cardsfolder/v/vraska_the_silencer.txt b/forge-gui/res/cardsfolder/v/vraska_the_silencer.txt index 3c4d2003b36..98951bc98f6 100644 --- a/forge-gui/res/cardsfolder/v/vraska_the_silencer.txt +++ b/forge-gui/res/cardsfolder/v/vraska_the_silencer.txt @@ -4,8 +4,8 @@ Types:Legendary Creature Gorgon Assassin PT:3/3 K:Deathtouch T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.OppCtrl+nonToken | TriggerZones$ Battlefield | Execute$ TrigChangeZone | OptionalDecider$ You | TriggerDescription$ Whenever a nontoken creature an opponent controls dies, you may pay {1}. If you do, return that card to the battlefield tapped under your control. It's a Treasure artifact with "{T}, Sacrifice this artifact: Add one mana of any color," and it loses all other card types. -SVar:TrigChangeZone:AB$ ChangeZone | Cost$ 1 | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | Tapped$ True | AnimateSubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Types$ Artifact,Treasure | RemoveCardTypes$ True | Abilities$ TreasureSac | Duration$ Permanent +SVar:TrigChangeZone:AB$ ChangeZone | Cost$ 1 | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | Tapped$ True | StaticEffect$ Animate +SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Artifact & Treasure | RemoveCardTypes$ True | AddAbility$ TreasureSac SVar:TreasureSac:AB$ Mana | Cost$ T Sac<1/CARDNAME/this artifact> | Produced$ Any | SpellDescription$ Add one mana of any color. DeckHas:Type$Artifact|Treasure Oracle:Deathtouch\nWhenever a nontoken creature an opponent controls dies, you may pay {1}. If you do, return that card to the battlefield tapped under your control. It's a Treasure artifact with "{T}, Sacrifice this artifact: Add one mana of any color," and it loses all other card types. From f077628803355def4dfc4da272cf7b0ec44075a9 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 28 Jan 2025 08:35:31 +0100 Subject: [PATCH 16/17] Fix order after creating it earlier --- forge-game/src/main/java/forge/game/GameActionUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index 89662c228ab..c615cf07a56 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -870,9 +870,9 @@ public static CardCollectionView orderCardsByTheirOwners(Game game, CardCollecti } if (eff != null) { int idx = completeList.indexOf(eff); - if (idx > 0) { + if (idx < completeList.size() - 1) { // effects with this param have the responsibility to realign it when later cards are reached - sa.setSVar("StaticEffectUntilCardID", String.valueOf(completeList.get(idx - 1).getId())); + sa.setSVar("StaticEffectUntilCardID", String.valueOf(completeList.get(idx + 1).getId())); // add generous offset to timestamp, to ensure it applies last compared to cards that were ordered to ETB before it idx += completeList.size() * 2; } From 660cae4ff0937732a45f9b2b9440b75e4ca01506 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 28 Jan 2025 10:15:48 +0100 Subject: [PATCH 17/17] Fix test --- forge-game/src/main/java/forge/game/GameAction.java | 2 +- forge-gui/res/cardsfolder/e/ever_after.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 29f4bbf5c2f..ff1a810c22c 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -765,7 +765,7 @@ private Card setupStaticEffect(Card copied, SpellAbility cause) { eff = SpellAbilityEffect.createEffect(cause, cause.getActivatingPlayer(), name, source.getImageKey(), timestamp); eff.setRenderForUI(false); StaticAbility stAb = eff.addStaticAbility(AbilityUtils.getSVar(cause, cause.getParam("StaticEffect"))); - stAb.putParam("EffectZone", "Command"); + stAb.setActiveZone(EnumSet.of(ZoneType.Command)); // needed for ETB lookahead like Bronzehide Lion stAb.putParam("AffectedZone", "Battlefield,Hand,Graveyard,Exile,Stack,Library,Command"); SpellAbilityEffect.addForgetOnMovedTrigger(eff, "Battlefield"); diff --git a/forge-gui/res/cardsfolder/e/ever_after.txt b/forge-gui/res/cardsfolder/e/ever_after.txt index fb4c9476c4d..fac2bcdb07e 100644 --- a/forge-gui/res/cardsfolder/e/ever_after.txt +++ b/forge-gui/res/cardsfolder/e/ever_after.txt @@ -1,7 +1,7 @@ Name:Ever After ManaCost:4 B B Types:Sorcery -A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose target creature card in your graveyard | ValidTgts$ Creature.YouOwn | TargetMin$ 0 | TargetMax$ 2 | StaticEffect$ Animate | SubAbility$ DBPut | SpellDescription$ Return up to two target creature cards from your graveyard onto the battlefield. +A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose target creature card in your graveyard | ValidTgts$ Creature.YouOwn | TargetMin$ 0 | TargetMax$ 2 | StaticEffect$ Animate | SubAbility$ DBPut | SpellDescription$ Return up to two target creature cards from your graveyard onto the battlefield. Each of those creatures is a black Zombie in addition to its other colors and types. SVar:Animate:Mode$ Continuous | Affected$ Card.IsRemembered | AddType$ Zombie | AddColor$ Black SVar:DBPut:DB$ ChangeZone | Defined$ Parent | Origin$ Stack | Destination$ Library | LibraryPosition$ -1 | SpellDescription$ Put CARDNAME on the bottom of its owner's library. DeckHints:Ability$Graveyard|Discard & Type$Zombie