mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
Added framework method for copying a StackAbility without casting it.
Modified the effects doing so with the new method.
This commit is contained in:
parent
b9ab16d945
commit
8823839a42
34 changed files with 158 additions and 313 deletions
|
@ -419,7 +419,9 @@ public class SimulatedPlayer2 extends ComputerPlayer {
|
||||||
if (options.isEmpty()) {
|
if (options.isEmpty()) {
|
||||||
logger.debug("simulating -- triggered ability:" + ability);
|
logger.debug("simulating -- triggered ability:" + ability);
|
||||||
game.getStack().push(new StackAbility(ability, playerId));
|
game.getStack().push(new StackAbility(ability, playerId));
|
||||||
ability.activate(game, false);
|
if (ability.activate(game, false) && ability.isUsesStack()) {
|
||||||
|
game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability.getSourceId(), ability.getControllerId()));
|
||||||
|
}
|
||||||
game.applyEffects();
|
game.applyEffects();
|
||||||
game.getPlayers().resetPassed();
|
game.getPlayers().resetPassed();
|
||||||
} else {
|
} else {
|
||||||
|
@ -439,7 +441,9 @@ public class SimulatedPlayer2 extends ComputerPlayer {
|
||||||
protected void addAbilityNode(SimulationNode2 parent, Ability ability, int depth, Game game) {
|
protected void addAbilityNode(SimulationNode2 parent, Ability ability, int depth, Game game) {
|
||||||
Game sim = game.copy();
|
Game sim = game.copy();
|
||||||
sim.getStack().push(new StackAbility(ability, playerId));
|
sim.getStack().push(new StackAbility(ability, playerId));
|
||||||
ability.activate(sim, false);
|
if (ability.activate(sim, false) && ability.isUsesStack()) {
|
||||||
|
game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability.getSourceId(), ability.getControllerId()));
|
||||||
|
}
|
||||||
sim.applyEffects();
|
sim.applyEffects();
|
||||||
SimulationNode2 newNode = new SimulationNode2(parent, sim, depth, playerId);
|
SimulationNode2 newNode = new SimulationNode2(parent, sim, depth, playerId);
|
||||||
logger.debug("simulating -- node #:" + SimulationNode2.getCount() + " triggered ability option");
|
logger.debug("simulating -- node #:" + SimulationNode2.getCount() + " triggered ability option");
|
||||||
|
|
|
@ -47,6 +47,7 @@ import mage.choices.Choice;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.combat.CombatGroup;
|
import mage.game.combat.CombatGroup;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.stack.StackAbility;
|
import mage.game.stack.StackAbility;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
@ -168,6 +169,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer {
|
||||||
if (ability.isUsesStack()) {
|
if (ability.isUsesStack()) {
|
||||||
game.getStack().push(new StackAbility(ability, playerId));
|
game.getStack().push(new StackAbility(ability, playerId));
|
||||||
if (ability.activate(game, false)) {
|
if (ability.activate(game, false)) {
|
||||||
|
game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability.getSourceId(), ability.getControllerId()));
|
||||||
actionCount++;
|
actionCount++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
|
|
||||||
package mage.player.ai;
|
package mage.player.ai;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
import mage.abilities.TriggeredAbility;
|
import mage.abilities.TriggeredAbility;
|
||||||
|
@ -42,9 +44,6 @@ import mage.game.stack.StackAbility;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
|
@ -239,7 +238,9 @@ public class SimulatedPlayer extends ComputerPlayer {
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
logger.debug("simulating -- triggered ability:" + ability);
|
logger.debug("simulating -- triggered ability:" + ability);
|
||||||
game.getStack().push(new StackAbility(ability, playerId));
|
game.getStack().push(new StackAbility(ability, playerId));
|
||||||
ability.activate(game, false);
|
if (ability.activate(game, false) && ability.isUsesStack()) {
|
||||||
|
game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability.getSourceId(), ability.getControllerId()));
|
||||||
|
}
|
||||||
game.applyEffects();
|
game.applyEffects();
|
||||||
game.getPlayers().resetPassed();
|
game.getPlayers().resetPassed();
|
||||||
}
|
}
|
||||||
|
@ -258,6 +259,9 @@ public class SimulatedPlayer extends ComputerPlayer {
|
||||||
Game sim = game.copy();
|
Game sim = game.copy();
|
||||||
sim.getStack().push(new StackAbility(ability, playerId));
|
sim.getStack().push(new StackAbility(ability, playerId));
|
||||||
ability.activate(sim, false);
|
ability.activate(sim, false);
|
||||||
|
if (ability.activate(sim, false) && ability.isUsesStack()) {
|
||||||
|
game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability.getSourceId(), ability.getControllerId()));
|
||||||
|
}
|
||||||
sim.applyEffects();
|
sim.applyEffects();
|
||||||
SimulationNode newNode = new SimulationNode(parent, sim, playerId);
|
SimulationNode newNode = new SimulationNode(parent, sim, playerId);
|
||||||
logger.debug(indent(newNode.getDepth()) + "simulating -- node #:" + SimulationNode.getCount() + " triggered ability option");
|
logger.debug(indent(newNode.getDepth()) + "simulating -- node #:" + SimulationNode.getCount() + " triggered ability option");
|
||||||
|
|
|
@ -28,22 +28,18 @@
|
||||||
package mage.sets.alarareborn;
|
package mage.sets.alarareborn;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.common.CopyTargetSpellEffect;
|
||||||
import mage.abilities.effects.common.DoIfCostPaid;
|
import mage.abilities.effects.common.DoIfCostPaid;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
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;
|
||||||
import mage.filter.predicate.mageobject.MulticoloredPredicate;
|
import mage.filter.predicate.mageobject.MulticoloredPredicate;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.stack.Spell;
|
|
||||||
import mage.players.Player;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -65,8 +61,9 @@ public class ClovenCasting extends CardImpl {
|
||||||
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));
|
Effect effect = new CopyTargetSpellEffect();
|
||||||
|
effect.setText("copy that spell. You may choose new targets for the copy");
|
||||||
|
this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(effect, new GenericManaCost(1)), filter, true, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClovenCasting(final ClovenCasting card) {
|
public ClovenCasting(final ClovenCasting card) {
|
||||||
|
@ -78,38 +75,3 @@ public class ClovenCasting extends CardImpl {
|
||||||
return new ClovenCasting(this);
|
return new ClovenCasting(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClovenCastingEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
public ClovenCastingEffect() {
|
|
||||||
super(Outcome.Copy);
|
|
||||||
staticText = "copy that spell. You may choose new targets for the copy";
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClovenCastingEffect(final ClovenCastingEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
|
||||||
if (spell != null) {
|
|
||||||
Spell copy = spell.copySpell(source.getControllerId());
|
|
||||||
game.getStack().push(copy);
|
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
|
||||||
String activateMessage = copy.getActivatedMessage(game);
|
|
||||||
if (activateMessage.startsWith(" casts ")) {
|
|
||||||
activateMessage = activateMessage.substring(6);
|
|
||||||
}
|
|
||||||
game.informPlayers(player.getLogName() + " copies " + activateMessage);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClovenCastingEffect copy() {
|
|
||||||
return new ClovenCastingEffect(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ class ZadaHedronGrinderEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
game.fireEvent(new GameEvent(GameEvent.EventType.COPIED_STACKOBJECT, copy.getId(), spell.getId(), source.getControllerId()));
|
||||||
String activateMessage = copy.getActivatedMessage(game);
|
String activateMessage = copy.getActivatedMessage(game);
|
||||||
if (activateMessage.startsWith(" casts ")) {
|
if (activateMessage.startsWith(" casts ")) {
|
||||||
activateMessage = activateMessage.substring(6);
|
activateMessage = activateMessage.substring(6);
|
||||||
|
|
|
@ -29,17 +29,15 @@ package mage.sets.commander;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
|
||||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.common.CopyTargetSpellEffect;
|
||||||
import mage.abilities.effects.common.DoIfCostPaid;
|
import mage.abilities.effects.common.DoIfCostPaid;
|
||||||
import mage.abilities.effects.common.PutTokenOntoBattlefieldCopyTargetEffect;
|
import mage.abilities.effects.common.PutTokenOntoBattlefieldCopyTargetEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.SetTargetPointer;
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
@ -49,9 +47,6 @@ import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
import mage.filter.predicate.permanent.AnotherPredicate;
|
import mage.filter.predicate.permanent.AnotherPredicate;
|
||||||
import mage.filter.predicate.permanent.TokenPredicate;
|
import mage.filter.predicate.permanent.TokenPredicate;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.stack.Spell;
|
|
||||||
import mage.players.Player;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -82,10 +77,12 @@ public class RikuOfTwoReflections extends CardImpl {
|
||||||
this.toughness = new MageInt(2);
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
// Whenever you cast an instant or sorcery spell, you may pay {U}{R}. If you do, copy that spell. You may choose new targets for the copy.
|
// Whenever you cast an instant or sorcery spell, you may pay {U}{R}. If you do, copy that spell. You may choose new targets for the copy.
|
||||||
this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(new RikuOfTwoReflectionsCopyEffect(), new ManaCostsImpl("{U}{R}")), filter, false, true));
|
Effect effect = new CopyTargetSpellEffect();
|
||||||
|
effect.setText("copy that spell. You may choose new targets for the copy");
|
||||||
|
this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(effect, new ManaCostsImpl("{U}{R}")), filter, false, true));
|
||||||
|
|
||||||
// Whenever another nontoken creature enters the battlefield under your control, you may pay {G}{U}. If you do, put a token that's a copy of that creature onto the battlefield.
|
// Whenever another nontoken creature enters the battlefield under your control, you may pay {G}{U}. If you do, put a token that's a copy of that creature onto the battlefield.
|
||||||
Effect effect = new DoIfCostPaid(new PutTokenOntoBattlefieldCopyTargetEffect(),
|
effect = new DoIfCostPaid(new PutTokenOntoBattlefieldCopyTargetEffect(),
|
||||||
new ManaCostsImpl("{G}{U}"), "Put a token that's a copy of that creature onto the battlefield?");
|
new ManaCostsImpl("{G}{U}"), "Put a token that's a copy of that creature onto the battlefield?");
|
||||||
effect.setText("you may pay {G}{U}. If you do, put a token that's a copy of that creature onto the battlefield");
|
effect.setText("you may pay {G}{U}. If you do, put a token that's a copy of that creature onto the battlefield");
|
||||||
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, effect, filterPermanent, false, SetTargetPointer.PERMANENT, null));
|
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, effect, filterPermanent, false, SetTargetPointer.PERMANENT, null));
|
||||||
|
@ -100,38 +97,3 @@ public class RikuOfTwoReflections extends CardImpl {
|
||||||
return new RikuOfTwoReflections(this);
|
return new RikuOfTwoReflections(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RikuOfTwoReflectionsCopyEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
public RikuOfTwoReflectionsCopyEffect() {
|
|
||||||
super(Outcome.Copy);
|
|
||||||
staticText = "copy that spell. You may choose new targets for the copy";
|
|
||||||
}
|
|
||||||
|
|
||||||
public RikuOfTwoReflectionsCopyEffect(final RikuOfTwoReflectionsCopyEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
|
||||||
if (spell != null) {
|
|
||||||
Spell copy = spell.copySpell(source.getControllerId());;
|
|
||||||
game.getStack().push(copy);
|
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
|
||||||
String activateMessage = copy.getActivatedMessage(game);
|
|
||||||
if (activateMessage.startsWith(" casts ")) {
|
|
||||||
activateMessage = activateMessage.substring(6);
|
|
||||||
}
|
|
||||||
game.informPlayers(player.getLogName() + " copies " + activateMessage);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RikuOfTwoReflectionsCopyEffect copy() {
|
|
||||||
return new RikuOfTwoReflectionsCopyEffect(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -28,18 +28,15 @@
|
||||||
package mage.sets.commander;
|
package mage.sets.commander;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.common.ChooseNewTargetsTargetEffect;
|
||||||
|
import mage.abilities.effects.common.CopyTargetSpellEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.filter.FilterStackObject;
|
import mage.filter.FilterStackObject;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.stack.Spell;
|
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.TargetStackObject;
|
import mage.target.TargetStackObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,9 +58,11 @@ public class WildRicochet extends CardImpl {
|
||||||
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 ChooseNewTargetsTargetEffect());
|
||||||
|
Effect effect = new CopyTargetSpellEffect();
|
||||||
|
effect.setText("Then copy that spell. You may choose new targets for the copy");
|
||||||
|
this.getSpellAbility().addEffect(effect);
|
||||||
this.getSpellAbility().addTarget(new TargetStackObject(filter));
|
this.getSpellAbility().addTarget(new TargetStackObject(filter));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public WildRicochet(final WildRicochet card) {
|
public WildRicochet(final WildRicochet card) {
|
||||||
|
@ -75,37 +74,3 @@ public class WildRicochet extends CardImpl {
|
||||||
return new WildRicochet(this);
|
return new WildRicochet(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WildRicochetEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
public WildRicochetEffect() {
|
|
||||||
super(Outcome.Neutral);
|
|
||||||
staticText = "You may choose new targets for target instant or sorcery spell. Then copy that spell. You may choose new targets for the copy";
|
|
||||||
}
|
|
||||||
|
|
||||||
public WildRicochetEffect(final WildRicochetEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Spell spell = game.getStack().getSpell(source.getFirstTarget());
|
|
||||||
Player you = game.getPlayer(source.getControllerId());
|
|
||||||
if (spell != null && you != null && you.chooseUse(Outcome.Benefit, "Do you wish to choose new targets for " + spell.getName() + "?", source, game)) {
|
|
||||||
spell.chooseNewTargets(game, you.getId());
|
|
||||||
}
|
|
||||||
if (spell != null) {
|
|
||||||
Spell copy = spell.copySpell(source.getControllerId());;
|
|
||||||
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)) {
|
|
||||||
return copy.chooseNewTargets(game, you.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WildRicochetEffect copy() {
|
|
||||||
return new WildRicochetEffect(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ 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;
|
||||||
|
|
||||||
|
@ -106,14 +107,14 @@ 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(source.getControllerId());;
|
StackObject stackObjectCopy = spell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
game.getStack().push(spellCopy);
|
if (stackObjectCopy != null && stackObjectCopy instanceof Spell) {
|
||||||
spellCopy.chooseNewTargets(game, controller.getId());
|
String activateMessage = ((Spell) stackObjectCopy).getActivatedMessage(game);
|
||||||
String activateMessage = spellCopy.getActivatedMessage(game);
|
if (activateMessage.startsWith(" casts ")) {
|
||||||
if (activateMessage.startsWith(" casts ")) {
|
activateMessage = activateMessage.substring(6);
|
||||||
activateMessage = activateMessage.substring(6);
|
}
|
||||||
|
game.informPlayers(controller.getLogName() + " copies " + activateMessage);
|
||||||
}
|
}
|
||||||
game.informPlayers(controller.getLogName() + " copies " + activateMessage);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,9 +151,7 @@ class CurseOfEchoesEffect extends OneShotEffect {
|
||||||
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(source.getControllerId());
|
spell.createCopyOnStack(game, source, player.getId(), true);
|
||||||
game.getStack().push(copy);
|
|
||||||
copy.chooseNewTargets(game, playerId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||||
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.Target;
|
import mage.target.Target;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
@ -99,17 +100,17 @@ 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(source.getControllerId());
|
StackObject stackObjectCopy = spell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
game.getStack().push(copy);
|
if (stackObjectCopy != null && stackObjectCopy instanceof Spell) {
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
game.informPlayers(new StringBuilder(controller.getLogName()).append(((Spell) stackObjectCopy).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(source.getControllerId());
|
stackObjectCopy = spell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
game.getStack().push(copy);
|
if (stackObjectCopy != null && stackObjectCopy instanceof Spell) {
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
game.informPlayers(new StringBuilder(controller.getLogName()).append(((Spell) stackObjectCopy).getActivatedMessage(game)).toString());
|
||||||
game.informPlayers(new StringBuilder(controller.getLogName()).append(copy.getActivatedMessage(game)).toString());
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -31,10 +31,9 @@ import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.common.CopyTargetSpellEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.FilterSpell;
|
import mage.filter.FilterSpell;
|
||||||
|
@ -43,9 +42,7 @@ import mage.filter.predicate.ObjectPlayerPredicate;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.stack.Spell;
|
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
|
@ -56,7 +53,7 @@ import mage.target.TargetSpell;
|
||||||
*/
|
*/
|
||||||
public class MirrorSheen extends CardImpl {
|
public class MirrorSheen extends CardImpl {
|
||||||
|
|
||||||
private static final FilterSpell filter = new FilterSpell();
|
private static final FilterSpell filter = new FilterSpell("instant or sorcery spell that targets you");
|
||||||
|
|
||||||
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)));
|
||||||
|
@ -68,7 +65,7 @@ public class MirrorSheen extends CardImpl {
|
||||||
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 CopyTargetSpellEffect(), new ManaCostsImpl("{1}{U/R}{U/R}"));
|
||||||
ability.addTarget(new TargetSpell(filter));
|
ability.addTarget(new TargetSpell(filter));
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
@ -84,41 +81,6 @@ public class MirrorSheen extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MirrorSheenEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
public MirrorSheenEffect() {
|
|
||||||
super(Outcome.Copy);
|
|
||||||
staticText = "Copy target instant or sorcery spell that targets you. You may choose new targets for the copy";
|
|
||||||
}
|
|
||||||
|
|
||||||
public MirrorSheenEffect(final MirrorSheenEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Spell spell = game.getStack().getSpell(source.getFirstTarget());
|
|
||||||
if (spell != null) {
|
|
||||||
Spell copy = spell.copySpell(source.getControllerId());
|
|
||||||
game.getStack().push(copy);
|
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
|
||||||
String activateMessage = copy.getActivatedMessage(game);
|
|
||||||
if (activateMessage.startsWith(" casts ")) {
|
|
||||||
activateMessage = activateMessage.substring(6);
|
|
||||||
}
|
|
||||||
game.informPlayers(player.getLogName() + " copies " + activateMessage);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MirrorSheenEffect copy() {
|
|
||||||
return new MirrorSheenEffect(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TargetYouPredicate implements ObjectPlayerPredicate<ObjectPlayer<StackObject>> {
|
class TargetYouPredicate implements ObjectPlayerPredicate<ObjectPlayer<StackObject>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -102,7 +102,7 @@ class AbilityActivatedTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
|
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
|
||||||
if (!(stackAbility.getStackAbility() instanceof ManaAbility)) {
|
if (!(stackAbility.getStackAbility() instanceof ManaAbility)) {
|
||||||
Effect effect = this.getEffects().get(0);
|
Effect effect = this.getEffects().get(0);
|
||||||
effect.setValue("stackAbility", stackAbility.getStackAbility());
|
effect.setValue("stackAbility", stackAbility);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,21 +133,11 @@ class CopyActivatedAbilityEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Ability ability = (Ability) getValue("stackAbility");
|
StackAbility ability = (StackAbility) getValue("stackAbility");
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||||
if (ability != null && controller != null && sourcePermanent != null) {
|
if (ability != null && controller != null && sourcePermanent != null) {
|
||||||
Ability newAbility = ability.copy();
|
ability.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
newAbility.newId();
|
|
||||||
game.getStack().push(new StackAbility(newAbility, source.getControllerId()));
|
|
||||||
if (newAbility.getTargets().size() > 0) {
|
|
||||||
if (controller.chooseUse(newAbility.getEffects().get(0).getOutcome(), "Choose new targets?", source, game)) {
|
|
||||||
newAbility.getTargets().clearChosen();
|
|
||||||
if (newAbility.getTargets().chooseTargets(newAbility.getEffects().get(0).getOutcome(), source.getControllerId(), newAbility, false, game) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied activated ability").toString());
|
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied activated ability").toString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,10 +106,8 @@ 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(affectedPlayer.getId());
|
spell.createCopyOnStack(game, source, affectedPlayer.getId(), true);
|
||||||
game.getStack().push(copy);
|
game.informPlayers(affectedPlayer.getLogName() + " copies " + spell.getName() + ".");
|
||||||
copy.chooseNewTargets(game, affectedPlayer.getId());
|
|
||||||
game.informPlayers(affectedPlayer.getLogName() + " copies " + copy.getName() + ".");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ 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;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
@ -96,6 +97,7 @@ class ForkEffect extends OneShotEffect {
|
||||||
copy.getColor(game).setRed(true);
|
copy.getColor(game).setRed(true);
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
copy.chooseNewTargets(game, controller.getId());
|
copy.chooseNewTargets(game, controller.getId());
|
||||||
|
game.fireEvent(new GameEvent(GameEvent.EventType.COPIED_STACKOBJECT, copy.getId(), spell.getId(), source.getControllerId()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -96,7 +96,7 @@ class RingsOfBrighthearthTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
|
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
|
||||||
if (stackAbility != null && !(stackAbility.getStackAbility() instanceof ManaAbility)) {
|
if (stackAbility != null && !(stackAbility.getStackAbility() instanceof ManaAbility)) {
|
||||||
Effect effect = this.getEffects().get(0);
|
Effect effect = this.getEffects().get(0);
|
||||||
effect.setValue("stackAbility", stackAbility.getStackAbility());
|
effect.setValue("stackAbility", stackAbility);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,21 +132,11 @@ class RingsOfBrighthearthEffect extends OneShotEffect {
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
if (player.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + "? If you do, copy that ability. You may choose new targets for the copy.", source, game)) {
|
if (player.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + "? If you do, copy that ability. You may choose new targets for the copy.", source, game)) {
|
||||||
if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) {
|
if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) {
|
||||||
Ability ability = (Ability) getValue("stackAbility");
|
StackAbility ability = (StackAbility) getValue("stackAbility");
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||||
if (ability != null && controller != null) {
|
if (ability != null && controller != null) {
|
||||||
Ability newAbility = ability.copy();
|
ability.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
newAbility.newId();
|
|
||||||
game.getStack().push(new StackAbility(newAbility, source.getControllerId()));
|
|
||||||
if (newAbility.getTargets().size() > 0) {
|
|
||||||
if (controller.chooseUse(newAbility.getEffects().get(0).getOutcome(), "Choose new targets?", source, game)) {
|
|
||||||
newAbility.getTargets().clearChosen();
|
|
||||||
if (newAbility.getTargets().chooseTargets(newAbility.getEffects().get(0).getOutcome(), source.getControllerId(), newAbility, false, game) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied activated ability").toString());
|
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied activated ability").toString());
|
||||||
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(playerId);
|
spell.createCopyOnStack(game, source, playerId, true);
|
||||||
game.getStack().push(copy);
|
|
||||||
copy.chooseNewTargets(game, playerId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -92,21 +92,10 @@ class StrionicResonatorEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(targetPointer.getFirst(game, source));
|
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(targetPointer.getFirst(game, source));
|
||||||
if (stackAbility != null) {
|
if (stackAbility != null) {
|
||||||
Ability ability = (Ability) stackAbility.getStackAbility();
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||||
if (ability != null && controller != null && sourcePermanent != null) {
|
if (controller != null && sourcePermanent != null) {
|
||||||
Ability newAbility = ability.copy();
|
stackAbility.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
newAbility.newId();
|
|
||||||
game.getStack().push(new StackAbility(newAbility, source.getControllerId()));
|
|
||||||
if (newAbility.getTargets().size() > 0) {
|
|
||||||
if (controller.chooseUse(newAbility.getEffects().get(0).getOutcome(), "Choose new targets?", source, game)) {
|
|
||||||
newAbility.getTargets().clearChosen();
|
|
||||||
if (newAbility.getTargets().chooseTargets(newAbility.getEffects().get(0).getOutcome(), source.getControllerId(), newAbility, false, game) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied activated ability").toString());
|
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied activated ability").toString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ class KurkeshOnakkeAncientTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
|
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
|
||||||
if (!(stackAbility.getStackAbility() instanceof ManaAbility)) {
|
if (!(stackAbility.getStackAbility() instanceof ManaAbility)) {
|
||||||
Effect effect = this.getEffects().get(0);
|
Effect effect = this.getEffects().get(0);
|
||||||
effect.setValue("stackAbility", stackAbility.getStackAbility());
|
effect.setValue("stackAbility", stackAbility);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,21 +144,11 @@ class KurkeshOnakkeAncientEffect extends OneShotEffect {
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
if (player.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + "? If you do, copy that ability. You may choose new targets for the copy.", source, game)) {
|
if (player.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + "? If you do, copy that ability. You may choose new targets for the copy.", source, game)) {
|
||||||
if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) {
|
if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) {
|
||||||
Ability ability = (Ability) getValue("stackAbility");
|
StackAbility ability = (StackAbility) getValue("stackAbility");
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||||
if (ability != null && controller != null) {
|
if (ability != null && controller != null) {
|
||||||
Ability newAbility = ability.copy();
|
ability.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
newAbility.newId();
|
|
||||||
game.getStack().push(new StackAbility(newAbility, source.getControllerId()));
|
|
||||||
if (newAbility.getTargets().size() > 0) {
|
|
||||||
if (controller.chooseUse(newAbility.getEffects().get(0).getOutcome(), "Choose new targets?", source, game)) {
|
|
||||||
newAbility.getTargets().clearChosen();
|
|
||||||
if (newAbility.getTargets().chooseTargets(newAbility.getEffects().get(0).getOutcome(), source.getControllerId(), newAbility, false, game) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied activated ability").toString());
|
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied activated ability").toString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,22 +104,21 @@ class PsychicRebuttalEffect extends OneShotEffect {
|
||||||
if (controller == null) {
|
if (controller == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
StackObject stackObject = game.getState().getStack().getStackObject(getTargetPointer().getFirst(game, source));
|
Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source));
|
||||||
if (stackObject != null) {
|
if (spell != null) {
|
||||||
game.getStack().counter(stackObject.getId(), source.getSourceId(), game);
|
game.getStack().counter(spell.getId(), source.getSourceId(), game);
|
||||||
|
|
||||||
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 " + spell.getName() + " (you may choose new targets for the copy)?", source, game)) {
|
||||||
|
|
||||||
Spell copy = ((Spell) stackObject).copySpell(source.getControllerId());
|
StackObject newStackObject = spell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
game.getStack().push(copy);
|
if (newStackObject != null && newStackObject instanceof Spell) {
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
String activateMessage = ((Spell) newStackObject).getActivatedMessage(game);
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
if (activateMessage.startsWith(" casts ")) {
|
||||||
String activateMessage = copy.getActivatedMessage(game);
|
activateMessage = activateMessage.substring(6);
|
||||||
if (activateMessage.startsWith(" casts ")) {
|
}
|
||||||
activateMessage = activateMessage.substring(6);
|
game.informPlayers(controller.getLogName() + activateMessage);
|
||||||
}
|
}
|
||||||
game.informPlayers(player.getLogName() + activateMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -41,6 +41,7 @@ import mage.filter.common.FilterControlledLandPermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
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.TargetControlledPermanent;
|
import mage.target.common.TargetControlledPermanent;
|
||||||
import mage.target.common.TargetNonlandPermanent;
|
import mage.target.common.TargetNonlandPermanent;
|
||||||
|
@ -103,14 +104,14 @@ 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(player.getId());
|
StackObject newStackObject = spell.createCopyOnStack(game, source, player.getId(), true);
|
||||||
game.getStack().push(copy);
|
if (newStackObject != null && newStackObject instanceof Spell) {
|
||||||
copy.chooseNewTargets(game, player.getId());
|
String activateMessage = ((Spell) newStackObject).getActivatedMessage(game);
|
||||||
String activateMessage = copy.getActivatedMessage(game);
|
if (activateMessage.startsWith(" casts ")) {
|
||||||
if (activateMessage.startsWith(" casts ")) {
|
activateMessage = activateMessage.substring(6);
|
||||||
activateMessage = activateMessage.substring(6);
|
}
|
||||||
|
game.informPlayers(player.getLogName() + " " + activateMessage);
|
||||||
}
|
}
|
||||||
game.informPlayers(player.getLogName() + " " + activateMessage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,11 +130,8 @@ class EchoMageEffect 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) {
|
||||||
for (int i = 0; i < 2; i++) {
|
spell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
Spell copy = spell.copySpell(source.getControllerId());
|
spell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
game.getStack().push(copy);
|
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -44,6 +44,7 @@ import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
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.Target;
|
import mage.target.Target;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
@ -104,15 +105,15 @@ 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(source.getControllerId());
|
StackObject newStackObject = spell.createCopyOnStack(game, source, spell.getControllerId(), true);
|
||||||
game.getStack().push(copy);
|
|
||||||
copy.chooseNewTargets(game, spell.getControllerId());
|
|
||||||
Player player = game.getPlayer(spell.getControllerId());
|
Player player = game.getPlayer(spell.getControllerId());
|
||||||
String activateMessage = copy.getActivatedMessage(game);
|
if (player != null && newStackObject != null && newStackObject instanceof Spell) {
|
||||||
if (activateMessage.startsWith(" casts ")) {
|
String activateMessage = ((Spell) newStackObject).getActivatedMessage(game);
|
||||||
activateMessage = activateMessage.substring(6);
|
if (activateMessage.startsWith(" casts ")) {
|
||||||
|
activateMessage = activateMessage.substring(6);
|
||||||
|
}
|
||||||
|
game.informPlayers(player.getLogName() + " copies " + activateMessage);
|
||||||
}
|
}
|
||||||
game.informPlayers(player.getLogName() + " copies " + activateMessage);;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -48,6 +48,7 @@ import mage.constants.Outcome;
|
||||||
import mage.constants.RangeOfInfluence;
|
import mage.constants.RangeOfInfluence;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.combat.CombatGroup;
|
import mage.game.combat.CombatGroup;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.stack.StackAbility;
|
import mage.game.stack.StackAbility;
|
||||||
import mage.player.ai.ComputerPlayer;
|
import mage.player.ai.ComputerPlayer;
|
||||||
|
@ -173,6 +174,7 @@ public class RandomPlayer extends ComputerPlayer {
|
||||||
if (ability.isUsesStack()) {
|
if (ability.isUsesStack()) {
|
||||||
game.getStack().push(new StackAbility(ability, playerId));
|
game.getStack().push(new StackAbility(ability, playerId));
|
||||||
if (ability.activate(game, false)) {
|
if (ability.activate(game, false)) {
|
||||||
|
game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability.getSourceId(), ability.getControllerId()));
|
||||||
actionCount++;
|
actionCount++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,16 +58,16 @@ 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(source.getControllerId());;
|
StackObject newStackObject = spell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
game.getStack().push(copy);
|
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
String activateMessage = copy.getActivatedMessage(game);
|
if (player != null && newStackObject != null && newStackObject instanceof Spell) {
|
||||||
if (activateMessage.startsWith(" casts ")) {
|
String activateMessage = ((Spell) newStackObject).getActivatedMessage(game);
|
||||||
activateMessage = activateMessage.substring(6);
|
if (activateMessage.startsWith(" casts ")) {
|
||||||
}
|
activateMessage = activateMessage.substring(6);
|
||||||
if (!game.isSimulation()) {
|
}
|
||||||
game.informPlayers(player.getLogName() + activateMessage);
|
if (!game.isSimulation()) {
|
||||||
|
game.informPlayers(player.getLogName() + activateMessage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,10 +140,7 @@ class EpicPushEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
// don't change the targets of the in the origin copied spell
|
spell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
Spell copySpell = spell.copy();
|
|
||||||
game.getStack().push(copySpell);
|
|
||||||
copySpell.chooseNewTargets(game, source.getControllerId());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ import mage.filter.predicate.permanent.TappedPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
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.TargetControlledPermanent;
|
import mage.target.common.TargetControlledPermanent;
|
||||||
|
|
||||||
|
@ -292,11 +293,9 @@ 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(source.getControllerId());
|
StackObject newStackObject = conspiredSpell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
game.getStack().push(copy);
|
if (newStackObject != null && newStackObject instanceof Spell && !game.isSimulation()) {
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
game.informPlayers(controller.getLogName() + ((Spell) newStackObject).getActivatedMessage(game));
|
||||||
if (!game.isSimulation()) {
|
|
||||||
game.informPlayers(controller.getLogName() + copy.getActivatedMessage(game));
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,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(source.getControllerId());
|
spell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
game.getStack().push(copy);
|
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,11 +247,9 @@ 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(source.getControllerId());
|
StackObject newStackObject = spell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
game.getStack().push(copy);
|
if (newStackObject != null && newStackObject instanceof Spell && !game.isSimulation()) {
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
game.informPlayers(controller.getLogName() + ((Spell) newStackObject).getActivatedMessage(game));
|
||||||
if (!game.isSimulation()) {
|
|
||||||
game.informPlayers(controller.getLogName() + copy.getActivatedMessage(game));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -109,9 +109,7 @@ class StormEffect extends OneShotEffect {
|
||||||
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(source.getControllerId());
|
spell.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
game.getStack().push(copy);
|
|
||||||
copy.chooseNewTargets(game, source.getControllerId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,6 +125,8 @@ public class GameEvent implements Serializable {
|
||||||
*/
|
*/
|
||||||
SPELL_CAST,
|
SPELL_CAST,
|
||||||
ACTIVATE_ABILITY, ACTIVATED_ABILITY,
|
ACTIVATE_ABILITY, ACTIVATED_ABILITY,
|
||||||
|
TRIGGERED_ABILITY,
|
||||||
|
COPIED_STACKOBJECT,
|
||||||
/* ADD_MANA
|
/* ADD_MANA
|
||||||
targetId id of the ability that added the mana
|
targetId id of the ability that added the mana
|
||||||
sourceId sourceId of the ability that added the mana
|
sourceId sourceId of the ability that added the mana
|
||||||
|
|
|
@ -56,6 +56,8 @@ import mage.constants.ZoneDetail;
|
||||||
import mage.counters.Counter;
|
import mage.counters.Counter;
|
||||||
import mage.counters.Counters;
|
import mage.counters.Counters;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.events.GameEvent.EventType;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
import mage.game.events.ZoneChangeEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.PermanentCard;
|
import mage.game.permanent.PermanentCard;
|
||||||
|
@ -873,4 +875,14 @@ public class Spell extends StackObjImpl implements Card {
|
||||||
throw new UnsupportedOperationException("Not supported for Spell");
|
throw new UnsupportedOperationException("Not supported for Spell");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StackObject createCopyOnStack(Game game, Ability source, UUID newControllerId, boolean chooseNewTargets) {
|
||||||
|
Spell copy = this.copySpell(newControllerId);
|
||||||
|
game.getStack().push(copy);
|
||||||
|
if (chooseNewTargets) {
|
||||||
|
copy.chooseNewTargets(game, newControllerId);
|
||||||
|
}
|
||||||
|
game.fireEvent(new GameEvent(EventType.COPIED_STACKOBJECT, copy.getId(), this.getId(), newControllerId));
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -580,4 +580,21 @@ public class StackAbility extends StackObjImpl implements Ability {
|
||||||
public void setCanFizzle(boolean canFizzle) {
|
public void setCanFizzle(boolean canFizzle) {
|
||||||
throw new UnsupportedOperationException("Not supported.");
|
throw new UnsupportedOperationException("Not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StackObject createCopyOnStack(Game game, Ability source, UUID newControllerId, boolean chooseNewTargets) {
|
||||||
|
Ability newAbility = this.copy();
|
||||||
|
newAbility.newId();
|
||||||
|
StackAbility newStackAbility = new StackAbility(newAbility, newControllerId);
|
||||||
|
game.getStack().push(newStackAbility);
|
||||||
|
if (chooseNewTargets && newAbility.getTargets().size() > 0) {
|
||||||
|
Player controller = game.getPlayer(newControllerId);
|
||||||
|
if (controller.chooseUse(newAbility.getEffects().get(0).getOutcome(), "Choose new targets?", source, game)) {
|
||||||
|
newAbility.getTargets().clearChosen();
|
||||||
|
newAbility.getTargets().chooseTargets(newAbility.getEffects().get(0).getOutcome(), newControllerId, newAbility, false, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
game.fireEvent(new GameEvent(GameEvent.EventType.COPIED_STACKOBJECT, newStackAbility.getId(), this.getId(), newControllerId));
|
||||||
|
return newStackAbility;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,8 @@ public interface StackObject extends MageObject, Controllable {
|
||||||
|
|
||||||
// int getConvertedManaCost();
|
// int getConvertedManaCost();
|
||||||
boolean chooseNewTargets(Game game, UUID playerId, boolean forceChange, boolean onlyOneTarget, FilterPermanent filterNewTarget);
|
boolean chooseNewTargets(Game game, UUID playerId, boolean forceChange, boolean onlyOneTarget, FilterPermanent filterNewTarget);
|
||||||
|
|
||||||
|
StackObject createCopyOnStack(Game game, Ability source, UUID newControllerId, boolean chooseNewTargets);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
StackObject copy();
|
StackObject copy();
|
||||||
|
|
|
@ -1239,6 +1239,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
if (!ability.isUsesStack()) {
|
if (!ability.isUsesStack()) {
|
||||||
ability.resolve(game);
|
ability.resolve(game);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
game.fireEvent(new GameEvent(EventType.TRIGGERED_ABILITY, ability.getId(), ability.getSourceId(), ability.getControllerId()));
|
||||||
|
}
|
||||||
game.removeBookmark(bookmark);
|
game.removeBookmark(bookmark);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue