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 a8de4e54fc2..11eb783bc78 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -86,10 +86,11 @@ public class AbilityUtils { // But then we only need update one function at a time once the casting is // everywhere. // Probably will move to One function solution sometime in the future - public static CardCollection getDefinedCards(final Card hostCard, final String def, final CardTraitBase sa) { + public static CardCollection getDefinedCards(final Card hostCard, final String def, CardTraitBase sa) { CardCollection cards = new CardCollection(); String changedDef = (def == null) ? "Self" : applyAbilityTextChangeEffects(def, sa); // default to Self final String[] incR = changedDef.split("\\.", 2); + sa = adjustTriggerContext(incR, sa); String defined = incR[0]; final Game game = hostCard.getGame(); @@ -433,7 +434,7 @@ public class AbilityUtils { public static int calculateAmount(final Card card, String amount, final CardTraitBase ability) { return calculateAmount(card, amount, ability, false); } - public static int calculateAmount(final Card card, String amount, final CardTraitBase ability, boolean maxto) { + public static int calculateAmount(final Card card, String amount, CardTraitBase ability, boolean maxto) { // return empty strings and constants if (StringUtils.isBlank(amount)) { return 0; } if (card == null) { return 0; } @@ -508,6 +509,8 @@ public class AbilityUtils { // modify amount string for text changes calcX[1] = applyAbilityTextChangeEffects(calcX[1], ability); + ability = adjustTriggerContext(calcX, ability); + Integer val = null; if (calcX[0].startsWith("Count")) { val = xCount(card, calcX[1], ability); @@ -986,16 +989,15 @@ public class AbilityUtils { * @return a {@link java.util.ArrayList} object. */ @SuppressWarnings("unchecked") - public static PlayerCollection getDefinedPlayers(final Card card, final String def, final CardTraitBase sa) { + public static PlayerCollection getDefinedPlayers(final Card card, final String def, CardTraitBase sa) { final PlayerCollection players = new PlayerCollection(); + final Player player = sa instanceof SpellAbility ? ((SpellAbility)sa).getActivatingPlayer() : card.getController(); + final Game game = card == null ? null : card.getGame(); String changedDef = (def == null) ? "You" : applyAbilityTextChangeEffects(def, sa); // default to Self final String[] incR = changedDef.split("\\.", 2); + sa = adjustTriggerContext(incR, sa); String defined = incR[0]; - final Game game = card == null ? null : card.getGame(); - - final Player player = sa instanceof SpellAbility ? ((SpellAbility)sa).getActivatingPlayer() : card.getController(); - if (defined.equals("Self") || defined.equals("TargetedCard") || defined.equals("ThisTargetedCard") || defined.startsWith("Valid") || getPaidCards(sa, defined) != null || defined.equals("TargetedSource") || defined.startsWith("CardUID_")) { @@ -3887,4 +3889,20 @@ public class AbilityUtils { } return false; } + + private static CardTraitBase adjustTriggerContext(String[] def, final CardTraitBase ctb) { + if (def[0].startsWith("Spawner>") && ctb instanceof SpellAbility) { + Trigger trig = ((SpellAbility) ctb).getTrigger(); + if (trig == null) { + return ctb; + } + SpellAbility spawner = trig.getSpawningAbility(); + if (spawner == null) { + return ctb; + } + def[0] = def[0].substring(8); + return spawner; + } + return ctb; + } } 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 29f975c6a67..a81688185da 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 @@ -81,10 +81,6 @@ public class DelayedTriggerEffect extends SpellAbilityEffect { overridingSA.setSVar("StoredTransform", String.valueOf(host.getTransformedTimestamp())); } - if (sa.hasParam("CopyTriggeringObjects")) { - overridingSA.setTriggeringObjects(sa.getTriggeringObjects()); - } - delTrig.setOverridingAbility(overridingSA); } final TriggerHandler trigHandler = game.getTriggerHandler(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java index 9584388d40f..e793e1ba600 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java @@ -70,10 +70,6 @@ public class ImmediateTriggerEffect extends SpellAbilityEffect { ((AbilitySub)overridingSA).setParent(null); } - if (sa.hasParam("CopyTriggeringObjects")) { - overridingSA.setTriggeringObjects(sa.getTriggeringObjects()); - } - immediateTrig.setOverridingAbility(overridingSA); } 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 cea6061e3f1..b85848a872a 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -186,7 +186,6 @@ public class CardFactory { copySA = getCopiedTriggeredAbility((WrappedAbility)targetSA, c, controller); } else { copySA = targetSA.copy(c, controller, false); - c.setCastSA(copySA); // need to copy keyword if (targetSA.getKeyword() != null) { KeywordInterface kw = targetSA.getKeyword().copy(c, false); @@ -206,13 +205,13 @@ public class CardFactory { if (copySA instanceof Spell) { Spell spell = (Spell) copySA; spell.setCastFaceDown(false); + c.setCastSA(copySA); } //remove all costs if (!copySA.isTrigger()) { copySA.setPayCosts(new Cost("", targetSA.isAbility())); } - copySA.setActivatingPlayer(controller); return copySA; } diff --git a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java index 70a1796f0d7..b0a8c26991f 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java @@ -1072,7 +1072,6 @@ public class PhaseHandler implements java.io.Serializable { triggerList.put(originZone.getZoneType(), currentZone.getZoneType(), saHost); triggerList.triggerChangesZoneAll(game, sa); } - } game.copyLastState(); loopCount++; diff --git a/forge-gui/res/cardsfolder/b/biting_palm_ninja.txt b/forge-gui/res/cardsfolder/b/biting_palm_ninja.txt index 07b9af23bc0..8e4ec7e90ec 100644 --- a/forge-gui/res/cardsfolder/b/biting_palm_ninja.txt +++ b/forge-gui/res/cardsfolder/b/biting_palm_ninja.txt @@ -5,7 +5,7 @@ PT:3/3 K:Ninjutsu:2 B K:etbCounter:Menace:1 T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | Execute$ TrigImmediateTrig | CombatDamage$ True | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, you may remove a menace counter from it. When you do, that player reveals their hand and you choose a nonland card from it. Exile that card. -SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ SubCounter<1/Menace> | Execute$ TrigReveal | CopyTriggeringObjects$ True | TriggerDescription$ When you do, that player reveals their hand and you choose a nonland card from it. Exile that card. -SVar:TrigReveal:DB$ RevealHand | Defined$ TriggeredTarget | SubAbility$ DBExile -SVar:DBExile:DB$ ChangeZone | Origin$ Hand | Destination$ Exile | DefinedPlayer$ TriggeredTarget | Chooser$ You | ChangeType$ Card.nonLand | ChangeNum$ 1 | IsCurse$ True +SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ SubCounter<1/Menace> | Execute$ TrigReveal | TriggerDescription$ When you do, that player reveals their hand and you choose a nonland card from it. Exile that card. +SVar:TrigReveal:DB$ RevealHand | Defined$ Spawner>TriggeredTarget | SubAbility$ DBExile +SVar:DBExile:DB$ ChangeZone | Origin$ Hand | Destination$ Exile | DefinedPlayer$ Spawner>TriggeredTarget | Chooser$ You | ChangeType$ Card.nonLand | ChangeNum$ 1 | IsCurse$ True Oracle:Ninjutsu {2}{B}\nBiting-Palm Ninja enters the battlefield with a menace counter on it.\nWhenever Biting-Palm Ninja deals combat damage to a player, you may remove a menace counter from it. When you do, that player reveals their hand and you choose a nonland card from it. Exile that card. diff --git a/forge-gui/res/cardsfolder/d/dokuchi_silencer.txt b/forge-gui/res/cardsfolder/d/dokuchi_silencer.txt index 0ad940140f3..f62cf4ceafd 100644 --- a/forge-gui/res/cardsfolder/d/dokuchi_silencer.txt +++ b/forge-gui/res/cardsfolder/d/dokuchi_silencer.txt @@ -4,8 +4,8 @@ Types:Creature Human Ninja PT:2/1 K:Ninjutsu:1 B T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | Execute$ TrigImmediateTrig | CombatDamage$ True | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, you may discard a creature card. When you do, destroy target creature or planeswalker that player controls. -SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ Discard<1/Creature> | Execute$ TrigDestroy | CopyTriggeringObjects$ True | TriggerDescription$ When you do, destroy target creature or planeswalker that player controls. -SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Creature.ControlledBy TriggeredTarget,Planeswalker.ControlledBy TriggeredTarget | TgtPrompt$ Select target creature or planeswalker damaged player controls +SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ Discard<1/Creature> | Execute$ TrigDestroy | TriggerDescription$ When you do, destroy target creature or planeswalker that player controls. +SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Creature.ControlledBy Spawner>TriggeredTarget,Planeswalker.ControlledBy Spawner>TriggeredTarget | TgtPrompt$ Select target creature or planeswalker damaged player controls DeckHas:Ability$Discard SVar:AIPreference:DiscardCost$Creature.cmcLE3 Oracle:Ninjutsu {1}{B} ({1}{B}, Return an unblocked attacker you control to hand: Put this card onto the battlefield from your hand tapped and attacking.)\nWhenever Dokuchi Silencer deals combat damage to a player, you may discard a creature card. When you do, destroy target creature or planeswalker that player controls. diff --git a/forge-gui/res/cardsfolder/h/halana_kessig_ranger.txt b/forge-gui/res/cardsfolder/h/halana_kessig_ranger.txt index 6a4d29b0cce..d7289b731b4 100644 --- a/forge-gui/res/cardsfolder/h/halana_kessig_ranger.txt +++ b/forge-gui/res/cardsfolder/h/halana_kessig_ranger.txt @@ -5,8 +5,8 @@ PT:3/4 K:Reach K:Partner T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Other+YouCtrl | Execute$ TrigPayCost | TriggerZones$ Battlefield | TriggerDescription$ Whenever another creature enters the battlefield under your control, you may pay {2}. When you do, that creature deals damage equal to its power to target creature. -SVar:TrigPayCost:AB$ ImmediateTrigger | Cost$ 2 | Execute$ TrigDealDamage | CopyTriggeringObjects$ True | TriggerDescription$ When you pay {2}, that creature deals damage equal to its power to target creature. -SVar:TrigDealDamage:DB$ DealDamage | DamageSource$ TriggeredCardLKICopy | NumDmg$ X | ValidTgts$ Creature -SVar:X:TriggeredCard$CardPower +SVar:TrigPayCost:AB$ ImmediateTrigger | Cost$ 2 | Execute$ TrigDealDamage | TriggerDescription$ When you pay {2}, that creature deals damage equal to its power to target creature. +SVar:TrigDealDamage:DB$ DealDamage | DamageSource$ Spawner>TriggeredCardLKICopy | NumDmg$ X | ValidTgts$ Creature +SVar:X:Spawner>TriggeredCard$CardPower DeckNeeds:Type$Creature Oracle:Reach\nWhenever another creature enters the battlefield under your control, you may pay {2}. When you do, that creature deals damage equal to its power to target creature.\nPartner (You can have two commanders if both have partner.) diff --git a/forge-gui/res/cardsfolder/h/heart_piercer_manticore.txt b/forge-gui/res/cardsfolder/h/heart_piercer_manticore.txt index 1832381f7d4..3503f05032b 100644 --- a/forge-gui/res/cardsfolder/h/heart_piercer_manticore.txt +++ b/forge-gui/res/cardsfolder/h/heart_piercer_manticore.txt @@ -3,10 +3,10 @@ ManaCost:2 R R Types:Creature Manticore PT:4/3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ DBTrigger | TriggerDescription$ When CARDNAME enters the battlefield, you may sacrifice another creature. When you do, CARDNAME deals damage equal to that creature's power to target creature or player. -SVar:DBTrigger:AB$ ImmediateTrigger | Cost$ Sac<1/Creature.Other/another creature> | Execute$ TrigDamage | AILogic$ SacForDamage | RememberObjects$ Sacrificed | TriggerDescription$ When you do, CARDNAME deals damage equal to that creature's power to any target. +SVar:DBTrigger:AB$ ImmediateTrigger | Cost$ Sac<1/Creature.Other/another creature> | Execute$ TrigDamage | AILogic$ SacForDamage | TriggerDescription$ When you do, CARDNAME deals damage equal to that creature's power to any target. SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Any | NumDmg$ XPower K:Embalm:5 R -SVar:XPower:TriggerRemembered$CardPower +SVar:XPower:Spawner>Sacrificed$CardPower SVar:AIPreferenceParams:CreatureEvalThreshold$ 200 DeckHas:Ability$Token|Sacrifice Oracle:When Heart-Piercer Manticore enters the battlefield, you may sacrifice another creature. When you do, Heart-Piercer Manticore deals damage equal to that creature's power to any target.\nEmbalm {5}{R} ({5}{R}, Exile this card from your graveyard: Create a token that's a copy of it, except it's a white Zombie Manticore with no mana cost. Embalm only as a sorcery.) diff --git a/forge-gui/res/cardsfolder/i/infinite_authority.txt b/forge-gui/res/cardsfolder/i/infinite_authority.txt index fc5a30ea39f..bd1c3cad01c 100644 --- a/forge-gui/res/cardsfolder/i/infinite_authority.txt +++ b/forge-gui/res/cardsfolder/i/infinite_authority.txt @@ -5,12 +5,12 @@ K:Enchant creature A:SP$ Attach | Cost$ W W W | ValidTgts$ Creature | AILogic$ Pump T:Mode$ AttackerBlockedByCreature | ValidCard$ Creature.EnchantedBy | ValidBlocker$ Creature.toughnessLE3 | Execute$ DelTrigBlocker | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted creature blocks or becomes blocked by a creature with toughness 3 or less, destroy the other creature at end of combat. At the beginning of the next end step, if that creature was destroyed this way, put a +1/+1 counter on the first creature. T:Mode$ AttackerBlockedByCreature | ValidCard$ Creature.toughnessLE3 | ValidBlocker$ Creature.EnchantedBy | Execute$ DelTrigBlocked | Secondary$ True | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted creature blocks or becomes blocked by a creature with toughness 3 or less, destroy the other creature at end of combat. At the beginning of the next end step, if that creature was destroyed this way, put a +1/+1 counter on the first creature. -SVar:DelTrigBlocked:DB$ DelayedTrigger | Mode$ Phase | Phase$ EndCombat | ValidPlayer$ Player | Execute$ TrigDestroyBlocked | CopyTriggeringObjects$ True | TriggerDescription$ Destroy blocked creature at end of combat. -SVar:DelTrigBlocker:DB$ DelayedTrigger | Mode$ Phase | Phase$ EndCombat | ValidPlayer$ Player | Execute$ TrigDestroyBlocker | CopyTriggeringObjects$ True | TriggerDescription$ Destroy blocking creature at end of combat. -SVar:TrigDestroyBlocked:DB$ Destroy | Defined$ TriggeredAttackerLKICopy | RememberDestroyed$ True | SubAbility$ DBDelTrigAttacker -SVar:TrigDestroyBlocker:DB$ Destroy | Defined$ TriggeredBlockerLKICopy | RememberDestroyed$ True | SubAbility$ DBDelTrigBlocker -SVar:DBDelTrigAttacker:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ DBPutCounter | RememberObjects$ TriggeredBlocker | TriggerDescription$ At the beginning of the next end step, if that creature was destroyed this way, put a +1/+1 counter on the first creature. | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | SubAbility$ DBCleanup -SVar:DBDelTrigBlocker:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ DBPutCounter | RememberObjects$ TriggeredAttacker | TriggerDescription$ At the beginning of the next end step, if that creature was destroyed this way, put a +1/+1 counter on the first creature. | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | SubAbility$ DBCleanup +SVar:DelTrigBlocked:DB$ DelayedTrigger | Mode$ Phase | Phase$ EndCombat | ValidPlayer$ Player | Execute$ TrigDestroyBlocked | TriggerDescription$ Destroy blocked creature at end of combat. +SVar:DelTrigBlocker:DB$ DelayedTrigger | Mode$ Phase | Phase$ EndCombat | ValidPlayer$ Player | Execute$ TrigDestroyBlocker | TriggerDescription$ Destroy blocking creature at end of combat. +SVar:TrigDestroyBlocked:DB$ Destroy | Defined$ Spawner>TriggeredAttackerLKICopy | RememberDestroyed$ True | SubAbility$ DBDelTrigAttacker +SVar:TrigDestroyBlocker:DB$ Destroy | Defined$ Spawner>TriggeredBlockerLKICopy | RememberDestroyed$ True | SubAbility$ DBDelTrigBlocker +SVar:DBDelTrigAttacker:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ DBPutCounter | RememberObjects$ Spawner>TriggeredBlocker | TriggerDescription$ At the beginning of the next end step, if that creature was destroyed this way, put a +1/+1 counter on the first creature. | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | SubAbility$ DBCleanup +SVar:DBDelTrigBlocker:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ DBPutCounter | RememberObjects$ Spawner>TriggeredAttacker | TriggerDescription$ At the beginning of the next end step, if that creature was destroyed this way, put a +1/+1 counter on the first creature. | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | SubAbility$ DBCleanup SVar:DBPutCounter:DB$ PutCounter | Defined$ DelayTriggerRemembered | CounterType$ P1P1 | CounterNum$ 1 SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True DeckHas:Ability$Counters diff --git a/forge-gui/res/cardsfolder/k/kappa_tech_wrecker.txt b/forge-gui/res/cardsfolder/k/kappa_tech_wrecker.txt index 30c2e0a5008..860bd153940 100644 --- a/forge-gui/res/cardsfolder/k/kappa_tech_wrecker.txt +++ b/forge-gui/res/cardsfolder/k/kappa_tech_wrecker.txt @@ -5,6 +5,6 @@ PT:1/3 K:Ninjutsu:1 G K:etbCounter:Deathtouch:1 T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | Execute$ TrigImmediateTrig | CombatDamage$ True | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, you may remove a deathtouch counter from it. When you do, exile target artifact or enchantment that player controls. -SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ SubCounter<1/Deathtouch> | Execute$ TrigExile | CopyTriggeringObjects$ True | TriggerDescription$ When you do, exile target artifact or enchantment that player controls. -SVar:TrigExile:DB$ ChangeZone | ValidTgts$ Artifact.ControlledBy TriggeredTarget,Enchantment.ControlledBy TriggeredTarget | TgtPrompt$ Select target artifact or enchantment creature that player controls | Origin$ Battlefield | Destination$ Exile +SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ SubCounter<1/Deathtouch> | Execute$ TrigExile | TriggerDescription$ When you do, exile target artifact or enchantment that player controls. +SVar:TrigExile:DB$ ChangeZone | ValidTgts$ Artifact.ControlledBy Spawner>TriggeredTarget,Enchantment.ControlledBy Spawner>TriggeredTarget | TgtPrompt$ Select target artifact or enchantment creature that player controls | Origin$ Battlefield | Destination$ Exile Oracle:Ninjutsu {1}{G}\nKappa Tech-Wrecker enters the battlefield with a deathtouch counter on it.\nWhenever Kappa Tech-Wrecker deals combat damage to a player, you may remove a deathtouch counter from it. When you do, exile target artifact or enchantment that player controls. diff --git a/forge-gui/res/cardsfolder/rebalanced/a-dokuchi_silencer.txt b/forge-gui/res/cardsfolder/rebalanced/a-dokuchi_silencer.txt index 634d7eff5e1..8ffef7e16da 100644 --- a/forge-gui/res/cardsfolder/rebalanced/a-dokuchi_silencer.txt +++ b/forge-gui/res/cardsfolder/rebalanced/a-dokuchi_silencer.txt @@ -4,8 +4,8 @@ Types:Creature Human Ninja PT:2/1 K:Ninjutsu:1 B T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | Execute$ TrigImmediateTrig | CombatDamage$ True | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, you may discard a card. When you do, destroy target creature or planeswalker that player controls. -SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ Discard<1/Card> | Execute$ TrigDestroy | CopyTriggeringObjects$ True | TriggerDescription$ When you do, destroy target creature or planeswalker that player controls. -SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Creature.ControlledBy TriggeredTarget,Planeswalker.ControlledBy TriggeredTarget | TgtPrompt$ Select target creature or planeswalker damaged player controls +SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ Discard<1/Card> | Execute$ TrigDestroy | TriggerDescription$ When you do, destroy target creature or planeswalker that player controls. +SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Creature.ControlledBy Spawner>TriggeredTarget,Planeswalker.ControlledBy Spawner>TriggeredTarget | TgtPrompt$ Select target creature or planeswalker damaged player controls DeckHas:Ability$Discard SVar:AIPreference:DiscardCost$Card.cmcLE3 Oracle:Ninjutsu {1}{B}\nWhenever Dokuchi Silencer deals combat damage to a player, you may discard a card. When you do, destroy target creature or planeswalker that player controls.