mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 19:41:59 -08:00
* Fixed a bug of spell copy that caused that added spliced spells were not copied.
This commit is contained in:
parent
1835671f3d
commit
6726f48669
25 changed files with 198 additions and 199 deletions
|
|
@ -64,9 +64,6 @@ public class ClovenCasting extends CardImpl {
|
||||||
super(ownerId, 86, "Cloven Casting", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{5}{U}{R}");
|
super(ownerId, 86, "Cloven Casting", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{5}{U}{R}");
|
||||||
this.expansionSetCode = "ARB";
|
this.expansionSetCode = "ARB";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 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.
|
// 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.
|
||||||
this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(new ClovenCastingEffect(), new GenericManaCost(1)), filter, true, true));
|
this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(new ClovenCastingEffect(), new GenericManaCost(1)), filter, true, true));
|
||||||
|
|
||||||
|
|
@ -97,9 +94,7 @@ class ClovenCastingEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
|
|
@ -117,4 +112,4 @@ class ClovenCastingEffect extends OneShotEffect {
|
||||||
public ClovenCastingEffect copy() {
|
public ClovenCastingEffect copy() {
|
||||||
return new ClovenCastingEffect(this);
|
return new ClovenCastingEffect(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,11 @@ import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||||
*/
|
*/
|
||||||
public class KorCastigator extends CardImpl {
|
public class KorCastigator extends CardImpl {
|
||||||
|
|
||||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Eldrazi Scions");
|
private static final FilterCreaturePermanent FILTER = new FilterCreaturePermanent("Eldrazi Scions");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new SubtypePredicate("Eldrazi"));
|
FILTER.add(new SubtypePredicate("Eldrazi"));
|
||||||
filter.add(new SubtypePredicate("Scion"));
|
FILTER.add(new SubtypePredicate("Scion"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public KorCastigator(UUID ownerId) {
|
public KorCastigator(UUID ownerId) {
|
||||||
|
|
@ -61,7 +61,7 @@ public class KorCastigator extends CardImpl {
|
||||||
this.toughness = new MageInt(1);
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
// Kor Castigator can't be blocked by Eldrazi Scions.
|
// Kor Castigator can't be blocked by Eldrazi Scions.
|
||||||
this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield)));
|
this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(FILTER, Duration.WhileOnBattlefield)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public KorCastigator(final KorCastigator card) {
|
public KorCastigator(final KorCastigator card) {
|
||||||
|
|
|
||||||
|
|
@ -103,13 +103,17 @@ class ZadaHedronGrinderTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||||
if (isControlledInstantOrSorcery(spell)) {
|
if (isControlledInstantOrSorcery(spell)) {
|
||||||
boolean targetsSource = false;
|
boolean targetsSource = false;
|
||||||
for (Mode mode : spell.getSpellAbility().getModes().getSelectedModes()) {
|
for (Ability ability : spell.getSpellAbilities()) {
|
||||||
for (Target target : mode.getTargets()) {
|
for (Mode mode : ability.getModes().getSelectedModes()) {
|
||||||
for (UUID targetId : target.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
if (targetId.equals(getSourceId())) {
|
if (!target.isNotTarget()) {
|
||||||
targetsSource = true;
|
for (UUID targetId : target.getTargets()) {
|
||||||
} else {
|
if (targetId.equals(getSourceId())) {
|
||||||
return false;
|
targetsSource = true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -159,14 +163,17 @@ class ZadaHedronGrinderEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (spell != null && controller != null) {
|
if (spell != null && controller != null) {
|
||||||
|
// search the target that targets source
|
||||||
Target usedTarget = null;
|
Target usedTarget = null;
|
||||||
setUsedTarget:
|
setUsedTarget:
|
||||||
for (Mode mode : spell.getSpellAbility().getModes().getSelectedModes()) {
|
for (Ability ability : spell.getSpellAbilities()) {
|
||||||
for (Target target : mode.getTargets()) {
|
for (Mode mode : ability.getModes().getSelectedModes()) {
|
||||||
if (target.getFirstTarget().equals(source.getSourceId())) {
|
for (Target target : mode.getTargets()) {
|
||||||
usedTarget = target.copy();
|
if (!target.isNotTarget() && target.getFirstTarget().equals(source.getSourceId())) {
|
||||||
usedTarget.clearChosen();
|
usedTarget = target.copy();
|
||||||
break setUsedTarget;
|
usedTarget.clearChosen();
|
||||||
|
break setUsedTarget;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +182,7 @@ class ZadaHedronGrinderEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
for (Permanent creature : game.getState().getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) {
|
for (Permanent creature : game.getState().getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) {
|
||||||
if (!creature.getId().equals(source.getSourceId()) && usedTarget.canTarget(source.getControllerId(), creature.getId(), source, game)) {
|
if (!creature.getId().equals(source.getSourceId()) && usedTarget.canTarget(source.getControllerId(), creature.getId(), source, game)) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
setTarget:
|
setTarget:
|
||||||
for (Mode mode : spell.getSpellAbility().getModes().getSelectedModes()) {
|
for (Mode mode : spell.getSpellAbility().getModes().getSelectedModes()) {
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
|
|
@ -188,8 +195,6 @@ class ZadaHedronGrinderEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
String activateMessage = copy.getActivatedMessage(game);
|
String activateMessage = copy.getActivatedMessage(game);
|
||||||
if (activateMessage.startsWith(" casts ")) {
|
if (activateMessage.startsWith(" casts ")) {
|
||||||
|
|
|
||||||
|
|
@ -116,9 +116,7 @@ class RikuOfTwoReflectionsCopyEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());;
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ public class WildRicochet extends CardImpl {
|
||||||
super(ownerId, 139, "Wild Ricochet", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{2}{R}{R}");
|
super(ownerId, 139, "Wild Ricochet", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{2}{R}{R}");
|
||||||
this.expansionSetCode = "CMD";
|
this.expansionSetCode = "CMD";
|
||||||
|
|
||||||
|
|
||||||
// You may choose new targets for target instant or sorcery spell. Then copy that spell. You may choose new targets for the copy.
|
// You may choose new targets for target instant or sorcery spell. Then copy that spell. You may choose new targets for the copy.
|
||||||
this.getSpellAbility().addEffect(new WildRicochetEffect());
|
this.getSpellAbility().addEffect(new WildRicochetEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetStackObject(filter));
|
this.getSpellAbility().addTarget(new TargetStackObject(filter));
|
||||||
|
|
@ -96,9 +95,7 @@ class WildRicochetEffect extends OneShotEffect {
|
||||||
spell.chooseNewTargets(game, you.getId());
|
spell.chooseNewTargets(game, you.getId());
|
||||||
}
|
}
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());;
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
if (you != null && you.chooseUse(Outcome.Benefit, "Do you wish to choose new targets for the copied " + spell.getName() + "?", source, game)) {
|
if (you != null && you.chooseUse(Outcome.Benefit, "Do you wish to choose new targets for the copied " + spell.getName() + "?", source, game)) {
|
||||||
return copy.chooseNewTargets(game, you.getId());
|
return copy.chooseNewTargets(game, you.getId());
|
||||||
|
|
|
||||||
|
|
@ -30,18 +30,14 @@ package mage.sets.commander2014;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.ObjectColor;
|
import mage.ObjectColor;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.DelayedTriggeredAbility;
|
|
||||||
import mage.abilities.common.delayed.AtTheBeginOfYourNextUpkeepDelayedTriggeredAbility;
|
|
||||||
import mage.abilities.condition.LockedInCondition;
|
import mage.abilities.condition.LockedInCondition;
|
||||||
import mage.abilities.condition.common.MorbidCondition;
|
import mage.abilities.condition.common.MorbidCondition;
|
||||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||||
import mage.abilities.effects.Effect;
|
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.CastSourceTriggeredAbility;
|
import mage.abilities.effects.common.CastSourceTriggeredAbility;
|
||||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
|
@ -49,7 +45,6 @@ import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.game.stack.StackObject;
|
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
|
@ -69,7 +64,6 @@ public class MaliciousAffliction extends CardImpl {
|
||||||
super(ownerId, 25, "Malicious Affliction", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{B}{B}");
|
super(ownerId, 25, "Malicious Affliction", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{B}{B}");
|
||||||
this.expansionSetCode = "C14";
|
this.expansionSetCode = "C14";
|
||||||
|
|
||||||
|
|
||||||
// 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.
|
// 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.
|
||||||
Ability ability = new ConditionalTriggeredAbility(
|
Ability ability = new ConditionalTriggeredAbility(
|
||||||
new CastSourceTriggeredAbility(new CopySourceSpellEffect(), true),
|
new CastSourceTriggeredAbility(new CopySourceSpellEffect(), true),
|
||||||
|
|
@ -112,9 +106,7 @@ class CopySourceSpellEffect extends OneShotEffect {
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
Spell spell = game.getStack().getSpell(source.getSourceId());
|
Spell spell = game.getStack().getSpell(source.getSourceId());
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Spell spellCopy = spell.copySpell();
|
Spell spellCopy = spell.copySpell(source.getControllerId());;
|
||||||
spellCopy.setCopiedSpell(true);
|
|
||||||
spellCopy.setControllerId(source.getControllerId());
|
|
||||||
game.getStack().push(spellCopy);
|
game.getStack().push(spellCopy);
|
||||||
spellCopy.chooseNewTargets(game, controller.getId());
|
spellCopy.chooseNewTargets(game, controller.getId());
|
||||||
String activateMessage = spellCopy.getActivatedMessage(game);
|
String activateMessage = spellCopy.getActivatedMessage(game);
|
||||||
|
|
@ -132,4 +124,4 @@ class CopySourceSpellEffect extends OneShotEffect {
|
||||||
public CopySourceSpellEffect copy() {
|
public CopySourceSpellEffect copy() {
|
||||||
return new CopySourceSpellEffect(this);
|
return new CopySourceSpellEffect(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,6 @@
|
||||||
package mage.sets.darkascension;
|
package mage.sets.darkascension;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import mage.constants.CardType;
|
|
||||||
import mage.constants.Rarity;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
|
|
@ -38,7 +35,9 @@ import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.AttachEffect;
|
import mage.abilities.effects.common.AttachEffect;
|
||||||
import mage.abilities.keyword.EnchantAbility;
|
import mage.abilities.keyword.EnchantAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Rarity;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.FilterSpell;
|
import mage.filter.FilterSpell;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
|
|
@ -63,7 +62,6 @@ public class CurseOfEchoes extends CardImpl {
|
||||||
this.subtype.add("Aura");
|
this.subtype.add("Aura");
|
||||||
this.subtype.add("Curse");
|
this.subtype.add("Curse");
|
||||||
|
|
||||||
|
|
||||||
// Enchant player
|
// Enchant player
|
||||||
TargetPlayer auraTarget = new TargetPlayer();
|
TargetPlayer auraTarget = new TargetPlayer();
|
||||||
this.getSpellAbility().addTarget(auraTarget);
|
this.getSpellAbility().addTarget(auraTarget);
|
||||||
|
|
@ -149,13 +147,11 @@ class CurseOfEchoesEffect extends OneShotEffect {
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
String chooseMessage = "Copy target spell? You may choose new targets for the copy.";
|
String chooseMessage = "Copy target spell? You may choose new targets for the copy.";
|
||||||
for (UUID playerId: game.getPlayerList()) {
|
for (UUID playerId : game.getPlayerList()) {
|
||||||
if (!playerId.equals(spell.getControllerId())) {
|
if (!playerId.equals(spell.getControllerId())) {
|
||||||
Player player = game.getPlayer(playerId);
|
Player player = game.getPlayer(playerId);
|
||||||
if (player.chooseUse(Outcome.Copy, chooseMessage, source, game)) {
|
if (player.chooseUse(Outcome.Copy, chooseMessage, source, game)) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());;
|
||||||
copy.setControllerId(playerId);
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, playerId);
|
copy.chooseNewTargets(game, playerId);
|
||||||
}
|
}
|
||||||
|
|
@ -171,7 +167,7 @@ class CurseOfEchoesEffect extends OneShotEffect {
|
||||||
return new CurseOfEchoesEffect(this);
|
return new CurseOfEchoesEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText(Mode mode) {
|
public String getText(Mode mode) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("Copy target ").append(mode.getTargets().get(0).getTargetName()).append(". You may choose new targets for the copy");
|
sb.append("Copy target ").append(mode.getTargets().get(0).getTargetName()).append(". You may choose new targets for the copy");
|
||||||
|
|
|
||||||
|
|
@ -28,13 +28,12 @@
|
||||||
package mage.sets.darkascension;
|
package mage.sets.darkascension;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import mage.constants.*;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.keyword.FlashbackAbility;
|
import mage.abilities.keyword.FlashbackAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.*;
|
||||||
import mage.filter.FilterSpell;
|
import mage.filter.FilterSpell;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
|
|
@ -64,7 +63,6 @@ public class IncreasingVengeance extends CardImpl {
|
||||||
super(ownerId, 95, "Increasing Vengeance", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{R}{R}");
|
super(ownerId, 95, "Increasing Vengeance", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{R}{R}");
|
||||||
this.expansionSetCode = "DKA";
|
this.expansionSetCode = "DKA";
|
||||||
|
|
||||||
|
|
||||||
// Copy target instant or sorcery spell you control. If Increasing Vengeance was cast from a graveyard, copy that spell twice instead. You may choose new targets for the copies.
|
// Copy target instant or sorcery spell you control. If Increasing Vengeance was cast from a graveyard, copy that spell twice instead. You may choose new targets for the copies.
|
||||||
this.getSpellAbility().addEffect(new IncreasingVengeanceEffect());
|
this.getSpellAbility().addEffect(new IncreasingVengeanceEffect());
|
||||||
Target target = new TargetSpell(filter);
|
Target target = new TargetSpell(filter);
|
||||||
|
|
@ -101,18 +99,14 @@ class IncreasingVengeanceEffect extends OneShotEffect {
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
game.informPlayers(new StringBuilder(controller.getLogName()).append(copy.getActivatedMessage(game)).toString());
|
game.informPlayers(new StringBuilder(controller.getLogName()).append(copy.getActivatedMessage(game)).toString());
|
||||||
Spell sourceSpell = (Spell) game.getStack().getStackObject(source.getSourceId());
|
Spell sourceSpell = (Spell) game.getStack().getStackObject(source.getSourceId());
|
||||||
if (sourceSpell != null) {
|
if (sourceSpell != null) {
|
||||||
if (sourceSpell.getFromZone() == Zone.GRAVEYARD) {
|
if (sourceSpell.getFromZone() == Zone.GRAVEYARD) {
|
||||||
copy = spell.copySpell();
|
copy = spell.copySpell(source.getControllerId());
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
game.informPlayers(new StringBuilder(controller.getLogName()).append(copy.getActivatedMessage(game)).toString());
|
game.informPlayers(new StringBuilder(controller.getLogName()).append(copy.getActivatedMessage(game)).toString());
|
||||||
|
|
|
||||||
|
|
@ -52,11 +52,12 @@ import mage.target.TargetSpell;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author jeffwadsworth
|
* @author jeffwadsworth
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class MirrorSheen extends CardImpl {
|
public class MirrorSheen extends CardImpl {
|
||||||
|
|
||||||
private static final FilterSpell filter = new FilterSpell();
|
private static final FilterSpell filter = new FilterSpell();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(Predicates.or(new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY)));
|
filter.add(Predicates.or(new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY)));
|
||||||
filter.add(new TargetYouPredicate());
|
filter.add(new TargetYouPredicate());
|
||||||
|
|
@ -66,12 +67,11 @@ public class MirrorSheen extends CardImpl {
|
||||||
super(ownerId, 105, "Mirror Sheen", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{U/R}{U/R}");
|
super(ownerId, 105, "Mirror Sheen", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{U/R}{U/R}");
|
||||||
this.expansionSetCode = "EVE";
|
this.expansionSetCode = "EVE";
|
||||||
|
|
||||||
|
|
||||||
// {1}{UR}{UR}: Copy target instant or sorcery spell that targets you. You may choose new targets for the copy.
|
// {1}{UR}{UR}: Copy target instant or sorcery spell that targets you. You may choose new targets for the copy.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MirrorSheenEffect(), new ManaCostsImpl("{1}{U/R}{U/R}"));
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MirrorSheenEffect(), new ManaCostsImpl("{1}{U/R}{U/R}"));
|
||||||
ability.addTarget(new TargetSpell(filter));
|
ability.addTarget(new TargetSpell(filter));
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MirrorSheen(final MirrorSheen card) {
|
public MirrorSheen(final MirrorSheen card) {
|
||||||
|
|
@ -99,9 +99,7 @@ class MirrorSheenEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Spell spell = game.getStack().getSpell(source.getFirstTarget());
|
Spell spell = game.getStack().getSpell(source.getFirstTarget());
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
|
|
@ -144,4 +142,4 @@ class TargetYouPredicate implements ObjectPlayerPredicate<ObjectPlayer<StackObje
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "spell that targets you";
|
return "spell that targets you";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ public class ChainLightning extends CardImpl {
|
||||||
super(ownerId, 137, "Chain Lightning", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{R}");
|
super(ownerId, 137, "Chain Lightning", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{R}");
|
||||||
this.expansionSetCode = "LEG";
|
this.expansionSetCode = "LEG";
|
||||||
|
|
||||||
|
|
||||||
// Chain Lightning deals 3 damage to target creature or player. Then that player or that creature's controller may pay {R}{R}. If the player does, he or she may copy this spell and may choose a new target for that copy.
|
// Chain Lightning deals 3 damage to target creature or player. Then that player or that creature's controller may pay {R}{R}. If the player does, he or she may copy this spell and may choose a new target for that copy.
|
||||||
this.getSpellAbility().addEffect(new ChainLightningEffect());
|
this.getSpellAbility().addEffect(new ChainLightningEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
|
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
|
||||||
|
|
@ -69,21 +68,21 @@ public class ChainLightning extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChainLightningEffect extends OneShotEffect {
|
class ChainLightningEffect extends OneShotEffect {
|
||||||
|
|
||||||
ChainLightningEffect() {
|
ChainLightningEffect() {
|
||||||
super(Outcome.Damage);
|
super(Outcome.Damage);
|
||||||
this.staticText = "Chain Lightning deals 3 damage to target creature or player. Then that player or that creature's controller may pay {R}{R}. If the player does, he or she may copy this spell and may choose a new target for that copy.";
|
this.staticText = "Chain Lightning deals 3 damage to target creature or player. Then that player or that creature's controller may pay {R}{R}. If the player does, he or she may copy this spell and may choose a new target for that copy.";
|
||||||
}
|
}
|
||||||
|
|
||||||
ChainLightningEffect(final ChainLightningEffect effect) {
|
ChainLightningEffect(final ChainLightningEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChainLightningEffect copy() {
|
public ChainLightningEffect copy() {
|
||||||
return new ChainLightningEffect(this);
|
return new ChainLightningEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
|
@ -94,8 +93,7 @@ class ChainLightningEffect extends OneShotEffect {
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
player.damage(3, source.getSourceId(), game, false, true);
|
player.damage(3, source.getSourceId(), game, false, true);
|
||||||
affectedPlayer = player;
|
affectedPlayer = player;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
Permanent permanent = game.getPermanent(targetId);
|
Permanent permanent = game.getPermanent(targetId);
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
permanent.damage(3, source.getSourceId(), game, false, true);
|
permanent.damage(3, source.getSourceId(), game, false, true);
|
||||||
|
|
@ -108,9 +106,7 @@ class ChainLightningEffect extends OneShotEffect {
|
||||||
if (cost.pay(source, game, source.getSourceId(), affectedPlayer.getId(), false, null)) {
|
if (cost.pay(source, game, source.getSourceId(), affectedPlayer.getId(), false, null)) {
|
||||||
Spell spell = game.getStack().getSpell(source.getSourceId());
|
Spell spell = game.getStack().getSpell(source.getSourceId());
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(affectedPlayer.getId());
|
||||||
copy.setControllerId(affectedPlayer.getId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, affectedPlayer.getId());
|
copy.chooseNewTargets(game, affectedPlayer.getId());
|
||||||
game.informPlayers(affectedPlayer.getLogName() + " copies " + copy.getName() + ".");
|
game.informPlayers(affectedPlayer.getLogName() + " copies " + copy.getName() + ".");
|
||||||
|
|
|
||||||
|
|
@ -92,10 +92,8 @@ class ForkEffect extends OneShotEffect {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
copy.getColor(game).setRed(true);
|
copy.getColor(game).setRed(true);
|
||||||
copy.setControllerId(controller.getId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, controller.getId());
|
copy.chooseNewTargets(game, controller.getId());
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -135,9 +135,7 @@ class HiveMindEffect extends OneShotEffect {
|
||||||
if (spell != null && player != null) {
|
if (spell != null && player != null) {
|
||||||
for (UUID playerId : game.getState().getPlayersInRange(player.getId(), game)) {
|
for (UUID playerId : game.getState().getPlayersInRange(player.getId(), game)) {
|
||||||
if (!playerId.equals(spell.getControllerId())) {
|
if (!playerId.equals(spell.getControllerId())) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(playerId);
|
||||||
copy.setControllerId(playerId);
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, playerId);
|
copy.chooseNewTargets(game, playerId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,9 +111,7 @@ class PsychicRebuttalEffect extends OneShotEffect {
|
||||||
if (SpellMasteryCondition.getInstance().apply(game, source)
|
if (SpellMasteryCondition.getInstance().apply(game, source)
|
||||||
&& controller.chooseUse(Outcome.PlayForFree, "Copy " + stackObject.getName() + " (you may choose new targets for the copy)?", source, game)) {
|
&& controller.chooseUse(Outcome.PlayForFree, "Copy " + stackObject.getName() + " (you may choose new targets for the copy)?", source, game)) {
|
||||||
|
|
||||||
Spell copy = ((Spell) stackObject).copySpell();
|
Spell copy = ((Spell) stackObject).copySpell(source.getControllerId());
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ class ChainOfVaporEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
controller.moveCards(permanent, null, Zone.HAND, source, game);
|
controller.moveCards(permanent, Zone.HAND, source, game);
|
||||||
Player player = game.getPlayer(permanent.getControllerId());
|
Player player = game.getPlayer(permanent.getControllerId());
|
||||||
TargetControlledPermanent target = new TargetControlledPermanent(0, 1, new FilterControlledLandPermanent("a land to sacrifice (to be able to copy " + sourceObject.getName() + ")"), true);
|
TargetControlledPermanent target = new TargetControlledPermanent(0, 1, new FilterControlledLandPermanent("a land to sacrifice (to be able to copy " + sourceObject.getName() + ")"), true);
|
||||||
if (player.chooseTarget(Outcome.Sacrifice, target, source, game)) {
|
if (player.chooseTarget(Outcome.Sacrifice, target, source, game)) {
|
||||||
|
|
@ -103,9 +103,7 @@ class ChainOfVaporEffect extends OneShotEffect {
|
||||||
if (player.chooseUse(outcome, "Copy the spell?", source, game)) {
|
if (player.chooseUse(outcome, "Copy the spell?", source, game)) {
|
||||||
Spell spell = game.getStack().getSpell(source.getSourceId());
|
Spell spell = game.getStack().getSpell(source.getSourceId());
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(player.getId());
|
||||||
copy.setControllerId(player.getId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, player.getId());
|
copy.chooseNewTargets(game, player.getId());
|
||||||
String activateMessage = copy.getActivatedMessage(game);
|
String activateMessage = copy.getActivatedMessage(game);
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,6 @@
|
||||||
package mage.sets.riseoftheeldrazi;
|
package mage.sets.riseoftheeldrazi;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.constants.CardType;
|
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.Rarity;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Abilities;
|
import mage.abilities.Abilities;
|
||||||
import mage.abilities.AbilitiesImpl;
|
import mage.abilities.AbilitiesImpl;
|
||||||
|
|
@ -43,8 +39,11 @@ import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.CopyTargetSpellEffect;
|
import mage.abilities.effects.common.CopyTargetSpellEffect;
|
||||||
import mage.abilities.keyword.LevelUpAbility;
|
import mage.abilities.keyword.LevelUpAbility;
|
||||||
import mage.abilities.keyword.LevelerCardBuilder;
|
import mage.abilities.keyword.LevelerCardBuilder;
|
||||||
import mage.cards.CardImpl;
|
|
||||||
import mage.cards.LevelerCard;
|
import mage.cards.LevelerCard;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
import mage.filter.FilterSpell;
|
import mage.filter.FilterSpell;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
|
|
@ -132,9 +131,7 @@ class EchoMageEffect extends OneShotEffect {
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ import mage.target.TargetSpell;
|
||||||
public class MeletisCharlatan extends CardImpl {
|
public class MeletisCharlatan extends CardImpl {
|
||||||
|
|
||||||
private static final FilterSpell filter = new FilterSpell("instant or sorcery spell");
|
private static final FilterSpell filter = new FilterSpell("instant or sorcery spell");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(Predicates.or(
|
filter.add(Predicates.or(
|
||||||
new CardTypePredicate(CardType.INSTANT),
|
new CardTypePredicate(CardType.INSTANT),
|
||||||
|
|
@ -103,9 +104,7 @@ class MeletisCharlatanCopyTargetSpellEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
copy.setControllerId(spell.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, spell.getControllerId());
|
copy.chooseNewTargets(game, spell.getControllerId());
|
||||||
Player player = game.getPlayer(spell.getControllerId());
|
Player player = game.getPlayer(spell.getControllerId());
|
||||||
|
|
|
||||||
|
|
@ -119,4 +119,58 @@ public class CopySpellTest extends CardTestPlayerBase {
|
||||||
assertPermanentCount(playerA, "Pillarfield Ox", 0);
|
assertPermanentCount(playerA, "Pillarfield Ox", 0);
|
||||||
assertHandCount(playerA, 4); // 2 draw + 2 creatures returned to hand
|
assertHandCount(playerA, 4); // 2 draw + 2 creatures returned to hand
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not to be a bother, but I posted earlier about how Zada, Hedron Grinder
|
||||||
|
* 's interaction with splice is broken. I didn't get a response on whether
|
||||||
|
* or not the problem was being looked at. Zada SHOULD copy spliced effects
|
||||||
|
* (and currently doesn't) because spliced effects are put onto the spell
|
||||||
|
* before it is cast and therefore before Zada's ability triggers, e.g.
|
||||||
|
* Desperate Ritual spliced onto Into the Fray should generate 3 red mana
|
||||||
|
* for every creature i control.
|
||||||
|
*
|
||||||
|
* 702.46a Splice is a static ability that functions while a card is in your
|
||||||
|
* hand. “Splice onto [subtype] [cost]” means “You may reveal this card from
|
||||||
|
* your hand as you cast a [subtype] spell. If you do, copy this card’s text
|
||||||
|
* box onto that spell and pay [cost] as an additional cost to cast that
|
||||||
|
* spell.” Paying a card’s splice cost follows the rules for paying
|
||||||
|
* additional costs in rules 601.2b and 601.2e–g. 601.2b If the spell is
|
||||||
|
* modal the player announces the mode choice (see rule 700.2). If the
|
||||||
|
* player wishes to splice any cards onto the spell (see rule 702.46), he or
|
||||||
|
* she reveals those cards in his or her hand. 706.10. To copy a spell,
|
||||||
|
* activated ability, or triggered ability means to put a copy of it onto
|
||||||
|
* the stack; a copy of a spell isn’t cast and a copy of an activated
|
||||||
|
* ability isn’t activated. A copy of a spell or ability copies both the
|
||||||
|
* characteristics of the spell or ability and all decisions made for it,
|
||||||
|
* including modes, targets, the value of X, and additional or alternative
|
||||||
|
* costs. (See rule 601, “Casting Spells.”)
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void ZadaHedronGrinderAndSplicedSpell() {
|
||||||
|
// Draw a card.
|
||||||
|
// Splice onto Arcane {1}{U}
|
||||||
|
addCard(Zone.HAND, playerA, "Evermind", 1); // no costs
|
||||||
|
// Target creature attacks this turn if able.
|
||||||
|
// Splice onto Arcane {R}
|
||||||
|
addCard(Zone.HAND, playerA, "Into the Fray", 1); // Instant - Arcane - {U}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||||
|
|
||||||
|
// Whenever you cast an instant or sorcery spell that targets only Zada, Hedron Grinder,
|
||||||
|
// copy that spell for each other creature you control that the spell could target.
|
||||||
|
// Each copy targets a different one of those creatures.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Zada, Hedron Grinder", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox", 1);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Into the Fray", "Zada, Hedron Grinder");
|
||||||
|
setChoice(playerA, "Yes");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, "Into the Fray", 1);
|
||||||
|
assertHandCount(playerA, "Evermind", 1);
|
||||||
|
assertHandCount(playerA, 3); // Evermind + 1 card from Evermind spliced on cast Into the fray and 1 from the copied spell with splice
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification, are
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
* permitted provided that the following conditions are met:
|
* permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
* conditions and the following disclaimer.
|
* conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
* provided with the distribution.
|
* provided with the distribution.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
|
@ -20,12 +20,11 @@
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
* authors and should not be interpreted as representing official policies, either expressed
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package mage.abilities.effects.common;
|
package mage.abilities.effects.common;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -54,14 +53,15 @@ import mage.util.TargetAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author duncant
|
* @author duncant
|
||||||
|
* @param <T>
|
||||||
*/
|
*/
|
||||||
public abstract class CopySpellForEachItCouldTargetEffect<T extends MageItem> extends OneShotEffect {
|
public abstract class CopySpellForEachItCouldTargetEffect<T extends MageItem> extends OneShotEffect {
|
||||||
|
|
||||||
protected final FilterInPlay<T> filter;
|
protected final FilterInPlay<T> filter;
|
||||||
|
|
||||||
public CopySpellForEachItCouldTargetEffect(FilterInPlay<T> filter) {
|
public CopySpellForEachItCouldTargetEffect(FilterInPlay<T> filter) {
|
||||||
super(Outcome.Copy);
|
super(Outcome.Copy);
|
||||||
this.staticText = "copy the spell for each other "+filter.getMessage()+" that spell could target. Each copy targets a different one";
|
this.staticText = "copy the spell for each other " + filter.getMessage() + " that spell could target. Each copy targets a different one";
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,10 +71,12 @@ public abstract class CopySpellForEachItCouldTargetEffect<T extends MageItem> ex
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Spell getSpell(Game game, Ability source);
|
protected abstract Spell getSpell(Game game, Ability source);
|
||||||
|
|
||||||
protected abstract boolean changeTarget(Target target, Game game, Ability source);
|
protected abstract boolean changeTarget(Target target, Game game, Ability source);
|
||||||
|
|
||||||
protected abstract void modifyCopy(Spell copy, Game game, Ability source);
|
protected abstract void modifyCopy(Spell copy, Game game, Ability source);
|
||||||
|
|
||||||
protected void modifyCopy(Spell copy, T newTarget, Game game, Ability source){
|
protected void modifyCopy(Spell copy, T newTarget, Game game, Ability source) {
|
||||||
modifyCopy(copy, game, source);
|
modifyCopy(copy, game, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,18 +99,17 @@ public abstract class CopySpellForEachItCouldTargetEffect<T extends MageItem> ex
|
||||||
targetsToBeChanged.add(addr);
|
targetsToBeChanged.add(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetsToBeChanged.size() < 1) {
|
if (targetsToBeChanged.size() < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect objects that can be targeted
|
// collect objects that can be targeted
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
modifyCopy(copy, game, source);
|
modifyCopy(copy, game, source);
|
||||||
Target sampleTarget = targetsToBeChanged.iterator().next().getTarget(copy);
|
Target sampleTarget = targetsToBeChanged.iterator().next().getTarget(copy);
|
||||||
sampleTarget.setNotTarget(true);
|
sampleTarget.setNotTarget(true);
|
||||||
|
|
||||||
Map<UUID, Map<UUID, Spell>> playerTargetCopyMap = new HashMap<>();
|
Map<UUID, Map<UUID, Spell>> playerTargetCopyMap = new HashMap<>();
|
||||||
for (UUID objId : sampleTarget.possibleTargets(controller.getId(), game)) {
|
for (UUID objId : sampleTarget.possibleTargets(controller.getId(), game)) {
|
||||||
MageItem obj = game.getObject(objId);
|
MageItem obj = game.getObject(objId);
|
||||||
|
|
@ -116,9 +117,7 @@ public abstract class CopySpellForEachItCouldTargetEffect<T extends MageItem> ex
|
||||||
obj = game.getPlayer(objId);
|
obj = game.getPlayer(objId);
|
||||||
}
|
}
|
||||||
if (obj != null) {
|
if (obj != null) {
|
||||||
copy = spell.copySpell();
|
copy = spell.copySpell(source.getControllerId());
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
modifyCopy(copy, (T) obj, game, source);
|
modifyCopy(copy, (T) obj, game, source);
|
||||||
if (!filter.match((T) obj, game)) {
|
if (!filter.match((T) obj, game)) {
|
||||||
|
|
@ -174,7 +173,7 @@ public abstract class CopySpellForEachItCouldTargetEffect<T extends MageItem> ex
|
||||||
|
|
||||||
// shortcut if there's only one possible target remaining
|
// shortcut if there's only one possible target remaining
|
||||||
if (targetCopyMap.size() > 1
|
if (targetCopyMap.size() > 1
|
||||||
&& target.canChoose(spell.getId(), player.getId(), game)) {
|
&& target.canChoose(spell.getId(), player.getId(), game)) {
|
||||||
player.choose(Outcome.Neutral, target, spell.getId(), game);
|
player.choose(Outcome.Neutral, target, spell.getId(), game);
|
||||||
}
|
}
|
||||||
Collection<UUID> chosenIds = target.getTargets();
|
Collection<UUID> chosenIds = target.getTargets();
|
||||||
|
|
@ -205,8 +204,6 @@ public abstract class CopySpellForEachItCouldTargetEffect<T extends MageItem> ex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CompoundFilter<T extends MageItem> extends FilterImpl<T> implements FilterInPlay<T> {
|
class CompoundFilter<T extends MageItem> extends FilterImpl<T> implements FilterInPlay<T> {
|
||||||
|
|
||||||
protected final FilterInPlay<T> filterA;
|
protected final FilterInPlay<T> filterA;
|
||||||
|
|
@ -228,7 +225,7 @@ class CompoundFilter<T extends MageItem> extends FilterImpl<T> implements Filter
|
||||||
public boolean match(T obj, Game game) {
|
public boolean match(T obj, Game game) {
|
||||||
return (filterA == null
|
return (filterA == null
|
||||||
|| !filterA.match(obj, game))
|
|| !filterA.match(obj, game))
|
||||||
&& (filterB == null
|
&& (filterB == null
|
||||||
|| !filterB.match(obj, game));
|
|| !filterB.match(obj, game));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,36 +233,35 @@ class CompoundFilter<T extends MageItem> extends FilterImpl<T> implements Filter
|
||||||
public boolean match(T obj, UUID sourceId, UUID playerId, Game game) {
|
public boolean match(T obj, UUID sourceId, UUID playerId, Game game) {
|
||||||
return (filterA == null
|
return (filterA == null
|
||||||
|| !filterA.match(obj, sourceId, playerId, game))
|
|| !filterA.match(obj, sourceId, playerId, game))
|
||||||
&& (filterB == null
|
&& (filterB == null
|
||||||
|| !filterB.match(obj, sourceId, playerId, game));
|
|| !filterB.match(obj, sourceId, playerId, game));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundFilter copy() {
|
public CompoundFilter copy() {
|
||||||
return new CompoundFilter(filterA == null ? null : filterA.copy(),
|
return new CompoundFilter(filterA == null ? null : filterA.copy(),
|
||||||
filterB == null ? null : filterB.copy(),
|
filterB == null ? null : filterB.copy(),
|
||||||
message);
|
message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class TargetWithAdditionalFilter<T extends MageItem> extends TargetImpl {
|
class TargetWithAdditionalFilter<T extends MageItem> extends TargetImpl {
|
||||||
|
|
||||||
protected final FilterInPlay<T> additionalFilter;
|
protected final FilterInPlay<T> additionalFilter;
|
||||||
protected final Target originalTarget;
|
protected final Target originalTarget;
|
||||||
protected static final Integer minNumberOfTargets = null;
|
protected static final Integer minNumberOfTargets = null;
|
||||||
protected static final Integer maxNumberOfTargets = null;
|
protected static final Integer maxNumberOfTargets = null;
|
||||||
protected static final Zone zone = null;
|
protected static final Zone zone = null;
|
||||||
|
|
||||||
public TargetWithAdditionalFilter(final TargetWithAdditionalFilter target){
|
public TargetWithAdditionalFilter(final TargetWithAdditionalFilter target) {
|
||||||
this(target.originalTarget, target.additionalFilter, false);
|
this(target.originalTarget, target.additionalFilter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetWithAdditionalFilter(Target originalTarget, FilterInPlay<T> additionalFilter){
|
public TargetWithAdditionalFilter(Target originalTarget, FilterInPlay<T> additionalFilter) {
|
||||||
this(originalTarget, additionalFilter, false);
|
this(originalTarget, additionalFilter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetWithAdditionalFilter(Target originalTarget, FilterInPlay<T> additionalFilter, boolean notTarget){
|
public TargetWithAdditionalFilter(Target originalTarget, FilterInPlay<T> additionalFilter, boolean notTarget) {
|
||||||
originalTarget = originalTarget.copy();
|
originalTarget = originalTarget.copy();
|
||||||
originalTarget.clearChosen();
|
originalTarget.clearChosen();
|
||||||
this.originalTarget = originalTarget;
|
this.originalTarget = originalTarget;
|
||||||
|
|
@ -283,7 +279,7 @@ class TargetWithAdditionalFilter<T extends MageItem> extends TargetImpl {
|
||||||
public int getMaxNumberOfTargets() {
|
public int getMaxNumberOfTargets() {
|
||||||
return originalTarget.getMaxNumberOfTargets();
|
return originalTarget.getMaxNumberOfTargets();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMinNumberOfTargets(int minNumberOfTargets) {
|
public void setMinNumberOfTargets(int minNumberOfTargets) {
|
||||||
originalTarget.setMinNumberOfTargets(minNumberOfTargets);
|
originalTarget.setMinNumberOfTargets(minNumberOfTargets);
|
||||||
|
|
@ -305,57 +301,53 @@ class TargetWithAdditionalFilter<T extends MageItem> extends TargetImpl {
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
obj = game.getPlayer(id);
|
obj = game.getPlayer(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return obj != null
|
return obj != null
|
||||||
&& originalTarget.canTarget(id, game)
|
&& originalTarget.canTarget(id, game)
|
||||||
&& additionalFilter.match((T) obj, game);
|
&& additionalFilter.match((T) obj, game);
|
||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canTarget(UUID id, Ability source, Game game) {
|
public boolean canTarget(UUID id, Ability source, Game game) {
|
||||||
MageItem obj = game.getObject(id);
|
MageItem obj = game.getObject(id);
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
obj = game.getPlayer(id);
|
obj = game.getPlayer(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return obj != null
|
return obj != null
|
||||||
&& originalTarget.canTarget(id, source, game)
|
&& originalTarget.canTarget(id, source, game)
|
||||||
&& additionalFilter.match((T) obj, source.getSourceId(), source.getControllerId(), game);
|
&& additionalFilter.match((T) obj, source.getSourceId(), source.getControllerId(), game);
|
||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
|
public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
|
||||||
MageItem obj = game.getObject(id);
|
MageItem obj = game.getObject(id);
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
obj = game.getPlayer(id);
|
obj = game.getPlayer(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return obj != null
|
return obj != null
|
||||||
&& originalTarget.canTarget(controllerId, id, source, game)
|
&& originalTarget.canTarget(controllerId, id, source, game)
|
||||||
&& additionalFilter.match((T) obj, source.getSourceId(), controllerId, game);
|
&& additionalFilter.match((T) obj, source.getSourceId(), controllerId, game);
|
||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FilterInPlay<T> getFilter() {
|
public FilterInPlay<T> getFilter() {
|
||||||
return new CompoundFilter((FilterInPlay<T>) originalTarget.getFilter(), additionalFilter, originalTarget.getFilter().getMessage());
|
return new CompoundFilter((FilterInPlay<T>) originalTarget.getFilter(), additionalFilter, originalTarget.getFilter().getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||||
int remainingTargets = getNumberOfTargets() - targets.size();
|
int remainingTargets = getNumberOfTargets() - targets.size();
|
||||||
|
|
@ -371,19 +363,19 @@ class TargetWithAdditionalFilter<T extends MageItem> extends TargetImpl {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (!targets.containsKey(objId)
|
if (!targets.containsKey(objId)
|
||||||
&& obj != null
|
&& obj != null
|
||||||
&& additionalFilter.match((T) obj, sourceId, sourceControllerId, game)) {
|
&& additionalFilter.match((T) obj, sourceId, sourceControllerId, game)) {
|
||||||
count++;
|
count++;
|
||||||
if (count >= remainingTargets) {
|
if (count >= remainingTargets) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ClassCastException e) {}
|
} catch (ClassCastException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canChoose(UUID sourceControllerId, Game game) {
|
public boolean canChoose(UUID sourceControllerId, Game game) {
|
||||||
int remainingTargets = getNumberOfTargets() - targets.size();
|
int remainingTargets = getNumberOfTargets() - targets.size();
|
||||||
|
|
@ -399,19 +391,19 @@ class TargetWithAdditionalFilter<T extends MageItem> extends TargetImpl {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (!targets.containsKey(objId)
|
if (!targets.containsKey(objId)
|
||||||
&& obj != null
|
&& obj != null
|
||||||
&& additionalFilter.match((T) obj, game)) {
|
&& additionalFilter.match((T) obj, game)) {
|
||||||
count++;
|
count++;
|
||||||
if (count >= remainingTargets) {
|
if (count >= remainingTargets) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ClassCastException e) {}
|
} catch (ClassCastException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
|
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||||
Set<UUID> ret = new HashSet<>();
|
Set<UUID> ret = new HashSet<>();
|
||||||
|
|
@ -422,15 +414,15 @@ class TargetWithAdditionalFilter<T extends MageItem> extends TargetImpl {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (obj != null
|
if (obj != null
|
||||||
&& additionalFilter.match((T) obj, sourceId, sourceControllerId, game)) {
|
&& additionalFilter.match((T) obj, sourceId, sourceControllerId, game)) {
|
||||||
ret.add(id);
|
ret.add(id);
|
||||||
}
|
}
|
||||||
} catch (ClassCastException e) {}
|
} catch (ClassCastException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
||||||
Set<UUID> ret = new HashSet<>();
|
Set<UUID> ret = new HashSet<>();
|
||||||
|
|
@ -441,15 +433,15 @@ class TargetWithAdditionalFilter<T extends MageItem> extends TargetImpl {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (obj != null
|
if (obj != null
|
||||||
&& additionalFilter.match((T) obj, game)) {
|
&& additionalFilter.match((T) obj, game)) {
|
||||||
ret.add(id);
|
ret.add(id);
|
||||||
}
|
}
|
||||||
} catch (ClassCastException e) {}
|
} catch (ClassCastException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TargetWithAdditionalFilter copy() {
|
public TargetWithAdditionalFilter copy() {
|
||||||
return new TargetWithAdditionalFilter(this);
|
return new TargetWithAdditionalFilter(this);
|
||||||
|
|
@ -458,7 +450,7 @@ class TargetWithAdditionalFilter<T extends MageItem> extends TargetImpl {
|
||||||
@Override
|
@Override
|
||||||
public String getTargetedName(Game game) {
|
public String getTargetedName(Game game) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (UUID targetId: getTargets()) {
|
for (UUID targetId : getTargets()) {
|
||||||
MageObject object = game.getObject(targetId);
|
MageObject object = game.getObject(targetId);
|
||||||
if (object != null) {
|
if (object != null) {
|
||||||
sb.append(object.getLogName()).append(" ");
|
sb.append(object.getLogName()).append(" ");
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,7 @@ public class CopyTargetSpellEffect extends OneShotEffect {
|
||||||
spell = (Spell) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.STACK);
|
spell = (Spell) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.STACK);
|
||||||
}
|
}
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());;
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,7 @@ public class EpicEffect extends OneShotEffect {
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
StackObject stackObject = game.getStack().getStackObject(source.getId());
|
StackObject stackObject = game.getStack().getStackObject(source.getId());
|
||||||
Spell spell = (Spell) stackObject;
|
Spell spell = (Spell) stackObject;
|
||||||
spell = spell.copySpell();
|
spell = spell.copySpell(source.getControllerId());
|
||||||
spell.setCopiedSpell(true);
|
|
||||||
spell.setControllerId(source.getControllerId());
|
|
||||||
// Remove Epic effect from the spell
|
// Remove Epic effect from the spell
|
||||||
Effect epicEffect = null;
|
Effect epicEffect = null;
|
||||||
for (Effect effect : spell.getSpellAbility().getEffects()) {
|
for (Effect effect : spell.getSpellAbility().getEffects()) {
|
||||||
|
|
|
||||||
|
|
@ -292,9 +292,7 @@ class ConspireEffect extends OneShotEffect {
|
||||||
if (controller != null && conspiredSpell != null) {
|
if (controller != null && conspiredSpell != null) {
|
||||||
Card card = game.getCard(conspiredSpell.getSourceId());
|
Card card = game.getCard(conspiredSpell.getSourceId());
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
Spell copy = conspiredSpell.copySpell();
|
Spell copy = conspiredSpell.copySpell(source.getControllerId());
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
if (!game.isSimulation()) {
|
if (!game.isSimulation()) {
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,7 @@
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
* authors and should not be interpreted as representing official policies, either expressed
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package mage.abilities.keyword;
|
package mage.abilities.keyword;
|
||||||
|
|
||||||
import mage.MageObjectReference;
|
import mage.MageObjectReference;
|
||||||
|
|
@ -42,8 +41,6 @@ import mage.game.stack.Spell;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
import mage.watchers.common.GravestormWatcher;
|
import mage.watchers.common.GravestormWatcher;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author emerald000
|
* @author emerald000
|
||||||
|
|
@ -57,6 +54,7 @@ public class GravestormAbility extends TriggeredAbilityImpl {
|
||||||
private GravestormAbility(final GravestormAbility ability) {
|
private GravestormAbility(final GravestormAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GravestormAbility copy() {
|
public GravestormAbility copy() {
|
||||||
return new GravestormAbility(this);
|
return new GravestormAbility(this);
|
||||||
|
|
@ -84,7 +82,7 @@ public class GravestormAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return "Gravestorm <i>(When you cast this spell, copy it for each permanent put into a graveyard this turn. You may choose new targets for the copies.</i>)" ;
|
return "Gravestorm <i>(When you cast this spell, copy it for each permanent put into a graveyard this turn. You may choose new targets for the copies.</i>)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,9 +109,7 @@ class GravestormEffect extends OneShotEffect {
|
||||||
game.informPlayers("Gravestorm: " + spell.getName() + " will be copied " + gravestormCount + " time" + (gravestormCount > 1 ? "s" : ""));
|
game.informPlayers("Gravestorm: " + spell.getName() + " will be copied " + gravestormCount + " time" + (gravestormCount > 1 ? "s" : ""));
|
||||||
}
|
}
|
||||||
for (int i = 0; i < gravestormCount; i++) {
|
for (int i = 0; i < gravestormCount; i++) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -247,9 +247,7 @@ class ReplicateCopyEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
// create the copies
|
// create the copies
|
||||||
for (int i = 0; i < replicateCount; i++) {
|
for (int i = 0; i < replicateCount; i++) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
if (!game.isSimulation()) {
|
if (!game.isSimulation()) {
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,7 @@
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
* authors and should not be interpreted as representing official policies, either expressed
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package mage.abilities.keyword;
|
package mage.abilities.keyword;
|
||||||
|
|
||||||
import mage.MageObjectReference;
|
import mage.MageObjectReference;
|
||||||
|
|
@ -42,8 +41,6 @@ import mage.game.stack.Spell;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
import mage.watchers.common.CastSpellLastTurnWatcher;
|
import mage.watchers.common.CastSpellLastTurnWatcher;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Plopman
|
* @author Plopman
|
||||||
|
|
@ -57,6 +54,7 @@ public class StormAbility extends TriggeredAbilityImpl {
|
||||||
private StormAbility(final StormAbility ability) {
|
private StormAbility(final StormAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StormAbility copy() {
|
public StormAbility copy() {
|
||||||
return new StormAbility(this);
|
return new StormAbility(this);
|
||||||
|
|
@ -84,7 +82,7 @@ public class StormAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return "Storm <i>(When you cast this spell, copy it for each spell cast before it this turn. You may choose new targets for the copies.)</i>" ;
|
return "Storm <i>(When you cast this spell, copy it for each spell cast before it this turn. You may choose new targets for the copies.)</i>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,12 +106,10 @@ class StormEffect extends OneShotEffect {
|
||||||
Spell spell = (Spell) this.getValue("StormSpell");
|
Spell spell = (Spell) this.getValue("StormSpell");
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
if (!game.isSimulation()) {
|
if (!game.isSimulation()) {
|
||||||
game.informPlayers("Storm: " + spell.getLogName() + " will be copied " + stormCount + " time" + (stormCount > 1 ?"s":""));
|
game.informPlayers("Storm: " + spell.getLogName() + " will be copied " + stormCount + " time" + (stormCount > 1 ? "s" : ""));
|
||||||
}
|
}
|
||||||
for (int i = 0; i < stormCount; i++) {
|
for (int i = 0; i < stormCount; i++) {
|
||||||
Spell copy = spell.copySpell();
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
copy.setControllerId(source.getControllerId());
|
|
||||||
copy.setCopiedSpell(true);
|
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
copy.chooseNewTargets(game, source.getControllerId());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -139,10 +139,8 @@ public class Spell extends StackObjImpl implements Card {
|
||||||
payNoMana |= spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE);
|
payNoMana |= spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE);
|
||||||
if (ignoreAbility) {
|
if (ignoreAbility) {
|
||||||
ignoreAbility = false;
|
ignoreAbility = false;
|
||||||
} else {
|
} else if (!spellAbility.activate(game, payNoMana)) {
|
||||||
if (!spellAbility.activate(game, payNoMana)) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -630,9 +628,21 @@ public class Spell extends StackObjImpl implements Card {
|
||||||
return new Spell(this);
|
return new Spell(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Spell copySpell() {
|
public Spell copySpell(UUID newController) {
|
||||||
// replaced card.copy by copy (card content should no longer be changed)
|
Spell copy = new Spell(this.card, this.ability.copySpell(), this.controllerId, this.fromZone);
|
||||||
return new Spell(this.card, this.ability.copySpell(), this.controllerId, this.fromZone);
|
boolean firstDone = false;
|
||||||
|
for (SpellAbility spellAbility : this.getSpellAbilities()) {
|
||||||
|
if (!firstDone) {
|
||||||
|
firstDone = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SpellAbility newAbility = spellAbility.copy(); // e.g. spliced spell
|
||||||
|
newAbility.newId();
|
||||||
|
copy.addSpellAbility(newAbility);
|
||||||
|
}
|
||||||
|
copy.setCopy(true);
|
||||||
|
copy.setControllerId(newController);
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue