From 9b040b063bc559c58c91504061e8c4f6e86d093c Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Wed, 4 Nov 2020 08:56:41 +0000 Subject: [PATCH] - DelayedTriggerAi: port over AILogic NarsetRebound and SpellCopy (the latter doesn't quite work yet and the spell somehow magically fizzles with no trace). --- .../java/forge/ai/PlayerControllerAi.java | 12 +- .../forge/ai/ability/DelayedTriggerAi.java | 100 +++++++- .../main/java/forge/ai/ability/EffectAi.java | 86 ------- .../src/main/java/forge/game/GameAction.java | 2 +- .../java/forge/game/ability/AbilityUtils.java | 8 +- .../game/ability/effects/AttachEffect.java | 17 +- .../effects/CopySpellAbilityEffect.java | 234 ++++++++++-------- .../ability/effects/DelayedTriggerEffect.java | 12 +- .../game/ability/effects/PermanentEffect.java | 8 + .../src/main/java/forge/game/card/Card.java | 4 +- .../java/forge/game/card/CardFactory.java | 59 ++--- .../java/forge/game/card/CardFactoryUtil.java | 18 +- .../main/java/forge/game/keyword/Keyword.java | 2 +- .../game/replacement/ReplaceCopySpell.java | 43 ++++ .../game/replacement/ReplacementType.java | 1 + .../forge/game/spellability/SpellAbility.java | 61 +++++ .../game/spellability/TargetChoices.java | 19 +- .../forge/game/trigger/TriggerHandler.java | 11 +- .../game/trigger/TriggerSpellAbilityCast.java | 2 +- .../main/java/forge/game/zone/MagicStack.java | 83 ++++--- .../src/main/java/forge/game/zone/Zone.java | 8 +- .../res/cardsfolder/b/banish_into_fable.txt | 5 +- forge-gui/res/cardsfolder/b/bitter_ordeal.txt | 7 +- forge-gui/res/cardsfolder/b/bonus_round.txt | 2 +- .../res/cardsfolder/c/chain_lightning.txt | 4 +- forge-gui/res/cardsfolder/c/chain_of_acid.txt | 5 +- .../res/cardsfolder/c/chain_of_plasma.txt | 4 +- .../res/cardsfolder/c/chain_of_silence.txt | 5 +- forge-gui/res/cardsfolder/c/chain_of_smog.txt | 3 +- .../res/cardsfolder/c/chain_of_vapor.txt | 3 +- forge-gui/res/cardsfolder/c/chain_stasis.txt | 3 +- .../cardsfolder/c/chandra_the_firebrand.txt | 11 +- .../res/cardsfolder/c/chandras_regulator.txt | 2 +- .../res/cardsfolder/c/cloven_casting.txt | 3 +- .../res/cardsfolder/c/curse_of_echoes.txt | 4 +- forge-gui/res/cardsfolder/d/double_stroke.txt | 2 +- forge-gui/res/cardsfolder/d/double_vision.txt | 2 +- forge-gui/res/cardsfolder/d/doublecast.txt | 6 +- forge-gui/res/cardsfolder/d/dual_casting.txt | 2 +- .../res/cardsfolder/d/dualcaster_mage.txt | 3 +- forge-gui/res/cardsfolder/e/echo_mage.txt | 11 +- forge-gui/res/cardsfolder/e/echo_storm.txt | 2 +- forge-gui/res/cardsfolder/e/echoing_boon.txt | 3 +- .../res/cardsfolder/e/empyrial_storm.txt | 2 +- .../res/cardsfolder/e/expansion_explosion.txt | 2 +- .../res/cardsfolder/f/finale_of_promise.txt | 4 +- forge-gui/res/cardsfolder/f/fork.txt | 3 +- forge-gui/res/cardsfolder/f/fury_storm.txt | 4 +- forge-gui/res/cardsfolder/g/geistblast.txt | 3 +- forge-gui/res/cardsfolder/g/genesis_storm.txt | 2 +- forge-gui/res/cardsfolder/h/hive_mind.txt | 3 +- .../res/cardsfolder/h/howl_of_the_horde.txt | 8 +- .../cardsfolder/i/illusionists_bracers.txt | 3 +- .../cardsfolder/i/increasing_vengeance.txt | 6 +- .../res/cardsfolder/i/insidious_will.txt | 3 +- .../res/cardsfolder/i/izzet_guildmage.txt | 5 +- .../res/cardsfolder/i/izzet_steam_maze.txt | 3 +- .../cardsfolder/k/kalamax_the_stormsire.txt | 2 +- .../cardsfolder/k/kurkesh_onakke_ancient.txt | 3 +- .../res/cardsfolder/l/league_guildmage.txt | 2 +- .../res/cardsfolder/l/lithoform_engine.txt | 8 + forge-gui/res/cardsfolder/l/lucky_clover.txt | 2 +- .../cardsfolder/l/lutri_the_spellchaser.txt | 2 +- .../cardsfolder/m/malicious_affliction.txt | 3 +- .../res/cardsfolder/m/melek_izzet_paragon.txt | 2 +- .../res/cardsfolder/m/meletis_charlatan.txt | 3 +- forge-gui/res/cardsfolder/m/mirari.txt | 3 +- forge-gui/res/cardsfolder/m/mirror_sheen.txt | 3 +- forge-gui/res/cardsfolder/m/mirrorpool.txt | 3 +- .../res/cardsfolder/m/mischievous_quanar.txt | 2 +- .../res/cardsfolder/n/narset_transcendent.txt | 7 +- .../res/cardsfolder/n/narsets_reversal.txt | 2 +- .../cardsfolder/n/naru_meha_master_wizard.txt | 2 +- .../res/cardsfolder/n/nivix_guildmage.txt | 3 +- forge-gui/res/cardsfolder/o/odds_ends.txt | 3 +- .../p/primal_amulet_primal_wellspring.txt | 4 +- .../res/cardsfolder/p/psychic_rebuttal.txt | 5 +- .../cardsfolder/p/pyromancer_ascension.txt | 5 +- .../res/cardsfolder/p/pyromancers_goggles.txt | 5 +- .../res/cardsfolder/r/ral_storm_conduit.txt | 6 +- .../res/cardsfolder/r/refuse_cooperate.txt | 6 +- forge-gui/res/cardsfolder/r/reiterate.txt | 3 +- .../cardsfolder/r/repeated_reverberation.txt | 7 +- forge-gui/res/cardsfolder/r/reverberate.txt | 3 +- .../cardsfolder/r/riku_of_two_reflections.txt | 5 +- .../cardsfolder/r/rings_of_brighthearth.txt | 3 +- forge-gui/res/cardsfolder/r/rowan_kenrith.txt | 2 +- .../cardsfolder/s/sea_gate_stormcaller.txt | 12 +- .../cardsfolder/s/sevinne_the_chronoclasm.txt | 2 +- .../cardsfolder/s/sevinnes_reclamation.txt | 2 +- forge-gui/res/cardsfolder/s/sigil_tracer.txt | 3 +- forge-gui/res/cardsfolder/s/skull_storm.txt | 2 +- forge-gui/res/cardsfolder/s/spelltwine.txt | 3 +- .../res/cardsfolder/s/split_decision.txt | 3 +- .../s/string_of_disappearances.txt | 2 +- .../res/cardsfolder/s/strionic_resonator.txt | 3 +- .../res/cardsfolder/s/swarm_intelligence.txt | 3 +- .../cardsfolder/t/tawnos_urzas_apprentice.txt | 2 +- .../cardsfolder/t/the_mirari_conjecture.txt | 2 +- .../res/cardsfolder/t/thousand_year_storm.txt | 2 +- forge-gui/res/cardsfolder/t/twincast.txt | 3 +- .../res/cardsfolder/t/twinning_staff.txt | 8 + .../res/cardsfolder/u/unbound_flourishing.txt | 2 +- .../res/cardsfolder/u/uyo_silent_prophet.txt | 3 +- .../v/verazol_the_split_current.txt | 15 ++ forge-gui/res/cardsfolder/w/wild_ricochet.txt | 3 +- forge-gui/res/cardsfolder/w/will_kenrith.txt | 2 +- .../forge/player/HumanPlaySpellAbility.java | 48 +--- .../forge/player/PlayerControllerHuman.java | 15 +- 109 files changed, 642 insertions(+), 540 deletions(-) create mode 100644 forge-game/src/main/java/forge/game/replacement/ReplaceCopySpell.java create mode 100644 forge-gui/res/cardsfolder/l/lithoform_engine.txt create mode 100644 forge-gui/res/cardsfolder/t/twinning_staff.txt create mode 100644 forge-gui/res/cardsfolder/v/verazol_the_split_current.txt diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index 94c9582e2d7..cc75147856b 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -970,8 +970,18 @@ public class PlayerControllerAi extends PlayerController { @Override public void orderAndPlaySimultaneousSa(List activePlayerSAs) { for (final SpellAbility sa : getAi().orderPlaySa(activePlayerSAs)) { - if (prepareSingleSa(sa.getHostCard(),sa,true)) { + if (sa.isTrigger() && prepareSingleSa(sa.getHostCard(), sa, true)) { ComputerUtil.playStack(sa, player, game); + } else if (sa.isCopied()) { + player.getGame().getStackZone().add(sa.getHostCard()); + // TODO check if static abilities needs to be run for things affecting the copy? + if (sa.isMayChooseNewTargets() && !sa.setupTargets()) { + // if targets can't be done, remove copy from existence + sa.getHostCard().ceaseToExist(); + continue; + } + // need finally add the new spell to the stack + player.getGame().getStack().add(sa); } } } diff --git a/forge-ai/src/main/java/forge/ai/ability/DelayedTriggerAi.java b/forge-ai/src/main/java/forge/ai/ability/DelayedTriggerAi.java index c5b17785e61..bd22d902785 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DelayedTriggerAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DelayedTriggerAi.java @@ -1,14 +1,18 @@ package forge.ai.ability; -import forge.ai.AiController; -import forge.ai.AiPlayDecision; -import forge.ai.PlayerControllerAi; -import forge.ai.SpellAbilityAi; -import forge.ai.SpellApiToAi; +import com.google.common.base.Predicate; +import forge.ai.*; +import forge.card.mana.ManaCost; import forge.game.ability.AbilityFactory; +import forge.game.ability.ApiType; +import forge.game.card.Card; +import forge.game.card.CardLists; +import forge.game.cost.Cost; +import forge.game.keyword.Keyword; import forge.game.player.Player; import forge.game.spellability.AbilitySub; import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; public class DelayedTriggerAi extends SpellAbilityAi { @@ -53,6 +57,92 @@ public class DelayedTriggerAi extends SpellAbilityAi { @Override protected boolean canPlayAI(Player ai, SpellAbility sa) { + // Card-specific logic + String logic = sa.getParamOrDefault("AILogic", ""); + if (logic.equals("SpellCopy")) { + // fetch Instant or Sorcery and AI has reason to play this turn + // does not try to get itself + final ManaCost costSa = sa.getPayCosts().getTotalMana(); + final int count = CardLists.count(ai.getCardsIn(ZoneType.Hand), new Predicate() { + @Override + public boolean apply(final Card c) { + if (!(c.isInstant() || c.isSorcery()) || c.equals(sa.getHostCard())) { + return false; + } + for (SpellAbility ab : c.getSpellAbilities()) { + if (ComputerUtilAbility.getAbilitySourceName(sa).equals(ComputerUtilAbility.getAbilitySourceName(ab)) + || ab.hasParam("AINoRecursiveCheck")) { + // prevent infinitely recursing mana ritual and other abilities with reentry + continue; + } else if ("SpellCopy".equals(ab.getParam("AILogic")) && ab.getApi() == ApiType.DelayedTrigger) { + // don't copy another copy spell, too complex for the AI + continue; + } + if (!ab.canPlay()) { + continue; + } + AiPlayDecision decision = ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(ab); + // see if we can pay both for this spell and for the Effect spell we're considering + if (decision == AiPlayDecision.WillPlay || decision == AiPlayDecision.WaitForMain2) { + ManaCost costAb = ab.getPayCosts().getTotalMana(); + ManaCost total = ManaCost.combine(costSa, costAb); + SpellAbility combinedAb = ab.copyWithDefinedCost(new Cost(total, false)); + // can we pay both costs? + if (ComputerUtilMana.canPayManaCost(combinedAb, ai, 0)) { + return true; + } + } + } + return false; + } + }); + + if(count == 0) { + return false; + } + return true; + } else if (logic.equals("NarsetRebound")) { + // should be done in Main2, but it might broke for other cards + //if (phase.getPhase().isBefore(PhaseType.MAIN2)) { + // return false; + //} + + // fetch Instant or Sorcery without Rebound and AI has reason to play this turn + // only need count, not the list + final int count = CardLists.count(ai.getCardsIn(ZoneType.Hand), new Predicate() { + @Override + public boolean apply(final Card c) { + if (!(c.isInstant() || c.isSorcery()) || c.hasKeyword(Keyword.REBOUND)) { + return false; + } + for (SpellAbility ab : c.getSpellAbilities()) { + if (ComputerUtilAbility.getAbilitySourceName(sa).equals(ComputerUtilAbility.getAbilitySourceName(ab)) + || ab.hasParam("AINoRecursiveCheck")) { + // prevent infinitely recursing mana ritual and other abilities with reentry + continue; + } + if (!ab.canPlay()) { + continue; + } + AiPlayDecision decision = ((PlayerControllerAi) ai.getController()).getAi().canPlaySa(ab); + if (decision == AiPlayDecision.WillPlay || decision == AiPlayDecision.WaitForMain2) { + if (ComputerUtilMana.canPayManaCost(ab, ai, 0)) { + return true; + } + } + } + return false; + } + }); + + if (count == 0) { + return false; + } + + return true; + } + + // Generic logic SpellAbility trigsa = null; if (sa.hasAdditionalAbility("Execute")) { trigsa = sa.getAdditionalAbility("Execute"); diff --git a/forge-ai/src/main/java/forge/ai/ability/EffectAi.java b/forge-ai/src/main/java/forge/ai/ability/EffectAi.java index 77a20350e69..566746434aa 100644 --- a/forge-ai/src/main/java/forge/ai/ability/EffectAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/EffectAi.java @@ -7,14 +7,11 @@ import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import forge.ai.*; -import forge.card.mana.ManaCost; import forge.game.Game; import forge.game.ability.ApiType; import forge.game.card.*; import forge.game.combat.Combat; import forge.game.combat.CombatUtil; -import forge.game.cost.Cost; -import forge.game.keyword.Keyword; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; @@ -109,89 +106,6 @@ public class EffectAi extends SpellAbilityAi { || CardLists.getType(ai.getCardsIn(ZoneType.Battlefield), "Planeswalker").isEmpty()) { return false; } - randomReturn = true; - } else if (logic.equals("SpellCopy")) { - // fetch Instant or Sorcery and AI has reason to play this turn - // does not try to get itself - final ManaCost costSa = sa.getPayCosts().getTotalMana(); - final int count = CardLists.count(ai.getCardsIn(ZoneType.Hand), new Predicate() { - @Override - public boolean apply(final Card c) { - if (!(c.isInstant() || c.isSorcery()) || c.equals(sa.getHostCard())) { - return false; - } - for (SpellAbility ab : c.getSpellAbilities()) { - if (ComputerUtilAbility.getAbilitySourceName(sa).equals(ComputerUtilAbility.getAbilitySourceName(ab)) - || ab.hasParam("AINoRecursiveCheck")) { - // prevent infinitely recursing mana ritual and other abilities with reentry - continue; - } else if ("SpellCopy".equals(ab.getParam("AILogic")) && ab.getApi() == ApiType.Effect) { - // don't copy another copy spell, too complex for the AI - continue; - } - if (!ab.canPlay()) { - continue; - } - AiPlayDecision decision = ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(ab); - // see if we can pay both for this spell and for the Effect spell we're considering - if (decision == AiPlayDecision.WillPlay || decision == AiPlayDecision.WaitForMain2) { - ManaCost costAb = ab.getPayCosts().getTotalMana(); - ManaCost total = ManaCost.combine(costSa, costAb); - SpellAbility combinedAb = ab.copyWithDefinedCost(new Cost(total, false)); - // can we pay both costs? - if (ComputerUtilMana.canPayManaCost(combinedAb, ai, 0)) { - return true; - } - } - } - - return false; - } - }); - - if(count == 0) { - return false; - } - - randomReturn = true; - } else if (logic.equals("NarsetRebound")) { - // should be done in Main2, but it might broke for other cards - //if (phase.getPhase().isBefore(PhaseType.MAIN2)) { - // return false; - //} - - // fetch Instant or Sorcery without Rebound and AI has reason to play this turn - // only need count, not the list - final int count = CardLists.count(ai.getCardsIn(ZoneType.Hand), new Predicate() { - @Override - public boolean apply(final Card c) { - if (!(c.isInstant() || c.isSorcery()) || c.hasKeyword(Keyword.REBOUND)) { - return false; - } - for (SpellAbility ab : c.getSpellAbilities()) { - if (ComputerUtilAbility.getAbilitySourceName(sa).equals(ComputerUtilAbility.getAbilitySourceName(ab)) - || ab.hasParam("AINoRecursiveCheck")) { - // prevent infinitely recursing mana ritual and other abilities with reentry - continue; - } - if (!ab.canPlay()) { - continue; - } - AiPlayDecision decision = ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(ab); - if (decision == AiPlayDecision.WillPlay || decision == AiPlayDecision.WaitForMain2) { - if (ComputerUtilMana.canPayManaCost(ab, ai, 0)) { - return true; - } - } - } - return false; - } - }); - - if(count == 0) { - return false; - } - randomReturn = true; } else if (logic.equals("Always")) { randomReturn = true; diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 16b2d97728e..6366d297ffd 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -103,7 +103,7 @@ public class GameAction { boolean wasFacedown = c.isFaceDown(); //Rule 110.5g: A token that has left the battlefield can't move to another zone - if (c.isToken() && zoneFrom != null && !fromBattlefield) { + if (c.isToken() && zoneFrom != null && !fromBattlefield && !zoneFrom.is(ZoneType.Stack)) { return c; } diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 9c45bc442a9..a925a35b5d4 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -1660,12 +1660,8 @@ public class AbilityUtils { // Count$Kicked.. if (sq[0].startsWith("Kicked")) { - if (((SpellAbility)ctb).isKicked()) { - return CardFactoryUtil.doXMath(Integer.parseInt(sq[1]), expr, c); // Kicked - } - else { - return CardFactoryUtil.doXMath(Integer.parseInt(sq[2]), expr, c); // not Kicked - } + boolean kicked = ((SpellAbility)ctb).isKicked() || c.getKickerMagnitude() > 0; + return CardFactoryUtil.doXMath(Integer.parseInt(kicked ? sq[1] : sq[2]), expr, c); } //Count$SearchedLibrary. diff --git a/forge-game/src/main/java/forge/game/ability/effects/AttachEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AttachEffect.java index cd8325cdba9..0156e9775c7 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AttachEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AttachEffect.java @@ -24,14 +24,23 @@ import java.util.List; public class AttachEffect extends SpellAbilityEffect { @Override public void resolve(SpellAbility sa) { - if (sa.getHostCard().isAura() && sa.isSpell()) { - + final Card host = sa.getHostCard(); + if (host.isAura() && sa.isSpell()) { final Player ap = sa.getActivatingPlayer(); // The Spell_Permanent (Auras) version of this AF needs to // move the card into play before Attaching - sa.getHostCard().setController(ap, 0); - final Card c = ap.getGame().getAction().moveTo(ap.getZone(ZoneType.Battlefield), sa.getHostCard(), sa); + host.setController(ap, 0); + + // 111.11. A copy of a permanent spell becomes a token as it resolves. + // The token has the characteristics of the spell that became that token. + // The token is not “created” for the purposes of any replacement effects or triggered abilities that refer to creating a token. + if (host.isCopiedSpell()) { + host.setCopiedSpell(false); + host.setToken(true); + } + + final Card c = ap.getGame().getAction().moveToPlay(host, ap, sa); sa.setHostCard(c); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java index 43e13b56480..c1596d087fb 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java @@ -4,7 +4,9 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import forge.game.Game; import forge.game.GameEntity; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -12,15 +14,16 @@ import forge.game.card.CardCollection; import forge.game.card.CardFactory; import forge.game.card.CardLists; import forge.game.player.Player; +import forge.game.replacement.ReplacementType; import forge.game.spellability.AbilitySub; import forge.game.spellability.SpellAbility; -import forge.util.Lang; import forge.util.Localizer; import forge.util.CardTranslation; -import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Map; + public class CopySpellAbilityEffect extends SpellAbilityEffect { @@ -56,7 +59,8 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { @Override public void resolve(SpellAbility sa) { final Card card = sa.getHostCard(); - Player controller = sa.getActivatingPlayer(); + final Game game = card.getGame(); + List controllers = Lists.newArrayList(sa.getActivatingPlayer()); int amount = 1; if (sa.hasParam("Amount")) { @@ -64,13 +68,9 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { } if (sa.hasParam("Controller")) { - controller = AbilityUtils.getDefinedPlayers(card, sa.getParam("Controller"), sa).get(0); + controllers = AbilityUtils.getDefinedPlayers(card, sa.getParam("Controller"), sa); } - boolean isOptional = sa.hasParam("Optional"); - if (isOptional && !controller.getController().confirmAction(sa, null, Localizer.getInstance().getMessage("lblDoyouWantCopyTheSpell", CardTranslation.getTranslatedName(card.getName())))) { - return; - } final List tgtSpells = getTargetSpells(sa); @@ -79,123 +79,143 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { return; } - boolean mayChooseNewTargets = true; - List copies = new ArrayList<>(); - - if (sa.hasParam("CopyMultipleSpells")) { - final int spellCount = Integer.parseInt(sa.getParam("CopyMultipleSpells")); + boolean isOptional = sa.hasParam("Optional"); - for (int multi = 0; multi < spellCount && !tgtSpells.isEmpty(); multi++) { - String prompt = Localizer.getInstance().getMessage("lblSelectMultiSpellCopyToStack", Lang.getOrdinal(multi + 1)); - SpellAbility chosen = controller.getController().chooseSingleSpellForEffect(tgtSpells, sa, prompt, - ImmutableMap.of()); - SpellAbility copiedSpell = CardFactory.copySpellAbilityAndPossiblyHost(card, chosen.getHostCard(), chosen, true); - copiedSpell.getHostCard().setController(card.getController(), card.getGame().getNextTimestamp()); - copiedSpell.setActivatingPlayer(controller); - copies.add(copiedSpell); - tgtSpells.remove(chosen); + for (Player controller : controllers) { + if (isOptional && !controller.getController().confirmAction(sa, null, Localizer.getInstance().getMessage("lblDoyouWantCopyTheSpell", CardTranslation.getTranslatedName(card.getName())))) { + continue; } - } - else if (sa.hasParam("CopyForEachCanTarget")) { + + List copies = Lists.newArrayList(); + SpellAbility chosenSA = controller.getController().chooseSingleSpellForEffect(tgtSpells, sa, Localizer.getInstance().getMessage("lblSelectASpellCopy"), ImmutableMap.of()); - chosenSA.setActivatingPlayer(controller); - // Find subability or rootability that has targets - SpellAbility targetedSA = chosenSA; - while (targetedSA != null) { - if (targetedSA.usesTargeting() && targetedSA.getTargets().getNumTargeted() != 0) { - break; + + if (sa.hasParam("CopyForEachCanTarget")) { + // Find subability or rootability that has targets + SpellAbility targetedSA = chosenSA; + while (targetedSA != null) { + if (targetedSA.usesTargeting() && targetedSA.getTargets().getNumTargeted() != 0) { + break; + } + targetedSA = targetedSA.getSubAbility(); } - targetedSA = targetedSA.getSubAbility(); - } - if (targetedSA == null) { - return; - } - final List candidates = targetedSA.getTargetRestrictions().getAllCandidates(targetedSA, true); - if (sa.hasParam("CanTargetPlayer")) { - // Radiate - // Remove targeted players because getAllCandidates include all the valid players - for(Player p : targetedSA.getTargets().getTargetPlayers()) - candidates.remove(p); - - mayChooseNewTargets = false; - for (GameEntity o : candidates) { - SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true); - resetFirstTargetOnCopy(copy, o, targetedSA); - copies.add(copy); + if (targetedSA == null) { + continue; } - } else {// Precursor Golem, Ink-Treader Nephilim - final String type = sa.getParam("CopyForEachCanTarget"); - CardCollection valid = new CardCollection(); - List players = Lists.newArrayList(); - Player originalTargetPlayer = Iterables.getFirst(getTargetPlayers(chosenSA), null); - for (final GameEntity o : candidates) { - if (o instanceof Card) { - valid.add((Card) o); - } else if (o instanceof Player) { - final Player p = (Player) o; - if (p.equals(originalTargetPlayer)) - continue; - if (p.isValid(type.split(","), chosenSA.getActivatingPlayer(), chosenSA.getHostCard(), sa)) { - players.add(p); + final List candidates = targetedSA.getTargetRestrictions().getAllCandidates(targetedSA, true); + if (sa.hasParam("CanTargetPlayer")) { + // Radiate + // Remove targeted players because getAllCandidates include all the valid players + for(Player p : targetedSA.getTargets().getTargetPlayers()) + candidates.remove(p); + + for (GameEntity o : candidates) { + SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(sa, chosenSA); + resetFirstTargetOnCopy(copy, o, targetedSA); + copies.add(copy); + } + } else {// Precursor Golem, Ink-Treader Nephilim + final String type = sa.getParam("CopyForEachCanTarget"); + CardCollection valid = new CardCollection(); + List players = Lists.newArrayList(); + Player originalTargetPlayer = Iterables.getFirst(getTargetPlayers(chosenSA), null); + for (final GameEntity o : candidates) { + if (o instanceof Card) { + valid.add((Card) o); + } else if (o instanceof Player) { + final Player p = (Player) o; + if (p.equals(originalTargetPlayer)) + continue; + if (p.isValid(type.split(","), chosenSA.getActivatingPlayer(), chosenSA.getHostCard(), sa)) { + players.add(p); + } } } - } - valid = CardLists.getValidCards(valid, type.split(","), chosenSA.getActivatingPlayer(), chosenSA.getHostCard(), sa); - Card originalTarget = Iterables.getFirst(getTargetCards(chosenSA), null); - valid.remove(originalTarget); - mayChooseNewTargets = false; - if (sa.hasParam("ChooseOnlyOne")) { - Card choice = controller.getController().chooseSingleEntityForEffect(valid, sa, Localizer.getInstance().getMessage("lblChooseOne"), null); - SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true); - resetFirstTargetOnCopy(copy, choice, targetedSA); - copies.add(copy); - } else { - for (final Card c : valid) { - SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true); + valid = CardLists.getValidCards(valid, type.split(","), chosenSA.getActivatingPlayer(), chosenSA.getHostCard(), sa); + Card originalTarget = Iterables.getFirst(getTargetCards(chosenSA), null); + valid.remove(originalTarget); + + if (sa.hasParam("ChooseOnlyOne")) { + Card choice = controller.getController().chooseSingleEntityForEffect(valid, sa, Localizer.getInstance().getMessage("lblChooseOne"), null); + if (choice != null) { + valid = new CardCollection(choice); + } + } + + for (final Card c : valid) { + SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(sa, chosenSA); resetFirstTargetOnCopy(copy, c, targetedSA); copies.add(copy); - } + } + for (final Player p : players) { + SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(sa, chosenSA); + resetFirstTargetOnCopy(copy, p, targetedSA); + copies.add(copy); + } } - for (final Player p : players) { - SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true); - resetFirstTargetOnCopy(copy, p, targetedSA); + } + else { + for (int i = 0; i < amount; i++) { + SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(sa, chosenSA); + if (sa.hasParam("MayChooseTarget")) { + copy.setMayChooseNewTargets(true); + if (copy.usesTargeting()) { + copy.getTargetRestrictions().setMandatory(true); + } + } + + // extra case for Epic to remove the keyword and the last part of the SpellAbility + if (sa.hasParam("Epic")) { + copy.getHostCard().removeIntrinsicKeyword("Epic"); + SpellAbility sub = copy; + while (sub.getSubAbility() != null && !sub.hasParam("Epic")) { + sub = sub.getSubAbility(); + } + if (sub != null) { + sub.getParent().setSubAbility(sub.getSubAbility()); + } + } + copies.add(copy); } } - } - else { - SpellAbility chosenSA = controller.getController().chooseSingleSpellForEffect(tgtSpells, sa, - Localizer.getInstance().getMessage("lblSelectASpellCopy"), ImmutableMap.of()); - chosenSA.setActivatingPlayer(controller); - for (int i = 0; i < amount; i++) { - SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost( - card, chosenSA.getHostCard(), chosenSA, true); - // extra case for Epic to remove the keyword and the last part of the SpellAbility - if (sa.hasParam("Epic")) { - copy.getHostCard().removeIntrinsicKeyword("Epic"); - SpellAbility sub = copy; - while (sub.getSubAbility() != null && !sub.hasParam("Epic")) { - sub = sub.getSubAbility(); - } - if (sub != null) { - sub.getParent().setSubAbility(sub.getSubAbility()); - } + if (copies.isEmpty()) { + continue; + } + + int addAmount = copies.size(); + final Map repParams = AbilityKey.mapFromAffected(controller); + repParams.put(AbilityKey.SpellAbility, chosenSA); + repParams.put(AbilityKey.Amount, addAmount); + + switch (game.getReplacementHandler().run(ReplacementType.CopySpell, repParams)) { + case NotReplaced: + break; + case Updated: { + addAmount = (int) repParams.get(AbilityKey.Amount); + break; + } + default: + addAmount = 0; + } + + if (addAmount <= 0) { + continue; + } + int extraAmount = addAmount - copies.size(); + for (int i = 0; i < extraAmount; i++) { + SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(sa, chosenSA); + // extra copies added with CopySpellReplacenment currently always has new choose targets + copy.setMayChooseNewTargets(true); + if (copy.usesTargeting()) { + copy.getTargetRestrictions().setMandatory(true); } - copies.add(copy); } - } - - for(SpellAbility copySA : copies) { - if (mayChooseNewTargets && copySA.usesTargeting()) { - // TODO: ideally this should be implemented by way of allowing the player to cancel targeting - // but in that case preserving whatever target was specified for the original spell (since - // "changing targets" is the optional part). - copySA.getTargetRestrictions().setMandatory(true); - } - controller.getController().playSpellAbilityForFree(copySA, mayChooseNewTargets); + + controller.getController().orderAndPlaySimultaneousSa(copies); } } // end resolve diff --git a/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java index 0a95d27b9e2..e91c675d653 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java @@ -5,7 +5,10 @@ import com.google.common.collect.Maps; import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.ability.SpellAbilityEffect; +import forge.game.card.Card; +import forge.game.card.CardUtil; import forge.game.player.Player; +import forge.game.spellability.AbilitySub; import forge.game.spellability.SpellAbility; import forge.game.trigger.Trigger; import forge.game.trigger.TriggerHandler; @@ -21,6 +24,8 @@ public class DelayedTriggerEffect extends SpellAbilityEffect { protected String getStackDescription(SpellAbility sa) { if (sa.hasParam("TriggerDescription")) { return sa.getParam("TriggerDescription"); + } else if (sa.hasParam("SpellDescription")) { + return sa.getParam("SpellDescription"); } return ""; @@ -44,7 +49,8 @@ public class DelayedTriggerEffect extends SpellAbilityEffect { triggerRemembered = sa.getParam("RememberObjects"); } - final Trigger delTrig = TriggerHandler.parseTrigger(mapParams, sa.getHostCard(), true); + Card lki = CardUtil.getLKICopy(sa.getHostCard()); + final Trigger delTrig = TriggerHandler.parseTrigger(mapParams, lki, true); if (triggerRemembered != null) { for (final String rem : triggerRemembered.split(",")) { @@ -67,7 +73,9 @@ public class DelayedTriggerEffect extends SpellAbilityEffect { } if (mapParams.containsKey("Execute") || sa.hasAdditionalAbility("Execute")) { - SpellAbility overridingSA = sa.getAdditionalAbility("Execute"); + AbilitySub overridingSA = (AbilitySub)sa.getAdditionalAbility("Execute").copy(lki, false); + // need to reset the parent, additionalAbility does set it to this + overridingSA.setParent(null); overridingSA.setActivatingPlayer(sa.getActivatingPlayer()); overridingSA.setDeltrigActivatingPlayer(sa.getActivatingPlayer()); // ensure that the original activator can be restored later // Set Transform timestamp when the delayed trigger is created diff --git a/forge-game/src/main/java/forge/game/ability/effects/PermanentEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PermanentEffect.java index f916ee8b67e..36437ae9dfb 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PermanentEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PermanentEffect.java @@ -22,6 +22,14 @@ public class PermanentEffect extends SpellAbilityEffect { sa.getHostCard().setController(p, 0); final Card host = sa.getHostCard(); + // 111.11. A copy of a permanent spell becomes a token as it resolves. + // The token has the characteristics of the spell that became that token. + // The token is not “created” for the purposes of any replacement effects or triggered abilities that refer to creating a token. + if (host.isCopiedSpell()) { + host.setCopiedSpell(false); + host.setToken(true); + } + final Card c = p.getGame().getAction().moveToPlay(host, p, sa); sa.setHostCard(c); 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 1ecff58ab29..7fbc2d9828c 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -3612,8 +3612,8 @@ public class Card extends GameEntity implements Comparable { if (multiKickerMagnitude > 0) { return multiKickerMagnitude; } - boolean hasK1 = costsPaid.contains(OptionalCost.Kicker1); - return hasK1 == costsPaid.contains(OptionalCost.Kicker2) ? (hasK1 ? 2 : 0) : 1; + boolean hasK1 = isOptionalCostPaid(OptionalCost.Kicker1); + return hasK1 == isOptionalCostPaid(OptionalCost.Kicker2) ? (hasK1 ? 2 : 0) : 1; } private int pseudoKickerMagnitude = 0; diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index d73dae2bc8f..1c9162cf4e2 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -125,12 +125,13 @@ public class CardFactory { * which wouldn't ordinarily get set during a simple Card.copy() call. *

* */ - private final static Card copySpellHost(final Card source, final Card original, final SpellAbility sa, final boolean bCopyDetails){ - Player controller = sa.getActivatingPlayer(); + private final static Card copySpellHost(final SpellAbility sourceSA, final SpellAbility targetSA){ + final Card source = sourceSA.getHostCard(); + final Card original = targetSA.getHostCard(); + Player controller = sourceSA.getActivatingPlayer(); final Card c = copyCard(original, true); // change the color of the copy (eg: Fork) - final SpellAbility sourceSA = source.getFirstSpellAbility(); if (null != sourceSA && sourceSA.hasParam("CopyIsColor")) { String tmp = ""; final String newColor = sourceSA.getParam("CopyIsColor"); @@ -148,13 +149,14 @@ public class CardFactory { c.setOwner(controller); c.setCopiedSpell(true); - if (bCopyDetails) { - c.setXManaCostPaidByColor(original.getXManaCostPaidByColor()); - c.setKickerMagnitude(original.getKickerMagnitude()); + c.setXManaCostPaidByColor(original.getXManaCostPaidByColor()); + c.setKickerMagnitude(original.getKickerMagnitude()); - for (OptionalCost cost : original.getOptionalCostsPaid()) { - c.addOptionalCostPaid(cost); - } + for (OptionalCost cost : original.getOptionalCostsPaid()) { + c.addOptionalCostPaid(cost); + } + if (targetSA.isBestow()) { + c.animateBestow(); } return c; } @@ -174,44 +176,33 @@ public class CardFactory { * @param bCopyDetails * a boolean. */ - public final static SpellAbility copySpellAbilityAndPossiblyHost(final Card source, final Card original, final SpellAbility sa, final boolean bCopyDetails) { - Player controller = sa.getActivatingPlayer(); + public final static SpellAbility copySpellAbilityAndPossiblyHost(final SpellAbility sourceSA, final SpellAbility targetSA) { + Player controller = sourceSA.getActivatingPlayer(); //it is only necessary to copy the host card if the SpellAbility is a spell, not an ability - final Card c; - if (sa.isSpell()){ - c = copySpellHost(source, original, sa, bCopyDetails); - } - else { - c = original; - } + final Card c = targetSA.isSpell() ? copySpellHost(sourceSA, targetSA) : targetSA.getHostCard(); final SpellAbility copySA; - if (sa.isTrigger() && sa.isWrapper()) { - copySA = getCopiedTriggeredAbility((WrappedAbility)sa, c); + if (targetSA.isTrigger() && targetSA.isWrapper()) { + copySA = getCopiedTriggeredAbility((WrappedAbility)targetSA, c); } else { - copySA = sa.copy(c, false); - } - - if (sa.isSpell()){ - //only update c's abilities if c is a copy. - //(it would be nice to move this into `copySpellHost`, - // so all the c-mutating code is together in one place. - // but copySA doesn't exist until after `copySpellHost` finishes executing, - // so it's hard to resolve that dependency.) - c.getCurrentState().setNonManaAbilities(copySA); + copySA = targetSA.copy(c, false); } copySA.setCopied(true); + + if (targetSA.usesTargeting()) { + // do for SubAbilities too? + copySA.setTargets(targetSA.getTargets().clone()); + } + //remove all costs if (!copySA.isTrigger()) { - copySA.setPayCosts(new Cost("", sa.isAbility())); + copySA.setPayCosts(new Cost("", targetSA.isAbility())); } copySA.setActivatingPlayer(controller); - if (bCopyDetails) { - copySA.setPaidHash(sa.getPaidHash()); - } + copySA.setPaidHash(targetSA.getPaidHash()); return copySA; } diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index d4a7bb506bf..8c016cfbc2e 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -2434,7 +2434,7 @@ public class CardFactoryUtil { inst.addTrigger(parsedTrigReturn); } else if (keyword.equals("Conspire")) { final String trigScript = "Mode$ SpellCast | ValidCard$ Card.Self | CheckSVar$ Conspire | Secondary$ True | TriggerDescription$ Copy CARDNAME if its conspire cost was paid"; - final String abString = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ 1"; + final String abString = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ 1 | MayChooseTarget$ True"; final Trigger conspireTrigger = TriggerHandler.parseTrigger(trigScript, card, intrinsic); conspireTrigger.setOverridingAbility(AbilityFactory.getAbility(abString, card)); @@ -2630,6 +2630,18 @@ public class CardFactoryUtil { trigger.setOverridingAbility(AbilityFactory.getAbility(sb.toString(), card)); + inst.addTrigger(trigger); + } else if (keyword.startsWith("Gravestorm")) { + String trigStr = "Mode$ SpellCast | ValidCard$ Card.Self | TriggerDescription$ Gravestorm (" + inst.getReminderText() + ")"; + String copyStr = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ GravestormCount | MayChooseTarget$ True"; + + SpellAbility copySa = AbilityFactory.getAbility(copyStr, card); + copySa.setSVar("GravestormCount", "Count$ThisTurnEntered_Graveyard_from_Battlefield_Permanent"); + + final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic); + + trigger.setOverridingAbility(copySa); + inst.addTrigger(trigger); } else if (keyword.startsWith("Haunt")) { final String[] k = keyword.split(":"); @@ -3069,7 +3081,7 @@ public class CardFactoryUtil { inst.addTrigger(myTrigger); } else if (keyword.startsWith("Replicate")) { final String trigScript = "Mode$ SpellCast | ValidCard$ Card.Self | CheckSVar$ ReplicateAmount | Secondary$ True | TriggerDescription$ Copy CARDNAME for each time you paid its replicate cost"; - final String abString = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ ReplicateAmount"; + final String abString = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ ReplicateAmount | MayChooseTarget$ True"; final Trigger replicateTrigger = TriggerHandler.parseTrigger(trigScript, card, intrinsic); final SpellAbility replicateAbility = AbilityFactory.getAbility(abString, card); @@ -3197,7 +3209,7 @@ public class CardFactoryUtil { final String actualTrigger = "Mode$ SpellCast | ValidCard$ Card.Self | Secondary$ True" + "| TriggerDescription$ Storm (" + inst.getReminderText() + ")"; - String effect = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ StormCount"; + String effect = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ StormCount | MayChooseTarget$ True"; final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, card, intrinsic); diff --git a/forge-game/src/main/java/forge/game/keyword/Keyword.java b/forge-game/src/main/java/forge/game/keyword/Keyword.java index bcf60c0a504..920188cef56 100644 --- a/forge-game/src/main/java/forge/game/keyword/Keyword.java +++ b/forge-game/src/main/java/forge/game/keyword/Keyword.java @@ -74,7 +74,7 @@ public enum Keyword { FORTIFY("Fortify", KeywordWithCost.class, false, "%s: Attach to target land you control. Fortify only as a sorcery."), FRENZY("Frenzy", KeywordWithAmount.class, false, "Whenever this creature attacks and isn't blocked, it gets +%d/+0 until end of turn."), GRAFT("Graft", KeywordWithAmount.class, false, "This permanent enters the battlefield with {%d:+1/+1 counter} on it. Whenever another creature enters the battlefield, you may move a +1/+1 counter from this permanent onto it."), - GRAVESTORM("Gravestorm", SimpleKeyword.class, false, "When you cast this spell, copy it for each permanent that was put into a graveyard from the battlefield this turn. You may choose new targets for the copies."), + GRAVESTORM("Gravestorm", SimpleKeyword.class, false, "When you cast this spell, copy it for each permanent that was put into a graveyard from the battlefield this turn. If the spell has any targets, you may choose new targets for any of the copies."), HASTE("Haste", SimpleKeyword.class, true, "This creature can attack and {T} as soon as it comes under your control."), HAUNT("Haunt", SimpleKeyword.class, false, "When this is put into a graveyard, exile it haunting target creature."), HEXPROOF("Hexproof", Hexproof.class, false, "This can't be the target of %s spells or abilities your opponents control."), diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceCopySpell.java b/forge-game/src/main/java/forge/game/replacement/ReplaceCopySpell.java new file mode 100644 index 00000000000..7fec930bf0a --- /dev/null +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceCopySpell.java @@ -0,0 +1,43 @@ +package forge.game.replacement; + +import java.util.Map; + +import forge.game.ability.AbilityKey; +import forge.game.card.Card; +import forge.game.spellability.SpellAbility; + +public class ReplaceCopySpell extends ReplacementEffect { + + public ReplaceCopySpell(Map map, Card host, boolean intrinsic) { + super(map, host, intrinsic); + } + + /* (non-Javadoc) + * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.Map) + */ + @Override + public boolean canReplace(Map runParams) { + if (((int) runParams.get(AbilityKey.Amount)) <= 0) { + return false; + } + if (hasParam("ValidPlayer")) { + if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), getHostCard())) { + return false; + } + } + if (hasParam("ValidSpell")) { + if (!matchesValid(runParams.get(AbilityKey.SpellAbility), getParam("ValidSpell").split(","), getHostCard())) { + return false; + } + } + return true; + } + + /* (non-Javadoc) + * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) + */ + @Override + public void setReplacingObjects(Map runParams, SpellAbility sa) { + sa.setReplacingObject(AbilityKey.Amount, runParams.get(AbilityKey.Amount)); + } +} diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementType.java b/forge-game/src/main/java/forge/game/replacement/ReplacementType.java index c13b3f172d0..88f55ebe554 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementType.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementType.java @@ -14,6 +14,7 @@ public enum ReplacementType { AddCounter(ReplaceAddCounter.class), Attached(ReplaceAttached.class), Counter(ReplaceCounter.class), + CopySpell(ReplaceCopySpell.class), CreateToken(ReplaceToken.class), DamageDone(ReplaceDamage.class), Destroy(ReplaceDestroy.class), diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 70be5f60696..ed48b7562b2 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -43,6 +43,7 @@ import forge.game.cost.CostRemoveCounter; import forge.game.keyword.Keyword; import forge.game.mana.Mana; import forge.game.player.Player; +import forge.game.player.PlayerCollection; import forge.game.replacement.ReplacementEffect; import forge.game.staticability.StaticAbility; import forge.game.trigger.Trigger; @@ -52,6 +53,7 @@ import forge.game.zone.ZoneType; import forge.util.Aggregates; import forge.util.Expressions; import forge.util.TextUtil; + import org.apache.commons.lang3.StringUtils; import java.util.*; @@ -148,6 +150,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit private boolean undoable; private boolean isCopied = false; + private boolean mayChooseNewTargets = false; private EnumSet optionalCosts = EnumSet.noneOf(OptionalCost.class); private TargetRestrictions targetRestrictions = null; @@ -863,6 +866,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit copyHelper(clone, host); + // always set this to false, it is only set in CopyEffect + clone.mayChooseNewTargets = false; + clone.triggeringObjects = AbilityKey.newMap(this.triggeringObjects); clone.setPayCosts(getPayCosts().copy()); @@ -884,6 +890,11 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit clone.setPaidHash(Maps.newHashMap(getPaidHash())); + if (usesTargeting()) { + // the targets need to be cloned, otherwise they might be cleared + clone.targetChosen = getTargets().clone(); + } + // clear maps for copy, the values will be added later clone.additionalAbilities = Maps.newHashMap(); clone.additionalAbilityLists = Maps.newHashMap(); @@ -1287,6 +1298,13 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } } + public boolean isMayChooseNewTargets() { + return mayChooseNewTargets; + } + public void setMayChooseNewTargets(boolean value) { + mayChooseNewTargets = value; + } + /** * Returns whether variable was present in the announce list. */ @@ -1358,6 +1376,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } public void setTargets(TargetChoices targets) { + // TODO should copy the target choices? targetChosen = targets; } @@ -1656,6 +1675,48 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit return p != null && p.isTargeting(o); } + public boolean setupTargets() { + // Skip to paying if parent ability doesn't target and has no subAbilities. + // (or trigger case where its already targeted) + SpellAbility currentAbility = this; + final Card source = getHostCard(); + do { + final TargetRestrictions tgt = currentAbility.getTargetRestrictions(); + if (tgt != null && tgt.doesTarget()) { + currentAbility.clearTargets(); + Player targetingPlayer; + if (currentAbility.hasParam("TargetingPlayer")) { + final PlayerCollection candidates = AbilityUtils.getDefinedPlayers(source, currentAbility.getParam("TargetingPlayer"), currentAbility); + // activator chooses targeting player + targetingPlayer = getActivatingPlayer().getController().chooseSingleEntityForEffect( + candidates, currentAbility, "Choose the targeting player", null); + } else { + targetingPlayer = getActivatingPlayer(); + } + currentAbility.setTargetingPlayer(targetingPlayer); + if (!targetingPlayer.getController().chooseTargetsFor(currentAbility)) { + return false; + } + } + final AbilitySub subAbility = currentAbility.getSubAbility(); + if (subAbility != null) { + // This is necessary for "TargetsWithDefinedController$ ParentTarget" + subAbility.setParent(currentAbility); + } + currentAbility = subAbility; + } while (currentAbility != null); + return true; + } + public final void clearTargets() { + final TargetRestrictions tg = getTargetRestrictions(); + if (tg != null) { + resetTargets(); + if (hasParam("DividedAsYouChoose")) { + tg.calculateStillToDivide(getParam("DividedAsYouChoose"), getHostCard(), this); + } + } + } + // Takes one argument like Permanent.Blue+withFlying @Override public final boolean isValid(final String restriction, final Player sourceController, final Card source, SpellAbility spellAbility) { diff --git a/forge-game/src/main/java/forge/game/spellability/TargetChoices.java b/forge-game/src/main/java/forge/game/spellability/TargetChoices.java index 1559a847038..500e469f707 100644 --- a/forge-game/src/main/java/forge/game/spellability/TargetChoices.java +++ b/forge-game/src/main/java/forge/game/spellability/TargetChoices.java @@ -25,6 +25,7 @@ import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardCollectionView; import forge.game.player.Player; +import forge.game.player.PlayerCollection; import java.util.ArrayList; import java.util.List; @@ -42,7 +43,7 @@ public class TargetChoices implements Cloneable { // Card or Player are legal targets. private final CardCollection targetCards = new CardCollection(); - private final List targetPlayers = new ArrayList<>(); + private final PlayerCollection targetPlayers = new PlayerCollection(); private final List targetSpells = new ArrayList<>(); public final int getNumTargeted() { @@ -70,8 +71,7 @@ public class TargetChoices implements Cloneable { } private final boolean addTarget(final Card c) { - if (!targetCards.contains(c)) { - targetCards.add(c); + if (targetCards.add(c)) { numTargeted++; return true; } @@ -79,8 +79,7 @@ public class TargetChoices implements Cloneable { } private final boolean addTarget(final Player p) { - if (!targetPlayers.contains(p)) { - targetPlayers.add(p); + if (targetPlayers.add(p)) { numTargeted++; return true; } @@ -213,16 +212,10 @@ public class TargetChoices implements Cloneable { if (obj instanceof TargetChoices) { TargetChoices compare = (TargetChoices)obj; - if (this.getNumTargeted() != compare.getNumTargeted()) { + if (getNumTargeted() != compare.getNumTargeted()) { return false; } - for (int i = 0; i < this.getTargets().size(); i++) { - if (!compare.getTargets().get(i).equals(this.getTargets().get(i))) { - return false; - } - } - return true; - + return getTargets().equals(compare.getTargets()); } else { return false; } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index 24a7e1e6feb..59d7aa47a7a 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -516,10 +516,17 @@ public class TriggerHandler { else { // get CardState does not work for transformed cards // also its about LKI + // TODO remove this part after all spellAbility can handle LKI as host + // Currently only true for delayed Trigger if (host.isInZone(ZoneType.Battlefield) || !host.hasAlternateState()) { // if host changes Zone with other cards, try to use original host - if (!regtrig.getMode().equals(TriggerType.ChangesZone)) - host = game.getCardState(host); + if (!regtrig.getMode().equals(TriggerType.ChangesZone)) { + Card gameHost = game.getCardState(host); + // TODO only set when the host equals the game state + if (gameHost.equalsWithTimestamp(host)) { + host = gameHost; + } + } } } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java b/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java index bf5e16496c9..7ac0c404c5c 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerSpellAbilityCast.java @@ -269,7 +269,7 @@ public class TriggerSpellAbilityCast extends Trigger { final SpellAbility castSA = (SpellAbility) runParams.get(AbilityKey.CastSA); final SpellAbilityStackInstance si = sa.getHostCard().getGame().getStack().getInstanceFromSpellAbility(castSA); sa.setTriggeringObject(AbilityKey.Card, castSA.getHostCard()); - sa.setTriggeringObject(AbilityKey.SpellAbility, castSA); + sa.setTriggeringObject(AbilityKey.SpellAbility, castSA.copy(castSA.getHostCard(), true)); sa.setTriggeringObject(AbilityKey.StackInstance, si); sa.setTriggeringObject(AbilityKey.SpellAbilityTargetingCards, (si != null ? si.getSpellAbility(true) : castSA).getTargets().getTargetCards()); sa.setTriggeringObjectsFrom( diff --git a/forge-game/src/main/java/forge/game/zone/MagicStack.java b/forge-game/src/main/java/forge/game/zone/MagicStack.java index d5c174b5e86..ddc426ac2e9 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -6,12 +6,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -65,7 +65,7 @@ import forge.util.TextUtil; *

* MagicStack class. *

- * + * * @author Forge * @version $Id$ */ @@ -135,14 +135,12 @@ public class MagicStack /* extends MyObservable */ implements Iterable runParams = AbilityKey.newMap(); - if (!(sp instanceof AbilityStatic) && !sp.isCopied()) { + if (!sp.isCopied()) { // Run SpellAbilityCast triggers runParams.put(AbilityKey.Cost, sp.getPayCosts()); runParams.put(AbilityKey.Player, sp.getHostCard().getController()); @@ -322,17 +322,15 @@ public class MagicStack /* extends MyObservable */ implements Iterable chosenTargets = sp.getAllTargetChoices(); - if (!chosenTargets.isEmpty()) { + if (!chosenTargets.isEmpty()) { runParams = Maps.newHashMap(); SpellAbility s = sp; if (si != null) { @@ -362,7 +360,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable params = AbilityKey.newMap(); @@ -864,8 +869,8 @@ public class MagicStack /* extends MyObservable */ implements Iterable { if (!c.isImmutable()) { final Zone oldZone = game.getZoneOf(c); final ZoneType zt = oldZone == null ? ZoneType.Stack : oldZone.getZoneType(); - cardsAddedThisTurn.add(zt, c); - latestStateCardsAddedThisTurn.add(zt, latestState != null ? latestState : c); + + // only if the zoneType differss from this + if (zt != zoneType) { + cardsAddedThisTurn.add(zt, c); + latestStateCardsAddedThisTurn.add(zt, latestState != null ? latestState : c); + } } c.setTurnInZone(game.getPhaseHandler().getTurn()); diff --git a/forge-gui/res/cardsfolder/b/banish_into_fable.txt b/forge-gui/res/cardsfolder/b/banish_into_fable.txt index 4aab936b038..8caa824e1f4 100644 --- a/forge-gui/res/cardsfolder/b/banish_into_fable.txt +++ b/forge-gui/res/cardsfolder/b/banish_into_fable.txt @@ -2,8 +2,9 @@ Name:Banish into Fable ManaCost:4 W U Types:Instant T:Mode$ SpellCast | ValidCard$ Card.Self+wasCastFromHand | Execute$ TrigCopy | TriggerDescription$ When you cast this spell from your hand, copy it if you control an artifact, then copy it if you control an enchantment. You may choose new targets for the copies. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | ConditionPresent$ Artifact.YouCtrl | ConditionCompare$ GE1 | SubAbility$ DBCopy -SVar:DBCopy:DB$ CopySpellAbility| Defined$ TriggeredSpellAbility | ConditionPresent$ Enchantment.YouCtrl | ConditionCompare$ GE1 +# TODO check ruling with Twinning Staff +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | ConditionPresent$ Artifact.YouCtrl | ConditionCompare$ GE1 | MayChooseTarget$ True | SubAbility$ DBCopy +SVar:DBCopy:DB$ CopySpellAbility| Defined$ TriggeredSpellAbility | ConditionPresent$ Enchantment.YouCtrl | ConditionCompare$ GE1 | MayChooseTarget$ True A:SP$ ChangeZone | Cost$ 4 W U | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | Origin$ Battlefield | Destination$ Hand | SubAbility$ DBToken | SpellDescription$ Return target nonland permanent to its owner's hand. You create a 2/2 white Knight creature token with vigilance. SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_2_2_knight_vigilance | TokenOwner$ You | LegacyImage$ w 2 2 knight vigilance eld DeckHas:Ability$Token diff --git a/forge-gui/res/cardsfolder/b/bitter_ordeal.txt b/forge-gui/res/cardsfolder/b/bitter_ordeal.txt index f089956ebb1..b2cedbcc4a1 100644 --- a/forge-gui/res/cardsfolder/b/bitter_ordeal.txt +++ b/forge-gui/res/cardsfolder/b/bitter_ordeal.txt @@ -2,8 +2,5 @@ Name:Bitter Ordeal ManaCost:2 B Types:Sorcery A:SP$ ChangeZone | Cost$ 2 B | Origin$ Library | Destination$ Exile | ValidTgts$ Player | ChangeType$ Card | ChangeNum$ 1 | IsCurse$ True | SpellDescription$ Search target player's library for a card and exile it. Then that player shuffles their library. -T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigGravestorm | TriggerDescription$ Gravestorm (When you cast this spell, copy it for each permanent put into a graveyard this turn. You may choose new targets for the copies.) -SVar:TrigGravestorm:DB$CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ GravestormCount | References$ GravestormCount -SVar:GravestormCount:Count$ThisTurnEntered_Graveyard_Permanent -SVar:Picture:http://www.wizards.com/global/images/magic/general/bitter_ordeal.jpg -Oracle:Search target player's library for a card and exile it. Then that player shuffles their library.\nGravestorm (When you cast this spell, copy it for each permanent put into a graveyard this turn. You may choose new targets for the copies.) +K:Gravestorm +Oracle:Search target player's library for a card and exile it. Then that player shuffles their library.\nGravestorm (When you cast this spell, copy it for each permanent that was put into a graveyard from the battlefield this turn. If the spell has any targets, you may choose new targets for any of the copies.) diff --git a/forge-gui/res/cardsfolder/b/bonus_round.txt b/forge-gui/res/cardsfolder/b/bonus_round.txt index 0cce52c3efd..bc199264cd0 100644 --- a/forge-gui/res/cardsfolder/b/bonus_round.txt +++ b/forge-gui/res/cardsfolder/b/bonus_round.txt @@ -3,7 +3,7 @@ ManaCost:1 R R Types:Sorcery A:SP$ Effect | Cost$ 1 R R | Name$ Bonus Round Effect | Triggers$ TrigSpellCast | SVars$ TrigCopySpell | SpellDescription$ Until end of turn, whenever a player casts an instant or sorcery spell, that player copies it and may choose new targets for the copy. SVar:TrigSpellCast:Mode$ SpellCast | ValidCard$ Instant,Sorcery | TriggerZones$ Command | ValidActivatingPlayer$ Player | Execute$ TrigCopySpell | TriggerDescription$ Until end of turn, whenever a player casts an instant or sorcery spell, that player copies it and may choose new targets for the copy. -SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always | Controller$ TriggeredCardController +SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always | Controller$ TriggeredCardController | MayChooseTarget$ True DeckNeeds:Type$Instant|Sorcery AI:RemoveDeck:Random SVar:PlayMain1:TRUE diff --git a/forge-gui/res/cardsfolder/c/chain_lightning.txt b/forge-gui/res/cardsfolder/c/chain_lightning.txt index b5045e1c9bf..7855ba374ec 100644 --- a/forge-gui/res/cardsfolder/c/chain_lightning.txt +++ b/forge-gui/res/cardsfolder/c/chain_lightning.txt @@ -2,7 +2,5 @@ Name:Chain Lightning ManaCost:R Types:Sorcery A:SP$ DealDamage | Cost$ R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select target | NumDmg$ 3 | SubAbility$ DBCopy1 | SpellDescription$ CARDNAME deals 3 damage to any target. Then that player or that permanent's controller may pay {R}{R}. If the player does, they may copy this spell and may choose a new target for that copy. -SVar:DBCopy1:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | UnlessPayer$ TargetedController | UnlessCost$ R R | UnlessSwitched$ True | ConditionDefined$ Targeted | ConditionPresent$ Permanent | ConditionCompare$ GE1 | SubAbility$ DBCopy2 | StackDescription$ None -SVar:DBCopy2:DB$ CopySpellAbility | Defined$ Parent | Controller$ Targeted | UnlessPayer$ Targeted | UnlessCost$ R R | UnlessSwitched$ True | ConditionDefined$ Targeted | ConditionPresent$ Permanent | ConditionCompare$ EQ0 | StackDescription$ None -SVar:Picture:http://www.wizards.com/global/images/magic/general/chain_lightning.jpg +SVar:DBCopy1:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedOrController | UnlessPayer$ TargetedOrController | UnlessCost$ R R | UnlessSwitched$ True | MayChooseTarget$ True | StackDescription$ None Oracle:Chain Lightning deals 3 damage to any target. Then that player or that permanent's controller may pay {R}{R}. If the player does, they may copy this spell and may choose a new target for that copy. diff --git a/forge-gui/res/cardsfolder/c/chain_of_acid.txt b/forge-gui/res/cardsfolder/c/chain_of_acid.txt index 2a69c266dcd..70f09a1ca7c 100644 --- a/forge-gui/res/cardsfolder/c/chain_of_acid.txt +++ b/forge-gui/res/cardsfolder/c/chain_of_acid.txt @@ -2,7 +2,6 @@ Name:Chain of Acid ManaCost:3 G Types:Sorcery A:SP$ Destroy | Cost$ 3 G | ValidTgts$ Permanent.nonCreature | SubAbility$ DBCopy | SpellDescription$ Destroy target noncreature permanent. Then that permanent's controller may copy this spell and may choose a new target for that copy. -SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | Optional$ True | AILogic$ ChainOfAcid | StackDescription$ None +SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | Optional$ True | AILogic$ ChainOfAcid | StackDescription$ None | MayChooseTarget$ True AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/chain_of_acid.jpg -Oracle:Destroy target noncreature permanent. Then that permanent's controller may copy this spell and may choose a new target for that copy. \ No newline at end of file +Oracle:Destroy target noncreature permanent. Then that permanent's controller may copy this spell and may choose a new target for that copy. diff --git a/forge-gui/res/cardsfolder/c/chain_of_plasma.txt b/forge-gui/res/cardsfolder/c/chain_of_plasma.txt index 8eea0a87f49..075b8756c46 100644 --- a/forge-gui/res/cardsfolder/c/chain_of_plasma.txt +++ b/forge-gui/res/cardsfolder/c/chain_of_plasma.txt @@ -2,7 +2,5 @@ Name:Chain of Plasma ManaCost:1 R Types:Instant A:SP$ DealDamage | Cost$ 1 R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 3 | SubAbility$ DBCopy1 | SpellDescription$ CARDNAME deals 3 damage to any target. Then that player or that permanent's controller may discard a card. If the player does, they may copy this spell and may choose a new target for that copy. -SVar:DBCopy1:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | UnlessPayer$ TargetedController | UnlessCost$ Discard<1/Card> | UnlessSwitched$ True | ConditionDefined$ Targeted | ConditionPresent$ Permanent | ConditionCompare$ GE1 | SubAbility$ DBCopy2 | StackDescription$ None -SVar:DBCopy2:DB$ CopySpellAbility | Defined$ Parent | Controller$ Targeted | UnlessPayer$ Targeted | UnlessCost$ Discard<1/Card> | UnlessSwitched$ True | ConditionDefined$ Targeted | ConditionPresent$ Permanent | ConditionCompare$ EQ0 | StackDescription$ None -SVar:Picture:http://www.wizards.com/global/images/magic/general/chain_of_plasma.jpg +SVar:DBCopy1:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedOrController | UnlessPayer$ TargetedOrController | UnlessCost$ Discard<1/Card> | UnlessSwitched$ True | StackDescription$ None | MayChooseTarget$ True Oracle:Chain of Plasma deals 3 damage to any target. Then that player or that permanent's controller may discard a card. If the player does, they may copy this spell and may choose a new target for that copy. diff --git a/forge-gui/res/cardsfolder/c/chain_of_silence.txt b/forge-gui/res/cardsfolder/c/chain_of_silence.txt index c19c6a5f5b4..451adee2b8d 100644 --- a/forge-gui/res/cardsfolder/c/chain_of_silence.txt +++ b/forge-gui/res/cardsfolder/c/chain_of_silence.txt @@ -2,6 +2,5 @@ Name:Chain of Silence ManaCost:1 W Types:Instant A:SP$ Pump | Cost$ 1 W | ValidTgts$ Creature | KW$ Prevent all damage that would be dealt by CARDNAME. | IsCurse$ True | TgtPrompt$ Select target creature | SubAbility$ DBCopy | SpellDescription$ Prevent all damage target creature would deal this turn. That creature's controller may sacrifice a land. If the player does, they may copy this spell and may choose a new target for that copy. | StackDescription$ SpellDescription -SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | Optional$ True | UnlessPayer$ TargetedController | UnlessCost$ Sac<1/Land> | UnlessSwitched$ True | UnlessAI$ Never | StackDescription$ None -SVar:Picture:http://www.wizards.com/global/images/magic/general/chain_of_silence.jpg -Oracle:Prevent all damage target creature would deal this turn. That creature's controller may sacrifice a land. If the player does, they may copy this spell and may choose a new target for that copy. \ No newline at end of file +SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | Optional$ True | UnlessPayer$ TargetedController | UnlessCost$ Sac<1/Land> | UnlessSwitched$ True | UnlessAI$ Never | StackDescription$ None | MayChooseTarget$ True +Oracle:Prevent all damage target creature would deal this turn. That creature's controller may sacrifice a land. If the player does, they may copy this spell and may choose a new target for that copy. diff --git a/forge-gui/res/cardsfolder/c/chain_of_smog.txt b/forge-gui/res/cardsfolder/c/chain_of_smog.txt index 6b210fded18..1fc9b650df1 100644 --- a/forge-gui/res/cardsfolder/c/chain_of_smog.txt +++ b/forge-gui/res/cardsfolder/c/chain_of_smog.txt @@ -2,7 +2,6 @@ Name:Chain of Smog ManaCost:1 B Types:Sorcery A:SP$ Discard | Cost$ 1 B | ValidTgts$ Player | NumCards$ 2 | Mode$ TgtChoose | SubAbility$ DBCopy | SpellDescription$ Target player discards two cards. That player may copy this spell and may choose a new target for that copy. -SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedPlayer | Optional$ True | AILogic$ ChainOfSmog | StackDescription$ None +SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedPlayer | Optional$ True | AILogic$ ChainOfSmog | StackDescription$ None | MayChooseTarget$ True AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/chain_of_smog.jpg Oracle:Target player discards two cards. That player may copy this spell and may choose a new target for that copy. diff --git a/forge-gui/res/cardsfolder/c/chain_of_vapor.txt b/forge-gui/res/cardsfolder/c/chain_of_vapor.txt index 4f3beaa6432..1ac6f4ae8c1 100644 --- a/forge-gui/res/cardsfolder/c/chain_of_vapor.txt +++ b/forge-gui/res/cardsfolder/c/chain_of_vapor.txt @@ -2,6 +2,5 @@ Name:Chain of Vapor ManaCost:U Types:Instant A:SP$ ChangeZone | Cost$ U | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | Origin$ Battlefield | Destination$ Hand | SubAbility$ DBCopy | StackDescription$ SpellDescription | SpellDescription$ Return target nonland permanent to its owner's hand. Then that permanent's controller may sacrifice a land. If the player does, they may copy this spell and may choose a new target for that copy. -SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | UnlessPayer$ TargetedController | UnlessCost$ Sac<1/Land> | UnlessSwitched$ True | StackDescription$ None -SVar:Picture:http://www.wizards.com/global/images/magic/general/chain_of_vapor.jpg +SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | UnlessPayer$ TargetedController | UnlessCost$ Sac<1/Land> | UnlessSwitched$ True | StackDescription$ None | MayChooseTarget$ True Oracle:Return target nonland permanent to its owner's hand. Then that permanent's controller may sacrifice a land. If the player does, they may copy this spell and may choose a new target for that copy. diff --git a/forge-gui/res/cardsfolder/c/chain_stasis.txt b/forge-gui/res/cardsfolder/c/chain_stasis.txt index 9a7571977e6..65baa729377 100644 --- a/forge-gui/res/cardsfolder/c/chain_stasis.txt +++ b/forge-gui/res/cardsfolder/c/chain_stasis.txt @@ -2,7 +2,6 @@ Name:Chain Stasis ManaCost:U Types:Instant A:SP$ TapOrUntap | Cost$ U | ValidTgts$ Creature | TgtPrompt$ Select target creature | SubAbility$ DBCopy | SpellDescription$ You may tap or untap target creature. Then that creature's controller may pay {2}{U}. If the player does, they may copy this spell and may choose a new target for that copy. -SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | UnlessPayer$ TargetedController | UnlessCost$ 2 U | UnlessSwitched$ True | StackDescription$ Then that creature's controller may pay {2}{U}. If the player does, they may copy this spell and may choose a new target for that copy. +SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | UnlessPayer$ TargetedController | UnlessCost$ 2 U | UnlessSwitched$ True | MayChooseTarget$ True | StackDescription$ Then that creature's controller may pay {2}{U}. If the player does, they may copy this spell and may choose a new target for that copy. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/chain_stasis.jpg Oracle:You may tap or untap target creature. Then that creature's controller may pay {2}{U}. If the player does, they may copy this spell and may choose a new target for that copy. diff --git a/forge-gui/res/cardsfolder/c/chandra_the_firebrand.txt b/forge-gui/res/cardsfolder/c/chandra_the_firebrand.txt index 10e65e21df6..bdcf9a769e7 100644 --- a/forge-gui/res/cardsfolder/c/chandra_the_firebrand.txt +++ b/forge-gui/res/cardsfolder/c/chandra_the_firebrand.txt @@ -2,11 +2,8 @@ Name:Chandra, the Firebrand ManaCost:3 R Types:Legendary Planeswalker Chandra Loyalty:3 -A:AB$DealDamage | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to any target. -A:AB$Effect | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | AILogic$ SpellCopy | Name$ Chandra, the Firebrand effect. | Image$ chandra_the_firebrand_effect | Triggers$ TrigCopy | SVars$ TrigCopyMain,DBCleanup | SpellDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. -A:AB$DealDamage | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | TargetMin$ 0 | TargetMax$ 6 | NumDmg$ 6 | SpellDescription$ CARDNAME deals 6 damage to each of up to six targets. -SVar:TrigCopy:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | OneOff$ True | Execute$ TrigCopyMain | TriggerZones$ Command | TriggerDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. -SVar:TrigCopyMain:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | SubAbility$ DBCleanup -SVar:DBCleanup:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile -SVar:Picture:http://www.wizards.com/global/images/magic/general/chandra_the_firebrand.jpg +A:AB$ DealDamage | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to any target. +A:AB$ DelayedTrigger | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | AILogic$ SpellCopy | Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | ThisTurn$ True | Execute$ EffTrigCopy | SpellDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. +SVar:EffTrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True +A:AB$ DealDamage | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | TargetMin$ 0 | TargetMax$ 6 | NumDmg$ 6 | SpellDescription$ CARDNAME deals 6 damage to each of up to six targets. Oracle:[+1]: Chandra, the Firebrand deals 1 damage to any target.\n[−2]: When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy.\n[−6]: Chandra, the Firebrand deals 6 damage to each of up to six targets. diff --git a/forge-gui/res/cardsfolder/c/chandras_regulator.txt b/forge-gui/res/cardsfolder/c/chandras_regulator.txt index 02515b748c4..e6fedd30b00 100644 --- a/forge-gui/res/cardsfolder/c/chandras_regulator.txt +++ b/forge-gui/res/cardsfolder/c/chandras_regulator.txt @@ -2,7 +2,7 @@ Name:Chandra's Regulator ManaCost:1 R Types:Legendary Artifact T:Mode$ AbilityCast | ValidCard$ Planeswalker.Chandra | ValidActivatingPlayer$ You | ValidSA$ Activated.Loyalty | TriggerZones$ Battlefield | Execute$ TrigCopyAbility | TriggerDescription$ Whenever you activate a loyalty ability of a Chandra planeswalker, you may pay {1}. If you do, copy that ability. You may choose new targets for the copy. -SVar:TrigCopyAbility:AB$ CopySpellAbility | Cost$ 1 | Defined$ TriggeredSpellAbility +SVar:TrigCopyAbility:AB$ CopySpellAbility | Cost$ 1 | Defined$ TriggeredSpellAbility | MayChooseTarget$ True A:AB$ Draw | Cost$ 1 T Discard<1/Mountain;Card.Red/Mountain card or a red card> | NumCards$ 1 | SpellDescription$ Draw a card. SVar:AIPreference:SacCost$Card.Mountain,Card.Red DeckNeeds:Type$Chandra diff --git a/forge-gui/res/cardsfolder/c/cloven_casting.txt b/forge-gui/res/cardsfolder/c/cloven_casting.txt index ea70f2dfb54..5cca89f3cc2 100644 --- a/forge-gui/res/cardsfolder/c/cloven_casting.txt +++ b/forge-gui/res/cardsfolder/c/cloven_casting.txt @@ -2,7 +2,6 @@ Name:Cloven Casting ManaCost:5 U R Types:Enchantment T:Mode$ SpellCast | ValidCard$ Instant.MultiColor,Sorcery.MultiColor | ValidActivatingPlayer$ You | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast a multicolored instant or sorcery spell, you may pay {1}. If you do, copy that spell. You may choose new targets for the copy. -SVar:TrigCopy:AB$ CopySpellAbility | Cost$ 1 | Defined$ TriggeredSpellAbility +SVar:TrigCopy:AB$ CopySpellAbility | Cost$ 1 | Defined$ TriggeredSpellAbility | MayChooseTarget$ True AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/cloven_casting.jpg Oracle:Whenever you cast a multicolored instant or sorcery spell, you may pay {1}. If you do, copy that spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/c/curse_of_echoes.txt b/forge-gui/res/cardsfolder/c/curse_of_echoes.txt index f88f4c50cbc..2b1b01ddba7 100644 --- a/forge-gui/res/cardsfolder/c/curse_of_echoes.txt +++ b/forge-gui/res/cardsfolder/c/curse_of_echoes.txt @@ -4,8 +4,8 @@ Types:Enchantment Aura Curse K:Enchant player A:SP$ Attach | Cost$ 4 U | ValidTgts$ Player | AILogic$ Curse T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ Player.EnchantedBy | Execute$ TrigCopy | TriggerZones$ Battlefield | OptionalDecider$ TriggeredCardOpponent | TriggerDescription$ Whenever enchanted player casts an instant or sorcery spell, each other player may copy that spell and may choose new targets for the copy they control. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ TriggeredCardOpponent +# TODO each player should copy it for multiplayer +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ TriggeredCardOpponent | MayChooseTarget$ True AI:RemoveDeck:All SVar:RemMultiplayer:True -SVar:Picture:http://www.wizards.com/global/images/magic/general/curse_of_echoes.jpg Oracle:Enchant player\nWhenever enchanted player casts an instant or sorcery spell, each other player may copy that spell and may choose new targets for the copy they control. diff --git a/forge-gui/res/cardsfolder/d/double_stroke.txt b/forge-gui/res/cardsfolder/d/double_stroke.txt index 5c45f500529..c6a464343c2 100644 --- a/forge-gui/res/cardsfolder/d/double_stroke.txt +++ b/forge-gui/res/cardsfolder/d/double_stroke.txt @@ -3,6 +3,6 @@ ManaCost:no cost Types:Conspiracy K:Hidden agenda T:Mode$ SpellCast | ValidCard$ Instant.NamedCard,Sorcery.NamedCard | ValidActivatingPlayer$ You | Execute$ TrigCopySpell | TriggerZones$ Command | OptionalDecider$ You | TriggerDescription$ Whenever you cast an instant or sorcery spell with the chosen name, you may copy it. You may choose new targets for the copy. -SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ 1 +SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ 1 | MayChooseTarget$ True SVar:AgendaLogic:MostProminentSpellInComputerDeck Oracle:Hidden agenda (Start the game with this conspiracy face down in the command zone and secretly name a card. You may turn this conspiracy face up any time and reveal the chosen name.)\nWhenever you cast an instant or sorcery spell with the chosen name, you may copy it. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/d/double_vision.txt b/forge-gui/res/cardsfolder/d/double_vision.txt index e4a079ee471..c1f40d94dd1 100644 --- a/forge-gui/res/cardsfolder/d/double_vision.txt +++ b/forge-gui/res/cardsfolder/d/double_vision.txt @@ -2,6 +2,6 @@ Name:Double Vision ManaCost:3 R R Types:Enchantment T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | ActivatorThisTurnCast$ EQ1 | NoResolvingCheck$ True | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast your first instant or sorcery spell each turn, copy that spell. You may choose new targets for the copy. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always | MayChooseTarget$ True DeckHints:Type$Instant|Sorcery Oracle:Whenever you cast your first instant or sorcery spell each turn, copy that spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/d/doublecast.txt b/forge-gui/res/cardsfolder/d/doublecast.txt index a985e86df03..ba6ffc6a365 100644 --- a/forge-gui/res/cardsfolder/d/doublecast.txt +++ b/forge-gui/res/cardsfolder/d/doublecast.txt @@ -1,9 +1,7 @@ Name:Doublecast ManaCost:R R Types:Sorcery -A:SP$ Effect | Cost$ R R | AILogic$ SpellCopy | Name$ Doublecast Effect | Triggers$ EffTModeSpellCast | SVars$ EffTrigCopy,EffDBCleanup | SpellDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. -SVar:EffTModeSpellCast:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | OneOff$ True | Execute$ EffTrigCopy | TriggerZones$ Command | TriggerDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. -SVar:EffTrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | SubAbility$ EffDBCleanup -SVar:EffDBCleanup:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile +A:SP$ DelayedTrigger | Cost$ R R | AILogic$ SpellCopy | Execute$ EffTrigCopy | ThisTurn$ True | Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | SpellDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. +SVar:EffTrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True SVar:AIPriorityModifier:9 Oracle:When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for that copy. diff --git a/forge-gui/res/cardsfolder/d/dual_casting.txt b/forge-gui/res/cardsfolder/d/dual_casting.txt index bf905034d4e..f1584a35835 100644 --- a/forge-gui/res/cardsfolder/d/dual_casting.txt +++ b/forge-gui/res/cardsfolder/d/dual_casting.txt @@ -4,6 +4,6 @@ Types:Enchantment Aura K:Enchant creature A:SP$ Attach | Cost$ 1 R | ValidTgts$ Creature | AILogic$ Pump S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddAbility$ ForkStick | Description$ Enchanted creature has "{R}, {T}: Copy target instant or sorcery spell you control. You may choose new targets for the copy." -SVar:ForkStick:AB$ CopySpellAbility | Cost$ R T | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | SpellDescription$ Copy target instant or sorcery spell you control. You may choose new targets for the copy. +SVar:ForkStick:AB$ CopySpellAbility | Cost$ R T | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell you control. You may choose new targets for the copy. SVar:Picture:http://www.wizards.com/global/images/magic/general/dual_casting.jpg Oracle:Enchant creature\nEnchanted creature has "{R}, {T}: Copy target instant or sorcery spell you control. You may choose new targets for the copy." diff --git a/forge-gui/res/cardsfolder/d/dualcaster_mage.txt b/forge-gui/res/cardsfolder/d/dualcaster_mage.txt index f303c17ffdb..7e2c7ced8f5 100644 --- a/forge-gui/res/cardsfolder/d/dualcaster_mage.txt +++ b/forge-gui/res/cardsfolder/d/dualcaster_mage.txt @@ -4,7 +4,6 @@ Types:Creature Human Wizard PT:2/2 K:Flash T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When CARDNAME enters the battlefield, copy target instant or sorcery spell. You may choose new targets for that copy. -SVar:TrigCopy:DB$ CopySpellAbility | ValidTgts$ Instant,Sorcery | TargetType$ Spell +SVar:TrigCopy:DB$ CopySpellAbility | ValidTgts$ Instant,Sorcery | TargetType$ Spell | MayChooseTarget$ True AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/dualcaster_mage.jpg Oracle:Flash\nWhen Dualcaster Mage enters the battlefield, copy target instant or sorcery spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/e/echo_mage.txt b/forge-gui/res/cardsfolder/e/echo_mage.txt index 755a94da0ba..a0ab3d1be7b 100644 --- a/forge-gui/res/cardsfolder/e/echo_mage.txt +++ b/forge-gui/res/cardsfolder/e/echo_mage.txt @@ -4,11 +4,8 @@ Types:Creature Human Wizard PT:2/3 K:Level up:1 U SVar:maxLevel:4 -S:Mode$ Continuous | Affected$ Card.Self | SetPower$ 2 | SetToughness$ 4 | AddAbility$ CopyOnce | CheckSVar$ X | SVarCompare$ EQ1 | Description$ LEVEL 2-3 2/4 CARDNAME gets U U,tap: Copy target instant or sorcery spell. You may choose new targets for the copy. -S:Mode$ Continuous | Affected$ Card.Self | SetPower$ 2 | SetToughness$ 5 | AddAbility$ CopyTwice | CheckSVar$ Y | SVarCompare$ EQ1 | Description$ LEVEL 4+ 2/5 CARDNAME gets U U,tap:Copy target instant or sorcery spell twice. You may choose new targets for the copies. -SVar:CopyOnce:AB$CopySpellAbility | Cost$ U U T | ValidTgts$ Instant,Sorcery | AILogic$ OnceIfViable | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. -SVar:CopyTwice:AB$CopySpellAbility | Cost$ U U T | ValidTgts$ Instant,Sorcery | Amount$ 2 | AILogic$ OnceIfViable | SpellDescription$ Copy target instant or sorcery spell twice. You may choose new targets for the copies. -SVar:X:Count$Valid Card.Self+counters_GE2_LEVEL+counters_LT4_LEVEL -SVar:Y:Count$Valid Card.Self+counters_GE4_LEVEL -SVar:Picture:http://www.wizards.com/global/images/magic/general/echo_mage.jpg +S:Mode$ Continuous | Affected$ Card.Self | SetPower$ 2 | SetToughness$ 4 | AddAbility$ CopyOnce | IsPresent$ Card.Self+counters_GE2_LEVEL+counters_LT4_LEVEL | Description$ LEVEL 2-3 2/4 CARDNAME gets U U,tap: Copy target instant or sorcery spell. You may choose new targets for the copy. +S:Mode$ Continuous | Affected$ Card.Self | SetPower$ 2 | SetToughness$ 5 | AddAbility$ CopyTwice | IsPresent$ Card.Self+counters_GE4_LEVEL | Description$ LEVEL 4+ 2/5 CARDNAME gets U U,tap:Copy target instant or sorcery spell twice. You may choose new targets for the copies. +SVar:CopyOnce:AB$ CopySpellAbility | Cost$ U U T | ValidTgts$ Instant,Sorcery | AILogic$ OnceIfViable | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. +SVar:CopyTwice:AB$ CopySpellAbility | Cost$ U U T | ValidTgts$ Instant,Sorcery | Amount$ 2 | AILogic$ OnceIfViable | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell twice. You may choose new targets for the copies. Oracle:Level up {1}{U} ({1}{U}: Put a level counter on this. Level up only as a sorcery.)\nLEVEL 2-3\n2/4\n{U}{U}, {T}: Copy target instant or sorcery spell. You may choose new targets for the copy.\nLEVEL 4+\n2/5\n{U}{U}, {T}: Copy target instant or sorcery spell twice. You may choose new targets for the copies. diff --git a/forge-gui/res/cardsfolder/e/echo_storm.txt b/forge-gui/res/cardsfolder/e/echo_storm.txt index 24fb9ef5449..fbc001e8eae 100644 --- a/forge-gui/res/cardsfolder/e/echo_storm.txt +++ b/forge-gui/res/cardsfolder/e/echo_storm.txt @@ -2,7 +2,7 @@ Name:Echo Storm ManaCost:3 U U Types:Sorcery T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When you cast this spell, copy it for each time you've cast your commander from the command zone this game. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X | MayChooseTarget$ True SVar:X:Count$TotalCommanderCastFromCommandZone A:SP$ CopyPermanent | Cost$ 3 U U | ValidTgts$ Artifact | TgtPrompt$ Select target artifact. | SpellDescription$ Create a token that's a copy of target artifact. DeckHas:Ability$Token diff --git a/forge-gui/res/cardsfolder/e/echoing_boon.txt b/forge-gui/res/cardsfolder/e/echoing_boon.txt index 9e7c9a7a83a..0f726404359 100644 --- a/forge-gui/res/cardsfolder/e/echoing_boon.txt +++ b/forge-gui/res/cardsfolder/e/echoing_boon.txt @@ -3,7 +3,6 @@ ManaCost:no cost Types:Conspiracy K:Hidden agenda T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Command | TargetsValid$ Card.NamedCard+YouCtrl | Execute$ TrigCopySpell | OptionalDecider$ You | TriggerDescription$ Whenever you cast an instant or sorcery spell, if it targets a creature you control with the chosen name, you may copy that spell and may choose new targets for the copy. -SVar:TrigCopySpell:DB$CopySpellAbility | Defined$ TriggeredSpellAbility +SVar:TrigCopySpell:DB$CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True SVar:AgendaLogic:BestCreatureInComputerDeck -SVar:Picture:http://www.wizards.com/global/images/magic/general/echoing_boon.jpg Oracle:Hidden agenda (Start the game with this conspiracy face down in the command zone and secretly name a card. You may turn this conspiracy face up any time and reveal the chosen name.)\nWhenever you cast an instant or sorcery spell, if it targets a creature you control with the chosen name, you may copy that spell and may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/e/empyrial_storm.txt b/forge-gui/res/cardsfolder/e/empyrial_storm.txt index 7925680042f..4fb4817b905 100644 --- a/forge-gui/res/cardsfolder/e/empyrial_storm.txt +++ b/forge-gui/res/cardsfolder/e/empyrial_storm.txt @@ -2,7 +2,7 @@ Name:Empyrial Storm ManaCost:4 W W Types:Sorcery T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When you cast this spell, copy it for each time you've cast your commander from the command zone this game. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X | MayChooseTarget$ True SVar:X:Count$TotalCommanderCastFromCommandZone A:SP$ Token | Cost$ 4 W W | TokenAmount$ 1 | TokenScript$ w_4_4_angel_flying | TokenOwner$ You | LegacyImage$ w 4 4 angel flying c18 | SpellDescription$ Create a 4/4 white Angel creature token with flying. DeckHas:Ability$Token diff --git a/forge-gui/res/cardsfolder/e/expansion_explosion.txt b/forge-gui/res/cardsfolder/e/expansion_explosion.txt index bb7bbd290ee..f071098855c 100644 --- a/forge-gui/res/cardsfolder/e/expansion_explosion.txt +++ b/forge-gui/res/cardsfolder/e/expansion_explosion.txt @@ -2,7 +2,7 @@ Name:Expansion ManaCost:U/R U/R Types:Instant AlternateMode: Split -A:SP$ CopySpellAbility | Cost$ U/R U/R | ValidTgts$ Card.Instant+cmcLE4,Card.Sorcery+cmcLE4 | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell with converted mana cost 4 or less. You may choose new targets for the copy. +A:SP$ CopySpellAbility | Cost$ U/R U/R | ValidTgts$ Card.Instant+cmcLE4,Card.Sorcery+cmcLE4 | TargetType$ Spell | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell with converted mana cost 4 or less. You may choose new targets for the copy. Oracle:Copy target instant or sorcery spell with converted mana cost 4 or less. You may choose new targets for the copy. ALTERNATE diff --git a/forge-gui/res/cardsfolder/f/finale_of_promise.txt b/forge-gui/res/cardsfolder/f/finale_of_promise.txt index 96f12977f1b..2f4fa83bd4e 100644 --- a/forge-gui/res/cardsfolder/f/finale_of_promise.txt +++ b/forge-gui/res/cardsfolder/f/finale_of_promise.txt @@ -5,6 +5,6 @@ A:SP$ Pump | Cost$ X R R | ValidTgts$ Instant.YouOwn+cmcLEX | TgtZone$ Graveyard SVar:DBPump:DB$ Pump | ValidTgts$ Sorcery.YouOwn+cmcLEX | TgtZone$ Graveyard | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select target sorcery card in your graveyard with converted mana cost X or less | RememberObjects$ Targeted | SubAbility$ DBPlay | References$ X | StackDescription$ None SVar:DBPlay:DB$ Play | Valid$ Card.IsRemembered | ValidZone$ Graveyard | Controller$ You | CopyCard$ True | CopyOnce$ True | WithoutManaCost$ True | Optional$ True | Amount$ All | SubAbility$ DBRepeat SVar:DBRepeat:DB$ RepeatEach | DefinedCards$ Remembered | ClearRemembered$ True | ChooseOrder$ True | RepeatSubAbility$ DBCopy | References$ X | ConditionCheckSVar$ X | ConditionSVarCompare$ GE10 -SVar:DBCopy:DB$ CopySpellAbility | Amount$ 2 | Defined$ Remembered +SVar:DBCopy:DB$ CopySpellAbility | Amount$ 2 | Defined$ Remembered | MayChooseTarget$ True SVar:X:Count$xPaid -Oracle:You may cast up to one target instant card and/or sorcery card from your graveyard each with converted mana cost X or less without paying their mana costs. If a card cast this way would be put into your graveyard this turn, exile it instead. If X is 10 or more, copy each of those spells twice. You may choose new targets for the copies. \ No newline at end of file +Oracle:You may cast up to one target instant card and/or sorcery card from your graveyard each with converted mana cost X or less without paying their mana costs. If a card cast this way would be put into your graveyard this turn, exile it instead. If X is 10 or more, copy each of those spells twice. You may choose new targets for the copies. diff --git a/forge-gui/res/cardsfolder/f/fork.txt b/forge-gui/res/cardsfolder/f/fork.txt index 84dd0f13fc4..ee58faa4933 100644 --- a/forge-gui/res/cardsfolder/f/fork.txt +++ b/forge-gui/res/cardsfolder/f/fork.txt @@ -1,6 +1,5 @@ Name:Fork ManaCost:R R Types:Instant -A:SP$ CopySpellAbility | Cost$ R R | ValidTgts$ Instant,Sorcery | TargetType$ Spell | CopyIsColor$ Red | OverwriteColors$ True | SpellDescription$ Copy target instant or sorcery spell, except that the copy is red. You may choose new targets for the copy. -SVar:Picture:http://www.wizards.com/global/images/magic/general/fork.jpg +A:SP$ CopySpellAbility | Cost$ R R | ValidTgts$ Instant,Sorcery | TargetType$ Spell | CopyIsColor$ Red | OverwriteColors$ True | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell, except that the copy is red. You may choose new targets for the copy. Oracle:Copy target instant or sorcery spell, except that the copy is red. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/f/fury_storm.txt b/forge-gui/res/cardsfolder/f/fury_storm.txt index 6895b278dd6..19c481c8bbb 100644 --- a/forge-gui/res/cardsfolder/f/fury_storm.txt +++ b/forge-gui/res/cardsfolder/f/fury_storm.txt @@ -2,7 +2,7 @@ Name:Fury Storm ManaCost:2 R R Types:Instant T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When you cast this spell, copy it for each time you've cast your commander from the command zone this game. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X | MayChooseTarget$ True SVar:X:Count$TotalCommanderCastFromCommandZone -A:SP$ CopySpellAbility | Cost$ 2 R R | ValidTgts$ Instant,Sorcery | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. +A:SP$ CopySpellAbility | Cost$ 2 R R | ValidTgts$ Instant,Sorcery | TargetType$ Spell | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. Oracle:When you cast this spell, copy it for each time you've cast your commander from the command zone this game. You may choose new targets for the copies.\nCopy target instant or sorcery spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/g/geistblast.txt b/forge-gui/res/cardsfolder/g/geistblast.txt index 4be13b50adf..aaad303346b 100644 --- a/forge-gui/res/cardsfolder/g/geistblast.txt +++ b/forge-gui/res/cardsfolder/g/geistblast.txt @@ -2,7 +2,6 @@ Name:Geistblast ManaCost:2 R Types:Instant A:SP$ DealDamage | Cost$ 2 R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to any target. -A:AB$ CopySpellAbility | Cost$ 2 U ExileFromGrave<1/CARDNAME> | ActivationZone$ Graveyard | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell you control. You may choose new targets for the copy. +A:AB$ CopySpellAbility | Cost$ 2 U ExileFromGrave<1/CARDNAME> | ActivationZone$ Graveyard | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell you control. You may choose new targets for the copy. SVar:AIPreference:ExileFromGraveCost$Card.Self -SVar:Picture:http://www.wizards.com/global/images/magic/general/geistblast.jpg Oracle:Geistblast deals 2 damage to any target.\n{2}{U}, Exile Geistblast from your graveyard: Copy target instant or sorcery spell you control. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/g/genesis_storm.txt b/forge-gui/res/cardsfolder/g/genesis_storm.txt index ed19640f1f0..6a004f82421 100644 --- a/forge-gui/res/cardsfolder/g/genesis_storm.txt +++ b/forge-gui/res/cardsfolder/g/genesis_storm.txt @@ -2,7 +2,7 @@ Name:Genesis Storm ManaCost:4 G G Types:Sorcery T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When you cast this spell, copy it for each time you've cast your commander from the command zone this game. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X | MayChooseTarget$ True SVar:X:Count$TotalCommanderCastFromCommandZone A:SP$ DigUntil | Cost$ 4 G G | Valid$ Permanent.nonland | ValidDescription$ nonland permanent | FoundDestination$ Battlefield | OptionalFoundMove$ True | RevealedDestination$ Library | RevealedLibraryPosition$ -1 | RevealRandomOrder$ True | SpellDescription$ Reveal cards from the top of your library until you reveal a nonland permanent card. You may put that card onto the battlefield. Then put all cards revealed this way that weren't put onto the battlefield on the bottom of your library in a random order. Oracle:When you cast this spell, copy it for each time you've cast your commander from the command zone this game. You may choose new targets for the copies.\nReveal cards from the top of your library until you reveal a nonland permanent card. You may put that card onto the battlefield. Then put all cards revealed this way that weren't put onto the battlefield on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/h/hive_mind.txt b/forge-gui/res/cardsfolder/h/hive_mind.txt index 2cb798a8cf2..122f08a861b 100644 --- a/forge-gui/res/cardsfolder/h/hive_mind.txt +++ b/forge-gui/res/cardsfolder/h/hive_mind.txt @@ -2,8 +2,7 @@ Name:Hive Mind ManaCost:5 U Types:Enchantment T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ Player | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever a player casts an instant or sorcery spell, each other player copies that spell. Each of those players may choose new targets for their copy. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ TriggeredCardOpponent +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ TriggeredCardOpponent | MayChooseTarget$ True AI:RemoveDeck:Random SVar:RemMultiplayer:True -SVar:Picture:http://www.wizards.com/global/images/magic/general/hive_mind.jpg Oracle:Whenever a player casts an instant or sorcery spell, each other player copies that spell. Each of those players may choose new targets for their copy. diff --git a/forge-gui/res/cardsfolder/h/howl_of_the_horde.txt b/forge-gui/res/cardsfolder/h/howl_of_the_horde.txt index 7ab1185033a..3e5470b7009 100644 --- a/forge-gui/res/cardsfolder/h/howl_of_the_horde.txt +++ b/forge-gui/res/cardsfolder/h/howl_of_the_horde.txt @@ -1,11 +1,9 @@ Name:Howl of the Horde ManaCost:2 R Types:Sorcery -A:SP$ Effect | Cost$ 2 R | AILogic$ SpellCopy | Name$ Howl of the Horde Effect 1 | Triggers$ TrigCopy | SVars$ TrigCopyMain,DBCleanup | SubAbility$ DBEffect | SpellDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. Raid — If you attacked this turn, when you cast your next instant or sorcery spell this turn, copy that spell an additional time. You may choose new targets for the copy. -SVar:DBEffect:DB$ Effect | Name$ Howl of the Horde Effect 2 | Triggers$ TrigCopy | SVars$ TrigCopyMain,DBCleanup | ConditionCheckSVar$ RaidTest | ConditionSVarCompare$ GE1 | References$ RaidTest +A:SP$ DelayedTrigger | Cost$ 2 R | AILogic$ SpellCopy | Execute$ EffTrigCopy | ThisTurn$ True | Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | | SubAbility$ DBEffect | SpellDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. +SVar:DBEffect:DB$ DelayedTrigger | AILogic$ SpellCopy | Execute$ EffTrigCopy | ThisTurn$ True | Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | ConditionCheckSVar$ RaidTest | ConditionSVarCompare$ GE1 | References$ RaidTest | SpellDescription$ Raid — If you attacked this turn, when you cast your next instant or sorcery spell this turn, copy that spell an additional time. You may choose new targets for the copy. SVar:RaidTest:Count$AttackersDeclared -SVar:TrigCopy:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | OneOff$ True | Execute$ TrigCopyMain | TriggerZones$ Command | TriggerDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. -SVar:TrigCopyMain:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | SubAbility$ DBCleanup -SVar:DBCleanup:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile +SVar:EffTrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True SVar:AIPriorityModifier:9 Oracle:When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy.\nRaid — If you attacked this turn, when you cast your next instant or sorcery spell this turn, copy that spell an additional time. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/i/illusionists_bracers.txt b/forge-gui/res/cardsfolder/i/illusionists_bracers.txt index 557c5f2d2ef..7be98b5b050 100644 --- a/forge-gui/res/cardsfolder/i/illusionists_bracers.txt +++ b/forge-gui/res/cardsfolder/i/illusionists_bracers.txt @@ -3,6 +3,5 @@ ManaCost:2 Types:Artifact Equipment K:Equip:3 T:Mode$ AbilityCast | ValidCard$ Creature.EquippedBy | TriggerZones$ Battlefield | Execute$ TrigCopyAbility | OptionalDecider$ You | TriggerDescription$ Whenever an ability of equipped creature is activated, if it isn't a mana ability, copy that ability. You may choose new targets for the copy. -SVar:TrigCopyAbility:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility -SVar:Picture:http://www.wizards.com/global/images/magic/general/illusionists_bracers.jpg +SVar:TrigCopyAbility:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True Oracle:Whenever an ability of equipped creature is activated, if it isn't a mana ability, copy that ability. You may choose new targets for the copy.\nEquip {3} diff --git a/forge-gui/res/cardsfolder/i/increasing_vengeance.txt b/forge-gui/res/cardsfolder/i/increasing_vengeance.txt index 1c864b599af..0b1ff154886 100644 --- a/forge-gui/res/cardsfolder/i/increasing_vengeance.txt +++ b/forge-gui/res/cardsfolder/i/increasing_vengeance.txt @@ -2,8 +2,6 @@ Name:Increasing Vengeance ManaCost:R R Types:Instant K:Flashback:3 R R -A:SP$ CopySpellAbility | Cost$ R R | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | SubAbility$ DBCopy2 | SpellDescription$ Copy target instant or sorcery spell you control. If this spell was cast from a graveyard, copy that spell twice instead. You may choose new targets for the copies. -SVar:DBCopy2:DB$ CopySpellAbility | Defined$ Targeted | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | References$ X | AILogic$ Always -SVar:X:Count$wasCastFromGraveyard.1.0 -SVar:Picture:http://www.wizards.com/global/images/magic/general/increasing_vengeance.jpg +A:SP$ CopySpellAbility | Cost$ R R | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | Amount$ X | References$ X | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell you control. If this spell was cast from a graveyard, copy that spell twice instead. You may choose new targets for the copies. +SVar:X:Count$wasCastFromGraveyard.2.1 Oracle:Copy target instant or sorcery spell you control. If this spell was cast from a graveyard, copy that spell twice instead. You may choose new targets for the copies.\nFlashback {3}{R}{R} (You may cast this card from your graveyard for its flashback cost. Then exile it.) diff --git a/forge-gui/res/cardsfolder/i/insidious_will.txt b/forge-gui/res/cardsfolder/i/insidious_will.txt index 31f34d6e891..f8b472cfc1b 100644 --- a/forge-gui/res/cardsfolder/i/insidious_will.txt +++ b/forge-gui/res/cardsfolder/i/insidious_will.txt @@ -4,6 +4,5 @@ Types:Instant A:SP$ Charm | Cost$ 2 U U | Choices$ DBCounter,DBChangeTargets,DBCopySpellAbility | Defined$ You SVar:DBCounter:DB$ Counter | TargetType$ Spell | ValidTgts$ Card | TgtPrompt$ Counter target spell | SpellDescription$ Counter target spell. SVar:DBChangeTargets:DB$ ChangeTargets | TargetType$ Spell | Optional$ True | ValidTgts$ Card | SpellDescription$ You may choose new targets for target spell. -SVar:DBCopySpellAbility:DB$ CopySpellAbility | ValidTgts$ Instant,Sorcery | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. -SVar:Picture:http://www.wizards.com/global/images/magic/general/insidious_will.jpg +SVar:DBCopySpellAbility:DB$ CopySpellAbility | ValidTgts$ Instant,Sorcery | TargetType$ Spell | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. Oracle:Choose one —\n• Counter target spell.\n• You may choose new targets for target spell.\n• Copy target instant or sorcery spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/i/izzet_guildmage.txt b/forge-gui/res/cardsfolder/i/izzet_guildmage.txt index 39c32abfe50..648c2d955b7 100644 --- a/forge-gui/res/cardsfolder/i/izzet_guildmage.txt +++ b/forge-gui/res/cardsfolder/i/izzet_guildmage.txt @@ -2,7 +2,6 @@ Name:Izzet Guildmage ManaCost:UR UR Types:Creature Human Wizard PT:2/2 -A:AB$ CopySpellAbility | Cost$ 2 U | ValidTgts$ Instant.YouCtrl+cmcLE2 | TargetType$ Spell | AILogic$ OnceIfViable | SpellDescription$ Copy target instant spell you control with converted mana cost 2 or less. You may choose new targets for the copy. -A:AB$ CopySpellAbility | Cost$ 2 R | ValidTgts$ Sorcery.YouCtrl+cmcLE2 | TargetType$ Spell | AILogic$ OnceIfViable | SpellDescription$ Copy target sorcery spell you control with converted mana cost 2 or less. You may choose new targets for the copy. -SVar:Picture:http://www.wizards.com/global/images/magic/general/izzet_guildmage.jpg +A:AB$ CopySpellAbility | Cost$ 2 U | ValidTgts$ Instant.YouCtrl+cmcLE2 | TargetType$ Spell | AILogic$ OnceIfViable | MayChooseTarget$ True | SpellDescription$ Copy target instant spell you control with converted mana cost 2 or less. You may choose new targets for the copy. +A:AB$ CopySpellAbility | Cost$ 2 R | ValidTgts$ Sorcery.YouCtrl+cmcLE2 | TargetType$ Spell | AILogic$ OnceIfViable | MayChooseTarget$ True | SpellDescription$ Copy target sorcery spell you control with converted mana cost 2 or less. You may choose new targets for the copy. Oracle:{2}{U}: Copy target instant spell you control with converted mana cost 2 or less. You may choose new targets for the copy.\n{2}{R}: Copy target sorcery spell you control with converted mana cost 2 or less. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/i/izzet_steam_maze.txt b/forge-gui/res/cardsfolder/i/izzet_steam_maze.txt index 98684d6922e..85e00e4bbef 100644 --- a/forge-gui/res/cardsfolder/i/izzet_steam_maze.txt +++ b/forge-gui/res/cardsfolder/i/izzet_steam_maze.txt @@ -2,10 +2,9 @@ Name:Izzet Steam Maze ManaCost:no cost Types:Plane Ravnica T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ Player | Execute$ TrigCopy | TriggerZones$ Command | TriggerDescription$ Whenever a player casts an instant or sorcery spell, that player copies it. The player may choose new targets for the copy. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ TriggeredActivator +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ TriggeredActivator | MayChooseTarget$ True T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll {CHAOS}, instant and sorcery spells you cast this turn cost {3} less to cast. SVar:RolledChaos:DB$ Effect | StaticAbilities$ ReduceSPcost SVar:ReduceSPcost:Mode$ ReduceCost | EffectZone$ Command | ValidCard$ Instant,Sorcery | Type$ Spell | Activator$ You | Amount$ 3 | Description$ Instant and sorcery spells you cast this turn cost 3 less to cast. -SVar:Picture:http://www.wizards.com/global/images/magic/general/izzet_steam_maze.jpg SVar:AIRollPlanarDieParams:Mode$ Always | RollInMain1$ True Oracle:Whenever a player casts an instant or sorcery spell, that player copies it. The player may choose new targets for the copy.\nWhenever you roll {CHAOS}, instant and sorcery spells you cast this turn cost {3} less to cast. diff --git a/forge-gui/res/cardsfolder/k/kalamax_the_stormsire.txt b/forge-gui/res/cardsfolder/k/kalamax_the_stormsire.txt index 05d6f1d4fc0..29a8ba0fa4b 100755 --- a/forge-gui/res/cardsfolder/k/kalamax_the_stormsire.txt +++ b/forge-gui/res/cardsfolder/k/kalamax_the_stormsire.txt @@ -3,7 +3,7 @@ ManaCost:1 G U R Types:Legendary Creature Elemental Dinosaur PT:4/4 T:Mode$ SpellCast | ValidCard$ Instant | ValidActivatingPlayer$ You | ActivatorThisTurnCast$ EQ1 | NoResolvingCheck$ True | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast your first instant spell each turn, if CARDNAME is tapped, copy that spell. You may choose new targets for the copy. -SVar:TrigCopy:DB$ CopySpellAbility | ConditionPresent$ Card.Self+tapped | Defined$ TriggeredSpellAbility | AILogic$ Always +SVar:TrigCopy:DB$ CopySpellAbility | ConditionPresent$ Card.Self+tapped | Defined$ TriggeredSpellAbility | AILogic$ Always | MayChooseTarget$ True SVar:BuffedBy:Instant T:Mode$ SpellCopy | ValidCard$ Instant | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever you copy an instant spell, put a +1/+1 counter on CARDNAME. DeckHas:Ability$Counters diff --git a/forge-gui/res/cardsfolder/k/kurkesh_onakke_ancient.txt b/forge-gui/res/cardsfolder/k/kurkesh_onakke_ancient.txt index 1d1d7ad43e5..bd3dd5592d9 100644 --- a/forge-gui/res/cardsfolder/k/kurkesh_onakke_ancient.txt +++ b/forge-gui/res/cardsfolder/k/kurkesh_onakke_ancient.txt @@ -3,6 +3,5 @@ ManaCost:2 R R Types:Legendary Creature Ogre Spirit PT:4/3 T:Mode$ AbilityCast | ValidCard$ Artifact | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigCopyAbility | TriggerDescription$ Whenever you activate an ability of an artifact, if it isn't a mana ability, you may pay {R}. If you do, copy that ability. You may choose new targets for the copy. -SVar:TrigCopyAbility:AB$ CopySpellAbility | Cost$ R | Defined$ TriggeredSpellAbility -SVar:Picture:http://www.wizards.com/global/images/magic/general/kurkesh_onakke_ancient.jpg +SVar:TrigCopyAbility:AB$ CopySpellAbility | Cost$ R | Defined$ TriggeredSpellAbility | MayChooseTarget$ True Oracle:Whenever you activate an ability of an artifact, if it isn't a mana ability, you may pay {R}. If you do, copy that ability. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/l/league_guildmage.txt b/forge-gui/res/cardsfolder/l/league_guildmage.txt index d8b6669129b..d3db5ea95b6 100644 --- a/forge-gui/res/cardsfolder/l/league_guildmage.txt +++ b/forge-gui/res/cardsfolder/l/league_guildmage.txt @@ -3,7 +3,7 @@ ManaCost:U R Types:Creature Human Wizard PT:2/2 A:AB$ Draw | Cost$ 3 U T | NumCards$ 1 | SpellDescription$ Draw a card. -A:AB$ CopySpellAbility | Cost$ X R T | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | AILogic$ OnceIfViable | SpellDescription$ Copy target instant or sorcery spell you control with converted mana cost X. You may choose new targets for the copy. +A:AB$ CopySpellAbility | Cost$ X R T | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | AILogic$ OnceIfViable | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell you control with converted mana cost X. You may choose new targets for the copy. SVar:X:Targeted$CardManaCost DeckHints:Type$Instant|Sorcery Oracle:{3}{U}, {T}: Draw a card.\n{X}{R}, {T}: Copy target instant or sorcery spell you control with converted mana cost X. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/l/lithoform_engine.txt b/forge-gui/res/cardsfolder/l/lithoform_engine.txt new file mode 100644 index 00000000000..d7ef57a8755 --- /dev/null +++ b/forge-gui/res/cardsfolder/l/lithoform_engine.txt @@ -0,0 +1,8 @@ +Name:Lithoform Engine +ManaCost:4 +Types:Legendary Artifact +A:AB$ CopySpellAbility | Cost$ 2 T | TgtPrompt$ Select target activated or triggered ability you control | TargetType$ Activated.YouCtrl,Triggered.YouCtrl | ValidTgts$ Card | MayChooseTarget$ True | StackDescription$ SpellDescription | SpellDescription$ Copy target activated or triggered ability you control. You may choose new targets for the copy. +A:AB$ CopySpellAbility | Cost$ 3 T | TgtPrompt$ Select target instant or sorcery spell you control | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell you control. You may choose new targets for the copy. +A:AB$ CopySpellAbility | Cost$ 4 T | TgtPrompt$ Select target permanent spell you control | ValidTgts$ Permanent.YouCtrl | TargetType$ Spell | SpellDescription$ Copy target permanent spell you control. (The copy becomes a token.) +Oracle:{2}, {T}: Copy target activated or triggered ability you control. You may choose new targets for the copy.\n{3}, {T}: Copy target instant or sorcery spell you control. You may choose new targets for the copy.\n{4}, {T}: Copy target permanent spell you control. (The copy becomes a token.) + diff --git a/forge-gui/res/cardsfolder/l/lucky_clover.txt b/forge-gui/res/cardsfolder/l/lucky_clover.txt index c53cfbfc01e..cb74d740cec 100644 --- a/forge-gui/res/cardsfolder/l/lucky_clover.txt +++ b/forge-gui/res/cardsfolder/l/lucky_clover.txt @@ -2,6 +2,6 @@ Name:Lucky Clover ManaCost:2 Types:Artifact T:Mode$ SpellCast | ValidCard$ Instant.Adventure,Sorcery.Adventure | ValidActivatingPlayer$ You | Execute$ TrigCopySpell | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast an Adventure instant or sorcery spell, copy it. You may choose new targets for the copy. -SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility +SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True AI:RemoveDeck:Random Oracle:Whenever you cast an Adventure instant or sorcery spell, copy it. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/l/lutri_the_spellchaser.txt b/forge-gui/res/cardsfolder/l/lutri_the_spellchaser.txt index 7d6d3ea81e0..e6f8409a447 100644 --- a/forge-gui/res/cardsfolder/l/lutri_the_spellchaser.txt +++ b/forge-gui/res/cardsfolder/l/lutri_the_spellchaser.txt @@ -5,6 +5,6 @@ PT:3/2 K:Companion:Special:UniqueNames:Each nonland card in your starting deck has a different name. K:Flash T:Mode$ ChangesZone | ValidCard$ Card.Self+wasCast | Origin$ Any | Destination$ Battlefield | Execute$ TrigCopy | TriggerDescription$ When CARDNAME enters the battlefield, if you cast it, copy target instant or sorcery spell you control. You may choose new targets for the copy. -SVar:TrigCopy:DB$ CopySpellAbility | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TgtPrompt$ Select target instant or sorcery spell you control +SVar:TrigCopy:DB$ CopySpellAbility | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TgtPrompt$ Select target instant or sorcery spell you control | MayChooseTarget$ True DeckHints:Type$Instant|Sorcery Oracle:Companion — Each nonland card in your starting deck has a different name. (If this card is your chosen companion, you may cast it once from outside the game.)\nFlash\nWhen Lutri, the Spellchaser enters the battlefield, if you cast it, copy target instant or sorcery spell you control. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/m/malicious_affliction.txt b/forge-gui/res/cardsfolder/m/malicious_affliction.txt index 392921f55b0..46c3f3108aa 100644 --- a/forge-gui/res/cardsfolder/m/malicious_affliction.txt +++ b/forge-gui/res/cardsfolder/m/malicious_affliction.txt @@ -3,7 +3,6 @@ ManaCost:B B Types:Instant A:SP$ Destroy | Cost$ B B | ValidTgts$ Creature.nonBlack | TgtPrompt$ Select target nonblack creature | SpellDescription$ Destroy target nonblack creature. T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | CheckSVar$ Morbid | SVarCompare$ GE1 | TriggerDescription$ Morbid — When you cast CARDNAME, if a creature died this turn, you may copy CARDNAME and may choose a new target for the copy. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True SVar:Morbid:Count$ThisTurnEntered_Graveyard_from_Battlefield_Creature -SVar:Picture:http://www.wizards.com/global/images/magic/general/malicious_affliction.jpg Oracle:Morbid — When you cast Malicious Affliction, if a creature died this turn, you may copy Malicious Affliction and may choose a new target for the copy.\nDestroy target nonblack creature. diff --git a/forge-gui/res/cardsfolder/m/melek_izzet_paragon.txt b/forge-gui/res/cardsfolder/m/melek_izzet_paragon.txt index d11a2faf11d..d8953117fc3 100644 --- a/forge-gui/res/cardsfolder/m/melek_izzet_paragon.txt +++ b/forge-gui/res/cardsfolder/m/melek_izzet_paragon.txt @@ -5,7 +5,7 @@ PT:2/4 S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl | AffectedZone$ Library | MayLookAt$ Player | Description$ Play with the top card of your library revealed. S:Mode$ Continuous | Affected$ Instant.TopLibrary+YouCtrl,Sorcery.TopLibrary+YouCtrl | AffectedZone$ Library | EffectZone$ Battlefield | MayPlay$ True | Description$ You may cast the top card of your library if it's an instant or sorcery card. T:Mode$ SpellCast | ValidCard$ Instant.wasCastFromLibrary,Sorcery.wasCastFromLibrary | ValidActivatingPlayer$ You | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast an instant or sorcery spell from your library, copy it. You may choose new targets for this copy. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True DeckNeeds:Type$Instant|Sorcery SVar:Picture:http://www.wizards.com/global/images/magic/general/melek_izzet_paragon.jpg Oracle:Play with the top card of your library revealed.\nYou may cast the top card of your library if it's an instant or sorcery card.\nWhenever you cast an instant or sorcery spell from your library, copy it. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/m/meletis_charlatan.txt b/forge-gui/res/cardsfolder/m/meletis_charlatan.txt index debe3fbbc08..28a09b2d8dd 100644 --- a/forge-gui/res/cardsfolder/m/meletis_charlatan.txt +++ b/forge-gui/res/cardsfolder/m/meletis_charlatan.txt @@ -2,6 +2,5 @@ Name:Meletis Charlatan ManaCost:2 U Types:Creature Human Wizard PT:2/3 -A:AB$ CopySpellAbility | Cost$ 2 U T | ValidTgts$ Instant,Sorcery | TargetType$ Spell | Controller$ TargetedController | AILogic$ OnceIfViable | AITgts$ OwnedOnly | SpellDescription$ The controller of target instant or sorcery spell copies it. That player may choose new targets for the copy. -SVar:Picture:http://www.wizards.com/global/images/magic/general/meletis_charlatan.jpg +A:AB$ CopySpellAbility | Cost$ 2 U T | ValidTgts$ Instant,Sorcery | TargetType$ Spell | Controller$ TargetedController | AILogic$ OnceIfViable | AITgts$ OwnedOnly | MayChooseTarget$ True | SpellDescription$ The controller of target instant or sorcery spell copies it. That player may choose new targets for the copy. Oracle:{2}{U}, {T}: The controller of target instant or sorcery spell copies it. That player may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/m/mirari.txt b/forge-gui/res/cardsfolder/m/mirari.txt index c1b674b58c3..ebff8dfd830 100644 --- a/forge-gui/res/cardsfolder/m/mirari.txt +++ b/forge-gui/res/cardsfolder/m/mirari.txt @@ -2,6 +2,5 @@ Name:Mirari ManaCost:5 Types:Legendary Artifact T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigCopy | TriggerDescription$ Whenever you cast an instant or sorcery spell, you may pay {3}. If you do, copy that spell. You may choose new targets for the copy. -SVar:TrigCopy:AB$CopySpellAbility | Cost$ 3 | Defined$ TriggeredSpellAbility | AILogic$ AlwaysIfViable -SVar:Picture:http://www.wizards.com/global/images/magic/general/mirari.jpg +SVar:TrigCopy:AB$CopySpellAbility | Cost$ 3 | Defined$ TriggeredSpellAbility | AILogic$ AlwaysIfViable | MayChooseTarget$ True Oracle:Whenever you cast an instant or sorcery spell, you may pay {3}. If you do, copy that spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/m/mirror_sheen.txt b/forge-gui/res/cardsfolder/m/mirror_sheen.txt index 490e40e5ba2..0f4c272d652 100644 --- a/forge-gui/res/cardsfolder/m/mirror_sheen.txt +++ b/forge-gui/res/cardsfolder/m/mirror_sheen.txt @@ -1,6 +1,5 @@ Name:Mirror Sheen ManaCost:1 UR UR Types:Enchantment -A:AB$ CopySpellAbility | Cost$ 1 UR UR | ValidTgts$ Instant,Sorcery | TargetType$ Spell | TargetValidTargeting$ You | AILogic$ AlwaysIfViable | SpellDescription$ Copy target instant or sorcery spell that targets you. You may choose new targets for the copy. -SVar:Picture:http://www.wizards.com/global/images/magic/general/mirror_sheen.jpg +A:AB$ CopySpellAbility | Cost$ 1 UR UR | ValidTgts$ Instant,Sorcery | TargetType$ Spell | TargetValidTargeting$ You | AILogic$ AlwaysIfViable | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell that targets you. You may choose new targets for the copy. Oracle:{1}{U/R}{U/R}: Copy target instant or sorcery spell that targets you. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/m/mirrorpool.txt b/forge-gui/res/cardsfolder/m/mirrorpool.txt index b48756c568b..3e9402a00ad 100644 --- a/forge-gui/res/cardsfolder/m/mirrorpool.txt +++ b/forge-gui/res/cardsfolder/m/mirrorpool.txt @@ -3,7 +3,6 @@ ManaCost:no cost Types:Land K:CARDNAME enters the battlefield tapped. A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. -A:AB$ CopySpellAbility | Cost$ 2 C T Sac<1/CARDNAME> | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell you control. You may choose new targets for the copy. +A:AB$ CopySpellAbility | Cost$ 2 C T Sac<1/CARDNAME> | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell you control. You may choose new targets for the copy. A:AB$ CopyPermanent | Cost$ 4 C T Sac<1/CARDNAME> | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | NumCopies$ 1 | SpellDescription$ Create a token that's a copy of target creature you control. -SVar:Picture:http://www.wizards.com/global/images/magic/general/mirrorpool.jpg Oracle:Mirrorpool enters the battlefield tapped.\n{T}: Add {C}.\n{2}{C}, {T}, Sacrifice Mirrorpool: Copy target instant or sorcery spell you control. You may choose new targets for the copy.\n{4}{C}, {T}, Sacrifice Mirrorpool: Create a token that's a copy of target creature you control. diff --git a/forge-gui/res/cardsfolder/m/mischievous_quanar.txt b/forge-gui/res/cardsfolder/m/mischievous_quanar.txt index ac3499046b8..9351883abc8 100644 --- a/forge-gui/res/cardsfolder/m/mischievous_quanar.txt +++ b/forge-gui/res/cardsfolder/m/mischievous_quanar.txt @@ -5,7 +5,7 @@ PT:3/3 K:Morph:1 U U A:AB$ SetState | Cost$ 3 U U | Defined$ Self | Mode$ TurnFace | SpellDescription$ Turn CARDNAME face down. T:Mode$ TurnFaceUp | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ When CARDNAME is turned face up, copy target instant or sorcery spell. You may choose new targets for that copy. -SVar:TrigCopy:DB$ CopySpellAbility | ValidTgts$ Instant,Sorcery +SVar:TrigCopy:DB$ CopySpellAbility | ValidTgts$ Instant,Sorcery | MayChooseTarget$ True AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/mischievous_quanar.jpg Oracle:{3}{U}{U}: Turn Mischievous Quanar face down.\nMorph {1}{U}{U} (You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)\nWhen Mischievous Quanar is turned face up, copy target instant or sorcery spell. You may choose new targets for that copy. diff --git a/forge-gui/res/cardsfolder/n/narset_transcendent.txt b/forge-gui/res/cardsfolder/n/narset_transcendent.txt index f00e39918ae..61fcf077414 100644 --- a/forge-gui/res/cardsfolder/n/narset_transcendent.txt +++ b/forge-gui/res/cardsfolder/n/narset_transcendent.txt @@ -5,11 +5,8 @@ Loyalty:6 A:AB$ PeekAndReveal | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | AILogic$ Main2 | PeekAmount$ 1 | RevealValid$ Card.nonCreature+nonLand | RevealOptional$ True | RememberRevealed$ True | SubAbility$ DBChangeZone | SpellDescription$ Look at the top card of your library. If it's a noncreature, nonland card, you may reveal it and put it into your hand. SVar:DBChangeZone:DB$ ChangeZone | Defined$ TopOfLibrary | Origin$ Library | Destination$ Hand | ConditionDefined$ Remembered | ConditionPresent$ Card.nonCreature+nonLand | ConditionCompare$ EQ1 | SubAbility$ DBCleanupOne SVar:DBCleanupOne:DB$ Cleanup | ClearRemembered$ True -A:AB$Effect | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | AILogic$ NarsetRebound | Stackable$ False | Name$ Narset Transcendent effect. | Triggers$ AddRebound | SVars$ AddReboundMain,DBCleanupTwo | SpellDescription$ When you cast your next instant or sorcery spell from your hand this turn, it gains rebound. (Exile the spell as it resolves. At the beginning of your next upkeep, you may cast that card from exile without paying its mana cost.) -SVar:AddRebound:Mode$ SpellCast | ValidCard$ Instant.wasCastFromHand,Sorcery.wasCastFromHand | ValidActivatingPlayer$ You | OneOff$ True | Execute$ AddReboundMain | TriggerZones$ Command | TriggerDescription$ When you cast your next instant or sorcery spell from your hand this turn, it gains rebound. -SVar:AddReboundMain:DB$ Pump | Defined$ TriggeredCard| KW$ Rebound | PumpZone$ Stack | SubAbility$ DBCleanupTwo -SVar:DBCleanupTwo:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile +A:AB$ DelayedTrigger | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | AILogic$ NarsetRebound | Stackable$ False | Mode$ SpellCast | ValidCard$ Instant.wasCastFromHand,Sorcery.wasCastFromHand | ValidActivatingPlayer$ You | Execute$ AddRebound | SpellDescription$ When you cast your next instant or sorcery spell from your hand this turn, it gains rebound. (Exile the spell as it resolves. At the beginning of your next upkeep, you may cast that card from exile without paying its mana cost.) +SVar:AddRebound:DB$ Pump | Defined$ TriggeredCard | KW$ Rebound | PumpZone$ Stack A:AB$ Effect | Cost$ SubCounter<9/LOYALTY> | Name$ Emblem - Narset Transcendent | StaticAbilities$ STNarset | Planeswalker$ True | Ultimate$ True | Stackable$ False | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Your opponents can't cast noncreature spells." SVar:STNarset:Mode$ CantBeCast | ValidCard$ Card.nonCreature | Caster$ Opponent | EffectZone$ Command | Description$ Your opponents can't cast noncreature spells. -SVar:Picture:http://www.wizards.com/global/images/magic/general/narset_transcendent.jpg Oracle:[+1]: Look at the top card of your library. If it's a noncreature, nonland card, you may reveal it and put it into your hand.\n[-2]: When you cast your next instant or sorcery spell from your hand this turn, it gains rebound. (Exile the spell as it resolves. At the beginning of your next upkeep, you may cast that card from exile without paying its mana cost.)\n[-9]: You get an emblem with "Your opponents can't cast noncreature spells." diff --git a/forge-gui/res/cardsfolder/n/narsets_reversal.txt b/forge-gui/res/cardsfolder/n/narsets_reversal.txt index 8ab37f1b62b..dc0c96b7126 100644 --- a/forge-gui/res/cardsfolder/n/narsets_reversal.txt +++ b/forge-gui/res/cardsfolder/n/narsets_reversal.txt @@ -1,6 +1,6 @@ Name:Narset's Reversal ManaCost:U U Types:Instant -A:SP$ CopySpellAbility | Cost$ U U | ValidTgts$ Instant,Sorcery | TargetType$ Spell | SubAbility$ DBReturn | SpellDescription$ Copy target instant or sorcery spell, then return it to its owner's hand. You may choose new targets for the copy. +A:SP$ CopySpellAbility | Cost$ U U | ValidTgts$ Instant,Sorcery | TargetType$ Spell | SubAbility$ DBReturn | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell, then return it to its owner's hand. You may choose new targets for the copy. SVar:DBReturn:DB$ChangeZone | Defined$ Targeted | Origin$ Stack | Destination$ Hand Oracle:Copy target instant or sorcery spell, then return it to its owner's hand. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/n/naru_meha_master_wizard.txt b/forge-gui/res/cardsfolder/n/naru_meha_master_wizard.txt index b63a4402f64..c14a2b50cd2 100644 --- a/forge-gui/res/cardsfolder/n/naru_meha_master_wizard.txt +++ b/forge-gui/res/cardsfolder/n/naru_meha_master_wizard.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Human Wizard PT:3/3 K:Flash T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When CARDNAME enters the battlefield, copy target instant or sorcery spell you control. You may choose new targets for that copy. -SVar:TrigCopy:DB$ CopySpellAbility | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TgtPrompt$ Select target instant or sorcery spell you control | TargetType$ Spell +SVar:TrigCopy:DB$ CopySpellAbility | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TgtPrompt$ Select target instant or sorcery spell you control | TargetType$ Spell | MayChooseTarget$ True S:Mode$ Continuous | Affected$ Wizard.Other+YouCtrl | AddPower$ 1 | AddToughness$ 1 | Description$ Other Wizards you control get +1/+1. DeckHints:Type$Wizard Oracle:Flash\nWhen Naru Meha, Master Wizard enters the battlefield, copy target instant or sorcery spell you control. You may choose new targets for the copy.\nOther Wizards you control get +1/+1. diff --git a/forge-gui/res/cardsfolder/n/nivix_guildmage.txt b/forge-gui/res/cardsfolder/n/nivix_guildmage.txt index 4d82d00d093..c5c5d2e5bb5 100644 --- a/forge-gui/res/cardsfolder/n/nivix_guildmage.txt +++ b/forge-gui/res/cardsfolder/n/nivix_guildmage.txt @@ -4,7 +4,6 @@ Types:Creature Human Wizard PT:2/2 A:AB$ Draw | Cost$ 1 U R | NumCards$ 1 | SpellDescription$ Draw a card, then discard a card. | SubAbility$ DBDiscard SVar:DBDiscard:DB$Discard | Defined$ You | NumCards$ 1 | Mode$ TgtChoose -A:AB$ CopySpellAbility | Cost$ 2 U R | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | AILogic$ OnceIfViable | SpellDescription$ Copy target instant or sorcery spell you control. You may choose new targets for the copy. +A:AB$ CopySpellAbility | Cost$ 2 U R | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | AILogic$ OnceIfViable | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell you control. You may choose new targets for the copy. DeckHints:Type$Instant|Sorcery -SVar:Picture:http://www.wizards.com/global/images/magic/general/nivix_guildmage.jpg Oracle:{1}{U}{R}: Draw a card, then discard a card.\n{2}{U}{R}: Copy target instant or sorcery spell you control. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/o/odds_ends.txt b/forge-gui/res/cardsfolder/o/odds_ends.txt index 7b9f91cede5..3dea750bd26 100644 --- a/forge-gui/res/cardsfolder/o/odds_ends.txt +++ b/forge-gui/res/cardsfolder/o/odds_ends.txt @@ -4,8 +4,7 @@ AlternateMode: Split Types:Instant A:SP$ FlipACoin | Cost$ U R | NoCall$ True | HeadsSubAbility$ OddCounter | TailsSubAbility$ OddCopy | TgtZone$ Stack | TargetType$ Spell | ValidTgts$ Instant,Sorcery | TgtPrompt$ Select target Instant or Sorcery spell | SpellDescription$ Flip a coin. If it comes up heads, counter target instant or sorcery spell. If it comes up tails, copy that spell and you may choose new targets for the copy. SVar:OddCounter:DB$ Counter | Defined$ Targeted -SVar:OddCopy:DB$ CopySpellAbility | Defined$ Targeted -SVar:Picture:http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=107445&type=card +SVar:OddCopy:DB$ CopySpellAbility | Defined$ Targeted | MayChooseTarget$ True Oracle:Flip a coin. If it comes up heads, counter target instant or sorcery spell. If it comes up tails, copy that spell and you may choose new targets for the copy. ALTERNATE diff --git a/forge-gui/res/cardsfolder/p/primal_amulet_primal_wellspring.txt b/forge-gui/res/cardsfolder/p/primal_amulet_primal_wellspring.txt index 51900199f54..d9036d6f932 100644 --- a/forge-gui/res/cardsfolder/p/primal_amulet_primal_wellspring.txt +++ b/forge-gui/res/cardsfolder/p/primal_amulet_primal_wellspring.txt @@ -13,7 +13,6 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | Execute$ DBInitSV SVar:DBInitSVar:DB$ StoreSVar | SVar$ FullyCharged | Type$ Number | Expression$ 0 | References$ FullyCharged SVar:FullyCharged:Number$0 AlternateMode:DoubleFaced -SVar:Picture:http://www.wizards.com/global/images/magic/general/primal_amulet.jpg Oracle:Instant and sorcery spells you cast cost {1} less to cast.\nWhenever you cast an instant or sorcery spell, put a charge counter on Primal Amulet. Then if there are four or more charge counters on it, you may remove those counters and transform it. ALTERNATE @@ -23,6 +22,5 @@ ManaCost:no cost Types:Land A:AB$ Mana | Cost$ T | Produced$ Any | TriggersWhenSpent$ TrigCopy | SpellDescription$ Add one mana of any color. When that mana is spent to cast an instant or sorcery spell, copy that spell and you may choose new targets for the copy. SVar:TrigCopy:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | OneOff$ True | Execute$ TrigCopyMain | TriggerDescription$ When that mana is spent to cast an instant or sorcery spell, copy that spell and you may choose new targets for the copy. -SVar:TrigCopyMain:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility -SVar:Picture:http://www.wizards.com/global/images/magic/general/primal_wellspring.jpg +SVar:TrigCopyMain:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True Oracle:(Transforms from Primal Amulet.)\n{T}: Add one mana of any color. When that mana is spent to cast an instant or sorcery spell, copy that spell and you may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/p/psychic_rebuttal.txt b/forge-gui/res/cardsfolder/p/psychic_rebuttal.txt index 4ab4bdebbc8..89afa121899 100644 --- a/forge-gui/res/cardsfolder/p/psychic_rebuttal.txt +++ b/forge-gui/res/cardsfolder/p/psychic_rebuttal.txt @@ -2,8 +2,7 @@ Name:Psychic Rebuttal ManaCost:1 U Types:Instant A:SP$ Counter | Cost$ 1 U | TargetType$ Spell | TargetValidTargeting$ You | TgtPrompt$ Select target spell that targets you | ValidTgts$ Instant,Sorcery | RememberCountered$ True | SubAbility$ DBCopy | SpellDescription$ Counter target instant or sorcery spell that targets you. Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, you may copy the spell countered this way. You may choose new targets for the copy. -SVar:DBCopy:DB$ CopySpellAbility | Defined$ Remembered | ConditionCheckSVar$ X | ConditionSVarCompare$ GE2 | References$ X | SubAbility$ DBCleanup +SVar:DBCopy:DB$ CopySpellAbility | Defined$ Remembered | ConditionCheckSVar$ X | ConditionSVarCompare$ GE2 | References$ X | MayChooseTarget$ True | SubAbility$ DBCleanup SVar:X:Count$ValidGraveyard Instant.YouOwn,Sorcery.YouOwn SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:Picture:http://www.wizards.com/global/images/magic/general/psychic_rebuttal.jpg -Oracle:Counter target instant or sorcery spell that targets you. \nSpell mastery — If there are two or more instant and/or sorcery cards in your graveyard, you may copy the spell countered this way. You may choose new targets for the copy. \ No newline at end of file +Oracle:Counter target instant or sorcery spell that targets you. \nSpell mastery — If there are two or more instant and/or sorcery cards in your graveyard, you may copy the spell countered this way. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/p/pyromancer_ascension.txt b/forge-gui/res/cardsfolder/p/pyromancer_ascension.txt index d04969a0e6a..e94edad87cc 100644 --- a/forge-gui/res/cardsfolder/p/pyromancer_ascension.txt +++ b/forge-gui/res/cardsfolder/p/pyromancer_ascension.txt @@ -3,11 +3,10 @@ ManaCost:1 R Types:Enchantment T:Mode$ SpellCast | ValidCard$ Instant.sharesNameWith YourGraveyard,Sorcery.sharesNameWith YourGraveyard | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | OptionalDecider$ You | TriggerDescription$ Whenever you cast an instant or sorcery spell that has the same name as a card in your graveyard, you may put a quest counter on CARDNAME. T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | IsPresent$ Card.Self+counters_GE2_QUEST | Execute$ TrigCopySpell | OptionalDecider$ You | TriggerDescription$ Whenever you cast an instant or sorcery spell while CARDNAME has two or more quest counters on it, you may copy that spell. You may choose new targets for the copy. -SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ QUEST | CounterNum$ 1 | ConditionDefined$ TriggeredCard -SVar:TrigCopySpell:DB$CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always +SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ QUEST | CounterNum$ 1 | ConditionDefined$ TriggeredCard +SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always | MayChooseTarget$ True DeckHints:Keyword$Retrace & Keyword$Flashback DeckNeeds:Type$Instant|Sorcery DeckHas:Ability$Counters SVar:MaxQuestEffect:2 -SVar:Picture:http://www.wizards.com/global/images/magic/general/pyromancer_ascension.jpg Oracle:Whenever you cast an instant or sorcery spell that has the same name as a card in your graveyard, you may put a quest counter on Pyromancer Ascension.\nWhenever you cast an instant or sorcery spell while Pyromancer Ascension has two or more quest counters on it, you may copy that spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/p/pyromancers_goggles.txt b/forge-gui/res/cardsfolder/p/pyromancers_goggles.txt index f44a6f5cc23..b3ebf4655db 100644 --- a/forge-gui/res/cardsfolder/p/pyromancers_goggles.txt +++ b/forge-gui/res/cardsfolder/p/pyromancers_goggles.txt @@ -3,6 +3,5 @@ ManaCost:5 Types:Legendary Artifact A:AB$ Mana | Cost$ T | Produced$ R | TriggersWhenSpent$ TrigCopy | SpellDescription$ Add {R}. When that mana is spent to cast a red instant or sorcery spell, copy that spell and you may choose new targets for the copy. SVar:TrigCopy:Mode$ SpellCast | ValidCard$ Instant.Red,Sorcery.Red | ValidActivatingPlayer$ You | OneOff$ True | Execute$ TrigCopyMain | TriggerDescription$ When that mana is spent to cast a red instant or sorcery spell, copy that spell and you may choose new targets for the copy. -SVar:TrigCopyMain:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility -SVar:Picture:http://www.wizards.com/global/images/magic/general/pyromancers_goggles.jpg -Oracle:{T}: Add {R}. When that mana is spent to cast a red instant or sorcery spell, copy that spell and you may choose new targets for the copy. \ No newline at end of file +SVar:TrigCopyMain:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True +Oracle:{T}: Add {R}. When that mana is spent to cast a red instant or sorcery spell, copy that spell and you may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/r/ral_storm_conduit.txt b/forge-gui/res/cardsfolder/r/ral_storm_conduit.txt index 1b326d0ee86..22928716d85 100644 --- a/forge-gui/res/cardsfolder/r/ral_storm_conduit.txt +++ b/forge-gui/res/cardsfolder/r/ral_storm_conduit.txt @@ -6,10 +6,8 @@ T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | Tr T:Mode$ SpellCopy | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDealDamage | Secondary$ True | TriggerDescription$ Whenever you cast or copy an instant or sorcery spell, CARDNAME deals 1 damage to target opponent or planeswalker. SVar:TrigDealDamage:DB$DealDamage | ValidTgts$ Opponent,Planeswalker | TgtPrompt$ Select target opponent or planeswalker | NumDmg$ 1 A:AB$ Scry | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | ScryNum$ 1 | SpellDescription$ Scry 1. -A:AB$ Effect | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | AILogic$ SpellCopy | Triggers$ EffTModeSpellCast | SVars$ EffTrigCopy,EffDBCleanup | SpellDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. -SVar:EffTModeSpellCast:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | OneOff$ True | Execute$ EffTrigCopy | TriggerZones$ Command | TriggerDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. -SVar:EffTrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | SubAbility$ EffDBCleanup -SVar:EffDBCleanup:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile +A:AB$ DelayedTrigger | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | AILogic$ SpellCopy | Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | ThisTurn$ True | Execute$ EffTrigCopy | SpellDescription$ When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. +SVar:EffTrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True SVar:BuffedBy:Instant,Sorcery DeckHints:Type$Instant|Sorcery Oracle:Whenever you cast or copy an instant or sorcery spell, Ral, Storm Conduit deals 1 damage to target opponent or planeswalker.\n[+2]: Scry 1.\n[-2]: When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/r/refuse_cooperate.txt b/forge-gui/res/cardsfolder/r/refuse_cooperate.txt index 3faa79eb7d1..e2e589b9b59 100644 --- a/forge-gui/res/cardsfolder/r/refuse_cooperate.txt +++ b/forge-gui/res/cardsfolder/r/refuse_cooperate.txt @@ -3,11 +3,9 @@ ManaCost:3 R AlternateMode: Split Types:Instant A:SP$ Pump | Cost$ 3 R | ValidTgts$ Card | TgtZone$ Stack | TgtPrompt$ Select target spell | PumpZone$ Stack | StackDescription$ None | SubAbility$ DBDmg | SpellDescription$ CARDNAME deals damage to target spell's controller equal to that spell's converted mana cost. - SVar:DBDmg:DB$ DealDamage | Defined$ TargetedController | NumDmg$ X | References$ X SVar:X:Targeted$CardManaCost AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/refuse_cooperate.jpg Oracle:Refuse deals damage to target spell's controller equal to that spell's converted mana cost. ALTERNATE @@ -16,5 +14,5 @@ Name:Cooperate ManaCost:2 U Types:Instant K:Aftermath -A:SP$ CopySpellAbility | Cost$ 2 U | ValidTgts$ Instant,Sorcery | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. -Oracle:Aftermath (Cast this spell only from your graveyard. Then exile it.)\nCopy target instant or sorcery spell. You may choose new targets for the copy. \ No newline at end of file +A:SP$ CopySpellAbility | Cost$ 2 U | ValidTgts$ Instant,Sorcery | TargetType$ Spell | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. +Oracle:Aftermath (Cast this spell only from your graveyard. Then exile it.)\nCopy target instant or sorcery spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/r/reiterate.txt b/forge-gui/res/cardsfolder/r/reiterate.txt index 3fcbd34eb41..1ffaf9fa118 100644 --- a/forge-gui/res/cardsfolder/r/reiterate.txt +++ b/forge-gui/res/cardsfolder/r/reiterate.txt @@ -2,6 +2,5 @@ Name:Reiterate ManaCost:1 R R Types:Instant K:Buyback:3 -A:SP$ CopySpellAbility | Cost$ 1 R R | ValidTgts$ Instant,Sorcery | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. -SVar:Picture:http://www.wizards.com/global/images/magic/general/reiterate.jpg +A:SP$ CopySpellAbility | Cost$ 1 R R | ValidTgts$ Instant,Sorcery | TargetType$ Spell | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. Oracle:Buyback {3} (You may pay an additional {3} as you cast this spell. If you do, put this card into your hand as it resolves.)\nCopy target instant or sorcery spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/r/repeated_reverberation.txt b/forge-gui/res/cardsfolder/r/repeated_reverberation.txt index e3929f56fbc..9f28c457011 100644 --- a/forge-gui/res/cardsfolder/r/repeated_reverberation.txt +++ b/forge-gui/res/cardsfolder/r/repeated_reverberation.txt @@ -1,9 +1,6 @@ Name:Repeated Reverberation ManaCost:2 R R Types:Instant -A:SP$ Effect | Cost$ 2 R R | AILogic$ SpellCopy | Name$ Repeated Reverberation Effect | Triggers$ TrigCopy,TrigCopy2 | SVars$ TrigCopyMain,DBCleanup | SpellDescription$ When you next cast an instant spell, cast a sorcery spell, or activate a loyalty ability this turn, copy that spell or ability twice. You may choose new targets for the copies. -SVar:TrigCopy:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | OneOff$ True | Execute$ TrigCopyMain | TriggerZones$ Command | TriggerDescription$ When you next cast an instant spell, cast a sorcery spell, or activate a loyalty ability this turn, copy that spell or ability twice. You may choose new targets for the copies. -SVar:TrigCopy2:Mode$ AbilityCast | ValidSA$ Activated.Loyalty | ValidActivatingPlayer$ You | OneOff$ True | Execute$ TrigCopyMain | TriggerZones$ Command | Secondary$ True | TriggerDescription$ When you next cast an instant spell, cast a sorcery spell, or activate a loyalty ability this turn, copy that spell or ability twice. You may choose new targets for the copies. -SVar:TrigCopyMain:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ 2 | SubAbility$ DBCleanup -SVar:DBCleanup:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile +A:SP$ DelayedTrigger | Cost$ 2 R R | AILogic$ SpellCopy | Mode$ SpellAbilityCast | ValidSA$ Spell.Instant,Spell.Sorcery,Activated.Loyalty | ValidActivatingPlayer$ You | ThisTurn$ True | Execute$ EffTrigCopy | SpellDescription$ When you next cast an instant spell, cast a sorcery spell, or activate a loyalty ability this turn, copy that spell or ability twice. You may choose new targets for the copies. +SVar:EffTrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ 2 | MayChooseTarget$ True Oracle:When you next cast an instant spell, cast a sorcery spell, or activate a loyalty ability this turn, copy that spell or ability twice. You may choose new targets for the copies. diff --git a/forge-gui/res/cardsfolder/r/reverberate.txt b/forge-gui/res/cardsfolder/r/reverberate.txt index 2cea6ba32d5..fdbecf88327 100644 --- a/forge-gui/res/cardsfolder/r/reverberate.txt +++ b/forge-gui/res/cardsfolder/r/reverberate.txt @@ -1,6 +1,5 @@ Name:Reverberate ManaCost:R R Types:Instant -A:SP$ CopySpellAbility | Cost$ R R | ValidTgts$ Instant,Sorcery | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. -SVar:Picture:http://www.wizards.com/global/images/magic/general/reverberate.jpg +A:SP$ CopySpellAbility | Cost$ R R | ValidTgts$ Instant,Sorcery | TargetType$ Spell | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. Oracle:Copy target instant or sorcery spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/r/riku_of_two_reflections.txt b/forge-gui/res/cardsfolder/r/riku_of_two_reflections.txt index 1f9f406f0af..bb1fb53aab7 100644 --- a/forge-gui/res/cardsfolder/r/riku_of_two_reflections.txt +++ b/forge-gui/res/cardsfolder/r/riku_of_two_reflections.txt @@ -4,7 +4,6 @@ Types:Legendary Creature Human Wizard PT:2/2 T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigCopySpell | TriggerDescription$ Whenever you cast an instant or sorcery spell, you may pay {U}{R}. If you do, copy that spell. You may choose new targets for the copy. T:Mode$ ChangesZone | ValidCard$ Creature.nonToken+Other+YouCtrl | Origin$ Any | Destination$ Battlefield | TriggerZones$ Battlefield | Execute$ TrigCopy | OptionalDecider$ You | TriggerDescription$ Whenever another nontoken creature enters the battlefield under your control, you may pay {G}{U}. If you do, create a token that's a copy of that creature. -SVar:TrigCopySpell:AB$CopySpellAbility | Cost$ U R | Defined$ TriggeredSpellAbility -SVar:TrigCopy:AB$CopyPermanent | Cost$ G U | Defined$ TriggeredCard -SVar:Picture:http://www.wizards.com/global/images/magic/general/riku_of_two_reflections.jpg +SVar:TrigCopySpell:AB$ CopySpellAbility | Cost$ U R | Defined$ TriggeredSpellAbility | MayChooseTarget$ True +SVar:TrigCopy:AB$ CopyPermanent | Cost$ G U | Defined$ TriggeredCard Oracle:Whenever you cast an instant or sorcery spell, you may pay {U}{R}. If you do, copy that spell. You may choose new targets for the copy.\nWhenever another nontoken creature enters the battlefield under your control, you may pay {G}{U}. If you do, create a token that's a copy of that creature. diff --git a/forge-gui/res/cardsfolder/r/rings_of_brighthearth.txt b/forge-gui/res/cardsfolder/r/rings_of_brighthearth.txt index e21f20983e6..956342757ca 100644 --- a/forge-gui/res/cardsfolder/r/rings_of_brighthearth.txt +++ b/forge-gui/res/cardsfolder/r/rings_of_brighthearth.txt @@ -2,6 +2,5 @@ Name:Rings of Brighthearth ManaCost:3 Types:Artifact T:Mode$ AbilityCast | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigCopySpell | OptionalDecider$ You | TriggerDescription$ Whenever you activate an ability, if it isn't a mana ability, you may pay {2}. If you do, copy that ability. You may choose new targets for the copy. -SVar:TrigCopySpell:AB$CopySpellAbility | Cost$ 2 | Defined$ TriggeredSpellAbility -SVar:Picture:http://www.wizards.com/global/images/magic/general/rings_of_brighthearth.jpg +SVar:TrigCopySpell:AB$ CopySpellAbility | Cost$ 2 | Defined$ TriggeredSpellAbility | MayChooseTarget$ True Oracle:Whenever you activate an ability, if it isn't a mana ability, you may pay {2}. If you do, copy that ability. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/r/rowan_kenrith.txt b/forge-gui/res/cardsfolder/r/rowan_kenrith.txt index 302a8e04b57..ef4d73251d9 100644 --- a/forge-gui/res/cardsfolder/r/rowan_kenrith.txt +++ b/forge-gui/res/cardsfolder/r/rowan_kenrith.txt @@ -12,6 +12,6 @@ SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True A:AB$ DamageAll | Cost$ SubCounter<2/LOYALTY> | ValidTgts$ Player | TgtPrompt$ Select target player | NumDmg$ 3 | ValidCards$ Creature.tapped | Planeswalker$ True | ValidDescription$ each tapped creature target player controls. | SpellDescription$ CARDNAME deals 3 damage to each tapped creature target player controls A:AB$ Effect | Cost$ SubCounter<8/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Player | EffectOwner$ Targeted | Name$ Emblem - Rowan Kenrith | Image$ emblem_rowan_kenrith | Triggers$ CopyAbility | SVars$ TrigCopy | Duration$ Permanent | AILogic$ Always | SpellDescription$ Target player gets an emblem with "Whenever you activate an ability that isn't a mana ability, copy it. You may choose new targets for the copy." SVar:CopyAbility:Mode$ AbilityCast | ValidActivatingPlayer$ You | TriggerZones$ Command | Execute$ TrigCopy | TriggerDescription$ Whenever you activate an ability that isn't a mana ability, copy it. You may choose new targets for the copy. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True DeckHints:Name$Will Kenrith Oracle:[+2]: During target player's next turn, each creature that player controls attacks if able.\n[-2]: Rowan Kenrith deals 3 damage to each tapped creature target player controls.\n[-8]: Target player gets an emblem with "Whenever you activate an ability that isn't a mana ability, copy it. You may choose new targets for the copy."\nPartner with Will Kenrith\nRowan Kenrith can be your commander.\n diff --git a/forge-gui/res/cardsfolder/s/sea_gate_stormcaller.txt b/forge-gui/res/cardsfolder/s/sea_gate_stormcaller.txt index bb79544f84d..c4e60d7f6e5 100755 --- a/forge-gui/res/cardsfolder/s/sea_gate_stormcaller.txt +++ b/forge-gui/res/cardsfolder/s/sea_gate_stormcaller.txt @@ -3,14 +3,10 @@ ManaCost:1 U Types:Creature Human Wizard PT:2/1 K:Kicker:4 U +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigEffect | TriggerDescription$ When CARDNAME enters the battlefield, copy the next instant or sorcery spell with converted mana cost 2 or less you cast this turn when you cast it. You may choose new targets for the copy. +SVar:TrigEffect:DB$ DelayedTrigger | AILogic$ SpellCopy | Mode$ SpellCast | ValidCard$ Instant.cmcLE2,Sorcery.cmcLE2 | ValidActivatingPlayer$ You | ThisTurn$ True | Execute$ TrigCopy | TriggerDescription$ Copy the next instant or sorcery spell with converted mana cost 2 or less you cast this turn when you cast it. You may choose new targets for the copy. +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always | Amount$ X | References$ X | MayChooseTarget$ True +SVar:X:Count$Kicked.2.1 SVar:PlayMain1:TRUE -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self+notkicked | Execute$ TrigEffect | Secondary$ True | TriggerDescription$ When CARDNAME enters the battlefield, copy the next instant or sorcery spell with converted mana cost 2 or less you cast this turn when you cast it. You may choose new targets for the copy. -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self+kicked | Execute$ TrigEffectKicked | TriggerDescription$ When CARDNAME enters the battlefield, copy the next instant or sorcery spell with converted mana cost 2 or less you cast this turn when you cast it. If CARDNAME was kicked, copy that spell twice instead. You may choose new targets for the copies. -SVar:TrigEffect:DB$ Effect | Triggers$ TrigCast | SVars$ TrigCopy -SVar:TrigCast:Mode$ SpellCast | OneOff$ True | ValidActivatingPlayer$ You | ValidCard$ Instant.cmcLE2,Sorcery.cmcLE2 | TriggerZones$ Command | Execute$ TrigCopy | TriggerDescription$ Copy the next instant or sorcery spell with converted mana cost 2 or less you cast this turn when you cast it. You may choose new targets for the copy. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always -SVar:TrigEffectKicked:DB$ Effect | Triggers$ TrigCastKicked | SVars$ TrigCopyKicked -SVar:TrigCastKicked:Mode$ SpellCast | OneOff$ True | ValidActivatingPlayer$ You | ValidCard$ Instant.cmcLE2,Sorcery.cmcLE2 | TriggerZones$ Command | Execute$ TrigCopyKicked | TriggerDescription$ Copy the next instant or sorcery spell with converted mana cost 2 or less you cast this turn twice when you cast it. You may choose new targets for the copies. -SVar:TrigCopyKicked:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always | Amount$ 2 DeckNeeds:Type$Instant|Sorcery Oracle:Kicker {4}{U}\nWhen Sea Gate Stormcaller enters the battlefield, copy the next instant or sorcery spell with converted mana cost 2 or less you cast this turn when you cast it. If Sea Gate Stormcaller was kicked, copy that spell twice instead. You may choose new targets for the copies. diff --git a/forge-gui/res/cardsfolder/s/sevinne_the_chronoclasm.txt b/forge-gui/res/cardsfolder/s/sevinne_the_chronoclasm.txt index f06d2b1f5be..f5ea7aaa247 100644 --- a/forge-gui/res/cardsfolder/s/sevinne_the_chronoclasm.txt +++ b/forge-gui/res/cardsfolder/s/sevinne_the_chronoclasm.txt @@ -4,6 +4,6 @@ Types:Legendary Creature Human Wizard PT:2/2 K:Prevent all damage that would be dealt to CARDNAME. T:Mode$ SpellCast | ValidCard$ Instant.YouCtrl+wasCastFromGraveyard,Sorcery.YouCtrl+wasCastFromGraveyard | ActivatorThisTurnCast$ EQ1 | NoResolvingCheck$ True | ValidActivatingPlayer$ You | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast your first instant or sorcery spell from your graveyard each turn, copy that spell. You may choose new targets for the copy. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True SVar:AIPriorityModifier:9 Oracle:Prevent all damage that would be dealt to Sevinne, the Chronoclasm.\nWhenever you cast your first instant or sorcery spell from your graveyard each turn, copy that spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/s/sevinnes_reclamation.txt b/forge-gui/res/cardsfolder/s/sevinnes_reclamation.txt index 8cc7d22d078..5d5965771d6 100644 --- a/forge-gui/res/cardsfolder/s/sevinnes_reclamation.txt +++ b/forge-gui/res/cardsfolder/s/sevinnes_reclamation.txt @@ -2,7 +2,7 @@ Name:Sevinne's Reclamation ManaCost:2 W Types:Sorcery A:SP$ ChangeZone | Cost$ 2 W | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose target permanent card with converted mana cost 3 or less from your graveyard | ValidTgts$ Permanent.cmcLE3+YouCtrl | SubAbility$ DBCpoy | SpellDescription$ Return target permanent card with converted mana cost 3 or less from your graveyard to the battlefield. If this spell was cast from a graveyard, you may copy this spell and may choose a new target for the copy. -SVar:DBCpoy:DB$ CopySpellAbility | Defined$ Parent | Optional$ True | ConditionDefined$ Self | ConditionPresent$ Card.wasCastFromGraveyard +SVar:DBCpoy:DB$ CopySpellAbility | Defined$ Parent | Optional$ True | MayChooseTarget$ True | ConditionDefined$ Self | ConditionPresent$ Card.wasCastFromGraveyard AI:RemoveDeck:Random K:Flashback:4 W Oracle:Return target permanent card with converted mana cost 3 or less from your graveyard to the battlefield. If this spell was cast from a graveyard, you may copy this spell and may choose a new target for the copy.\nFlashback {4}{W} (You may cast this card from your graveyard for its flashback cost. Then exile it.) diff --git a/forge-gui/res/cardsfolder/s/sigil_tracer.txt b/forge-gui/res/cardsfolder/s/sigil_tracer.txt index 1cdca3526fe..09b58c48055 100644 --- a/forge-gui/res/cardsfolder/s/sigil_tracer.txt +++ b/forge-gui/res/cardsfolder/s/sigil_tracer.txt @@ -2,6 +2,5 @@ Name:Sigil Tracer ManaCost:1 U U Types:Creature Merfolk Wizard PT:2/2 -A:AB$CopySpellAbility | Cost$ 1 U tapXType<2/Wizard> | ValidTgts$ Instant,Sorcery | AILogic$ OnceIfViable | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. -SVar:Picture:http://www.wizards.com/global/images/magic/general/sigil_tracer.jpg +A:AB$CopySpellAbility | Cost$ 1 U tapXType<2/Wizard> | ValidTgts$ Instant,Sorcery | AILogic$ OnceIfViable | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. Oracle:{1}{U}, Tap two untapped Wizards you control: Copy target instant or sorcery spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/s/skull_storm.txt b/forge-gui/res/cardsfolder/s/skull_storm.txt index 8575431914b..eb34c18aeb9 100644 --- a/forge-gui/res/cardsfolder/s/skull_storm.txt +++ b/forge-gui/res/cardsfolder/s/skull_storm.txt @@ -2,7 +2,7 @@ Name:Skull Storm ManaCost:7 B B Types:Sorcery T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | TriggerDescription$ When you cast this spell, copy it for each time you've cast your commander from the command zone this game. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X | MayChooseTarget$ True SVar:X:Count$TotalCommanderCastFromCommandZone A:SP$ Sacrifice | Cost$ 7 B B | Defined$ Player.Opponent | SacValid$ Creature | RememberSacrificed$ True | SubAbility$ DBRepeatEach SVar:DBRepeatEach:DB$ RepeatEach | RepeatPlayers$ Player.Opponent | RepeatSubAbility$ DBLoseLife | SubAbility$ DBCleanup diff --git a/forge-gui/res/cardsfolder/s/spelltwine.txt b/forge-gui/res/cardsfolder/s/spelltwine.txt index 87e3b6f5ec5..5c401b433fe 100644 --- a/forge-gui/res/cardsfolder/s/spelltwine.txt +++ b/forge-gui/res/cardsfolder/s/spelltwine.txt @@ -3,9 +3,8 @@ ManaCost:5 U Types:Sorcery A:SP$ ChangeZone | Cost$ 5 U | Origin$ Graveyard | Destination$ Exile | TgtPrompt$ Choose target instant or sorcery card in your graveyard | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | RememberChanged$ True | SubAbility$ TgtOpp | SpellDescription$ Exile target instant or sorcery card from your graveyard and target instant or sorcery from your opponent's graveyard. Copy those cards. Cast the copies if able without paying their mana cost. SVar:TgtOpp:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | TgtPrompt$ Choose target instant or sorcery card in your opponent's graveyard | ValidTgts$ Instant.OppOwn,Sorcery.OppOwn | RememberChanged$ True | SubAbility$ CopyYou -SVar:CopyYou:DB$ CopySpellAbility | Defined$ Remembered | SubAbility$ CopyOpp | CopyMultipleSpells$ 2 | SubAbility$ ExileSelf +SVar:CopyYou:DB$ Play | Defined$ Remembered | Amount$ All | CopyCard$ True | WithoutManaCost$ True | SubAbility$ ExileSelf SVar:ExileSelf:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | Defined$ Self | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/spelltwine.jpg Oracle:Exile target instant or sorcery card from your graveyard and target instant or sorcery card from an opponent's graveyard. Copy those cards. Cast the copies if able without paying their mana costs. Exile Spelltwine. diff --git a/forge-gui/res/cardsfolder/s/split_decision.txt b/forge-gui/res/cardsfolder/s/split_decision.txt index 85c1a30fc3b..8cdae3d0a57 100644 --- a/forge-gui/res/cardsfolder/s/split_decision.txt +++ b/forge-gui/res/cardsfolder/s/split_decision.txt @@ -3,7 +3,6 @@ ManaCost:1 U Types:Instant A:SP$ Vote | Cost$ 1 U | ValidTgts$ Instant,Sorcery | TgtZone$ Stack | TargetType$ Spell | Defined$ Player | VoteDenial$ DBDenial | VoteDuplication$ DBDuplication | Tied$ DBDuplication | VoteType$ Denial,Duplication | SpellDescription$ Will of the Council — Choose target instant or sorcery spell. Starting with you, each player votes for denial or duplication. If denial gets more votes, counter that spell. If duplication gets more votes or the vote is tied, copy the spell. You may choose new targets for the copy. SVar:DBDenial:DB$ Counter | Defined$ Targeted -SVar:DBDuplication:DB$ CopySpellAbility | Defined$ Targeted +SVar:DBDuplication:DB$ CopySpellAbility | Defined$ Targeted | MayChooseTarget$ True AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/split_decision.jpg Oracle:Will of the council — Choose target instant or sorcery spell. Starting with you, each player votes for denial or duplication. If denial gets more votes, counter the spell. If duplication gets more votes or the vote is tied, copy the spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/s/string_of_disappearances.txt b/forge-gui/res/cardsfolder/s/string_of_disappearances.txt index 446129daac2..b45f42c0e83 100644 --- a/forge-gui/res/cardsfolder/s/string_of_disappearances.txt +++ b/forge-gui/res/cardsfolder/s/string_of_disappearances.txt @@ -2,5 +2,5 @@ Name:String of Disappearances ManaCost:U Types:Instant A:SP$ ChangeZone | Cost$ U | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Hand | SubAbility$ DBCopy | SpellDescription$ Return target creature to its owner's hand. Then that creature's controller may pay {U}{U}. If the player does, they may copy this spell and may choose a new target for that copy. -SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | UnlessPayer$ TargetedController | UnlessCost$ U U | UnlessSwitched$ True | ConditionDefined$ Targeted | ConditionPresent$ Permanent | ConditionCompare$ GE1 | StackDescription$ None +SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedController | UnlessPayer$ TargetedController | UnlessCost$ U U | UnlessSwitched$ True | ConditionDefined$ Targeted | ConditionPresent$ Permanent | ConditionCompare$ GE1 | StackDescription$ None | MayChooseTarget$ True Oracle:Return target creature to its owner's hand. Then that creature's controller may pay {U}{U}. If the player does, they may copy this spell and may choose a new target for that copy. diff --git a/forge-gui/res/cardsfolder/s/strionic_resonator.txt b/forge-gui/res/cardsfolder/s/strionic_resonator.txt index d24f160d254..b043b300c75 100644 --- a/forge-gui/res/cardsfolder/s/strionic_resonator.txt +++ b/forge-gui/res/cardsfolder/s/strionic_resonator.txt @@ -1,8 +1,7 @@ Name:Strionic Resonator ManaCost:2 Types:Artifact -A:AB$ CopySpellAbility | Cost$ 2 T | TargetType$ Triggered.YouCtrl | ValidTgts$ Card | SpellDescription$ Copy target triggered ability you control. You may choose new targets for the copy. +A:AB$ CopySpellAbility | Cost$ 2 T | TargetType$ Triggered.YouCtrl | ValidTgts$ Card | MayChooseTarget$ True | SpellDescription$ Copy target triggered ability you control. You may choose new targets for the copy. AI:RemoveDeck:All AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/strionic_resonator.jpg Oracle:{2}, {T}: Copy target triggered ability you control. You may choose new targets for the copy. (A triggered ability uses the words "when," "whenever," or "at.") diff --git a/forge-gui/res/cardsfolder/s/swarm_intelligence.txt b/forge-gui/res/cardsfolder/s/swarm_intelligence.txt index d0b3eda2a2d..6cd271abf27 100644 --- a/forge-gui/res/cardsfolder/s/swarm_intelligence.txt +++ b/forge-gui/res/cardsfolder/s/swarm_intelligence.txt @@ -2,8 +2,7 @@ Name:Swarm Intelligence ManaCost:6 U Types:Enchantment T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | Execute$ TrigCopySpell | OptionalDecider$ You | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast an instant or sorcery spell, you may copy that spell. You may choose new targets for the copy. -SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always +SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always | MayChooseTarget$ True DeckHints:Keyword$Retrace & Keyword$Flashback DeckNeeds:Type$Instant|Sorcery -SVar:Picture:http://www.wizards.com/global/images/magic/general/swarm_intelligence.jpg Oracle:Whenever you cast an instant or sorcery spell, you may copy that spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/t/tawnos_urzas_apprentice.txt b/forge-gui/res/cardsfolder/t/tawnos_urzas_apprentice.txt index 24714b0ad0e..6b75029a526 100644 --- a/forge-gui/res/cardsfolder/t/tawnos_urzas_apprentice.txt +++ b/forge-gui/res/cardsfolder/t/tawnos_urzas_apprentice.txt @@ -3,5 +3,5 @@ ManaCost:U R Types:Legendary Creature Human Artificer PT:1/3 K:Haste -A:AB$ CopySpellAbility | Cost$ U R T | TgtPrompt$ Select target activated or triggered ability you control from an artifact source | TargetType$ Activated.YouCtrl,Triggered.YouCtrl | ValidTgts$ Artifact | AILogic$ AlwaysCopyActivatedAbilities | StackDescription$ SpellDescription | SpellDescription$ Copy target activated or triggered ability you control from an artifact source. You may choose new targets for the copy. (Mana abilities can't be targeted.) +A:AB$ CopySpellAbility | Cost$ U R T | TgtPrompt$ Select target activated or triggered ability you control from an artifact source | TargetType$ Activated.YouCtrl,Triggered.YouCtrl | ValidTgts$ Artifact | AILogic$ AlwaysCopyActivatedAbilities | MayChooseTarget$ True | StackDescription$ SpellDescription | SpellDescription$ Copy target activated or triggered ability you control from an artifact source. You may choose new targets for the copy. (Mana abilities can't be targeted.) Oracle:Haste\n{U}{R}, {T}: Copy target activated or triggered ability you control from an artifact source. You may choose new targets for the copy. (Mana abilities can't be targeted.) diff --git a/forge-gui/res/cardsfolder/t/the_mirari_conjecture.txt b/forge-gui/res/cardsfolder/t/the_mirari_conjecture.txt index c43bdc70132..18b18155cae 100644 --- a/forge-gui/res/cardsfolder/t/the_mirari_conjecture.txt +++ b/forge-gui/res/cardsfolder/t/the_mirari_conjecture.txt @@ -6,7 +6,7 @@ SVar:DBChangeZoneI:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | Vali SVar:DBChangeZoneII:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | ValidTgts$ Sorcery.YouCtrl | SpellDescription$ Return target sorcery card from your graveyard to your hand. SVar:DBEffect:DB$ Effect | Name$ The Mirari Conjecture Effect | Triggers$ InstantSorceryCast | SVars$ TrigCopySpell | SpellDescription$ Until end of turn, whenever you cast an instant or sorcery spell, copy it. You may choose new targets for the copy. SVar:InstantSorceryCast:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | Execute$ TrigCopySpell | TriggerZones$ Command | TriggerDescription$ Until end of turn, whenever you cast an instant or sorcery spell, copy it. You may choose new targets for the copy. -SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility +SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True SVar:NeedsToPlayVar:Z GE1 SVar:Z:Count$ValidGraveyard Instant.YouOwn,Sorcery.YouOwn DeckHints:Type$Instant|Sorcery diff --git a/forge-gui/res/cardsfolder/t/thousand_year_storm.txt b/forge-gui/res/cardsfolder/t/thousand_year_storm.txt index e4425747b73..2f1701645e6 100644 --- a/forge-gui/res/cardsfolder/t/thousand_year_storm.txt +++ b/forge-gui/res/cardsfolder/t/thousand_year_storm.txt @@ -2,7 +2,7 @@ Name:Thousand-Year Storm ManaCost:4 U R Types:Enchantment T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast an instant or sorcery spell, copy it for each other instant and sorcery spell you've cast before it this turn. You may choose new targets for the copies. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X | References$ X | MayChooseTarget$ True SVar:X:TriggerObjectsCurrentCastSpells$Valid Sorcery.YouCtrl,Instant.YouCtrl/Minus.1 DeckHints:Type$Instant|Sorcery Oracle:Whenever you cast an instant or sorcery spell, copy it for each other instant and sorcery spell you've cast before it this turn. You may choose new targets for the copies. diff --git a/forge-gui/res/cardsfolder/t/twincast.txt b/forge-gui/res/cardsfolder/t/twincast.txt index a7f995a1afa..e219746f856 100644 --- a/forge-gui/res/cardsfolder/t/twincast.txt +++ b/forge-gui/res/cardsfolder/t/twincast.txt @@ -1,6 +1,5 @@ Name:Twincast ManaCost:U U Types:Instant -A:SP$ CopySpellAbility | Cost$ U U | ValidTgts$ Instant,Sorcery | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. -SVar:Picture:http://www.wizards.com/global/images/magic/general/twincast.jpg +A:SP$ CopySpellAbility | Cost$ U U | ValidTgts$ Instant,Sorcery | TargetType$ Spell | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. Oracle:Copy target instant or sorcery spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/t/twinning_staff.txt b/forge-gui/res/cardsfolder/t/twinning_staff.txt new file mode 100644 index 00000000000..5bc515dc796 --- /dev/null +++ b/forge-gui/res/cardsfolder/t/twinning_staff.txt @@ -0,0 +1,8 @@ +Name:Twinning Staff +ManaCost:3 +Types:Artifact +R:Event$ CopySpell | ActiveZones$ Battlefield | ValidPlayer$ You | ValidSpell$ Spell | ReplaceWith$ AddOneMore | Description$ If you would copy a spell one or more times, instead copy it that many times plus an additional time. You may choose new targets for the additional copy. +SVar:AddOneMore:DB$ ReplaceEffect | VarName$ Amount | VarValue$ X | References$ X +SVar:X:ReplaceCount$Amount/Plus.1 +A:AB$ CopySpellAbility | Cost$ 7 T | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell you control. You may choose new targets for the copy. +Oracle:If you would copy a spell one or more times, instead copy it that many times plus an additional time. You may choose new targets for the additional copy.\n{7}, {T}: Copy target instant or sorcery spell you control. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/u/unbound_flourishing.txt b/forge-gui/res/cardsfolder/u/unbound_flourishing.txt index da2350e6d30..f4fa0c35137 100644 --- a/forge-gui/res/cardsfolder/u/unbound_flourishing.txt +++ b/forge-gui/res/cardsfolder/u/unbound_flourishing.txt @@ -4,6 +4,6 @@ Types:Enchantment T:Mode$ SpellCast | ValidCard$ Permanent | ValidActivatingPlayer$ You | Execute$ TrigDouble | TriggerZones$ Battlefield | HasXManaCost$ True | TriggerDescription$ Whenever you cast a permanent spell with a mana cost that contains X, double the value of X. SVar:TrigDouble:DB$ ChangeX | Defined$ TriggeredStackInstance T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | Execute$ TrigCopySpell | HasXManaCost$ True | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast an instant or sorcery spell or activate an ability, if that spell's mana cost or that ability's activation cost contains X, copy that spell or ability. You may choose new targets for the copy. -SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | AILogic$ Always +SVar:TrigCopySpell:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True | AILogic$ Always T:Mode$ AbilityCast | HasXManaCost$ True | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigCopySpell | Secondary$ True | TriggerDescription$ Whenever you cast an instant or sorcery spell or activate an ability, if that spell's mana cost or that ability's activation cost contains X, copy that spell or ability. You may choose new targets for the copy. Oracle:Whenever you cast a permanent spell with a mana cost that contains X, double the value of X.\nWhenever you cast an instant or sorcery spell or activate an ability, if that spell's mana cost or that ability's activation cost contains X, copy that spell or ability. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/u/uyo_silent_prophet.txt b/forge-gui/res/cardsfolder/u/uyo_silent_prophet.txt index 9474f574879..4a55b2c8fcc 100644 --- a/forge-gui/res/cardsfolder/u/uyo_silent_prophet.txt +++ b/forge-gui/res/cardsfolder/u/uyo_silent_prophet.txt @@ -3,7 +3,6 @@ ManaCost:4 U U Types:Legendary Creature Moonfolk Wizard PT:4/4 K:Flying -A:AB$CopySpellAbility | Cost$ 2 Return<2/Land> | ValidTgts$ Instant,Sorcery | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. +A:AB$CopySpellAbility | Cost$ 2 Return<2/Land> | ValidTgts$ Instant,Sorcery | MayChooseTarget$ True | SpellDescription$ Copy target instant or sorcery spell. You may choose new targets for the copy. AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/uyo_silent_prophet.jpg Oracle:Flying\n{2}, Return two lands you control to their owner's hand: Copy target instant or sorcery spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/v/verazol_the_split_current.txt b/forge-gui/res/cardsfolder/v/verazol_the_split_current.txt new file mode 100644 index 00000000000..7c508de8bd2 --- /dev/null +++ b/forge-gui/res/cardsfolder/v/verazol_the_split_current.txt @@ -0,0 +1,15 @@ +Name:Verazol, the Split Current +ManaCost:X G U +Types:Legendary Creature Serpent +PT:0/0 +K:etbCounter:P1P1:Y:no Condition:CARDNAME enters the battlefield with a +1/+1 counter on it for each mana spent to cast it. +SVar:X:Count$xPaid +SVar:Y:Count$FirstSpellTotalManaSpent +T:Mode$ SpellCast | ValidSA$ Spell.Kicked | ValidActivatingPlayer$ You | Execute$ DBRemoveCounters | TriggerZones$ Battlefield | OptionalDecider$ You | TriggerDescription$ Whenever you cast a kicked spell, you may remove two +1/+1 counters from CARDNAME. +SVar:DBRemoveCounters:DB$ RemoveCounter | CounterType$ P1P1 | CounterNum$ 2 | RememberRemoved$ True | SubAbility$ DBCopy +SVar:DBCopy:DB$ CopySpellAbility | ConditionCheckSVar$ Z | ConditionSVarCompare$ GE1 | References$ Z | SubAbility$ DBCleanup | Defined$ TriggeredSpellAbility | AILogic$ Always | MayChooseTarget$ True | SpellDescription$ If you do, copy that spell. You may choose new targets for that copy. (A copy of a permanent spell becomes a token.) +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:Z:Count$RememberedSize +DeckHas:Ability$Counters +Oracle:Verazol, the Split Current enters the battlefield with a +1/+1 counter on it for each mana spent to cast it.\nWhenever you cast a kicked spell, you may remove two +1/+1 counters from Verazol, the Split Current. If you do, copy that spell. You may choose new targets for that copy. (A copy of a permanent spell becomes a token.) + diff --git a/forge-gui/res/cardsfolder/w/wild_ricochet.txt b/forge-gui/res/cardsfolder/w/wild_ricochet.txt index 0b584273e8e..2a40428f2ba 100644 --- a/forge-gui/res/cardsfolder/w/wild_ricochet.txt +++ b/forge-gui/res/cardsfolder/w/wild_ricochet.txt @@ -2,7 +2,6 @@ Name:Wild Ricochet ManaCost:2 R R Types:Instant A:SP$ ChangeTargets | Cost$ 2 R R | TargetType$ Spell | Optional$ True | ValidTgts$ Instant,Sorcery | SubAbility$ DBCopy | SpellDescription$ You may choose new targets for target instant or sorcery spell. Then copy that spell. You may choose new targets for the copy. -SVar:DBCopy:DB$ CopySpellAbility | Defined$ Targeted | Controller$ You +SVar:DBCopy:DB$ CopySpellAbility | Defined$ Targeted | Controller$ You | MayChooseTarget$ True AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/wild_ricochet.jpg Oracle:You may choose new targets for target instant or sorcery spell. Then copy that spell. You may choose new targets for the copy. diff --git a/forge-gui/res/cardsfolder/w/will_kenrith.txt b/forge-gui/res/cardsfolder/w/will_kenrith.txt index 250aa84fe73..369d0b2b37b 100644 --- a/forge-gui/res/cardsfolder/w/will_kenrith.txt +++ b/forge-gui/res/cardsfolder/w/will_kenrith.txt @@ -10,6 +10,6 @@ SVar:DBEffect:DB$ Effect | StaticAbilities$ WillReduceCost | RememberObjects$ Ta SVar:WillReduceCost:Mode$ ReduceCost | EffectZone$ Command | ValidCard$ Instant,Sorcery,Planeswalker | Type$ Spell | Activator$ Player.IsRemembered | Amount$ 2 | Description$ Until your next turn, instant, sorcery, and planeswalker spells that player casts cost {2} less to cast. A:AB$ Effect | Cost$ SubCounter<8/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Player | EffectOwner$ Targeted | Name$ Emblem - Will Kenrith | Image$ emblem_will_kenrith | Triggers$ CopySpell | SVars$ TrigCopy | Duration$ Permanent | AILogic$ Always | SpellDescription$ Target player gets an emblem with "Whenever you cast an instant or sorcery spell, copy it. You may choose new targets for the copy." SVar:CopySpell:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | Execute$ TrigCopy | TriggerZones$ Command | TriggerDescription$ Whenever you cast an instant or sorcery spell, copy it. You may choose new targets for the copy. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | MayChooseTarget$ True DeckHints:Name$Rowan Kenrith Oracle:[+2]: Until your next turn, up to two target creatures each have base power and toughness 0/3 and lose all abilities.\n[-2]: Target player draws two cards. Until your next turn, instant, sorcery, and planeswalker spells that player casts cost {2} less to cast.\n[-8]: Target player gets an emblem with "Whenever you cast an instant or sorcery spell, copy it. You may choose new targets for the copy."\nPartner with Rowan Kenrith\nWill Kenrith can be your commander. diff --git a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java index 649d023bdbb..c2a05dfc343 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java +++ b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java @@ -38,7 +38,6 @@ import forge.game.player.Player; import forge.game.player.PlayerController; import forge.game.spellability.*; import forge.game.zone.Zone; -import forge.util.collect.FCollection; import org.apache.commons.lang3.StringUtils; import java.util.Collections; @@ -151,7 +150,7 @@ public class HumanPlaySpellAbility { // is only executed or evaluated if the first argument does not suffice to determine the value of the expression final boolean prerequisitesMet = announceValuesLikeX() && announceType() - && (!mayChooseTargets || setupTargets()) // if you can choose targets, then do choose them. + && (!mayChooseTargets || ability.setupTargets()) // if you can choose targets, then do choose them. && (isFree || payment.payCost(new HumanCostDecision(controller, human, ability, ability.getHostCard()))); if (!prerequisitesMet) { @@ -190,7 +189,7 @@ public class HumanPlaySpellAbility { // no worries here. The same thread must resolve, and by this moment ability will have been resolved already // Triggers haven't resolved yet ?? if (mayChooseTargets) { - clearTargets(ability); + ability.clearTargets(); } if (manaTypeConversion || manaColorConversion || keywordColor) { manapool.restoreColorReplacements(); @@ -199,47 +198,6 @@ public class HumanPlaySpellAbility { return true; } - private final boolean setupTargets() { - // Skip to paying if parent ability doesn't target and has no subAbilities. - // (or trigger case where its already targeted) - SpellAbility currentAbility = ability; - final Card source = ability.getHostCard(); - do { - final TargetRestrictions tgt = currentAbility.getTargetRestrictions(); - if (tgt != null && tgt.doesTarget()) { - clearTargets(currentAbility); - Player targetingPlayer; - if (currentAbility.hasParam("TargetingPlayer")) { - final FCollection candidates = AbilityUtils.getDefinedPlayers(source, currentAbility.getParam("TargetingPlayer"), currentAbility); - // activator chooses targeting player - targetingPlayer = ability.getActivatingPlayer().getController().chooseSingleEntityForEffect( - candidates, currentAbility, "Choose the targeting player", null); - } else { - targetingPlayer = ability.getActivatingPlayer(); - } - currentAbility.setTargetingPlayer(targetingPlayer); - if (!targetingPlayer.getController().chooseTargetsFor(currentAbility)) { - return false; - } - } - final AbilitySub subAbility = currentAbility.getSubAbility(); - if (subAbility != null) { - // This is necessary for "TargetsWithDefinedController$ ParentTarget" - subAbility.setParent(currentAbility); - } - currentAbility = subAbility; - } while (currentAbility != null); - return true; - } - - public final void clearTargets(final SpellAbility ability) { - final TargetRestrictions tg = ability.getTargetRestrictions(); - if (tg != null) { - ability.resetTargets(); - tg.calculateStillToDivide(ability.getParam("DividedAsYouChoose"), ability.getHostCard(), ability); - } - } - private void rollbackAbility(final Zone fromZone, final int zonePosition, CostPayment payment) { // cancel ability during target choosing final Game game = ability.getActivatingPlayer().getGame(); @@ -251,7 +209,7 @@ public class HumanPlaySpellAbility { game.getAction().moveTo(fromZone, ability.getHostCard(), zonePosition >= 0 ? Integer.valueOf(zonePosition) : null, null); } - clearTargets(ability); + ability.clearTargets(); ability.resetOnceResolved(); payment.refundPayment(); diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 3469b1776ca..31f0b729c32 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1671,7 +1671,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont List orderedSAs = activePlayerSAs; if (activePlayerSAs.size() > 1) { final String firstStr = activePlayerSAs.get(0).toString(); - boolean needPrompt = false; + boolean needPrompt = !activePlayerSAs.get(0).isTrigger(); // for the purpose of pre-ordering, no need for extra granularity Integer idxAdditionalInfo = firstStr.indexOf(" ["); @@ -1682,6 +1682,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont SpellAbility currentSa = activePlayerSAs.get(i); String saStr = currentSa.toString(); + // if current SA isn't a trigger and it uses Targeting, try to show prompt + if (!currentSa.isTrigger() && currentSa.usesTargeting()) { + needPrompt = true; + } if (!needPrompt && !saStr.equals(firstStr)) { needPrompt = true; // prompt by default unless all abilities // are the same @@ -1738,6 +1742,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont if (next.isTrigger()) { HumanPlay.playSpellAbility(this, player, next); } else { + if (next.isCopied()) { + // copied spell always add to stack + player.getGame().getStackZone().add(next.getHostCard()); + // TODO check if static abilities needs to be run for things affecting the copy? + if (next.isMayChooseNewTargets() && !next.setupTargets()) { + // if targets can't be done, remove copy from existence + next.getHostCard().ceaseToExist(); + } + } player.getGame().getStack().add(next); } }