diff --git a/.gitattributes b/.gitattributes index f730ec23d61..f5f981a368e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8731,6 +8731,7 @@ res/cardsfolder/r/red_suns_zenith.txt svneol=native#text/plain res/cardsfolder/r/red_ward.txt svneol=native#text/plain res/cardsfolder/r/redeem.txt svneol=native#text/plain res/cardsfolder/r/redeem_the_lost.txt svneol=native#text/plain +res/cardsfolder/r/redirect.txt -text res/cardsfolder/r/reduce_to_dreams.txt svneol=native#text/plain res/cardsfolder/r/redwood_treefolk.txt svneol=native#text/plain res/cardsfolder/r/reef_pirates.txt svneol=native#text/plain diff --git a/res/cardsfolder/r/redirect.txt b/res/cardsfolder/r/redirect.txt new file mode 100644 index 00000000000..7451c951744 --- /dev/null +++ b/res/cardsfolder/r/redirect.txt @@ -0,0 +1,6 @@ +Name:Redirect +ManaCost:U U +Types:Instant +A:SP$ ChangeTargets | Cost$ U U | TargetType$ Spell | Optional$ True | ValidTgts$ Card | SpellDescription$ You may choose new targets for target spell. +SVar:RemAIDeck:True +Oracle:You may choose new targets for target spell. \ No newline at end of file diff --git a/res/cardsfolder/s/seeds_of_strength.txt b/res/cardsfolder/s/seeds_of_strength.txt index bec17c2c039..50b6d2b66ea 100644 --- a/res/cardsfolder/s/seeds_of_strength.txt +++ b/res/cardsfolder/s/seeds_of_strength.txt @@ -1,9 +1,9 @@ Name:Seeds of Strength ManaCost:G W Types:Instant -A:SP$ Pump | Cost$ G W | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ 1 | NumDef$ 1 | SubAbility$ DBPump1 | SpellDescription$ Target creature gets +1/+1 until end of turn. Target creature gets +1/+1 until end of turn. Target creature gets +1/+1 until end of turn. -SVar:DBPump1:DB$Pump | Cost$ 0 | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ 1 | NumDef$ 1 | SubAbility$ DBPump2 -SVar:DBPump2:DB$Pump | Cost$ 0 | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ 1 | NumDef$ 1 +A:SP$ Pump | Cost$ G W | ValidTgts$ Creature | TgtPrompt$ Select target creature (1) | NumAtt$ 1 | NumDef$ 1 | SubAbility$ DBPump1 | SpellDescription$ Target creature gets +1/+1 until end of turn. Target creature gets +1/+1 until end of turn. Target creature gets +1/+1 until end of turn. +SVar:DBPump1:DB$Pump | Cost$ 0 | ValidTgts$ Creature | TgtPrompt$ Select target creature (2) | NumAtt$ 1 | NumDef$ 1 | SubAbility$ DBPump2 +SVar:DBPump2:DB$Pump | Cost$ 0 | ValidTgts$ Creature | TgtPrompt$ Select target creature (3)| NumAtt$ 1 | NumDef$ 1 SVar:Picture:http://www.wizards.com/global/images/magic/general/seeds_of_strength.jpg Oracle:Target creature gets +1/+1 until end of turn.\nTarget creature gets +1/+1 until end of turn.\nTarget creature gets +1/+1 until end of turn. SetInfo:RAV Common \ No newline at end of file diff --git a/src/main/java/forge/card/ability/effects/ChangeTargetsEffect.java b/src/main/java/forge/card/ability/effects/ChangeTargetsEffect.java index 8e20e5d4e87..a77d834a796 100644 --- a/src/main/java/forge/card/ability/effects/ChangeTargetsEffect.java +++ b/src/main/java/forge/card/ability/effects/ChangeTargetsEffect.java @@ -8,7 +8,6 @@ import org.apache.commons.lang3.tuple.Pair; import com.google.common.collect.Iterables; -import forge.Card; import forge.ITargetable; import forge.card.ability.SpellAbilityEffect; import forge.card.spellability.SpellAbility; @@ -38,13 +37,18 @@ public class ChangeTargetsEffect extends SpellAbilityEffect { // If there isn't a Stack Instance, there isn't really a target continue; } - - boolean preserveNumber = sa.hasParam("PreserveNumber"); // Redirect is not supposed to change number of targets + boolean changesOneTarget = sa.hasParam("ChangeSingleTarget"); // The only card known to replace targets with self is Spellskite + // There is also Muck Drubb but it replaces ALL occurences of a single target with itself (unlike Spellskite that has to be activated for each). SpellAbilityStackInstance changingTgtSI = si; Player chooser = sa.getActivatingPlayer(); + // Redirect rules read 'you MAY choose new targets' ... okay! + boolean isOptional = sa.hasParam("Optional"); + if( isOptional && !chooser.getController().confirmAction(sa, null, "Do you want to change targets of " + tgtSA.getSourceCard() + "?")) + continue; + if( changesOneTarget ) { // 1. choose a target of target spell List> allTargets = new ArrayList<>(); @@ -57,6 +61,7 @@ public class ChangeTargetsEffect extends SpellAbilityEffect { changingTgtSI = changingTgtSI.getSubInstace(); } if( allTargets.isEmpty() ) { + // is it an error or not? System.err.println("Player managed to target a spell without targets with Spellskite's ability."); return; } @@ -81,7 +86,7 @@ public class ChangeTargetsEffect extends SpellAbilityEffect { // Update targets, with a potential new target SpellAbility changingTgtSA = changingTgtSI.getSpellAbility(); TargetChoices newTarget = sa.getActivatingPlayer().getController().chooseNewTargetsFor(changingTgtSA); - if ( null != newTarget) + if (null != newTarget) changingTgtSI.updateTarget(newTarget); changingTgtSI = changingTgtSI.getSubInstace(); } diff --git a/src/main/java/forge/card/cardfactory/CardFactory.java b/src/main/java/forge/card/cardfactory/CardFactory.java index d0d7d0f4367..46350adeef3 100644 --- a/src/main/java/forge/card/cardfactory/CardFactory.java +++ b/src/main/java/forge/card/cardfactory/CardFactory.java @@ -28,7 +28,6 @@ import forge.CardColor; import forge.CardUtil; import forge.Command; import forge.CounterType; -import forge.ITargetable; import forge.ImageCache; import forge.card.CardCharacteristics; import forge.card.CardDb; diff --git a/src/main/java/forge/card/spellability/HumanPlaySpellAbility.java b/src/main/java/forge/card/spellability/HumanPlaySpellAbility.java index 6861cb52710..8df97928b50 100644 --- a/src/main/java/forge/card/spellability/HumanPlaySpellAbility.java +++ b/src/main/java/forge/card/spellability/HumanPlaySpellAbility.java @@ -109,7 +109,7 @@ public class HumanPlaySpellAbility { if( tgt != null && tgt.doesTarget()) { clearTargets(beingTargeted); final TargetSelection select = new TargetSelection(beingTargeted); - if (!select.chooseTargets() ) { + if (!select.chooseTargets(null) ) { return false; } } diff --git a/src/main/java/forge/card/spellability/TargetSelection.java b/src/main/java/forge/card/spellability/TargetSelection.java index 7f875a075a9..999d860d0bf 100644 --- a/src/main/java/forge/card/spellability/TargetSelection.java +++ b/src/main/java/forge/card/spellability/TargetSelection.java @@ -65,14 +65,15 @@ public class TargetSelection { *

*/ - public final boolean chooseTargets() { + public final boolean chooseTargets(Integer numTargets) { TargetRestrictions tgt = getTgt(); final boolean canTarget = tgt != null && tgt.doesTarget(); if( !canTarget ) throw new RuntimeException("TargetSelection.chooseTargets called for ability that does not target - " + ability); - final int minTargets = tgt.getMinTargets(ability.getSourceCard(), ability); - final int maxTargets = tgt.getMaxTargets(ability.getSourceCard(), ability); + // Number of targets is explicitly set only if spell is being redirected (ex. Swerve or Redirect) + final int minTargets = numTargets != null ? numTargets.intValue() : tgt.getMinTargets(ability.getSourceCard(), ability); + final int maxTargets = numTargets != null ? numTargets.intValue() : tgt.getMaxTargets(ability.getSourceCard(), ability); final int numTargeted = ability.getTargets().getNumTargeted(); boolean hasEnoughTargets = minTargets == 0 || numTargeted >= minTargets; @@ -81,7 +82,6 @@ public class TargetSelection { // if not enough targets chosen, cancel Ability if (this.bTargetingDone && !hasEnoughTargets) return false; - if (this.bTargetingDone && hasEnoughTargets || hasAllTargets || tgt.isDividedAsYouChoose() && tgt.getStillToDivide() == 0) { return true; @@ -118,7 +118,7 @@ public class TargetSelection { } } // some inputs choose cards one-by-one and need to be called again - return choiceResult && chooseTargets(); + return choiceResult && chooseTargets(numTargets); } diff --git a/src/main/java/forge/game/player/PlayerControllerHuman.java b/src/main/java/forge/game/player/PlayerControllerHuman.java index f19ecb6f380..811f0c37a53 100644 --- a/src/main/java/forge/game/player/PlayerControllerHuman.java +++ b/src/main/java/forge/game/player/PlayerControllerHuman.java @@ -454,7 +454,7 @@ public class PlayerControllerHuman extends PlayerController { TargetChoices oldTarget = ability.getTargets(); TargetSelection select = new TargetSelection(ability); ability.resetTargets(); - if (select.chooseTargets()) { + if (select.chooseTargets(oldTarget.getNumTargeted())) { return ability.getTargets(); } else { // Return old target, since we had to reset them above