mirror of
https://github.com/correl/mage.git
synced 2025-03-30 09:08:36 -09:00
Merge origin/master
This commit is contained in:
commit
aa525bf0d2
110 changed files with 1531 additions and 1545 deletions
Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai
Mage.Sets/src/mage/sets
avacynrestored
commander2014
darksteel
dragonsmaze
eventide
exodus
fifthdawn
gatecrash
guildpact
iceage
innistrad
journeyintonyx
judgment
limitedalpha
lorwyn
magic2010
magic2011
magic2012
magic2014
magic2015
magicorigins
mirrodinbesieged
newphyrexia
planeshift
riseoftheeldrazi
saviorsofkamigawa
scarsofmirrodin
shadowmoor
AphoticWisps.javaCemeteryPuca.javaDrownerInitiate.javaFateTransfer.javaLeechBonder.javaLureboundScarecrow.javaMirrorweave.javaWickerWarcrawler.java
shardsofalara
tempest
theros
unlimitededition
urzassaga
worldwake
zendikar
Mage.Tests/src/test/java/org/mage/test
cards
abilities
enters
oneshot/counter
other
conditional
copy
triggers
player
serverside/base/impl
Mage/src/mage
abilities
common
condition/common
costs
AlternativeCost2Impl.javaCompositeCost.javaCost.javaCostImpl.javaCostsImpl.javaOptionalAdditionalCostImpl.javaOrCost.javaVariableCostImpl.java
common
mana
decorator
effects
AuraReplacementEffect.javaContinuousEffects.javaContinuousEffectsList.javaContinuousRuleModifyingEffectImpl.javaEntersBattlefieldEffect.java
common
keyword
cards
game
|
@ -436,29 +436,32 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
|||
}
|
||||
|
||||
protected void resolve(SimulationNode2 node, int depth, Game game) {
|
||||
StackObject ability = game.getStack().pop();
|
||||
if (ability instanceof StackAbility) {
|
||||
SearchEffect effect = getSearchEffect((StackAbility) ability);
|
||||
if (effect != null && ability.getControllerId().equals(playerId)) {
|
||||
StackObject stackObject = game.getStack().getFirst();
|
||||
if (stackObject instanceof StackAbility) {
|
||||
SearchEffect effect = getSearchEffect((StackAbility) stackObject);
|
||||
if (effect != null && stackObject.getControllerId().equals(playerId)) {
|
||||
Target target = effect.getTarget();
|
||||
if (!target.doneChosing()) {
|
||||
for (UUID targetId : target.possibleTargets(ability.getSourceId(), ability.getControllerId(), game)) {
|
||||
for (UUID targetId : target.possibleTargets(stackObject.getSourceId(), stackObject.getControllerId(), game)) {
|
||||
Game sim = game.copy();
|
||||
StackAbility newAbility = (StackAbility) ability.copy();
|
||||
StackAbility newAbility = (StackAbility) stackObject.copy();
|
||||
SearchEffect newEffect = getSearchEffect(newAbility);
|
||||
newEffect.getTarget().addTarget(targetId, newAbility, sim);
|
||||
sim.getStack().push(newAbility);
|
||||
SimulationNode2 newNode = new SimulationNode2(node, sim, depth, ability.getControllerId());
|
||||
SimulationNode2 newNode = new SimulationNode2(node, sim, depth, stackObject.getControllerId());
|
||||
node.children.add(newNode);
|
||||
newNode.getTargets().add(targetId);
|
||||
logger.trace("Sim search -- node#: " + SimulationNode2.getCount() + " for player: " + sim.getPlayer(ability.getControllerId()).getName());
|
||||
logger.trace("Sim search -- node#: " + SimulationNode2.getCount() + " for player: " + sim.getPlayer(stackObject.getControllerId()).getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
//logger.info("simulating resolve ");
|
||||
ability.resolve(game);
|
||||
stackObject.resolve(game);
|
||||
if (stackObject instanceof StackAbility) {
|
||||
game.getStack().remove(stackObject);
|
||||
}
|
||||
game.applyEffects();
|
||||
game.getPlayers().resetPassed();
|
||||
game.getPlayerList().setCurrent(game.getActivePlayerId());
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
*/
|
||||
package mage.sets.avacynrestored;
|
||||
|
||||
import mage.constants.*;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
|
@ -37,6 +38,11 @@ import mage.abilities.effects.ReplacementEffectImpl;
|
|||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
|
@ -47,8 +53,6 @@ import mage.target.TargetPermanent;
|
|||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.util.functions.EmptyApplyToPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author noxx
|
||||
|
@ -60,7 +64,6 @@ public class InfiniteReflection extends CardImpl {
|
|||
this.expansionSetCode = "AVR";
|
||||
this.subtype.add("Aura");
|
||||
|
||||
|
||||
// Enchant creature
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
|
@ -109,9 +112,9 @@ class InfiniteReflectionTriggeredEffect extends OneShotEffect {
|
|||
if (sourcePermanent != null && sourcePermanent.getAttachedTo() != null) {
|
||||
Permanent toCopyFromPermanent = game.getPermanent(sourcePermanent.getAttachedTo());
|
||||
if (toCopyFromPermanent != null) {
|
||||
for (Permanent toCopyToPermanent: game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
|
||||
for (Permanent toCopyToPermanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
|
||||
if (!toCopyToPermanent.equals(toCopyFromPermanent) && !(toCopyToPermanent instanceof PermanentToken)) {
|
||||
game.copyPermanent(toCopyFromPermanent, toCopyToPermanent, source, new EmptyApplyToPermanent());
|
||||
game.copyPermanent(toCopyFromPermanent, toCopyToPermanent.getId(), source, new EmptyApplyToPermanent());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -135,7 +138,7 @@ class InfiniteReflectionEntersBattlefieldEffect extends ReplacementEffectImpl {
|
|||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
|
@ -144,15 +147,14 @@ class InfiniteReflectionEntersBattlefieldEffect extends ReplacementEffectImpl {
|
|||
&& !(permanent instanceof PermanentToken);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Permanent toCopyToPermanent = game.getPermanent(event.getTargetId());
|
||||
MageObject toCopyToObject = game.getObject(event.getTargetId());
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (sourcePermanent != null && toCopyToPermanent != null && sourcePermanent.getAttachedTo() != null) {
|
||||
if (sourcePermanent != null && toCopyToObject != null && sourcePermanent.getAttachedTo() != null) {
|
||||
Permanent toCopyFromPermanent = game.getPermanent(sourcePermanent.getAttachedTo());
|
||||
if (toCopyFromPermanent != null) {
|
||||
game.copyPermanent(toCopyFromPermanent, toCopyToPermanent, source, new EmptyApplyToPermanent());
|
||||
game.copyPermanent(toCopyFromPermanent, toCopyToObject.getId(), source, new EmptyApplyToPermanent());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -30,25 +30,25 @@ package mage.sets.commander2014;
|
|||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.RequirementEffect;
|
||||
import mage.abilities.effects.common.UntapTargetEffect;
|
||||
import mage.abilities.effects.common.combat.BlocksIfAbleTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.permanent.AttackingPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.SecondTargetPointer;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -66,7 +66,6 @@ public class DomineeringWill extends CardImpl {
|
|||
super(ownerId, 13, "Domineering Will", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{3}{U}");
|
||||
this.expansionSetCode = "C14";
|
||||
|
||||
|
||||
// Target player gains control of up to three target nonattacking creatures until end of turn. Untap those creatures. They block this turn if able.
|
||||
this.getSpellAbility().addEffect(new DomineeringWillEffect());
|
||||
this.getSpellAbility().addTarget(new TargetPlayer());
|
||||
|
@ -102,14 +101,20 @@ class DomineeringWillEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (targetPlayer != null) {
|
||||
ContinuousEffect effect = new DomineeringWillControlEffect();
|
||||
ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfTurn, targetPlayer.getId());
|
||||
effect.setTargetPointer(new SecondTargetPointer());
|
||||
effect.setText("Target player gains control of up to three target nonattacking creatures until end of turn");
|
||||
game.addEffect(effect, source);
|
||||
Effect effect2 = new DomineeringWillUntapTargetEffect();
|
||||
|
||||
Effect effect2 = new UntapTargetEffect();
|
||||
effect2.setTargetPointer(new SecondTargetPointer());
|
||||
effect2.setText("Untap those creatures");
|
||||
effect2.apply(game, source);
|
||||
RequirementEffect effect3 = new DomineeringWillBlocksIfAbleTargetEffect(Duration.EndOfTurn);
|
||||
|
||||
RequirementEffect effect3 = new BlocksIfAbleTargetEffect(Duration.EndOfTurn);
|
||||
effect3.setTargetPointer(new SecondTargetPointer());
|
||||
effect3.setText("They block this turn if able");
|
||||
game.addEffect(effect3, source);
|
||||
return true;
|
||||
|
@ -117,109 +122,3 @@ class DomineeringWillEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class DomineeringWillControlEffect extends ContinuousEffectImpl {
|
||||
|
||||
public DomineeringWillControlEffect() {
|
||||
super(Duration.EndOfTurn, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
|
||||
}
|
||||
|
||||
public DomineeringWillControlEffect(final DomineeringWillControlEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomineeringWillControlEffect copy() {
|
||||
return new DomineeringWillControlEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
if (targetPlayer != null) {
|
||||
boolean targetStillExists = false;
|
||||
for (UUID permanentId : source.getTargets().get(1).getTargets()) {
|
||||
Permanent permanent = game.getPermanent(permanentId);
|
||||
if (permanent != null) {
|
||||
targetStillExists = true;
|
||||
if (targetPlayer != null) {
|
||||
permanent.changeControllerId(targetPlayer.getId(), game);
|
||||
permanent.getAbilities().setControllerId(targetPlayer.getId());
|
||||
} else {
|
||||
permanent.changeControllerId(source.getControllerId(), game);
|
||||
permanent.getAbilities().setControllerId(source.getControllerId());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!targetStillExists) {
|
||||
// no valid target exists, effect can be discarded
|
||||
discard();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class DomineeringWillUntapTargetEffect extends OneShotEffect {
|
||||
|
||||
public DomineeringWillUntapTargetEffect() {
|
||||
super(Outcome.Untap);
|
||||
}
|
||||
|
||||
public DomineeringWillUntapTargetEffect(final DomineeringWillUntapTargetEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomineeringWillUntapTargetEffect copy() {
|
||||
return new DomineeringWillUntapTargetEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
for (UUID target : source.getTargets().get(1).getTargets()) {
|
||||
Permanent permanent = game.getPermanent(target);
|
||||
if (permanent != null) {
|
||||
permanent.untap(game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class DomineeringWillBlocksIfAbleTargetEffect extends RequirementEffect {
|
||||
|
||||
public DomineeringWillBlocksIfAbleTargetEffect(Duration duration) {
|
||||
super(duration);
|
||||
}
|
||||
|
||||
public DomineeringWillBlocksIfAbleTargetEffect(final DomineeringWillBlocksIfAbleTargetEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomineeringWillBlocksIfAbleTargetEffect copy() {
|
||||
return new DomineeringWillBlocksIfAbleTargetEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
return source.getTargets().get(1).getTargets().contains(permanent.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mustAttack(Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mustBlock(Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mustBlockAny(Game game) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,20 +29,22 @@ package mage.sets.darksteel;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.abilities.condition.InvertCondition;
|
||||
import mage.abilities.condition.common.SourceTappedCondition;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LoneFox
|
||||
|
||||
*
|
||||
*/
|
||||
public class NimAbomination extends CardImpl {
|
||||
|
||||
|
@ -55,7 +57,7 @@ public class NimAbomination extends CardImpl {
|
|||
|
||||
// At the beginning of your end step, if Nim Abomination is untapped, you lose 3 life.
|
||||
this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new LoseLifeSourceControllerEffect(3),
|
||||
TargetController.YOU, new InvertCondition(new SourceTappedCondition()), false));
|
||||
TargetController.YOU, new SourceUntappedCondition(), false));
|
||||
}
|
||||
|
||||
public NimAbomination(final NimAbomination card) {
|
||||
|
@ -67,3 +69,26 @@ public class NimAbomination extends CardImpl {
|
|||
return new NimAbomination(this);
|
||||
}
|
||||
}
|
||||
|
||||
class SourceUntappedCondition implements Condition {
|
||||
|
||||
private static final SourceUntappedCondition fInstance = new SourceUntappedCondition();
|
||||
|
||||
public static SourceUntappedCondition getInstance() {
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
return !permanent.isTapped();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "if {this} is untapped";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,7 +157,6 @@ class PossibilityStormEffect extends OneShotEffect {
|
|||
if (exile != null) {
|
||||
while (exile.size() > 0) {
|
||||
card = exile.getRandom(game);
|
||||
exile.remove(card.getId());
|
||||
spellController.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.EXILED, false, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,11 +50,11 @@ import mage.target.TargetPlayer;
|
|||
* @author jeffwadsworth
|
||||
*/
|
||||
public class MerrowBonegnawer extends CardImpl {
|
||||
|
||||
|
||||
private UUID exileId = UUID.randomUUID();
|
||||
|
||||
|
||||
private static final FilterSpell filter = new FilterSpell("black spell");
|
||||
|
||||
|
||||
static {
|
||||
filter.add(new ColorPredicate(ObjectColor.BLACK));
|
||||
}
|
||||
|
@ -69,13 +69,13 @@ public class MerrowBonegnawer extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// {tap}: Target player exiles a card from his or her graveyard.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileFromZoneTargetEffect(Zone.GRAVEYARD, exileId, "Merrow Bonegnawer", new FilterCard("a card")), new TapSourceCost());
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileFromZoneTargetEffect(Zone.GRAVEYARD, exileId, getIdName(), new FilterCard()), new TapSourceCost());
|
||||
ability.addTarget(new TargetPlayer());
|
||||
this.addAbility(ability);
|
||||
|
||||
|
||||
// Whenever you cast a black spell, you may untap Merrow Bonegnawer.
|
||||
this.addAbility(new SpellCastControllerTriggeredAbility(Zone.BATTLEFIELD, new UntapSourceEffect(), filter, true, false));
|
||||
|
||||
|
||||
}
|
||||
|
||||
public MerrowBonegnawer(final MerrowBonegnawer card) {
|
||||
|
|
|
@ -27,17 +27,19 @@
|
|||
*/
|
||||
package mage.sets.exodus;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.Cards;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
|
@ -51,8 +53,7 @@ public class Manabond extends CardImpl {
|
|||
super(ownerId, 113, "Manabond", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{G}");
|
||||
this.expansionSetCode = "EXO";
|
||||
|
||||
|
||||
// At the beginning of your end step, you may reveal your hand and put all land cards from it onto the battlefield. If you do, discard your hand.
|
||||
// At the beginning of your end step, reveal your hand and put all land cards from it onto the battlefield. If you do, discard your hand.
|
||||
this.addAbility(new BeginningOfYourEndStepTriggeredAbility(new ManabondEffect(), true));
|
||||
}
|
||||
|
||||
|
@ -66,12 +67,11 @@ public class Manabond extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class ManabondEffect extends OneShotEffect {
|
||||
|
||||
public ManabondEffect() {
|
||||
super(Outcome.PutCardInPlay);
|
||||
staticText = "reveal your hand and put all land cards from it onto the battlefield. If you do, discard your hand";
|
||||
staticText = "you may reveal your hand and put all land cards from it onto the battlefield. If you do, discard your hand";
|
||||
}
|
||||
|
||||
public ManabondEffect(final ManabondEffect effect) {
|
||||
|
@ -80,24 +80,22 @@ class ManabondEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
player.revealCards("Manabond", player.getHand(), game);
|
||||
|
||||
Cards hand = player.getHand().copy();
|
||||
for(UUID uuid : hand){
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller != null && sourceObject != null) {
|
||||
controller.revealCards(sourceObject.getIdName(), controller.getHand(), game);
|
||||
Set<Card> toBattlefield = new LinkedHashSet<>();
|
||||
for (UUID uuid : controller.getHand()) {
|
||||
Card card = game.getCard(uuid);
|
||||
if(card != null){
|
||||
if(card.getCardType().contains(CardType.LAND)){
|
||||
card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false);
|
||||
}
|
||||
else{
|
||||
player.discard(card, source, game);
|
||||
}
|
||||
if (card != null && card.getCardType().contains(CardType.LAND)) {
|
||||
toBattlefield.add(card);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
controller.moveCards(toBattlefield, Zone.BATTLEFIELD, source, game, false, false, true, null);
|
||||
controller.discard(controller.getHand().size(), false, source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -105,4 +103,4 @@ class ManabondEffect extends OneShotEffect {
|
|||
public ManabondEffect copy() {
|
||||
return new ManabondEffect(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,9 +31,7 @@ import java.util.UUID;
|
|||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.keyword.FirstStrikeAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
|
@ -83,12 +81,12 @@ class CantBeEquippedSourceEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
}
|
||||
|
||||
public CantBeEquippedSourceEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Neutral);
|
||||
staticText = "{this} can't be equipped";
|
||||
super(Duration.WhileOnBattlefield, Outcome.Neutral);
|
||||
staticText = "{this} can't be equipped";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ContinuousEffect copy() {
|
||||
public CantBeEquippedSourceEffect copy() {
|
||||
return new CantBeEquippedSourceEffect(this);
|
||||
}
|
||||
|
||||
|
@ -96,14 +94,14 @@ class CantBeEquippedSourceEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ATTACH;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getTargetId().equals(source.getSourceId())) {
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if(permanent != null && permanent.getSubtype().contains("Equipment")){
|
||||
return true;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (permanent != null && permanent.getSubtype().contains("Equipment")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -54,14 +54,7 @@ import mage.players.Player;
|
|||
* @author jeffwadsworth
|
||||
*/
|
||||
public class MycosynthGolem extends CardImpl {
|
||||
|
||||
private static final FilterSpell filter = new FilterSpell("Artifact creature spells you cast");
|
||||
|
||||
static {
|
||||
filter.add(new CardTypePredicate(CardType.ARTIFACT));
|
||||
filter.add(new CardTypePredicate(CardType.CREATURE));
|
||||
}
|
||||
|
||||
public MycosynthGolem(UUID ownerId) {
|
||||
super(ownerId, 137, "Mycosynth Golem", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{11}");
|
||||
this.expansionSetCode = "5DN";
|
||||
|
@ -75,8 +68,8 @@ public class MycosynthGolem extends CardImpl {
|
|||
|
||||
// Artifact creature spells you cast have affinity for artifacts.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
Zone.BATTLEFIELD, new MycosynthGolemGainAbilitySpellsEffect(new AffinityForArtifactsAbility(), filter)));
|
||||
|
||||
Zone.BATTLEFIELD, new MycosynthGolemGainAbilitySpellsEffect()));
|
||||
|
||||
}
|
||||
|
||||
public MycosynthGolem(final MycosynthGolem card) {
|
||||
|
@ -91,20 +84,21 @@ public class MycosynthGolem extends CardImpl {
|
|||
|
||||
class MycosynthGolemGainAbilitySpellsEffect extends ContinuousEffectImpl {
|
||||
|
||||
private final Ability ability;
|
||||
private final FilterSpell filter;
|
||||
private static final FilterSpell filter = new FilterSpell("Artifact creature spells you cast");
|
||||
private static final Ability ability = new AffinityForArtifactsAbility();
|
||||
|
||||
public MycosynthGolemGainAbilitySpellsEffect(Ability ability, FilterSpell filter) {
|
||||
static {
|
||||
filter.add(new CardTypePredicate(CardType.ARTIFACT));
|
||||
filter.add(new CardTypePredicate(CardType.CREATURE));
|
||||
}
|
||||
|
||||
public MycosynthGolemGainAbilitySpellsEffect() {
|
||||
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
|
||||
this.ability = ability;
|
||||
this.filter = filter;
|
||||
staticText = filter.getMessage() + " have " + ability.getRule();
|
||||
staticText = "Artifact creature spells you cast have affinity for artifacts";
|
||||
}
|
||||
|
||||
public MycosynthGolemGainAbilitySpellsEffect(final MycosynthGolemGainAbilitySpellsEffect effect) {
|
||||
super(effect);
|
||||
this.ability = effect.ability;
|
||||
this.filter = effect.filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -114,17 +108,15 @@ class MycosynthGolemGainAbilitySpellsEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (player != null && permanent != null) {
|
||||
if (controller != null && permanent != null) {
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
// only spells cast, so no copies of spells
|
||||
if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) {
|
||||
Spell spell = (Spell) stackObject;
|
||||
if (filter.match(spell, game)) {
|
||||
if (!spell.getAbilities().contains(ability)) {
|
||||
game.getState().addOtherAbility(spell.getCard(), ability);
|
||||
}
|
||||
game.getState().addOtherAbility(spell.getCard(), ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,6 @@
|
|||
package mage.sets.gatecrash;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
|
@ -39,6 +35,9 @@ import mage.abilities.costs.mana.GenericManaCost;
|
|||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
@ -80,7 +79,7 @@ class ThespiansStageCopyEffect extends OneShotEffect {
|
|||
|
||||
public ThespiansStageCopyEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "Thespian's Stage becomes a copy of target land and gains this ability";
|
||||
this.staticText = "{this} becomes a copy of target land and gains this ability";
|
||||
}
|
||||
|
||||
public ThespiansStageCopyEffect(final ThespiansStageCopyEffect effect) {
|
||||
|
@ -97,7 +96,7 @@ class ThespiansStageCopyEffect extends OneShotEffect {
|
|||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (sourcePermanent != null && copyFromPermanent != null) {
|
||||
Permanent newPermanent = game.copyPermanent(copyFromPermanent, sourcePermanent, source, new EmptyApplyToPermanent());
|
||||
Permanent newPermanent = game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent());
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThespiansStageCopyEffect(), new GenericManaCost(2));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addTarget(new TargetLandPermanent());
|
||||
|
|
|
@ -57,7 +57,7 @@ public class MizziumTransreliquat extends CardImpl {
|
|||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MizziumTransreliquatCopyEffect(), new ManaCostsImpl("{3}"));
|
||||
ability.addTarget(new TargetArtifactPermanent());
|
||||
this.addAbility(ability);
|
||||
|
||||
|
||||
// {1}{U}{R}: Mizzium Transreliquat becomes a copy of target artifact and gains this ability.
|
||||
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MizziumTransreliquatCopyAndGainAbilityEffect(), new ManaCostsImpl("{1}{U}{R}"));
|
||||
ability.addTarget(new TargetArtifactPermanent());
|
||||
|
@ -74,12 +74,11 @@ public class MizziumTransreliquat extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class MizziumTransreliquatCopyEffect extends OneShotEffect {
|
||||
|
||||
public MizziumTransreliquatCopyEffect() {
|
||||
super(Outcome.Copy);
|
||||
this.staticText = "Mizzium Transreliquat becomes a copy of target artifact until end of turn";
|
||||
this.staticText = "{this} becomes a copy of target artifact until end of turn";
|
||||
}
|
||||
|
||||
public MizziumTransreliquatCopyEffect(final MizziumTransreliquatCopyEffect effect) {
|
||||
|
@ -96,17 +95,18 @@ class MizziumTransreliquatCopyEffect extends OneShotEffect {
|
|||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (sourcePermanent != null && copyFromPermanent != null) {
|
||||
game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent, source, new EmptyApplyToPermanent());
|
||||
game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class MizziumTransreliquatCopyAndGainAbilityEffect extends OneShotEffect {
|
||||
|
||||
public MizziumTransreliquatCopyAndGainAbilityEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "Mizzium Transreliquat becomes a copy of target artifact and gains this ability";
|
||||
this.staticText = "{this} becomes a copy of target artifact and gains this ability";
|
||||
}
|
||||
|
||||
public MizziumTransreliquatCopyAndGainAbilityEffect(final MizziumTransreliquatCopyAndGainAbilityEffect effect) {
|
||||
|
@ -123,7 +123,7 @@ class MizziumTransreliquatCopyAndGainAbilityEffect extends OneShotEffect {
|
|||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (sourcePermanent != null && copyFromPermanent != null) {
|
||||
Permanent newPermanent = game.copyPermanent(copyFromPermanent, sourcePermanent, source, new EmptyApplyToPermanent());
|
||||
Permanent newPermanent = game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent());
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MizziumTransreliquatCopyAndGainAbilityEffect(), new ManaCostsImpl("{1}{U}{R}"));
|
||||
ability.addTarget(new TargetArtifactPermanent());
|
||||
newPermanent.addAbility(ability, source.getSourceId(), game);
|
||||
|
@ -131,4 +131,4 @@ class MizziumTransreliquatCopyAndGainAbilityEffect extends OneShotEffect {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect;
|
||||
|
@ -50,24 +49,24 @@ import mage.counters.CounterType;
|
|||
|
||||
/**
|
||||
*
|
||||
* @author anonymous
|
||||
* @author Luna Skyrise
|
||||
*/
|
||||
public class LandCap extends CardImpl {
|
||||
|
||||
public LandCap(UUID ownerId) {
|
||||
super(ownerId, 319, "Land Cap", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
||||
super(ownerId, 338, "Land Cap", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
||||
this.expansionSetCode = "ICE";
|
||||
|
||||
// Land Cap doesn't untap during your untap step if it has a depletion counter on it.
|
||||
Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(),
|
||||
new SourceHasCounterCondition(CounterType.DEPLETION, 0));
|
||||
Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(false, true),
|
||||
new SourceHasCounterCondition(CounterType.DEPLETION, 1, Integer.MAX_VALUE));
|
||||
effect.setText("{this} doesn't untap during your untap step if it has a depletion counter on it");
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
|
||||
this.addAbility(ability);
|
||||
// At the beginning of your upkeep, remove a depletion counter from Land Cap.
|
||||
Ability ability2 = new BeginningOfUpkeepTriggeredAbility(new RemoveCounterSourceEffect(CounterType.DEPLETION.createInstance()), TargetController.YOU, false);
|
||||
this.addAbility(ability2);
|
||||
// {tap}: Add {W} or {U} to your mana pool. Put a depletion counter on Land Cap.
|
||||
// {T}: Add {W} or {U} to your mana pool. Put a depletion counter on Land Cap.
|
||||
Ability ability3 = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana, new TapSourceCost());
|
||||
ability3.addEffect(new AddCountersSourceEffect(CounterType.DEPLETION.createInstance()));
|
||||
this.addAbility(ability3);
|
||||
|
|
|
@ -49,7 +49,7 @@ import mage.counters.CounterType;
|
|||
|
||||
/**
|
||||
*
|
||||
* @author anonymous
|
||||
* @author Luna Skyrise
|
||||
*/
|
||||
public class LavaTubes extends CardImpl {
|
||||
|
||||
|
@ -58,8 +58,8 @@ public class LavaTubes extends CardImpl {
|
|||
this.expansionSetCode = "ICE";
|
||||
|
||||
// Lava Tubes doesn't untap during your untap step if it has a depletion counter on it.
|
||||
Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(),
|
||||
new SourceHasCounterCondition(CounterType.DEPLETION, 0));
|
||||
Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(false, true),
|
||||
new SourceHasCounterCondition(CounterType.DEPLETION, 1, Integer.MAX_VALUE));
|
||||
effect.setText("{this} doesn't untap during your untap step if it has a depletion counter on it");
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
|
||||
this.addAbility(ability);
|
||||
|
|
|
@ -34,7 +34,6 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect;
|
||||
|
@ -50,7 +49,7 @@ import mage.counters.CounterType;
|
|||
|
||||
/**
|
||||
*
|
||||
* @author anonymous
|
||||
* @author Luna Skyrise
|
||||
*/
|
||||
public class RiverDelta extends CardImpl {
|
||||
|
||||
|
@ -59,8 +58,8 @@ public class RiverDelta extends CardImpl {
|
|||
this.expansionSetCode = "ICE";
|
||||
|
||||
// River Delta doesn't untap during your untap step if it has a depletion counter on it.
|
||||
Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(),
|
||||
new SourceHasCounterCondition(CounterType.DEPLETION, 0));
|
||||
Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(false, true),
|
||||
new SourceHasCounterCondition(CounterType.DEPLETION, 1, Integer.MAX_VALUE));
|
||||
effect.setText("{this} doesn't untap during your untap step if it has a depletion counter on it");
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
|
||||
this.addAbility(ability);
|
||||
|
|
|
@ -49,7 +49,7 @@ import mage.counters.CounterType;
|
|||
|
||||
/**
|
||||
*
|
||||
* @author anonymous
|
||||
* @author Luna Skyrise
|
||||
*/
|
||||
public class TimberlineRidge extends CardImpl {
|
||||
|
||||
|
@ -58,8 +58,8 @@ public class TimberlineRidge extends CardImpl {
|
|||
this.expansionSetCode = "ICE";
|
||||
|
||||
// Timberline Ridge doesn't untap during your untap step if it has a depletion counter on it.
|
||||
Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(),
|
||||
new SourceHasCounterCondition(CounterType.DEPLETION, 0));
|
||||
Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(false, true),
|
||||
new SourceHasCounterCondition(CounterType.DEPLETION, 1, Integer.MAX_VALUE));
|
||||
effect.setText("{this} doesn't untap during your untap step if it has a depletion counter on it");
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
|
||||
this.addAbility(ability);
|
||||
|
|
|
@ -49,7 +49,7 @@ import mage.counters.CounterType;
|
|||
|
||||
/**
|
||||
*
|
||||
* @author anonymous
|
||||
* @author Luna Skyrise
|
||||
*/
|
||||
public class Veldt extends CardImpl {
|
||||
|
||||
|
@ -58,8 +58,8 @@ public class Veldt extends CardImpl {
|
|||
this.expansionSetCode = "ICE";
|
||||
|
||||
// Veldt doesn't untap during your untap step if it has a depletion counter on it.
|
||||
Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(),
|
||||
new SourceHasCounterCondition(CounterType.DEPLETION, 0));
|
||||
Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(false, true),
|
||||
new SourceHasCounterCondition(CounterType.DEPLETION, 1, Integer.MAX_VALUE));
|
||||
effect.setText("{this} doesn't untap during your untap step if it has a depletion counter on it");
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
|
||||
this.addAbility(ability);
|
||||
|
|
|
@ -27,14 +27,9 @@
|
|||
*/
|
||||
package mage.sets.innistrad;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.Zone;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.DiscardTargetCost;
|
||||
|
@ -47,6 +42,13 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
@ -101,15 +103,21 @@ class GrimoireOfTheDeadEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
for (Player player: game.getPlayers().values()) {
|
||||
for (Card card: player.getGraveyard().getCards(game)) {
|
||||
if (card.getCardType().contains(CardType.CREATURE)) {
|
||||
card.putOntoBattlefield(game, Zone.GRAVEYARD, source.getSourceId(), source.getControllerId());
|
||||
game.addEffect(new GrimoireOfTheDeadEffect2(card.getId()), source);
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Set<Card> creatureCards = new LinkedHashSet<>();
|
||||
for (Player player : game.getPlayers().values()) {
|
||||
for (Card card : player.getGraveyard().getCards(game)) {
|
||||
if (card.getCardType().contains(CardType.CREATURE)) {
|
||||
creatureCards.add(card);
|
||||
game.addEffect(new GrimoireOfTheDeadEffect2(card.getId()), source);
|
||||
}
|
||||
}
|
||||
}
|
||||
controller.moveCards(creatureCards, Zone.BATTLEFIELD, source, game, false, false, true, null);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -121,10 +129,10 @@ class GrimoireOfTheDeadEffect extends OneShotEffect {
|
|||
|
||||
class GrimoireOfTheDeadEffect2 extends ContinuousEffectImpl {
|
||||
|
||||
private UUID targetId;
|
||||
private final UUID targetId;
|
||||
|
||||
public GrimoireOfTheDeadEffect2(UUID targetId) {
|
||||
super(Duration.EndOfGame, Outcome.Neutral);
|
||||
super(Duration.Custom, Outcome.Neutral);
|
||||
this.targetId = targetId;
|
||||
staticText = "Becomes a black Zombie in addition to its other colors and types";
|
||||
}
|
||||
|
@ -170,4 +178,4 @@ class GrimoireOfTheDeadEffect2 extends ContinuousEffectImpl {
|
|||
return layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ public class PolymorphousRush extends CardImpl {
|
|||
|
||||
// Strive - Polymorphous Rush costs {1}{U} more to cast for each target beyond the first.
|
||||
this.addAbility(new StriveAbility("{1}{U}"));
|
||||
|
||||
|
||||
// Choose a creature on the battlefield. Any number of target creatures you control each become a copy of that creature until end of turn.
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, false));
|
||||
this.getSpellAbility().addEffect(new PolymorphousRushCopyEffect());
|
||||
|
@ -82,21 +82,21 @@ public class PolymorphousRush extends CardImpl {
|
|||
}
|
||||
|
||||
class PolymorphousRushCopyEffect extends OneShotEffect {
|
||||
|
||||
|
||||
public PolymorphousRushCopyEffect() {
|
||||
super(Outcome.Copy);
|
||||
this.staticText = "Choose a creature on the battlefield. Any number of target creatures you control each become a copy of that creature until end of turn";
|
||||
}
|
||||
|
||||
|
||||
public PolymorphousRushCopyEffect(final PolymorphousRushCopyEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PolymorphousRushCopyEffect copy() {
|
||||
return new PolymorphousRushCopyEffect(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
|
@ -107,10 +107,10 @@ class PolymorphousRushCopyEffect extends OneShotEffect {
|
|||
if (target.canChoose(source.getId(), controller.getId(), game) && controller.chooseTarget(outcome, target, source, game)) {
|
||||
Permanent copyFromCreature = game.getPermanent(target.getFirstTarget());
|
||||
if (copyFromCreature != null) {
|
||||
for (UUID copyToId: getTargetPointer().getTargets(game, source)) {
|
||||
for (UUID copyToId : getTargetPointer().getTargets(game, source)) {
|
||||
Permanent copyToCreature = game.getPermanent(copyToId);
|
||||
if (copyToCreature != null) {
|
||||
game.copyPermanent(Duration.EndOfTurn, copyFromCreature, copyToCreature, source, new EmptyApplyToPermanent());
|
||||
game.copyPermanent(Duration.EndOfTurn, copyFromCreature, copyToId, source, new EmptyApplyToPermanent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,4 +119,5 @@ class PolymorphousRushCopyEffect extends OneShotEffect {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ class WorldgorgerDragonEntersEffect extends OneShotEffect {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller != null) {
|
||||
UUID exileId = CardUtil.getObjectExileZoneId(game, sourceObject);
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
if (exileId != null) {
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
|
||||
if (!permanent.getId().equals(source.getSourceId())) { // Another
|
||||
|
@ -145,7 +145,7 @@ class WorldgorgerDragonLeavesEffect extends OneShotEffect {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller != null && sourceObject != null) {
|
||||
int zoneChangeCounter = (sourceObject instanceof PermanentToken) ? source.getSourceObjectZoneChangeCounter() : source.getSourceObjectZoneChangeCounter() -1;
|
||||
int zoneChangeCounter = (sourceObject instanceof PermanentToken) ? source.getSourceObjectZoneChangeCounter() : source.getSourceObjectZoneChangeCounter() - 1;
|
||||
ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter));
|
||||
if (exile != null) {
|
||||
exile = exile.copy();
|
||||
|
|
|
@ -114,15 +114,15 @@ class CopyArtifactEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (player != null && sourcePermanent != null) {
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (player != null && sourceObject != null) {
|
||||
Target target = new TargetPermanent(filter);
|
||||
target.setNotTarget(true);
|
||||
if (target.canChoose(source.getControllerId(), game)) {
|
||||
player.choose(Outcome.Copy, target, source.getSourceId(), game);
|
||||
Permanent copyFromPermanent = game.getPermanent(target.getFirstTarget());
|
||||
if (copyFromPermanent != null) {
|
||||
game.copyPermanent(copyFromPermanent, sourcePermanent, source, applier);
|
||||
game.copyPermanent(copyFromPermanent, sourceObject.getId(), source, applier);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ import mage.target.TargetPermanent;
|
|||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.util.functions.EmptyApplyToPermanent;
|
||||
|
||||
|
||||
/**
|
||||
* @author duncant
|
||||
*/
|
||||
|
@ -68,11 +67,11 @@ public class Shapesharer extends CardImpl {
|
|||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
this.addAbility(ChangelingAbility.getInstance());
|
||||
|
||||
|
||||
// {2}{U}: Target Shapeshifter becomes a copy of target creature until your next turn.
|
||||
Ability copyAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new ShapesharerEffect(),
|
||||
new ManaCostsImpl("{2}{U}"));
|
||||
new ShapesharerEffect(),
|
||||
new ManaCostsImpl("{2}{U}"));
|
||||
copyAbility.addTarget(new TargetPermanent(filterShapeshifter));
|
||||
copyAbility.addTarget(new TargetCreaturePermanent());
|
||||
this.addAbility(copyAbility);
|
||||
|
@ -89,6 +88,7 @@ public class Shapesharer extends CardImpl {
|
|||
}
|
||||
|
||||
class ShapesharerEffect extends OneShotEffect {
|
||||
|
||||
public ShapesharerEffect() {
|
||||
super(Outcome.Copy);
|
||||
this.staticText = "Target Shapeshifter becomes a copy of target creature until your next turn.";
|
||||
|
@ -105,10 +105,12 @@ class ShapesharerEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability ability) {
|
||||
Permanent copyTo = game.getPermanent(ability.getFirstTarget());
|
||||
Permanent copyTo = game.getPermanent(getTargetPointer().getFirst(game, ability));
|
||||
if (copyTo != null) {
|
||||
Permanent copyFrom = game.getPermanentOrLKIBattlefield(ability.getTargets().get(1).getFirstTarget());
|
||||
game.copyPermanent(Duration.EndOfTurn, copyFrom, copyTo, ability, new EmptyApplyToPermanent());
|
||||
if (copyFrom != null) {
|
||||
game.copyPermanent(Duration.EndOfTurn, copyFrom, copyTo.getId(), ability, new EmptyApplyToPermanent());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
@ -20,28 +20,29 @@
|
|||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.sets.magic2010;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.LoyaltyAbility;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.discard.DiscardTargetEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.effects.common.discard.DiscardTargetEffect;
|
||||
import mage.abilities.effects.common.search.SearchLibraryPutOnLibraryEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
@ -98,14 +99,16 @@ class LilianaVessEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
for (UUID playerId: controller.getInRange()) {
|
||||
for (UUID playerId : controller.getInRange()) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
for (Card card: player.getGraveyard().getCards(game)) {
|
||||
Set<Card> creatureCards = new LinkedHashSet<>();
|
||||
for (Card card : player.getGraveyard().getCards(game)) {
|
||||
if (card.getCardType().contains(CardType.CREATURE)) {
|
||||
card.putOntoBattlefield(game, Zone.GRAVEYARD, source.getSourceId(), source.getControllerId());
|
||||
creatureCards.add(card);
|
||||
}
|
||||
}
|
||||
controller.moveCards(creatureCards, Zone.BATTLEFIELD, source, game, false, false, false, null);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
@ -20,32 +20,34 @@
|
|||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.sets.magic2011;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -82,34 +84,36 @@ class MassPolymorphEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
int count;
|
||||
List<Permanent> creatures = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game);
|
||||
count = creatures.size();
|
||||
for (Permanent creature: creatures) {
|
||||
creature.moveToExile(null, null, source.getSourceId(), game);
|
||||
}
|
||||
Cards revealed = new CardsImpl();
|
||||
Cards creatureCards = new CardsImpl();
|
||||
Cards nonCreatureCards = new CardsImpl();
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
while (creatureCards.size() < count && player.getLibrary().size() > 0) {
|
||||
Card card = player.getLibrary().removeFromTop(game);
|
||||
revealed.add(card);
|
||||
if (card.getCardType().contains(CardType.CREATURE)) {
|
||||
creatureCards.add(card);
|
||||
} else {
|
||||
nonCreatureCards.add(card);
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller != null && sourceObject != null) {
|
||||
int count;
|
||||
// Cards creatures = new CardsImpl();
|
||||
List<Permanent> creatures = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game);
|
||||
Set<Card> creaturesToExile = new HashSet<>();
|
||||
creaturesToExile.addAll(creatures);
|
||||
count = creatures.size();
|
||||
controller.moveCards(creaturesToExile, null, Zone.HAND, source, game);
|
||||
|
||||
Cards revealed = new CardsImpl();
|
||||
Set<Card> creatureCards = new LinkedHashSet<>();
|
||||
Cards nonCreatureCards = new CardsImpl();
|
||||
while (creatureCards.size() < count && controller.getLibrary().size() > 0) {
|
||||
Card card = controller.getLibrary().removeFromTop(game);
|
||||
revealed.add(card);
|
||||
if (card.getCardType().contains(CardType.CREATURE)) {
|
||||
creatureCards.add(card);
|
||||
} else {
|
||||
nonCreatureCards.add(card);
|
||||
}
|
||||
}
|
||||
controller.revealCards(sourceObject.getIdName(), revealed, game);
|
||||
controller.moveCards(creatureCards, Zone.BATTLEFIELD, source, game, false, false, true, null);
|
||||
controller.putCardsOnTopOfLibrary(nonCreatureCards, game, source, false);
|
||||
controller.shuffleLibrary(game);
|
||||
return true;
|
||||
}
|
||||
player.revealCards("Mass Polymorph", revealed, game);
|
||||
for (Card creatureCard: creatureCards.getCards(game)) {
|
||||
creatureCard.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), source.getControllerId());
|
||||
}
|
||||
for (Card card: nonCreatureCards.getCards(game)) {
|
||||
player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.GRAVEYARD, true, true);
|
||||
}
|
||||
player.shuffleLibrary(game);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,4 +121,4 @@ class MassPolymorphEffect extends OneShotEffect {
|
|||
return new MassPolymorphEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,12 +25,9 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.sets.magic2012;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.*;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
|
@ -38,6 +35,11 @@ import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
|
|||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.AttachmentType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
|
@ -47,20 +49,23 @@ import mage.target.common.TargetCreaturePermanent;
|
|||
*/
|
||||
public class Flight extends CardImpl {
|
||||
|
||||
public Flight (UUID ownerId) {
|
||||
public Flight(UUID ownerId) {
|
||||
super(ownerId, 53, "Flight", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{U}");
|
||||
this.expansionSetCode = "M12";
|
||||
this.subtype.add("Aura");
|
||||
|
||||
// Enchant creature
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility));
|
||||
Ability ability = new EnchantAbility(auraTarget.getTargetName());
|
||||
this.addAbility(ability);
|
||||
|
||||
// Enchanted creature has flying.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA)));
|
||||
}
|
||||
|
||||
public Flight (final Flight card) {
|
||||
public Flight(final Flight card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
|
|
|
@ -97,15 +97,15 @@ class PhantasmalImageCopyEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (player != null && sourcePermanent != null) {
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (player != null && sourceObject != null) {
|
||||
Target target = new TargetPermanent(new FilterCreaturePermanent("creature (you copy from)"));
|
||||
target.setNotTarget(true);
|
||||
if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) {
|
||||
player.choose(Outcome.Copy, target, source.getSourceId(), game);
|
||||
Permanent copyFromPermanent = game.getPermanent(target.getFirstTarget());
|
||||
if (copyFromPermanent != null) {
|
||||
game.copyPermanent(copyFromPermanent, sourcePermanent, source, new ApplyToPermanent() {
|
||||
game.copyPermanent(copyFromPermanent, sourceObject.getId(), source, new ApplyToPermanent() {
|
||||
@Override
|
||||
public Boolean apply(Game game, Permanent permanent) {
|
||||
if (!permanent.getSubtype().contains("Illusion")) {
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
*/
|
||||
package mage.sets.magic2014;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
|
@ -49,7 +51,6 @@ public class RiseOfTheDarkRealms extends CardImpl {
|
|||
super(ownerId, 111, "Rise of the Dark Realms", Rarity.MYTHIC, new CardType[]{CardType.SORCERY}, "{7}{B}{B}");
|
||||
this.expansionSetCode = "M14";
|
||||
|
||||
|
||||
// Put all creature cards from all graveyards onto the battlefield under your control.
|
||||
this.getSpellAbility().addEffect(new RiseOfTheDarkRealmsEffect());
|
||||
}
|
||||
|
@ -78,17 +79,23 @@ class RiseOfTheDarkRealmsEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
for (UUID playerId: controller.getInRange()) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
for (Card card: player.getGraveyard().getCards(game)) {
|
||||
if (card.getCardType().contains(CardType.CREATURE)) {
|
||||
card.putOntoBattlefield(game, Zone.GRAVEYARD, source.getSourceId(), source.getControllerId());
|
||||
if (controller != null) {
|
||||
|
||||
Set<Card> creatureCards = new LinkedHashSet<>();
|
||||
for (UUID playerId : controller.getInRange()) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
for (Card card : player.getGraveyard().getCards(game)) {
|
||||
if (card.getCardType().contains(CardType.CREATURE)) {
|
||||
creatureCards.add(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
controller.moveCards(creatureCards, Zone.BATTLEFIELD, source, game, false, false, true, null);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,6 +29,7 @@ package mage.sets.magic2015;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
|
@ -96,15 +97,15 @@ class MercurialPretenderCopyEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (player != null && sourcePermanent != null) {
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (player != null && sourceObject != null) {
|
||||
Target target = new TargetPermanent(new FilterControlledCreaturePermanent());
|
||||
target.setNotTarget(true);
|
||||
if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) {
|
||||
player.choose(Outcome.Copy, target, source.getSourceId(), game);
|
||||
Permanent copyFromPermanent = game.getPermanent(target.getFirstTarget());
|
||||
if (copyFromPermanent != null) {
|
||||
game.copyPermanent(copyFromPermanent, sourcePermanent, source,
|
||||
game.copyPermanent(copyFromPermanent, sourceObject.getId(), source,
|
||||
// {2}{U}{U}: Return this creature to its owner's hand.
|
||||
new AbilityApplier(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandSourceEffect(true), new ManaCostsImpl("{2}{U}{U}")))
|
||||
);
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
*/
|
||||
package mage.sets.magicorigins;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -94,23 +94,22 @@ class AnimistsAwakeningEffect extends OneShotEffect {
|
|||
Cards cards = new CardsImpl(Zone.LIBRARY);
|
||||
int xValue = source.getManaCostsToPay().getX();
|
||||
cards.addAll(controller.getLibrary().getTopCards(game, xValue));
|
||||
List<Permanent> lands = new ArrayList<>();
|
||||
if (cards.size() > 0) {
|
||||
controller.revealCards(sourceObject.getIdName(), cards, game);
|
||||
Set<Card> toBattlefield = new LinkedHashSet<>();
|
||||
for (Card card : cards.getCards(new FilterLandCard(), source.getSourceId(), source.getControllerId(), game)) {
|
||||
cards.remove(card);
|
||||
controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, source.getSourceId(), true);
|
||||
Permanent land = game.getPermanent(card.getId());
|
||||
if (land != null) {
|
||||
lands.add(land);
|
||||
}
|
||||
|
||||
toBattlefield.add(card);
|
||||
}
|
||||
controller.moveCards(toBattlefield, Zone.BATTLEFIELD, source, game, true, false, true, null);
|
||||
controller.putCardsOnBottomOfLibrary(cards, game, source, true);
|
||||
|
||||
if (SpellMasteryCondition.getInstance().apply(game, source)) {
|
||||
for (Permanent land : lands) {
|
||||
land.untap(game);
|
||||
for (Card card : toBattlefield) {
|
||||
Permanent land = game.getPermanent(card.getId());
|
||||
if (land != null) {
|
||||
land.untap(game);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,23 +29,14 @@ package mage.sets.magicorigins;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ChangeATargetOfTargetSpellAbilityToSourceEffect;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackAbility;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetStackObject;
|
||||
import mage.target.Targets;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -63,9 +54,9 @@ public class MizziumMeddler extends CardImpl {
|
|||
|
||||
// Flash
|
||||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// When Mizzium Meddler enters the battlefield, change a target of target spell or ability to Mizzium Meddler.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new MizziumMeddlerEffect());
|
||||
|
||||
// When Mizzium Meddler enters the battlefield, you may change a target of target spell or ability to Mizzium Meddler.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ChangeATargetOfTargetSpellAbilityToSourceEffect(), true);
|
||||
ability.addTarget(new TargetStackObject());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
@ -79,92 +70,3 @@ public class MizziumMeddler extends CardImpl {
|
|||
return new MizziumMeddler(this);
|
||||
}
|
||||
}
|
||||
|
||||
class MizziumMeddlerEffect extends OneShotEffect {
|
||||
|
||||
public MizziumMeddlerEffect() {
|
||||
super(Outcome.Neutral);
|
||||
staticText = "Change a target of target spell or ability to {this}";
|
||||
}
|
||||
|
||||
public MizziumMeddlerEffect(final MizziumMeddlerEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget());
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (stackObject != null && sourceObject != null) {
|
||||
Targets targets;
|
||||
Ability sourceAbility;
|
||||
MageObject oldTarget = null;
|
||||
if (stackObject instanceof Spell) {
|
||||
Spell spell = (Spell)stackObject;
|
||||
sourceAbility = spell.getSpellAbility();
|
||||
targets = spell.getSpellAbility().getTargets();
|
||||
} else if (stackObject instanceof StackAbility) {
|
||||
StackAbility stackAbility = (StackAbility)stackObject;
|
||||
sourceAbility = stackAbility;
|
||||
targets = stackAbility.getTargets();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
boolean twoTimesTarget = false;
|
||||
if (targets.size() == 1 && targets.get(0).getTargets().size() == 1) {
|
||||
Target target = targets.get(0);
|
||||
if (target.canTarget(stackObject.getControllerId(), source.getSourceId(), sourceAbility, game)) {
|
||||
oldTarget = game.getObject(targets.getFirstTarget());
|
||||
target.clearChosen();
|
||||
// The source is still the spell on the stack
|
||||
target.addTarget(source.getSourceId(), stackObject.getStackAbility(), game);
|
||||
}
|
||||
} else {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
for (Target target: targets) {
|
||||
for (UUID targetId: target.getTargets()) {
|
||||
MageObject object = game.getObject(targetId);
|
||||
String name;
|
||||
if (object == null) {
|
||||
Player targetPlayer = game.getPlayer(targetId);
|
||||
name = targetPlayer.getLogName();
|
||||
} else {
|
||||
name = object.getName();
|
||||
}
|
||||
if (!targetId.equals(source.getSourceId()) && target.getTargets().contains(source.getSourceId())) {
|
||||
// you can't change this target to MizziumMeddler because MizziumMeddler is already another targetId of that target.
|
||||
twoTimesTarget = true;
|
||||
continue;
|
||||
}
|
||||
if (name != null && player.chooseUse(Outcome.Neutral, new StringBuilder("Change target from ").append(name).append(" to ").append(sourceObject.getName()).append("?").toString(), source, game)) {
|
||||
if (target.canTarget(stackObject.getControllerId(), source.getSourceId(), sourceAbility, game)) {
|
||||
oldTarget = game.getObject(targets.getFirstTarget());
|
||||
target.remove(targetId);
|
||||
// The source is still the spell on the stack
|
||||
target.addTarget(source.getSourceId(), stackObject.getStackAbility(), game);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldTarget != null) {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Changed target of " +stackObject.getLogName() + " from " + oldTarget.getLogName() + " to " + sourceObject.getLogName());
|
||||
} else {
|
||||
if (twoTimesTarget) {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its not valid to target it twice for " + stackObject.getName());
|
||||
} else {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its no valid target for " + stackObject.getName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MizziumMeddlerEffect copy() {
|
||||
return new MizziumMeddlerEffect(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -44,6 +44,7 @@ import mage.filter.common.FilterNonlandCard;
|
|||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
|
@ -100,7 +101,8 @@ class KnowledgePoolEffect1 extends OneShotEffect {
|
|||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
player.moveCardsToExile(player.getLibrary().getTopCards(game, 3), source, game, true,
|
||||
CardUtil.getObjectExileZoneId(game, sourceObject), sourceObject.getIdName() + " (" + sourceObject.getZoneChangeCounter(game) + ")");
|
||||
CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()),
|
||||
sourceObject.getIdName() + " (" + sourceObject.getZoneChangeCounter(game) + ")");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -168,7 +170,8 @@ class KnowledgePoolEffect2 extends OneShotEffect {
|
|||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null && spell != null && sourceObject != null) {
|
||||
UUID exileZoneId = CardUtil.getObjectExileZoneId(game, sourceObject);
|
||||
int zoneChangeCounter = (sourceObject instanceof PermanentToken) ? source.getSourceObjectZoneChangeCounter() : source.getSourceObjectZoneChangeCounter() - 1;
|
||||
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter);
|
||||
if (controller.moveCardsToExile(spell, source, game, true, exileZoneId, sourceObject.getIdName())) {
|
||||
Player player = game.getPlayer(spell.getControllerId());
|
||||
if (player != null && player.chooseUse(Outcome.PlayForFree, "Cast another nonland card exiled with " + sourceObject.getLogName() + " without paying that card's mana cost?", source, game)) {
|
||||
|
|
|
@ -88,7 +88,7 @@ public class PhyrexianMetamorph extends CardImpl {
|
|||
// You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types.
|
||||
Effect effect = new CopyPermanentEffect(filter, phyrexianMetamorphApplier);
|
||||
effect.setText("You may have {this} enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types");
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new EntersBattlefieldEffect(effect));
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new EntersBattlefieldEffect(effect));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,24 +29,15 @@ package mage.sets.newphyrexia;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ChangeATargetOfTargetSpellAbilityToSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackAbility;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetStackObject;
|
||||
import mage.target.Targets;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -62,7 +53,7 @@ public class Spellskite extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// {UP}: Change a target of target spell or ability to Spellskite.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SpellskiteEffect(), new ManaCostsImpl("{UP}"));
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChangeATargetOfTargetSpellAbilityToSourceEffect(), new ManaCostsImpl("{UP}"));
|
||||
ability.addTarget(new TargetStackObject());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
@ -76,110 +67,3 @@ public class Spellskite extends CardImpl {
|
|||
return new Spellskite(this);
|
||||
}
|
||||
}
|
||||
|
||||
class SpellskiteEffect extends OneShotEffect {
|
||||
|
||||
public SpellskiteEffect() {
|
||||
super(Outcome.Neutral);
|
||||
staticText = "Change a target of target spell or ability to {this}";
|
||||
}
|
||||
|
||||
public SpellskiteEffect(final SpellskiteEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget());
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (stackObject != null && sourceObject != null) {
|
||||
Targets targets = new Targets();
|
||||
Ability sourceAbility;
|
||||
String oldTargetName = null;
|
||||
if (stackObject instanceof Spell) {
|
||||
Spell spell = (Spell) stackObject;
|
||||
sourceAbility = spell.getSpellAbility();
|
||||
} else if (stackObject instanceof StackAbility) {
|
||||
StackAbility stackAbility = (StackAbility) stackObject;
|
||||
sourceAbility = stackAbility;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
for (UUID modeId : sourceAbility.getModes().getSelectedModes()) {
|
||||
sourceAbility.getModes().setActiveMode(modeId);
|
||||
targets.addAll(sourceAbility.getTargets());
|
||||
}
|
||||
|
||||
boolean twoTimesTarget = false;
|
||||
if (targets.size() == 1 && targets.get(0).getTargets().size() == 1) {
|
||||
Target target = targets.get(0);
|
||||
if (target.canTarget(stackObject.getControllerId(), source.getSourceId(), sourceAbility, game)) {
|
||||
oldTargetName = getTargetName(targets.getFirstTarget(), game);
|
||||
target.clearChosen();
|
||||
// The source is still the spell on the stack
|
||||
target.addTarget(source.getSourceId(), stackObject.getStackAbility(), game);
|
||||
}
|
||||
} else {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
boolean validTargets = false;
|
||||
do {
|
||||
for (Target target : targets) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
String name = getTargetName(targets.getFirstTarget(), game);
|
||||
if (!targetId.equals(source.getSourceId()) && target.getTargets().contains(source.getSourceId())) {
|
||||
// you can't change this target to Spellskite because Spellskite is already another targetId of that target.
|
||||
twoTimesTarget = true;
|
||||
continue;
|
||||
}
|
||||
if (target.canTarget(stackObject.getControllerId(), source.getSourceId(), sourceAbility, game)) {
|
||||
validTargets = true;
|
||||
if (name != null
|
||||
&& controller.chooseUse(Outcome.Neutral, "Change target from " + name + " to " + sourceObject.getLogName() + "?", source, game)) {
|
||||
oldTargetName = getTargetName(targetId, game);
|
||||
target.remove(targetId);
|
||||
// The source is still the spell on the stack
|
||||
target.addTarget(source.getSourceId(), stackObject.getStackAbility(), game);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldTargetName != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (oldTargetName == null) {
|
||||
game.informPlayer(controller, "You have to select at least one target to change to spellskite!");
|
||||
}
|
||||
} while (validTargets && oldTargetName == null);
|
||||
}
|
||||
if (oldTargetName != null) {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Changed target of " + stackObject.getLogName() + " from " + oldTargetName + " to " + sourceObject.getLogName());
|
||||
} else {
|
||||
if (twoTimesTarget) {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its not valid to target it twice for " + stackObject.getLogName());
|
||||
} else {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its no valid target for " + stackObject.getLogName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellskiteEffect copy() {
|
||||
return new SpellskiteEffect(this);
|
||||
}
|
||||
|
||||
private String getTargetName(UUID objectId, Game game) {
|
||||
MageObject object = game.getObject(objectId);
|
||||
if (object != null) {
|
||||
return object.getLogName();
|
||||
}
|
||||
Player player = game.getPlayer(objectId);
|
||||
if (player != null) {
|
||||
return player.getLogName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ class SkyshipWeatherlightEffect extends SearchEffect {
|
|||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (sourceObject != null && controller != null) {
|
||||
if (controller.searchLibrary(target, game)) {
|
||||
UUID exileZone = CardUtil.getObjectExileZoneId(game, sourceObject);
|
||||
UUID exileZone = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
if (target.getTargets().size() > 0) {
|
||||
for (UUID cardID : target.getTargets()) {
|
||||
Card card = controller.getLibrary().getCard(cardID, game);
|
||||
|
|
|
@ -46,7 +46,6 @@ import mage.game.permanent.Permanent;
|
|||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.functions.EmptyApplyToPermanent;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author North
|
||||
|
@ -142,7 +141,7 @@ class RenegadeDoppelgangerEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
|
||||
game.copyPermanent(Duration.EndOfTurn, targetCreature, permanent, source, new EmptyApplyToPermanent());
|
||||
game.copyPermanent(Duration.EndOfTurn, targetCreature, permanent.getId(), source, new EmptyApplyToPermanent());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,15 +98,15 @@ class SakashimaTheImpostorCopyEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (player != null && sourcePermanent != null) {
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (player != null && sourceObject != null) {
|
||||
Target target = new TargetPermanent(new FilterCreaturePermanent());
|
||||
target.setNotTarget(true);
|
||||
if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) {
|
||||
player.choose(Outcome.Copy, target, source.getSourceId(), game);
|
||||
Permanent copyFromPermanent = game.getPermanent(target.getFirstTarget());
|
||||
if (copyFromPermanent != null) {
|
||||
game.copyPermanent(copyFromPermanent, sourcePermanent, source, new ApplyToPermanent() {
|
||||
game.copyPermanent(copyFromPermanent, sourceObject.getId(), source, new ApplyToPermanent() {
|
||||
@Override
|
||||
public Boolean apply(Game game, Permanent permanent) {
|
||||
if (!permanent.getSupertype().contains("Legendary")) {
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
*/
|
||||
package mage.sets.scarsofmirrodin;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -115,13 +117,15 @@ class GenesisWaveEffect extends OneShotEffect {
|
|||
target1.setRequired(false);
|
||||
|
||||
controller.choose(Outcome.PutCardInPlay, cards, target1, game);
|
||||
Set<Card> toBattlefield = new LinkedHashSet<>();
|
||||
for (UUID cardId : target1.getTargets()) {
|
||||
Card card = cards.get(cardId, game);
|
||||
if (card != null) {
|
||||
cards.remove(card);
|
||||
controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, source.getSourceId());
|
||||
toBattlefield.add(card);
|
||||
}
|
||||
}
|
||||
controller.moveCards(toBattlefield, Zone.BATTLEFIELD, source, game, false, false, false, null);
|
||||
controller.moveCards(cards, Zone.LIBRARY, Zone.GRAVEYARD, source, game);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -25,20 +25,19 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.sets.shadowmoor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.BecomesColorTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.keyword.FearAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Rarity;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
/**
|
||||
|
@ -47,19 +46,25 @@ import mage.target.common.TargetCreaturePermanent;
|
|||
*/
|
||||
public class AphoticWisps extends CardImpl {
|
||||
|
||||
public AphoticWisps (UUID ownerId) {
|
||||
public AphoticWisps(UUID ownerId) {
|
||||
super(ownerId, 55, "Aphotic Wisps", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{B}");
|
||||
this.expansionSetCode = "SHM";
|
||||
|
||||
// Target creature becomes black and gains fear until end of turn. (It can't be blocked except by artifact creatures and/or black creatures.)
|
||||
// Target creature becomes black and gains fear until end of turn. (It can't be blocked except by artifact creatures and/or black creatures.)
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
this.getSpellAbility().addEffect(new BecomesColorTargetEffect(ObjectColor.BLACK, Duration.EndOfTurn));
|
||||
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(FearAbility.getInstance(), Duration.EndOfTurn));
|
||||
Effect effect = new BecomesColorTargetEffect(ObjectColor.BLACK, Duration.EndOfTurn);
|
||||
effect.setText("Target creature becomes black");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
effect = new GainAbilityTargetEffect(FearAbility.getInstance(), Duration.EndOfTurn);
|
||||
effect.setText("and gains fear until end of turn");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
// Draw a card.
|
||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
|
||||
effect = new DrawCardSourceControllerEffect(1);
|
||||
effect.setText("<br>Draw a card");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
}
|
||||
|
||||
public AphoticWisps (final AphoticWisps card) {
|
||||
public AphoticWisps(final AphoticWisps card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
|
@ -69,4 +74,3 @@ public class AphoticWisps extends CardImpl {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ class CemeteryPucaEffect extends OneShotEffect {
|
|||
if (copyToCreature != null) {
|
||||
Permanent copyFromCreature = (Permanent) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.BATTLEFIELD);
|
||||
if (copyFromCreature != null) {
|
||||
game.copyPermanent(Duration.WhileOnBattlefield, copyFromCreature, copyToCreature, source, new EmptyApplyToPermanent());
|
||||
game.copyPermanent(Duration.WhileOnBattlefield, copyFromCreature, copyToCreature.getId(), source, new EmptyApplyToPermanent());
|
||||
ContinuousEffect effect = new GainAbilityTargetEffect(new DiesCreatureTriggeredAbility(new DoIfCostPaid(new CemeteryPucaEffect(), new ManaCostsImpl("{1}")), false, new FilterCreaturePermanent("a creature"), true), Duration.WhileOnBattlefield);
|
||||
effect.setTargetPointer(new FixedTarget(copyToCreature.getId()));
|
||||
game.addEffect(effect, source);
|
||||
|
|
|
@ -45,12 +45,12 @@ import mage.target.TargetPlayer;
|
|||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
|
||||
*
|
||||
*/
|
||||
public class DrownerInitiate extends CardImpl {
|
||||
|
||||
|
||||
private static final FilterSpell filter = new FilterSpell("a blue spell");
|
||||
|
||||
|
||||
static {
|
||||
filter.add(new ColorPredicate(ObjectColor.BLUE));
|
||||
}
|
||||
|
@ -65,10 +65,10 @@ public class DrownerInitiate extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Whenever a player casts a blue spell, you may pay {1}. If you do, target player puts the top two cards of his or her library into his or her graveyard.
|
||||
Ability ability = new SpellCastAllTriggeredAbility(new DoIfCostPaid(new PutLibraryIntoGraveTargetEffect(2), new ManaCostsImpl("{1}")), filter, true);
|
||||
Ability ability = new SpellCastAllTriggeredAbility(new DoIfCostPaid(new PutLibraryIntoGraveTargetEffect(2), new ManaCostsImpl("{1}")), filter, false);
|
||||
ability.addTarget(new TargetPlayer());
|
||||
this.addAbility(ability);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public DrownerInitiate(final DrownerInitiate card) {
|
||||
|
|
|
@ -53,7 +53,6 @@ public class FateTransfer extends CardImpl {
|
|||
super(ownerId, 161, "Fate Transfer", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{U/B}");
|
||||
this.expansionSetCode = "SHM";
|
||||
|
||||
|
||||
// Move all counters from target creature onto another target creature.
|
||||
this.getSpellAbility().addEffect(new FateTransferEffect());
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
|
||||
|
@ -96,9 +95,8 @@ class FateTransferEffect extends OneShotEffect {
|
|||
&& creatureToMoveCountersTo != null) {
|
||||
Permanent copyCreature = creatureToMoveCountersFrom.copy();
|
||||
for (Counter counter : copyCreature.getCounters().values()) {
|
||||
Counter newCounterTest = new Counter(counter.getName(), counter.getCount());
|
||||
creatureToMoveCountersFrom.removeCounters(newCounterTest, game);
|
||||
creatureToMoveCountersTo.addCounters(newCounterTest, game);
|
||||
creatureToMoveCountersFrom.removeCounters(counter, game);
|
||||
creatureToMoveCountersTo.addCounters(counter, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ public class LeechBonder extends CardImpl {
|
|||
// Leech Bonder enters the battlefield with two -1/-1 counters on it.
|
||||
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(2))));
|
||||
|
||||
// {U}, {untap}: Move a counter from target creature onto a second target creature.
|
||||
// {U}, {untap}: Move a counter from target creature onto another target creature.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LeechBonderEffect(), new ManaCostsImpl("{U}"));
|
||||
ability.addCost(new UntapSourceCost());
|
||||
ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature to remove counter from")));
|
||||
|
|
|
@ -30,22 +30,16 @@ package mage.sets.shadowmoor;
|
|||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.StateTriggeredAbility;
|
||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.SacrificeSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.choices.ChoiceColor;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -62,7 +56,7 @@ public class LureboundScarecrow extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// As Lurebound Scarecrow enters the battlefield, choose a color.
|
||||
this.addAbility(new AsEntersBattlefieldAbility(new LureboundScarecrowChooseColorEffect()));
|
||||
this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect()));
|
||||
|
||||
// When you control no permanents of the chosen color, sacrifice Lurebound Scarecrow.
|
||||
this.addAbility(new LureboundScarecrowTriggeredAbility());
|
||||
|
@ -78,40 +72,6 @@ public class LureboundScarecrow extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class LureboundScarecrowChooseColorEffect extends OneShotEffect {
|
||||
|
||||
public LureboundScarecrowChooseColorEffect() {
|
||||
super(Outcome.BoostCreature);
|
||||
staticText = "choose a color";
|
||||
}
|
||||
|
||||
public LureboundScarecrowChooseColorEffect(final LureboundScarecrowChooseColorEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
StackObject sourceStackObject = game.getStack().getStackObject(source.getSourceId());
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (player != null && sourceStackObject != null && permanent != null) {
|
||||
ChoiceColor colorChoice = new ChoiceColor();
|
||||
if (player.choose(Outcome.BoostCreature, colorChoice, game)) {
|
||||
game.informPlayers(sourceStackObject.getName() + ": " + player.getLogName() + " has chosen " + colorChoice.getChoice());
|
||||
game.getState().setValue(permanent.getId() + "_color", colorChoice.getColor());
|
||||
permanent.addInfo("chosen color", new StringBuilder("<font color='blue'>Chosen color: ").append(colorChoice.getColor().getDescription()).append("</font>").toString(), game);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LureboundScarecrowChooseColorEffect copy() {
|
||||
return new LureboundScarecrowChooseColorEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class LureboundScarecrowTriggeredAbility extends StateTriggeredAbility {
|
||||
|
||||
private static final String staticText = "When you control no permanents of the chosen color, sacrifice {this}.";
|
||||
|
|
|
@ -61,7 +61,6 @@ public class Mirrorweave extends CardImpl {
|
|||
super(ownerId, 143, "Mirrorweave", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{2}{W/U}{W/U}");
|
||||
this.expansionSetCode = "SHM";
|
||||
|
||||
|
||||
// Each other creature becomes a copy of target nonlegendary creature until end of turn.
|
||||
this.getSpellAbility().addEffect(new MirrorWeaveEffect());
|
||||
this.getSpellAbility().addTarget(new TargetPermanent(filter));
|
||||
|
@ -105,7 +104,7 @@ class MirrorWeaveEffect extends OneShotEffect {
|
|||
filter.add(Predicates.not(new PermanentIdPredicate(copyFromCreature.getId())));
|
||||
for (Permanent copyToCreature : game.getBattlefield().getAllActivePermanents(filter, game)) {
|
||||
if (copyToCreature != null) {
|
||||
game.copyPermanent(Duration.EndOfTurn, copyFromCreature, copyToCreature, source, new EmptyApplyToPermanent());
|
||||
game.copyPermanent(Duration.EndOfTurn, copyFromCreature, copyToCreature.getId(), source, new EmptyApplyToPermanent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,19 +29,16 @@ package mage.sets.shadowmoor;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.common.AttacksOrBlocksTriggeredAbility;
|
||||
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -57,7 +54,10 @@ public class WickerWarcrawler extends CardImpl {
|
|||
this.toughness = new MageInt(6);
|
||||
|
||||
// Whenever Wicker Warcrawler attacks or blocks, put a -1/-1 counter on it at end of combat.
|
||||
this.addAbility(new AttacksOrBlocksTriggeredAbility(new WickerWarcrawlerEffect(), false));
|
||||
Effect effect = new AddCountersSourceEffect(CounterType.M1M1.createInstance(), true);
|
||||
effect.setText("put a -1/-1 counter on it at end of combat");
|
||||
DelayedTriggeredAbility ability = new AtTheEndOfCombatDelayedTriggeredAbility(effect);
|
||||
this.addAbility(new AttacksOrBlocksTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(ability, false, false), false));
|
||||
|
||||
}
|
||||
|
||||
|
@ -70,35 +70,3 @@ public class WickerWarcrawler extends CardImpl {
|
|||
return new WickerWarcrawler(this);
|
||||
}
|
||||
}
|
||||
|
||||
class WickerWarcrawlerEffect extends OneShotEffect {
|
||||
|
||||
WickerWarcrawlerEffect() {
|
||||
super(Outcome.Detriment);
|
||||
staticText = "put a -1/-1 counter on {this} at the end of combat";
|
||||
}
|
||||
|
||||
WickerWarcrawlerEffect(final WickerWarcrawlerEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent wickerWarcrawler = game.getPermanent(source.getSourceId());
|
||||
if (wickerWarcrawler != null) {
|
||||
AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new AddCountersTargetEffect(CounterType.M1M1.createInstance()));
|
||||
delayedAbility.setSourceId(source.getSourceId());
|
||||
delayedAbility.setControllerId(source.getControllerId());
|
||||
delayedAbility.setSourceObject(source.getSourceObject(game), game);
|
||||
delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(source.getSourceId()));
|
||||
game.addDelayedTriggeredAbility(delayedAbility);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WickerWarcrawlerEffect copy() {
|
||||
return new WickerWarcrawlerEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ class TidehollowScullerExileEffect extends OneShotEffect {
|
|||
if (controller.choose(Outcome.Exile, opponent.getHand(), target, game)) {
|
||||
Card card = opponent.getHand().get(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
controller.moveCardToExileWithInfo(card, CardUtil.getObjectExileZoneId(game, sourcePermanent), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.HAND, true);
|
||||
controller.moveCardToExileWithInfo(card, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.HAND, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,6 @@
|
|||
package mage.sets.tempest;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -39,7 +36,9 @@ import mage.abilities.costs.common.TapSourceCost;
|
|||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
|
@ -56,9 +55,10 @@ public class RootwaterMatriarch extends CardImpl {
|
|||
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// {TAP}: Gain control of target creature for as long as that creature is enchanted
|
||||
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(new GainControlTargetEffect(Duration.OneUse), EnchantedTargetCondition.getInstance(), "Gain control of target creature for as long as that creature is enchanted");
|
||||
|
||||
// {T}: Gain control of target creature for as long as that creature is enchanted
|
||||
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(new GainControlTargetEffect(Duration.Custom), EnchantedTargetCondition.getInstance(),
|
||||
"Gain control of target creature for as long as that creature is enchanted");
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
|
||||
ability.addTarget(new TargetCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
|
|
|
@ -73,7 +73,6 @@ public class AshiokNightmareWeaver extends CardImpl {
|
|||
this.expansionSetCode = "THS";
|
||||
this.subtype.add("Ashiok");
|
||||
|
||||
|
||||
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(3)), false));
|
||||
|
||||
// +2: Exile the top three cards of target opponent's library.
|
||||
|
@ -121,14 +120,9 @@ class AshiokNightmareWeaverExileEffect extends OneShotEffect {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (sourceObject != null && opponent != null && controller != null) {
|
||||
UUID exileZone = CardUtil.getObjectExileZoneId(game, sourceObject);
|
||||
UUID exileZone = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
if (exileZone != null) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Card card = opponent.getLibrary().getFromTop(game);
|
||||
if (card != null) {
|
||||
controller.moveCardToExileWithInfo(card, exileZone, sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true);
|
||||
}
|
||||
}
|
||||
controller.moveCardsToExile(opponent.getLibrary().getTopCards(game, 3), source, game, true, exileZone, sourceObject.getIdName());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -167,11 +161,10 @@ class AshiokNightmareWeaverPutIntoPlayEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
|
||||
FilterCard filter = new FilterCreatureCard(new StringBuilder("creature card with converted mana cost {").append(cmc).append("} exiled with Ashiok, Nightmare Weaver").toString());
|
||||
FilterCard filter = new FilterCreatureCard("creature card with converted mana cost {" + cmc + "} exiled with " + sourceObject.getIdName());
|
||||
filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.Equal, cmc));
|
||||
|
||||
Target target = new TargetCardInExile(filter, CardUtil.getObjectExileZoneId(game, sourceObject));
|
||||
|
||||
Target target = new TargetCardInExile(filter, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()));
|
||||
|
||||
if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
|
||||
if (controller.chooseTarget(Outcome.PutCreatureInPlay, target, source, game)) {
|
||||
|
@ -182,7 +175,7 @@ class AshiokNightmareWeaverPutIntoPlayEffect extends OneShotEffect {
|
|||
if (permanent != null) {
|
||||
permanent.changeControllerId(source.getControllerId(), game);
|
||||
}
|
||||
|
||||
|
||||
ContinuousEffectImpl effect = new AshiokNightmareWeaverAddTypeEffect();
|
||||
effect.setTargetPointer(new FixedTarget(card.getId()));
|
||||
game.addEffect(effect, source);
|
||||
|
@ -267,7 +260,7 @@ class AshiokNightmareWeaverExileAllEffect extends OneShotEffect {
|
|||
if (exileId == null) {
|
||||
return false;
|
||||
}
|
||||
for (UUID opponentId: game.getOpponents(source.getControllerId())) {
|
||||
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
|
||||
Player opponent = game.getPlayer(opponentId);
|
||||
if (opponent != null) {
|
||||
Cards cards = new CardsImpl();
|
||||
|
@ -280,7 +273,7 @@ class AshiokNightmareWeaverExileAllEffect extends OneShotEffect {
|
|||
}
|
||||
cards.clear();
|
||||
cards.addAll(opponent.getGraveyard());
|
||||
for (UUID cardId :cards) {
|
||||
for (UUID cardId : cards) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (card != null) {
|
||||
controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.GRAVEYARD, true);
|
||||
|
|
|
@ -108,7 +108,7 @@ class VesuvanDoppelgangerCopyEffect extends OneShotEffect {
|
|||
controller.choose(Outcome.Copy, target, source.getSourceId(), game);
|
||||
Permanent copyFromPermanent = game.getPermanent(target.getFirstTarget());
|
||||
if (copyFromPermanent != null) {
|
||||
game.copyPermanent(copyFromPermanent, sourcePermanent, source, new ApplyToPermanent() {
|
||||
game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new ApplyToPermanent() {
|
||||
@Override
|
||||
public Boolean apply(Game game, Permanent permanent) {
|
||||
permanent.getColor(game).setColor(sourcePermanent.getColor(game));
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
package mage.sets.urzassaga;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
|
@ -102,7 +104,7 @@ class ShowAndTellEffect extends OneShotEffect {
|
|||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
List<Card> cardsToPutIntoPlay = new ArrayList<>();
|
||||
Set<Card> cardsToPutIntoPlay = new LinkedHashSet<>();
|
||||
TargetCardInHand target = new TargetCardInHand(filter);
|
||||
|
||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
|
@ -119,12 +121,6 @@ class ShowAndTellEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (Card card : cardsToPutIntoPlay) {
|
||||
Player player = game.getPlayer(card.getOwnerId());
|
||||
if (player != null) {
|
||||
player.putOntoBattlefieldWithInfo(card, game, Zone.HAND, source.getSourceId());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return controller.moveCards(cardsToPutIntoPlay, Zone.BATTLEFIELD, source, game, false, false, true, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import java.util.UUID;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.RequirementEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -53,8 +52,7 @@ public class FeralContest extends CardImpl {
|
|||
super(ownerId, 100, "Feral Contest", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{G}");
|
||||
this.expansionSetCode = "WWK";
|
||||
|
||||
|
||||
// Put a +1/+1 counter on target creature you control.
|
||||
// Put a +1/+1 counter on target creature you control.
|
||||
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
|
||||
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
|
||||
// Another target creature blocks it this turn if able.
|
||||
|
@ -88,7 +86,7 @@ class FeralContestEffect extends RequirementEffect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
if (permanent.getId().equals(source.getTargets().get(1).getFirstTarget())) {
|
||||
return permanent.canBlock(source.getFirstTarget(), game);
|
||||
}
|
||||
|
@ -116,4 +114,3 @@ class FeralContestEffect extends RequirementEffect {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -33,8 +33,6 @@ import mage.constants.Outcome;
|
|||
import mage.constants.Rarity;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.common.KickedCondition;
|
||||
import mage.abilities.costs.OptionalAdditionalCost;
|
||||
import mage.abilities.costs.OptionalAdditionalCostImpl;
|
||||
import mage.abilities.costs.common.TapTargetCost;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
|
@ -56,7 +54,7 @@ import mage.target.common.TargetOpponent;
|
|||
*/
|
||||
public class BloodTribute extends CardImpl {
|
||||
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Vampire you control");
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an untapped Vampire you control");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(new TappedPredicate()));
|
||||
|
@ -67,20 +65,18 @@ public class BloodTribute extends CardImpl {
|
|||
super(ownerId, 81, "Blood Tribute", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{B}{B}");
|
||||
this.expansionSetCode = "ZEN";
|
||||
|
||||
|
||||
// Kicker - Tap an untapped Vampire you control.
|
||||
OptionalAdditionalCost cost = new OptionalAdditionalCostImpl("Kicker-","",new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true)));
|
||||
this.addAbility(new KickerAbility(cost));
|
||||
this.addAbility(new KickerAbility(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))));
|
||||
|
||||
// Target opponent loses half his or her life, rounded up.
|
||||
this.getSpellAbility().addTarget(new TargetOpponent());
|
||||
this.getSpellAbility().addEffect(new BloodTributeLoseLifeEffect());
|
||||
|
||||
|
||||
// If Blood Tribute was kicked, you gain life equal to the life lost this way.
|
||||
Effect effect = new ConditionalOneShotEffect(
|
||||
new BloodTributeGainLifeEffect(),
|
||||
KickedCondition.getInstance(),
|
||||
"If Blood Tribute was kicked, you gain life equal to the life lost this way");
|
||||
"If {this} was kicked, you gain life equal to the life lost this way");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,10 @@ public class ProteanHydraTest extends CardTestPlayerBase {
|
|||
@Test
|
||||
public void testEnteringWithCounters() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
|
||||
addCard(Zone.HAND, playerA, "Protean Hydra");
|
||||
// Protean Hydra enters the battlefield with X +1/+1 counters on it.
|
||||
// If damage would be dealt to Protean Hydra, prevent that damage and remove that many +1/+1 counters from it.
|
||||
// Whenever a +1/+1 counter is removed from Protean Hydra, put two +1/+1 counters on it at the beginning of the next end step.
|
||||
addCard(Zone.HAND, playerA, "Protean Hydra"); // CREATURE - {X}{G}
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Protean Hydra");
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class MovingCounterTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
|
@ -51,12 +50,11 @@ public class MovingCounterTest extends CardTestPlayerBase {
|
|||
|
||||
// Move any number of +1/+1 counters from target creature onto another target creature with the same controller.
|
||||
addCard(Zone.HAND, playerA, "Bioshift", 1);
|
||||
|
||||
// Protean Hydra enters the battlefield with X +1/+1 counters on it.
|
||||
// If damage would be dealt to Protean Hydra, prevent that damage and remove that many +1/+1 counters from it.
|
||||
// Whenever a +1/+1 counter is removed from Protean Hydra, put two +1/+1 counters on it at the beginning of the next end step.
|
||||
addCard(Zone.HAND, playerA, "Protean Hydra", 1);
|
||||
|
||||
// Protean Hydra enters the battlefield with X +1/+1 counters on it.
|
||||
// If damage would be dealt to Protean Hydra, prevent that damage and remove that many +1/+1 counters from it.
|
||||
// Whenever a +1/+1 counter is removed from Protean Hydra, put two +1/+1 counters on it at the beginning of the next end step.
|
||||
addCard(Zone.HAND, playerA, "Protean Hydra", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Protean Hydra");
|
||||
setChoice(playerA, "X=4");
|
||||
|
@ -67,14 +65,45 @@ public class MovingCounterTest extends CardTestPlayerBase {
|
|||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Bioshift", 1);
|
||||
|
||||
assertPermanentCount(playerA, "Silvercoat Lion", 1);
|
||||
|
||||
assertPermanentCount(playerA, "Silvercoat Lion", 1);
|
||||
assertPowerToughness(playerA, "Silvercoat Lion", 4, 4); // added 2 counters
|
||||
|
||||
assertPermanentCount(playerA, "Protean Hydra", 1);
|
||||
assertPermanentCount(playerA, "Protean Hydra", 1);
|
||||
assertPowerToughness(playerA, "Protean Hydra", 6, 6); // started with 4, removed 2, added 4 at end = 6
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* I'm having an issue when using Bioshift to move only a portion of
|
||||
* counters to another creature. When I attempt to do this, it moves all of
|
||||
* the counters (and in some cases with my Simic deck) kills the creature.
|
||||
*/
|
||||
@Test
|
||||
public void testFateTransfer() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||
// Noxious Hatchling enters the battlefield with four -1/-1 counters on it.
|
||||
// Wither (This deals damage to creatures in the form of -1/-1 counters.)
|
||||
// Whenever you cast a black spell, remove a -1/-1 counter from Noxious Hatchling.
|
||||
// Whenever you cast a green spell, remove a -1/-1 counter from Noxious Hatchling.
|
||||
addCard(Zone.HAND, playerA, "Noxious Hatchling", 1);// 6/6
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Ruin Processor", 1); // Creature 7/8
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
|
||||
// Move all counters from target creature onto another target creature.
|
||||
addCard(Zone.HAND, playerB, "Fate Transfer", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Noxious Hatchling");
|
||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, "Fate Transfer", "Noxious Hatchling^Ruin Processor");
|
||||
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerB, "Fate Transfer", 1);
|
||||
|
||||
assertPowerToughness(playerA, "Noxious Hatchling", 6, 6);
|
||||
|
||||
assertPowerToughness(playerA, "Ruin Processor", 3, 4);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,8 +51,10 @@ public class MycosynthGolemTest extends CardTestPlayerBase {
|
|||
public void testSpellsAffinity() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
// Affinity for artifacts
|
||||
// Artifact creature spells you cast have affinity for artifacts.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mycosynth Golem");
|
||||
addCard(Zone.HAND, playerA, "Alpha Myr");
|
||||
addCard(Zone.HAND, playerA, "Alpha Myr"); // Creature - Myr 2/1
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Alpha Myr");
|
||||
|
||||
|
|
|
@ -66,6 +66,9 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
|
|||
@Test
|
||||
public void testSpellsReturnToHand() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
||||
// Lifelink
|
||||
// Instant and sorcery spells you control have lifelink.
|
||||
// {2}{U/R}{U/R}: The next time you cast an instant or sorcery spell from your hand this turn, put that card into your hand instead of your graveyard as it resolves.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Soulfire Grand Master");
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||
|
||||
|
@ -199,7 +202,6 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
|
|||
* Test that if Soulfire Grand Master has left the battlefield spell has no
|
||||
* longer lifelink
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testSoulfireLeft() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
|
@ -231,7 +233,6 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
|
|||
* the elemental, so stoke didnt resolve, but i still got the life from
|
||||
* lifelink.
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testSoulfireStokeTheFlames() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8);
|
||||
|
@ -296,7 +297,6 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
|
|||
* Constructed.
|
||||
*
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testWithDeflectingPalm() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.test.cards.conditional;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
|
@ -14,10 +10,10 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
* @author jeff
|
||||
*/
|
||||
public class RootwaterMatriarchTest extends CardTestPlayerBase {
|
||||
|
||||
|
||||
@Test
|
||||
public void testTargetFail() {
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Rootwater Matriarch");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Memnite");
|
||||
|
||||
|
@ -25,73 +21,73 @@ public class RootwaterMatriarchTest extends CardTestPlayerBase {
|
|||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Rootwater Matriarch", 1);
|
||||
assertPermanentCount(playerB, "Memnite", 1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTargetSuccess() {
|
||||
|
||||
// {T}: Gain control of target creature for as long as that creature is enchanted
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Rootwater Matriarch");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Memnite");
|
||||
|
||||
|
||||
addCard(Zone.HAND, playerA, "Flight");
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flight", "Memnite");
|
||||
|
||||
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{T}: Gain control of target creature for as long as that creature is enchanted.", "Memnite");
|
||||
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Rootwater Matriarch", 1);
|
||||
assertPermanentCount(playerA, "Memnite", 1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGainControlEnchantedTargetAndRWLeavesPlay() {
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Rootwater Matriarch");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Memnite");
|
||||
addCard(Zone.HAND, playerA, "Unsummon");
|
||||
addCard(Zone.HAND, playerA, "Flight");
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flight", "Memnite");
|
||||
|
||||
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{T}: Gain control of target creature for as long as that creature is enchanted.", "Memnite");
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Unsummon", "Rootwater Matriarch");
|
||||
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Rootwater Matriarch", 0);
|
||||
assertPermanentCount(playerA, "Memnite", 1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGainControlEnchantedTargetAndAuraIsDisenchanted() {
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Rootwater Matriarch");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Memnite");
|
||||
addCard(Zone.HAND, playerA, "Disenchant");
|
||||
addCard(Zone.HAND, playerA, "Flight");
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flight", "Memnite");
|
||||
|
||||
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{T}: Gain control of target creature for as long as that creature is enchanted.", "Memnite");
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disenchant", "Flight");
|
||||
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Rootwater Matriarch", 1);
|
||||
assertPermanentCount(playerB, "Memnite", 1);
|
||||
}
|
||||
|
|
|
@ -202,6 +202,9 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Llanowar Elves");
|
||||
addCard(Zone.HAND, playerA, "Phantasmal Image");
|
||||
|
||||
// As Lurebound Scarecrow enters the battlefield, choose a color.
|
||||
// When you control no permanents of the chosen color, sacrifice Lurebound Scarecrow.
|
||||
addCard(Zone.HAND, playerA, "Lurebound Scarecrow");
|
||||
|
||||
setChoice(playerA, "Green");
|
||||
|
@ -324,7 +327,7 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
|
|||
addCard(Zone.HAND, playerB, "Phantasmal Image");
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Phantasmal Image"); // not targeted
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Veil of Secrecy", "Frost Titan"); // so it's no longer targetable
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Veil of Secrecy", "Frost Titan"); // so it's no longer targetable
|
||||
setChoice(playerB, "Frost Titan");
|
||||
|
||||
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Terror", "Frost Titan"); // of player Bs Phantasmal Image copying Frost Titan
|
||||
|
@ -346,7 +349,7 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
|
|||
}
|
||||
|
||||
// I've casted a Phantasmal Image targeting opponent's Wurmcoil Engine
|
||||
// When my Phantasmal Image died, it didn't triggered the Wurmcoil Engine's last ability
|
||||
// When my Phantasmal Image died, it didn't triggered the Wurmcoil Engine's last ability
|
||||
// (When Wurmcoil Engine dies, put a 3/3 colorless Wurm artifact creature token with deathtouch and
|
||||
// a 3/3 colorless Wurm artifact creature token with lifelink onto the battlefield.)
|
||||
@Test
|
||||
|
@ -418,31 +421,39 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Action
|
||||
* Game State 1 -----------------> Game State 2
|
||||
* (On 'field) (Move to GY) (In graveyard)
|
||||
*
|
||||
* LTB abilities such as Persist are expceptional in that they trigger based on their existence and
|
||||
* state of objects before the event (Game State 1, when the card is on the battlefield) rather than
|
||||
* after (Game State 2, when the card is in the graveyard). It doesn't matter that the LTB ability
|
||||
* doesn't exist in Game State 2. [CR 603.6d]
|
||||
*
|
||||
* 603.6d Normally, objects that exist immediately after an event are checked to see if the event matched any trigger conditions.
|
||||
* Continuous effects that exist at that time are used to determine what the trigger conditions are and what the objects involved
|
||||
* in the event look like. However, some triggered abilities must be treated specially. Leaves-the-battlefield abilities, abilities
|
||||
* that trigger when a permanent phases out, abilities that trigger when an object that all players can see is put into a hand or
|
||||
* library, abilities that trigger specifically when an object becomes unattached, abilities that trigger when a player loses control
|
||||
* of an object, and abilities that trigger when a player planeswalks away from a plane will trigger based on their existence, and
|
||||
* the appearance of objects, prior to the event rather than afterward. The game has to “look back in time” to determine if these abilities trigger.
|
||||
*
|
||||
* Example: Two creatures are on the battlefield along with an artifact that has the ability “Whenever a creature dies, you gain 1 life.”
|
||||
* Someone plays a spell that destroys all artifacts, creatures, and enchantments. The artifact’s ability triggers twice, even though
|
||||
* the artifact goes to its owner’s graveyard at the same time as the creatures.
|
||||
*
|
||||
* Action Game State 1 -----------------> Game State 2 (On 'field) (Move to
|
||||
* GY) (In graveyard)
|
||||
*
|
||||
* LTB abilities such as Persist are expceptional in that they trigger based
|
||||
* on their existence and state of objects before the event (Game State 1,
|
||||
* when the card is on the battlefield) rather than after (Game State 2,
|
||||
* when the card is in the graveyard). It doesn't matter that the LTB
|
||||
* ability doesn't exist in Game State 2. [CR 603.6d]
|
||||
*
|
||||
* 603.6d Normally, objects that exist immediately after an event are
|
||||
* checked to see if the event matched any trigger conditions. Continuous
|
||||
* effects that exist at that time are used to determine what the trigger
|
||||
* conditions are and what the objects involved in the event look like.
|
||||
* However, some triggered abilities must be treated specially.
|
||||
* Leaves-the-battlefield abilities, abilities that trigger when a permanent
|
||||
* phases out, abilities that trigger when an object that all players can
|
||||
* see is put into a hand or library, abilities that trigger specifically
|
||||
* when an object becomes unattached, abilities that trigger when a player
|
||||
* loses control of an object, and abilities that trigger when a player
|
||||
* planeswalks away from a plane will trigger based on their existence, and
|
||||
* the appearance of objects, prior to the event rather than afterward. The
|
||||
* game has to “look back in time” to determine if these abilities trigger.
|
||||
*
|
||||
* Example: Two creatures are on the battlefield along with an artifact that
|
||||
* has the ability “Whenever a creature dies, you gain 1 life.” Someone
|
||||
* plays a spell that destroys all artifacts, creatures, and enchantments.
|
||||
* The artifact’s ability triggers twice, even though the artifact goes to
|
||||
* its owner’s graveyard at the same time as the creatures.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testPersist() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||
// When Kitchen Finks enters the battlefield, you gain 2 life.
|
||||
// Persist (When this creature dies, if it had no -1/-1 counters on it, return it to the battlefield under its owner's control with a -1/-1 counter on it.)
|
||||
addCard(Zone.HAND, playerA, "Kitchen Finks");
|
||||
|
@ -452,21 +463,20 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
|
||||
|
||||
|
||||
// You may have Phantasmal Image enter the battlefield as a copy of any creature
|
||||
// on the battlefield, except it's an Illusion in addition to its other types and
|
||||
// it gains "When this creature becomes the target of a spell or ability, sacrifice it."
|
||||
// it gains "When this creature becomes the target of a spell or ability, sacrifice it."
|
||||
addCard(Zone.HAND, playerB, "Phantasmal Image");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitchen Finks");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitchen Finks");
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Phantasmal Image"); // not targeted
|
||||
setChoice(playerB, "Kitchen Finks");
|
||||
|
||||
|
||||
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Public Execution", "Kitchen Finks");
|
||||
setChoice(playerB, "Kitchen Finks");
|
||||
|
||||
|
||||
setStopAt(2, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
|
@ -480,13 +490,13 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
|
|||
assertHandCount(playerB, "Phantasmal Image", 0);
|
||||
assertGraveyardCount(playerB, "Phantasmal Image", 0);
|
||||
assertPermanentCount(playerB, "Kitchen Finks", 1);
|
||||
assertPowerToughness(playerB, "Kitchen Finks", 2, 1);
|
||||
assertPowerToughness(playerB, "Kitchen Finks", 2, 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUndying() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
// Undying (When this creature dies, if it had no +1/+1 counters on it, return it to the battlefield under its owner's control with a +1/+1 counter on it.)
|
||||
addCard(Zone.HAND, playerA, "Butcher Ghoul");
|
||||
|
||||
|
@ -495,21 +505,20 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
|
||||
|
||||
|
||||
// You may have Phantasmal Image enter the battlefield as a copy of any creature
|
||||
// on the battlefield, except it's an Illusion in addition to its other types and
|
||||
// it gains "When this creature becomes the target of a spell or ability, sacrifice it."
|
||||
// it gains "When this creature becomes the target of a spell or ability, sacrifice it."
|
||||
addCard(Zone.HAND, playerB, "Phantasmal Image");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Butcher Ghoul");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Butcher Ghoul");
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Phantasmal Image"); // not targeted
|
||||
setChoice(playerB, "Butcher Ghoul");
|
||||
|
||||
|
||||
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Public Execution", "Butcher Ghoul");
|
||||
setChoice(playerB, "Butcher Ghoul");
|
||||
|
||||
|
||||
setStopAt(2, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
|
@ -523,29 +532,25 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
|
|||
assertHandCount(playerB, "Phantasmal Image", 0);
|
||||
assertGraveyardCount(playerB, "Phantasmal Image", 0);
|
||||
assertPermanentCount(playerB, "Butcher Ghoul", 1);
|
||||
assertPowerToughness(playerB, "Butcher Ghoul", 2, 2);
|
||||
assertPowerToughness(playerB, "Butcher Ghoul", 2, 2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 12:29: Attacker: Wurmcoil Engine [466] (6/6) blocked by Wurmcoil Engine
|
||||
* [4ed] (6/6)
|
||||
* 12:29: yespair gains 6 life
|
||||
* 12:29: HipSomHap gains 6 life
|
||||
* 12:29: Wurmcoil Engine [4ed] died
|
||||
* 12:29: Ability triggers: Wurmcoil Engine [4ed] - When Wurmcoil Engine [4ed] dies, put a a 3/3 colorless
|
||||
* [4ed] (6/6) 12:29: yespair gains 6 life 12:29: HipSomHap gains 6 life
|
||||
* 12:29: Wurmcoil Engine [4ed] died 12:29: Ability triggers: Wurmcoil
|
||||
* Engine [4ed] - When Wurmcoil Engine [4ed] dies, put a a 3/3 colorless
|
||||
* Wurm artifact creature token with deathtouch onto the battlefield. Put a
|
||||
* a 3/3 colorless Wurm artifact creature token with lifelink onto the
|
||||
* battlefield.
|
||||
* 12:29: Phantasmal Image [466] died
|
||||
* 12:29: HipSomHap puts a Wurm [7d0] token onto the battlefield
|
||||
* 12:29: HipSomHap puts a Wurm [186] token onto the battlefield
|
||||
* battlefield. 12:29: Phantasmal Image [466] died 12:29: HipSomHap puts a
|
||||
* Wurm [7d0] token onto the battlefield 12:29: HipSomHap puts a Wurm [186]
|
||||
* token onto the battlefield
|
||||
*
|
||||
* To the best of my knowledge, the Phantasmal Image [466], which entered
|
||||
* the battlefield as a Wurmcoil Engine, should grant tokens through the
|
||||
* Dies-trigger as well, right?
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testDiesTriggered2() {
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Wurmcoil Engine");
|
||||
|
@ -570,5 +575,5 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
|
|||
assertPermanentCount(playerA, "Wurm", 2);
|
||||
assertPermanentCount(playerB, "Wurm", 2);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,10 +36,8 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class PhyrexianMetamorphTest extends CardTestPlayerBase {
|
||||
|
||||
|
||||
@Test
|
||||
public void testCopyCreature() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
|
@ -48,7 +46,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
|
|||
// You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types.
|
||||
addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{UP}
|
||||
addCard(Zone.HAND, playerA, "Cloudshift");
|
||||
|
||||
|
||||
//Flying
|
||||
// Vanishing 3 (This permanent enters the battlefield with three time counters on it. At the beginning of your upkeep, remove a time counter from it. When the last is removed, sacrifice it.)
|
||||
// When Aven Riftwatcher enters the battlefield or leaves the battlefield, you gain 2 life.
|
||||
|
@ -68,13 +66,13 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
|
|||
|
||||
assertLife(playerA, 24);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
|
||||
assertGraveyardCount(playerA, "Cloudshift", 1);
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Ponyback Brigade", 1);
|
||||
assertPermanentCount(playerA, "Goblin", 3);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An opponent cast Phyrexian Metamorph and cloned another opponent's
|
||||
|
@ -84,7 +82,6 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
|
|||
* to choose a new creature to clone when the Phyrexian Metamorph re-entered
|
||||
* the battlefield.
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testFlickerWithBrago() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
|
@ -93,9 +90,9 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
|
|||
addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{UP}
|
||||
|
||||
// Flying
|
||||
// When Brago, King Eternal deals combat damage to a player, exile any number of target nonland permanents you control, then return those cards to the battlefield under their owner's control.
|
||||
// When Brago, King Eternal deals combat damage to a player, exile any number of target nonland permanents you control, then return those cards to the battlefield under their owner's control.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Brago, King Eternal"); // 2/4
|
||||
|
||||
|
||||
// Creatures you control have haste.
|
||||
// Cascade, cascade
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Maelstrom Wanderer"); // 7/5
|
||||
|
@ -106,19 +103,19 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
|
|||
setChoice(playerA, "Maelstrom Wanderer");
|
||||
|
||||
attack(3, playerA, "Brago, King Eternal");
|
||||
addTarget(playerA, "Maelstrom Wanderer");
|
||||
addTarget(playerA, "Maelstrom Wanderer");
|
||||
setChoice(playerA, "Ponyback Brigade");
|
||||
|
||||
|
||||
setStopAt(3, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 18);
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Ponyback Brigade", 1);
|
||||
assertPermanentCount(playerA, "Goblin", 3);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* I had a Harmonic Sliver, my opponent played Phyrexian Metamorph copying
|
||||
|
@ -126,7 +123,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
|
|||
* destroying ability, where it should have had two of them and triggered
|
||||
* twice (the Metamorph might have nothing to do with this)
|
||||
*/
|
||||
@Test
|
||||
@Test
|
||||
public void testHarmonicSliver() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
|
||||
|
@ -137,7 +134,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerB, "Kitesail", 1);
|
||||
// All Slivers have "When this permanent enters the battlefield, destroy target artifact or enchantment."
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Harmonic Sliver"); // 2/4
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Phyrexian Metamorph");
|
||||
setChoice(playerA, "Harmonic Sliver");
|
||||
addTarget(playerA, "Alloy Myr");
|
||||
|
@ -145,66 +142,116 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
|
|||
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Harmonic Sliver", 1);
|
||||
|
||||
assertGraveyardCount(playerB, "Alloy Myr", 1);
|
||||
assertGraveyardCount(playerB, "Kitesail", 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* If a Harmonic Sliver enters the battlefield
|
||||
* the controller has to destroy one artifacts or enchantments
|
||||
* If a Harmonic Sliver enters the battlefield the controller has to destroy
|
||||
* one artifacts or enchantments
|
||||
*/
|
||||
@Test
|
||||
public void testHarmonicSliverNative1() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
|
||||
// All Slivers have "When this permanent enters the battlefield, destroy target artifact or enchantment."
|
||||
addCard(Zone.HAND, playerA, "Harmonic Sliver");
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Alloy Myr", 2); // 2/2
|
||||
|
||||
// All Slivers have "When this permanent enters the battlefield, destroy target artifact or enchantment."
|
||||
addCard(Zone.HAND, playerA, "Harmonic Sliver");
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Alloy Myr", 2); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Harmonic Sliver");
|
||||
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Harmonic Sliver", 1);
|
||||
|
||||
assertGraveyardCount(playerB, "Alloy Myr", 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* If a Harmonic Sliver enters the battlefield and there is already one on the battlefield
|
||||
* the controller has to destroy two artifacts or enchantments
|
||||
* If a Harmonic Sliver enters the battlefield and there is already one on
|
||||
* the battlefield the controller has to destroy two artifacts or
|
||||
* enchantments
|
||||
*/
|
||||
@Test
|
||||
public void testHarmonicSliverNative2() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
|
||||
addCard(Zone.HAND, playerA, "Harmonic Sliver");
|
||||
|
||||
addCard(Zone.HAND, playerA, "Harmonic Sliver");
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Alloy Myr", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Kitesail", 1);
|
||||
// All Slivers have "When this permanent enters the battlefield, destroy target artifact or enchantment."
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Harmonic Sliver"); // 2/4
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Harmonic Sliver");
|
||||
addTarget(playerA, "Alloy Myr");
|
||||
addTarget(playerA, "Kitesail");
|
||||
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Harmonic Sliver", 1);
|
||||
|
||||
assertGraveyardCount(playerB, "Alloy Myr", 1);
|
||||
assertGraveyardCount(playerB, "Kitesail", 1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* I cast Show and Tell, and put Sheoldred, Whispering One into play and my
|
||||
* opponent put Phyrexian Metamorph into play and he was able to clone my
|
||||
* Sheoldred, Whispering One.
|
||||
*
|
||||
* 6/1/2011 If Phyrexian Metamorph somehow enters the battlefield at the
|
||||
* same time as another permanent (due to Mass Polymorph or Liliana Vess's
|
||||
* third ability, for example), Phyrexian Metamorph can't become a copy of
|
||||
* that permanent. You may only choose a permanent that's already on the
|
||||
* battlefield.
|
||||
*
|
||||
* 400.6. If an object would move from one zone to another, determine what
|
||||
* event is moving the object. If the object is moving to a public zone, all
|
||||
* players look at it to see if it has any abilities that would affect the
|
||||
* move. Then any appropriate replacement effects, whether they come from
|
||||
* that object or from elsewhere, are applied to that event. If any effects
|
||||
* or rules try to do two or more contradictory or mutually exclusive things
|
||||
* to a particular object, that object's controller -- or its owner if it
|
||||
* has no controller -- chooses which effect to apply, and what that effect
|
||||
* does. (Note that multiple instances of the same thing may be mutually
|
||||
* exclusive; for example, two simultaneous "destroy" effects.) Then the
|
||||
* event moves the object.
|
||||
*/
|
||||
@Test
|
||||
public void testShowAndTell() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||
|
||||
// Each player may put an artifact, creature, enchantment, or land card from his or her hand onto the battlefield.
|
||||
addCard(Zone.HAND, playerA, "Show and Tell"); // SORCERY {2}{U}
|
||||
|
||||
// Swampwalk
|
||||
// At the beginning of your upkeep, return target creature card from your graveyard to the battlefield.
|
||||
// At the beginning of each opponent's upkeep, that player sacrifices a creature.
|
||||
addCard(Zone.HAND, playerA, "Sheoldred, Whispering One");
|
||||
|
||||
addCard(Zone.HAND, playerB, "Phyrexian Metamorph");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Show and Tell");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Sheoldred, Whispering One", 1);
|
||||
assertPermanentCount(playerB, "Sheoldred, Whispering One", 0);
|
||||
|
||||
assertGraveyardCount(playerB, "Phyrexian Metamorph", 1);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,10 +92,10 @@ public class OblivionRingTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Jace Beleren");
|
||||
addCard(Zone.HAND, playerA, "Revoke Existence");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-1: Target player draws one card", playerA);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-1: Target player draws a card", playerA);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oblivion Ring");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Revoke Existence", "Oblivion Ring");
|
||||
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "-1: Target player draws one card", playerA);
|
||||
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "-1: Target player draws a card", playerA);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
|
|
@ -554,7 +554,7 @@ public class TestPlayer implements Player {
|
|||
if (!choices.isEmpty()) {
|
||||
for (String choice : choices) {
|
||||
for (int index = 0; index < rEffects.size(); index++) {
|
||||
if (choice.equals(rEffects.get(index))) {
|
||||
if (choice.equals(rEffects.get(Integer.toString(index)))) {
|
||||
choices.remove(choice);
|
||||
return index;
|
||||
}
|
||||
|
@ -1951,6 +1951,11 @@ public class TestPlayer implements Player {
|
|||
return computerPlayer.scry(value, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) {
|
||||
return computerPlayer.moveCards(cards, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
|
||||
}
|
||||
|
||||
public void setAIPlayer(boolean AIPlayer) {
|
||||
this.AIPlayer = AIPlayer;
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
if (card == null) {
|
||||
throw new IllegalArgumentException("[TEST] Couldn't find a card: " + cardName);
|
||||
}
|
||||
PermanentCard p = new PermanentCard(card, null, currentGame);
|
||||
PermanentCard p = new PermanentCard(card, player.getId(), currentGame);
|
||||
p.setTapped(tapped);
|
||||
getBattlefieldCards(player).add(p);
|
||||
}
|
||||
|
|
|
@ -2,17 +2,25 @@ package mage.abilities.common;
|
|||
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
public class AttacksOrBlocksTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
protected String startText = "Whenever";
|
||||
|
||||
public AttacksOrBlocksTriggeredAbility(Effect effect, boolean optional) {
|
||||
super(Zone.BATTLEFIELD, effect, optional);
|
||||
if (effect instanceof CreateDelayedTriggeredAbilityEffect) {
|
||||
startText = "When";
|
||||
}
|
||||
}
|
||||
|
||||
public AttacksOrBlocksTriggeredAbility(final AttacksOrBlocksTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.startText = ability.startText;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -22,8 +30,9 @@ public class AttacksOrBlocksTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When {this} attacks or blocks, " + super.getRule();
|
||||
return startText + " {this} attacks or blocks, " + super.getRule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ATTACKER_DECLARED || event.getType() == GameEvent.EventType.BLOCKER_DECLARED;
|
||||
|
|
|
@ -60,7 +60,7 @@ public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl {
|
|||
// So check here with the LKI of the enchantment
|
||||
Permanent attachment = game.getPermanentOrLKIBattlefield(getSourceId());
|
||||
if (attachment != null && attachment.getAttachedTo().equals(zEvent.getTargetId())
|
||||
&& attachment.getAttachedToZoneChangeCounter() == zEvent.getTarget().getZoneChangeCounter(game)) {
|
||||
&& attachment.getAttachedToZoneChangeCounter() == zEvent.getTarget().getZoneChangeCounter(game) - 1) {
|
||||
triggered = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.constants.CardType;
|
||||
|
@ -15,8 +13,8 @@ import mage.target.Target;
|
|||
* @author Jeff
|
||||
*/
|
||||
public class EnchantedTargetCondition implements Condition {
|
||||
|
||||
private static EnchantedTargetCondition fInstance = new EnchantedTargetCondition();
|
||||
|
||||
private static final EnchantedTargetCondition fInstance = new EnchantedTargetCondition();
|
||||
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
|
|
|
@ -25,20 +25,18 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.costs;
|
||||
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* Alternative costs
|
||||
*
|
||||
*
|
||||
* @author LevelX2
|
||||
*
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
|
||||
public class AlternativeCost2Impl <T extends AlternativeCost2Impl<T>> extends CostsImpl<Cost> implements AlternativeCost2 {
|
||||
public class AlternativeCost2Impl<T extends AlternativeCost2Impl<T>> extends CostsImpl<Cost> implements AlternativeCost2 {
|
||||
|
||||
protected String name;
|
||||
protected String reminderText;
|
||||
|
@ -72,6 +70,7 @@ public class AlternativeCost2Impl <T extends AlternativeCost2Impl<T>> extends Co
|
|||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the complete text for the addional cost or if onlyCost is true
|
||||
* only the pure text for the included native cost
|
||||
|
@ -84,7 +83,7 @@ public class AlternativeCost2Impl <T extends AlternativeCost2Impl<T>> extends Co
|
|||
if (onlyCost) {
|
||||
return getText();
|
||||
} else {
|
||||
return new StringBuffer(name != null ? name: "").append(delimiter != null ? delimiter: "").append(getText()).toString();
|
||||
return (name != null ? name : "") + (delimiter != null ? delimiter : "") + getText();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,20 +102,20 @@ public class AlternativeCost2Impl <T extends AlternativeCost2Impl<T>> extends Co
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a text suffix for the game log, that can be added to
|
||||
* the cast message.
|
||||
* Returns a text suffix for the game log, that can be added to the cast
|
||||
* message.
|
||||
*
|
||||
* @param position - if there are multiple costs, it's the postion the cost is set (starting with 0)
|
||||
* @param position - if there are multiple costs, it's the postion the cost
|
||||
* is set (starting with 0)
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getCastSuffixMessage(int position) {
|
||||
StringBuilder sb = new StringBuilder(position > 0 ? " and ":"").append(" with ");
|
||||
StringBuilder sb = new StringBuilder(position > 0 ? " and " : "").append(" with ");
|
||||
sb.append(name);
|
||||
return sb.toString();
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If the player intends to pay the cost, the cost will be activated
|
||||
*
|
||||
|
@ -124,7 +123,9 @@ public class AlternativeCost2Impl <T extends AlternativeCost2Impl<T>> extends Co
|
|||
@Override
|
||||
public void activate() {
|
||||
activated = true;
|
||||
};
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* Reset the activate and count information
|
||||
|
@ -142,9 +143,11 @@ public class AlternativeCost2Impl <T extends AlternativeCost2Impl<T>> extends Co
|
|||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isActivated(Game game){
|
||||
public boolean isActivated(Game game) {
|
||||
return activated;
|
||||
};
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
@Override
|
||||
public AlternativeCost2Impl copy() {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package mage.abilities.costs;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.Game;
|
||||
import mage.target.Targets;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CompositeCost implements Cost {
|
||||
private Cost firstCost;
|
||||
private Cost secondCost;
|
||||
|
||||
private final Cost firstCost;
|
||||
private final Cost secondCost;
|
||||
private String description;
|
||||
|
||||
public CompositeCost(Cost firstCost, Cost secondCost, String description) {
|
||||
|
@ -28,6 +28,11 @@ public class CompositeCost implements Cost {
|
|||
throw new RuntimeException("Not supported method");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String text) {
|
||||
this.description = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return description;
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.costs;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -37,12 +36,21 @@ import mage.target.Targets;
|
|||
public interface Cost extends Serializable {
|
||||
|
||||
UUID getId();
|
||||
|
||||
String getText();
|
||||
|
||||
void setText(String text);
|
||||
|
||||
boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game);
|
||||
|
||||
boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana);
|
||||
|
||||
boolean isPaid();
|
||||
|
||||
void clearPaid();
|
||||
|
||||
void setPaid();
|
||||
|
||||
Targets getTargets();
|
||||
|
||||
Cost copy();
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.costs;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -57,6 +56,7 @@ public abstract class CostImpl implements Cost {
|
|||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.costs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -44,12 +43,16 @@ import mage.target.Targets;
|
|||
*/
|
||||
public class CostsImpl<T extends Cost> extends ArrayList<T> implements Costs<T> {
|
||||
|
||||
public CostsImpl() {}
|
||||
protected String text = null;
|
||||
|
||||
public CostsImpl() {
|
||||
}
|
||||
|
||||
public CostsImpl(final CostsImpl<T> costs) {
|
||||
for (Cost cost: costs) {
|
||||
this.add((T)cost.copy());
|
||||
for (Cost cost : costs) {
|
||||
this.add((T) cost.copy());
|
||||
}
|
||||
this.text = costs.text;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,20 +60,28 @@ public class CostsImpl<T extends Cost> extends ArrayList<T> implements Costs<T>
|
|||
throw new RuntimeException("Not supported method");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
if (text != null) {
|
||||
return text;
|
||||
}
|
||||
if (this.size() == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder sbText = new StringBuilder();
|
||||
for (T cost: this) {
|
||||
String text = cost.getText();
|
||||
if (text != null && !text.isEmpty()) {
|
||||
sbText.append(Character.toUpperCase(text.charAt(0))).append(text.substring(1)).append(", ");
|
||||
for (T cost : this) {
|
||||
String textCost = cost.getText();
|
||||
if (textCost != null && !textCost.isEmpty()) {
|
||||
sbText.append(Character.toUpperCase(textCost.charAt(0))).append(textCost.substring(1)).append(", ");
|
||||
}
|
||||
}
|
||||
if (sbText.length() > 1){
|
||||
if (sbText.length() > 1) {
|
||||
sbText.setLength(sbText.length() - 2);
|
||||
}
|
||||
return sbText.toString();
|
||||
|
@ -78,7 +89,7 @@ public class CostsImpl<T extends Cost> extends ArrayList<T> implements Costs<T>
|
|||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||
for (T cost: this) {
|
||||
for (T cost : this) {
|
||||
if (!cost.canPay(ability, sourceId, controllerId, game)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -101,7 +112,7 @@ public class CostsImpl<T extends Cost> extends ArrayList<T> implements Costs<T>
|
|||
|
||||
@Override
|
||||
public boolean isPaid() {
|
||||
for (T cost: this) {
|
||||
for (T cost : this) {
|
||||
if (!(cost instanceof VariableManaCost) && !cost.isPaid()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -111,14 +122,14 @@ public class CostsImpl<T extends Cost> extends ArrayList<T> implements Costs<T>
|
|||
|
||||
@Override
|
||||
public void clearPaid() {
|
||||
for (T cost: this) {
|
||||
for (T cost : this) {
|
||||
cost.clearPaid();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaid() {
|
||||
for (T cost: this) {
|
||||
for (T cost : this) {
|
||||
cost.setPaid();
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +137,7 @@ public class CostsImpl<T extends Cost> extends ArrayList<T> implements Costs<T>
|
|||
@Override
|
||||
public Costs<T> getUnpaid() {
|
||||
Costs<T> unpaid = new CostsImpl<>();
|
||||
for (T cost: this) {
|
||||
for (T cost : this) {
|
||||
if (!cost.isPaid()) {
|
||||
unpaid.add(cost);
|
||||
}
|
||||
|
@ -140,17 +151,17 @@ public class CostsImpl<T extends Cost> extends ArrayList<T> implements Costs<T>
|
|||
return unpaid.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VariableCost> getVariableCosts() {
|
||||
List<VariableCost> variableCosts = new ArrayList<>();
|
||||
for (T cost: this) {
|
||||
for (T cost : this) {
|
||||
if (cost instanceof VariableCost) {
|
||||
variableCosts.add((VariableCost) cost);
|
||||
}
|
||||
if (cost instanceof ManaCosts) {
|
||||
variableCosts.addAll(((ManaCosts)cost).getVariableCosts());
|
||||
variableCosts.addAll(((ManaCosts) cost).getVariableCosts());
|
||||
}
|
||||
}
|
||||
return variableCosts;
|
||||
|
@ -159,7 +170,7 @@ public class CostsImpl<T extends Cost> extends ArrayList<T> implements Costs<T>
|
|||
@Override
|
||||
public Targets getTargets() {
|
||||
Targets targets = new Targets();
|
||||
for (T cost: this) {
|
||||
for (T cost : this) {
|
||||
if (cost.getTargets() != null) {
|
||||
targets.addAll(cost.getTargets());
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public class OptionalAdditionalCostImpl<T extends OptionalAdditionalCostImpl> ex
|
|||
this.activated = false;
|
||||
this.name = name;
|
||||
this.delimiter = delimiter;
|
||||
this.reminderText = new StringBuilder("<i>").append(reminderText).append("</i>").toString();
|
||||
this.reminderText = "<i>(" + reminderText + ")</i>";
|
||||
this.activatedCounter = 0;
|
||||
this.add((Cost) cost);
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ public class OptionalAdditionalCostImpl<T extends OptionalAdditionalCostImpl> ex
|
|||
if (onlyCost) {
|
||||
return getText();
|
||||
} else {
|
||||
return new StringBuffer(name).append(delimiter).append(getText()).toString();
|
||||
return name + delimiter + getText();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@ import mage.target.Targets;
|
|||
|
||||
public class OrCost implements Cost {
|
||||
|
||||
private Cost firstCost;
|
||||
private Cost secondCost;
|
||||
private final Cost firstCost;
|
||||
private final Cost secondCost;
|
||||
private String description;
|
||||
// which cost was slected to pay
|
||||
private Cost selectedCost;
|
||||
|
@ -61,6 +61,11 @@ public class OrCost implements Cost {
|
|||
throw new RuntimeException("Not supported method");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String text) {
|
||||
this.description = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return description;
|
||||
|
|
|
@ -77,6 +77,11 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
|||
this.amountPaid = cost.amountPaid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return text;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
@ -20,21 +20,20 @@
|
|||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.costs.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.constants.Outcome;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
|
@ -44,23 +43,23 @@ import mage.target.common.TargetCardInHand;
|
|||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class DiscardTargetCost extends CostImpl {
|
||||
|
||||
|
||||
List<Card> cards = new ArrayList<>();
|
||||
protected boolean randomDiscard;
|
||||
|
||||
public DiscardTargetCost(TargetCardInHand target) {
|
||||
this(target, false);
|
||||
}
|
||||
|
||||
|
||||
public DiscardTargetCost(TargetCardInHand target, boolean randomDiscard) {
|
||||
this.addTarget(target);
|
||||
this.randomDiscard = randomDiscard;
|
||||
this.text = "Discard " + target.getTargetName();
|
||||
this.text = "discard " + target.getTargetName();
|
||||
}
|
||||
|
||||
public DiscardTargetCost(DiscardTargetCost cost) {
|
||||
super(cost);
|
||||
for (Card card: cost.cards) {
|
||||
for (Card card : cost.cards) {
|
||||
this.cards.add(card.copy());
|
||||
}
|
||||
this.randomDiscard = cost.randomDiscard;
|
||||
|
@ -74,11 +73,11 @@ public class DiscardTargetCost extends CostImpl {
|
|||
return false;
|
||||
}
|
||||
int amount = this.getTargets().get(0).getNumberOfTargets();
|
||||
if (randomDiscard) {
|
||||
if (randomDiscard) {
|
||||
this.cards.addAll(player.discard(amount, true, ability, game).getCards(game));
|
||||
} else {
|
||||
if (targets.choose(Outcome.Discard, controllerId, sourceId, game)) {
|
||||
for (UUID targetId: targets.get(0).getTargets()) {
|
||||
if (targets.choose(Outcome.Discard, controllerId, sourceId, game)) {
|
||||
for (UUID targetId : targets.get(0).getTargets()) {
|
||||
Card card = player.getHand().get(targetId, game);
|
||||
if (card == null) {
|
||||
return false;
|
||||
|
@ -94,7 +93,7 @@ public class DiscardTargetCost extends CostImpl {
|
|||
|
||||
@Override
|
||||
public void clearPaid() {
|
||||
super.clearPaid();
|
||||
super.clearPaid();
|
||||
cards.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class TapTargetCost extends CostImpl {
|
|||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||
return target.canChoose(controllerId, game);
|
||||
return target.canChoose(sourceId, controllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -51,6 +51,7 @@ import mage.util.ManaUtil;
|
|||
public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements ManaCosts<T> {
|
||||
|
||||
protected UUID id;
|
||||
protected String text = null;
|
||||
|
||||
private static Map<String, ManaCosts> costs = new HashMap<>();
|
||||
|
||||
|
@ -372,8 +373,16 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
|||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
if (text != null) {
|
||||
return text;
|
||||
}
|
||||
if (this.size() == 0) {
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ import mage.game.events.GameEvent;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ConditionalContinuousRuleModifyingEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
public class ConditionalContinuousRuleModifyingEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
protected ContinuousRuleModifyingEffect effect;
|
||||
protected ContinuousRuleModifyingEffect otherwiseEffect;
|
||||
|
@ -88,7 +88,6 @@ public class ConditionalContinuousRuleModifyingEffect extends ContinuousRuleModi
|
|||
initDone = true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDiscarded() {
|
||||
return effect.isDiscarded() || (otherwiseEffect != null && otherwiseEffect.isDiscarded());
|
||||
|
@ -136,4 +135,20 @@ public class ConditionalContinuousRuleModifyingEffect extends ContinuousRuleModi
|
|||
public ConditionalContinuousRuleModifyingEffect copy() {
|
||||
return new ConditionalContinuousRuleModifyingEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendMessageToGameLog() {
|
||||
return effect.sendMessageToGameLog(); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendMessageToUser() {
|
||||
return effect.sendMessageToUser(); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
return effect.getInfoMessage(source, event, game); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,13 +36,13 @@ import mage.cards.Card;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackAbility;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
|
@ -103,12 +103,12 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
UUID targetId = null;
|
||||
MageObject sourceObject = game.getObject(sourceId);
|
||||
boolean enchantCardInGraveyard = false;
|
||||
if (sourceObject instanceof Spell) {
|
||||
if (fromZone.equals(Zone.EXILED)) {
|
||||
// cast from exile (e.g. Neightveil Spector) -> no replacement
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// if (sourceObject instanceof Spell) {
|
||||
// if (fromZone.equals(Zone.EXILED)) {
|
||||
// // cast from exile (e.g. Neightveil Spector) -> no replacement
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
if (sourceObject instanceof StackAbility) {
|
||||
StackAbility stackAbility = (StackAbility) sourceObject;
|
||||
if (!stackAbility.getEffects().isEmpty()) {
|
||||
|
@ -118,25 +118,34 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
|
||||
game.applyEffects(); // So continuousEffects are removed if previous effect of the same ability did move objects that cuase continuous effects
|
||||
if (targetId == null) {
|
||||
Target target = card.getSpellAbility().getTargets().get(0).copy();
|
||||
SpellAbility spellAbility = card.getSpellAbility();
|
||||
if (spellAbility.getTargets().isEmpty()) {
|
||||
for (Ability ability : card.getAbilities(game)) {
|
||||
if ((ability instanceof SpellAbility)
|
||||
&& SpellAbilityType.BASE_ALTERNATE.equals(((SpellAbility) ability).getSpellAbilityType())
|
||||
&& !ability.getTargets().isEmpty()) {
|
||||
spellAbility = (SpellAbility) ability;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (spellAbility.getTargets().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Target target = spellAbility.getTargets().get(0).copy();
|
||||
Outcome auraOutcome = Outcome.BoostCreature;
|
||||
for (Effect effect : spellAbility.getEffects()) {
|
||||
if (effect instanceof AttachEffect) {
|
||||
auraOutcome = effect.getOutcome();
|
||||
break;
|
||||
}
|
||||
}
|
||||
enchantCardInGraveyard = target instanceof TargetCardInGraveyard;
|
||||
if (target != null) {
|
||||
target.setNotTarget(true); // always not target because this way it's not handled targeted
|
||||
target.clearChosen(); // neccessary if e.g. aura is blinked multiple times
|
||||
}
|
||||
Player player = game.getPlayer(card.getOwnerId());
|
||||
Outcome auraOutcome = Outcome.BoostCreature;
|
||||
Ability:
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
if (ability instanceof SpellAbility) {
|
||||
for (Effect effect : ability.getEffects()) {
|
||||
if (effect instanceof AttachEffect) {
|
||||
auraOutcome = effect.getOutcome();
|
||||
break Ability;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target != null && player != null && player.choose(auraOutcome, target, card.getId(), game)) {
|
||||
targetId = target.getFirstTarget();
|
||||
}
|
||||
|
@ -151,44 +160,27 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
Player targetPlayer = game.getPlayer(targetId);
|
||||
if (targetCard != null || targetPermanent != null || targetPlayer != null) {
|
||||
switch (fromZone) {
|
||||
case EXILED:
|
||||
game.getExile().removeCard(card, game);
|
||||
break;
|
||||
case GRAVEYARD:
|
||||
game.getPlayer(card.getOwnerId()).removeFromGraveyard(card, game);
|
||||
break;
|
||||
case HAND:
|
||||
game.getPlayer(card.getOwnerId()).removeFromHand(card, game);
|
||||
break;
|
||||
case LIBRARY:
|
||||
game.getPlayer(card.getOwnerId()).removeFromLibrary(card, game);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
game.rememberLKI(card.getId(), fromZone, card);
|
||||
|
||||
card.removeFromZone(game, fromZone, sourceId);
|
||||
card.updateZoneChangeCounter(game);
|
||||
PermanentCard permanent = new PermanentCard(card, card.getOwnerId(), game);
|
||||
game.getBattlefield().addPermanent(permanent);
|
||||
card.setZone(Zone.BATTLEFIELD, game);
|
||||
boolean entered = permanent.entersBattlefield(event.getSourceId(), game, fromZone, true);
|
||||
game.applyEffects();
|
||||
if (!entered) {
|
||||
return false;
|
||||
}
|
||||
game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD));
|
||||
if (permanent.entersBattlefield(event.getSourceId(), game, fromZone, true)) {
|
||||
if (targetCard != null) {
|
||||
permanent.attachTo(targetCard.getId(), game);
|
||||
} else if (targetPermanent != null) {
|
||||
targetPermanent.addAttachment(permanent.getId(), game);
|
||||
} else if (targetPlayer != null) {
|
||||
targetPlayer.addAttachment(permanent.getId(), game);
|
||||
}
|
||||
game.applyEffects();
|
||||
|
||||
if (targetCard != null) {
|
||||
permanent.attachTo(targetCard.getId(), game);
|
||||
}
|
||||
if (targetPermanent != null) {
|
||||
targetPermanent.addAttachment(permanent.getId(), game);
|
||||
}
|
||||
if (targetPlayer != null) {
|
||||
targetPlayer.addAttachment(permanent.getId(), game);
|
||||
game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -199,7 +191,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (((ZoneChangeEvent) event).getToZone().equals(Zone.BATTLEFIELD)
|
||||
&& !(((ZoneChangeEvent) event).getFromZone().equals(Zone.HAND))) {
|
||||
&& !(((ZoneChangeEvent) event).getFromZone().equals(Zone.STACK))) {
|
||||
Card card = game.getCard(event.getTargetId());
|
||||
if (card != null && card.getCardType().contains(CardType.ENCHANTMENT) && card.hasSubtype("Aura")) {
|
||||
return true;
|
||||
|
|
|
@ -1147,18 +1147,18 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
private void setControllerForEffect(ContinuousEffectsList<?> effects, UUID cardId, UUID controllerId) {
|
||||
private void setControllerForEffect(ContinuousEffectsList<?> effects, UUID sourceId, UUID controllerId) {
|
||||
for (Effect effect : effects) {
|
||||
HashSet<Ability> abilities = effects.getAbility(effect.getId());
|
||||
if (abilities != null) {
|
||||
for (Ability ability : abilities) {
|
||||
if (ability.getSourceId() != null) {
|
||||
if (ability.getSourceId().equals(cardId)) {
|
||||
if (ability.getSourceId().equals(sourceId)) {
|
||||
ability.setControllerId(controllerId);
|
||||
}
|
||||
} else {
|
||||
if (!ability.getZone().equals(Zone.COMMAND)) {
|
||||
logger.fatal(new StringBuilder("No sourceId Ability: ").append(ability));
|
||||
logger.fatal("Continuous effect for ability with no sourceId Ability: " + ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
/*
|
||||
* Copyright 2012 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL , EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
* Copyright 2012 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL , EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.effects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -46,18 +46,19 @@ import org.apache.log4j.Logger;
|
|||
* @param <T>
|
||||
*/
|
||||
public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList<T> {
|
||||
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ContinuousEffectsList.class);
|
||||
|
||||
// the effectAbilityMap holds for each effect all abilities that are connected (used) with this effect
|
||||
private final Map<UUID, HashSet<Ability>> effectAbilityMap = new HashMap<>();
|
||||
|
||||
public ContinuousEffectsList() { }
|
||||
public ContinuousEffectsList() {
|
||||
}
|
||||
|
||||
public ContinuousEffectsList(final ContinuousEffectsList<T> effects) {
|
||||
this.ensureCapacity(effects.size());
|
||||
for (ContinuousEffect cost: effects) {
|
||||
this.add((T)cost.copy());
|
||||
for (ContinuousEffect cost : effects) {
|
||||
this.add((T) cost.copy());
|
||||
}
|
||||
for (Map.Entry<UUID, HashSet<Ability>> entry : effects.effectAbilityMap.entrySet()) {
|
||||
HashSet<Ability> newSet = new HashSet<>();
|
||||
|
@ -113,12 +114,12 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
Ability ability = it.next();
|
||||
if (ability == null) {
|
||||
it.remove();
|
||||
} else if (ability instanceof MageSingleton) {
|
||||
} else if (ability instanceof MageSingleton) {
|
||||
return false;
|
||||
} else if (effect.isDiscarded()) {
|
||||
} else if (effect.isDiscarded()) {
|
||||
it.remove();
|
||||
} else {
|
||||
switch(effect.getDuration()) {
|
||||
switch (effect.getDuration()) {
|
||||
case WhileOnBattlefield:
|
||||
case WhileInGraveyard:
|
||||
case WhileOnStack:
|
||||
|
@ -133,8 +134,8 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
break;
|
||||
case Custom:
|
||||
case UntilYourNextTurn:
|
||||
if (effect.isInactive(ability , game)) {
|
||||
it.remove();
|
||||
if (effect.isInactive(ability, game)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,9 +144,9 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
}
|
||||
|
||||
/**
|
||||
* Adds an effect and its connected ability to the list.
|
||||
* For each effect will be stored, which abilities are connected to the effect.
|
||||
* So an effect can be connected to multiple abilities.
|
||||
* Adds an effect and its connected ability to the list. For each effect
|
||||
* will be stored, which abilities are connected to the effect. So an effect
|
||||
* can be connected to multiple abilities.
|
||||
*
|
||||
* @param effect - effect to add
|
||||
* @param source - connected ability
|
||||
|
@ -153,8 +154,8 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
public void addEffect(T effect, Ability source) {
|
||||
if (effectAbilityMap.containsKey(effect.getId())) {
|
||||
HashSet<Ability> set = effectAbilityMap.get(effect.getId());
|
||||
for (Ability ability: set) {
|
||||
if (ability.getId().equals(source.getId()) && ability.getSourceId().equals(source.getSourceId()) ) {
|
||||
for (Ability ability : set) {
|
||||
if (ability.getId().equals(source.getId()) && ability.getSourceId().equals(source.getSourceId())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.effects;
|
||||
|
||||
import mage.MageObject;
|
||||
|
@ -45,20 +44,18 @@ public abstract class ContinuousRuleModifyingEffectImpl extends ContinuousEffect
|
|||
protected final boolean messageToUser;
|
||||
protected final boolean messageToGameLog;
|
||||
protected final String infoMessage;
|
||||
|
||||
|
||||
// 613.10
|
||||
// Some continuous effects affect game rules rather than objects. For example, effects may modify
|
||||
// Some continuous effects affect game rules rather than objects. For example, effects may modify
|
||||
// a players maximum hand size, or say that a creature must attack this turn if able. These effects
|
||||
// are applied after all other continuous effects have been applied. Continuous effects that affect
|
||||
// the costs of spells or abilities are applied according to the order specified in rule 601.2e.
|
||||
// All other such effects are applied in timestamp order. See also the rules for timestamp order
|
||||
// the costs of spells or abilities are applied according to the order specified in rule 601.2e.
|
||||
// All other such effects are applied in timestamp order. See also the rules for timestamp order
|
||||
// and dependency (rules 613.6 and 613.7).
|
||||
|
||||
// Some of this rule modifying effects are implemented as normal CONTINUOUS effects using the Layer.RulesEffects.
|
||||
// But if the rule change can be implemented simply by preventing an event from happening, CONTINUOUS_RULE_MODIFICATION effects can be used.
|
||||
// They work technical like a replacement effect that replaces the event completely.
|
||||
// They work technical like a replacement effect that replaces the event completely.
|
||||
// But player isn't asked to choose order of effects if multiple are applied to the same event.
|
||||
|
||||
public ContinuousRuleModifyingEffectImpl(Duration duration, Outcome outcome) {
|
||||
this(duration, outcome, true, false);
|
||||
}
|
||||
|
@ -67,11 +64,13 @@ public abstract class ContinuousRuleModifyingEffectImpl extends ContinuousEffect
|
|||
*
|
||||
* @param duration
|
||||
* @param outcome
|
||||
* @param messageToUser - Every time the effect replaces an event, the user gets a message in a dialog window.
|
||||
* Don't set it to true if the event happens regularly or very often. The message itself can be
|
||||
* changed by overriding the getInfoMessage method.
|
||||
* @param messageToLog - Every time the effect replaces an event, a message is posted to the game log. The message
|
||||
* can be changed by overriding the getInfoMessage method.
|
||||
* @param messageToUser - Every time the effect replaces an event, the user
|
||||
* gets a message in a dialog window. Don't set it to true if the event
|
||||
* happens regularly or very often. The message itself can be changed by
|
||||
* overriding the getInfoMessage method.
|
||||
* @param messageToLog - Every time the effect replaces an event, a message
|
||||
* is posted to the game log. The message can be changed by overriding the
|
||||
* getInfoMessage method.
|
||||
*/
|
||||
public ContinuousRuleModifyingEffectImpl(Duration duration, Outcome outcome, boolean messageToUser, boolean messageToLog) {
|
||||
super(duration, outcome);
|
||||
|
@ -89,9 +88,11 @@ public abstract class ContinuousRuleModifyingEffectImpl extends ContinuousEffect
|
|||
}
|
||||
|
||||
/**
|
||||
* An early check for the event types this effect applies to. This check was added
|
||||
* to speed up event handling. Once all existing ContinuousRuleModifiyingEffects have
|
||||
* implemented this method, the method should be changed to abstract here or removed.
|
||||
* An early check for the event types this effect applies to. This check was
|
||||
* added to speed up event handling. Once all existing
|
||||
* ContinuousRuleModifiyingEffects have implemented this method, the method
|
||||
* should be changed to abstract here or removed.
|
||||
*
|
||||
* @param event
|
||||
* @param game
|
||||
* @return
|
||||
|
@ -112,10 +113,10 @@ public abstract class ContinuousRuleModifyingEffectImpl extends ContinuousEffect
|
|||
String message;
|
||||
MageObject object = game.getObject(source.getSourceId());
|
||||
if (object != null) {
|
||||
message = source.getRule(object.getLogName());
|
||||
message = source.getRule(messageToUser ? object.getIdName() : object.getLogName());
|
||||
} else {
|
||||
message = source.getRule();
|
||||
}
|
||||
}
|
||||
return message;
|
||||
} else {
|
||||
return infoMessage;
|
||||
|
@ -132,5 +133,4 @@ public abstract class ContinuousRuleModifyingEffectImpl extends ContinuousEffect
|
|||
return messageToGameLog;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,42 +1,43 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.effects;
|
||||
|
||||
import mage.constants.Duration;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
|
@ -116,12 +117,17 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
}
|
||||
Spell spell = game.getStack().getSpell(event.getSourceId());
|
||||
for (Effect effect: baseEffects) {
|
||||
if (spell == null) {
|
||||
StackObject stackObject = (StackObject) game.getLastKnownInformation(event.getSourceId(), Zone.STACK);
|
||||
if (stackObject instanceof Spell) {
|
||||
spell = (Spell) stackObject;
|
||||
}
|
||||
}
|
||||
for (Effect effect : baseEffects) {
|
||||
if (source.activate(game, false)) {
|
||||
if (effect instanceof ContinuousEffect) {
|
||||
game.addEffect((ContinuousEffect) effect, source);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (spell != null) {
|
||||
effect.setValue(SOURCE_CAST_SPELL_ABILITY, spell.getSpellAbility());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackAbility;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.Targets;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ChangeATargetOfTargetSpellAbilityToSourceEffect extends OneShotEffect {
|
||||
|
||||
public ChangeATargetOfTargetSpellAbilityToSourceEffect() {
|
||||
super(Outcome.Neutral);
|
||||
staticText = "Change a target of target spell or ability to {this}";
|
||||
}
|
||||
|
||||
public ChangeATargetOfTargetSpellAbilityToSourceEffect(final ChangeATargetOfTargetSpellAbilityToSourceEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget());
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (stackObject != null && sourceObject != null) {
|
||||
Targets targets = new Targets();
|
||||
Ability sourceAbility;
|
||||
String oldTargetName = null;
|
||||
if (stackObject instanceof Spell) {
|
||||
Spell spell = (Spell) stackObject;
|
||||
sourceAbility = spell.getSpellAbility();
|
||||
} else if (stackObject instanceof StackAbility) {
|
||||
StackAbility stackAbility = (StackAbility) stackObject;
|
||||
sourceAbility = stackAbility;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
for (UUID modeId : sourceAbility.getModes().getSelectedModes()) {
|
||||
sourceAbility.getModes().setActiveMode(modeId);
|
||||
targets.addAll(sourceAbility.getTargets());
|
||||
}
|
||||
|
||||
boolean twoTimesTarget = false;
|
||||
if (targets.size() == 1 && targets.get(0).getTargets().size() == 1) {
|
||||
Target target = targets.get(0);
|
||||
if (target.canTarget(stackObject.getControllerId(), source.getSourceId(), sourceAbility, game)) {
|
||||
oldTargetName = getTargetName(targets.getFirstTarget(), game);
|
||||
target.clearChosen();
|
||||
// The source is still the spell on the stack
|
||||
target.addTarget(source.getSourceId(), stackObject.getStackAbility(), game);
|
||||
}
|
||||
} else {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
boolean validTargets = false;
|
||||
do {
|
||||
for (Target target : targets) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
String name = getTargetName(targets.getFirstTarget(), game);
|
||||
if (!targetId.equals(source.getSourceId()) && target.getTargets().contains(source.getSourceId())) {
|
||||
// you can't change this target to source because the source is already another targetId of that target.
|
||||
twoTimesTarget = true;
|
||||
continue;
|
||||
}
|
||||
if (target.canTarget(stackObject.getControllerId(), source.getSourceId(), sourceAbility, game)) {
|
||||
validTargets = true;
|
||||
if (name != null
|
||||
&& controller.chooseUse(Outcome.Neutral, "Change target from " + name + " to " + sourceObject.getLogName() + "?", source, game)) {
|
||||
oldTargetName = getTargetName(targetId, game);
|
||||
target.remove(targetId);
|
||||
// The source is still the spell on the stack
|
||||
target.addTarget(source.getSourceId(), stackObject.getStackAbility(), game);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldTargetName != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (oldTargetName == null) {
|
||||
game.informPlayer(controller, "You have to select at least one target to change to " + sourceObject.getIdName() + "!");
|
||||
}
|
||||
} while (validTargets && oldTargetName == null);
|
||||
}
|
||||
if (oldTargetName != null) {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Changed target of " + stackObject.getLogName() + " from " + oldTargetName + " to " + sourceObject.getLogName());
|
||||
} else {
|
||||
if (twoTimesTarget) {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its not valid to target it twice for " + stackObject.getLogName());
|
||||
} else {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its no valid target for " + stackObject.getLogName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeATargetOfTargetSpellAbilityToSourceEffect copy() {
|
||||
return new ChangeATargetOfTargetSpellAbilityToSourceEffect(this);
|
||||
}
|
||||
|
||||
private String getTargetName(UUID objectId, Game game) {
|
||||
MageObject object = game.getObject(objectId);
|
||||
if (object != null) {
|
||||
return object.getLogName();
|
||||
}
|
||||
Player player = game.getPlayer(objectId);
|
||||
if (player != null) {
|
||||
return player.getLogName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
@ -20,13 +20,14 @@
|
|||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
|
@ -66,6 +67,7 @@ public class CopyPermanentEffect extends OneShotEffect {
|
|||
public CopyPermanentEffect(FilterPermanent filter, ApplyToPermanent applier) {
|
||||
this(filter, applier, false);
|
||||
}
|
||||
|
||||
public CopyPermanentEffect(FilterPermanent filter, ApplyToPermanent applier, boolean useTarget) {
|
||||
super(Outcome.Copy);
|
||||
this.applier = applier;
|
||||
|
@ -85,8 +87,8 @@ public class CopyPermanentEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (player != null && sourcePermanent != null) {
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (player != null && sourceObject != null) {
|
||||
Permanent copyFromPermanent = null;
|
||||
if (useTargetOfAbility) {
|
||||
copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
|
@ -99,7 +101,7 @@ public class CopyPermanentEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
if (copyFromPermanent != null) {
|
||||
bluePrintPermanent = game.copyPermanent(copyFromPermanent, sourcePermanent, source, applier);
|
||||
bluePrintPermanent = game.copyPermanent(copyFromPermanent, sourceObject.getId(), source, applier);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
|
@ -56,7 +55,8 @@ public class CounterTargetWithReplacementEffect extends OneShotEffect {
|
|||
/**
|
||||
*
|
||||
* @param targetZone
|
||||
* @param flag use to specify when moving card to library <ul><li>true = put on top</li><li>false = put on bottom</li></ul>
|
||||
* @param flag use to specify when moving card to library <ul><li>true = put
|
||||
* on top</li><li>false = put on bottom</li></ul>
|
||||
*/
|
||||
public CounterTargetWithReplacementEffect(Zone targetZone, boolean flag) {
|
||||
super(Outcome.Detriment);
|
||||
|
@ -83,33 +83,14 @@ public class CounterTargetWithReplacementEffect extends OneShotEffect {
|
|||
if (controller != null) {
|
||||
StackObject stackObject = game.getStack().getStackObject(objectId);
|
||||
if (stackObject != null && !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) {
|
||||
boolean spell = false;
|
||||
if (stackObject instanceof Spell) {
|
||||
game.rememberLKI(objectId, Zone.STACK, stackObject);
|
||||
spell = true;
|
||||
}
|
||||
game.getStack().remove(stackObject);
|
||||
if (spell && !((Spell) stackObject).isCopiedSpell()) {
|
||||
MageObject mageObject = game.getObject(stackObject.getSourceId());
|
||||
if (mageObject instanceof Card) {
|
||||
Card card = (Card) mageObject;
|
||||
switch (targetZone) {
|
||||
case LIBRARY:
|
||||
controller.moveCardToLibraryWithInfo(card, sourceId, game, Zone.STACK, flag, true);
|
||||
break;
|
||||
case EXILED:
|
||||
controller.moveCardToExileWithInfo(card, null, "", sourceId, game, Zone.STACK, true);
|
||||
break;
|
||||
default:
|
||||
controller.moveCards(card, Zone.STACK, targetZone, source, game);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
controller.moveCards((Card) stackObject, null, targetZone, source, game);
|
||||
} else {
|
||||
game.getStack().remove(stackObject);
|
||||
}
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, sourceId, stackObject.getControllerId()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -27,11 +27,11 @@
|
|||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
|
@ -44,7 +44,11 @@ import mage.game.permanent.Permanent;
|
|||
public class DontUntapInControllersUntapStepSourceEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
public DontUntapInControllersUntapStepSourceEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment, false, true);
|
||||
this(false, true);
|
||||
}
|
||||
|
||||
public DontUntapInControllersUntapStepSourceEffect(boolean messageToUser, boolean messageToLog) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment, messageToUser, messageToLog);
|
||||
staticText = "{this} doesn't untap during your untap step";
|
||||
}
|
||||
|
||||
|
@ -78,4 +82,5 @@ public class DontUntapInControllersUntapStepSourceEffect extends ContinuousRuleM
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
@ -51,6 +50,7 @@ public class DrawCardTargetEffect extends OneShotEffect {
|
|||
public DrawCardTargetEffect(int amount) {
|
||||
this(new StaticValue(amount));
|
||||
}
|
||||
|
||||
public DrawCardTargetEffect(int amount, boolean optional) {
|
||||
this(new StaticValue(amount), optional);
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ public class DrawCardTargetEffect extends OneShotEffect {
|
|||
if (upTo) {
|
||||
sb.append("up to ");
|
||||
}
|
||||
sb.append(CardUtil.numberToText(amount.toString())).append(" card");
|
||||
sb.append(CardUtil.numberToText(amount.toString(), "a")).append(" card");
|
||||
try {
|
||||
if (Integer.parseInt(amount.toString()) > 1) {
|
||||
sb.append("s");
|
||||
|
@ -133,5 +133,4 @@ public class DrawCardTargetEffect extends OneShotEffect {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
@ -20,7 +20,7 @@
|
|||
* 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
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
|
@ -28,17 +28,18 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -110,10 +111,6 @@ public class ExileFromZoneTargetEffect extends OneShotEffect {
|
|||
}
|
||||
|
||||
private void setText() {
|
||||
if (amount == 1) {
|
||||
staticText = "Target player exiles a " + filter.getMessage() + " from his or her " + zone.toString().toLowerCase();
|
||||
} else {
|
||||
staticText = "Target player exiles " + amount + " " + filter.getMessage() + " from his or her " + zone.toString().toLowerCase();
|
||||
}
|
||||
staticText = "target player exiles " + CardUtil.numberToText(exileName, "a") + filter.getMessage() + " from his or her " + zone.toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,14 +44,14 @@ import mage.target.targetpointer.FixedTarget;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class BecomesColorOrColorsTargetEffect extends OneShotEffect {
|
||||
|
||||
Duration duration;
|
||||
|
||||
/**
|
||||
* This effect let the controller choose one or more colors the target will
|
||||
* become to.
|
||||
* Use effect.setText() if case you use a targetPointer, otherwise the rule text will be empty.
|
||||
* become to. Use effect.setText() if case you use a targetPointer,
|
||||
* otherwise the rule text will be empty.
|
||||
*
|
||||
* @param duration
|
||||
*/
|
||||
|
@ -81,8 +81,9 @@ public class BecomesColorOrColorsTargetEffect extends OneShotEffect {
|
|||
if (!controller.canRespond()) {
|
||||
return false;
|
||||
}
|
||||
if (!game.isSimulation())
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(target.getName() + ": " + controller.getLogName() + " has chosen " + choiceColor.getChoice());
|
||||
}
|
||||
if (choiceColor.getColor().isBlack()) {
|
||||
sb.append("B");
|
||||
} else if (choiceColor.getColor().isBlue()) {
|
||||
|
@ -119,7 +120,7 @@ public class BecomesColorOrColorsTargetEffect extends OneShotEffect {
|
|||
StringBuilder sb = new StringBuilder();
|
||||
if (mode.getTargets().size() > 0) {
|
||||
sb.append("target ");
|
||||
sb.append(mode.getTargets().get(0).getMessage());
|
||||
sb.append(mode.getTargets().get(0).getFilter().getMessage());
|
||||
sb.append(" becomes the color or colors of your choice");
|
||||
if (duration.toString().length() > 0) {
|
||||
sb.append(" ").append(duration.toString());
|
||||
|
|
|
@ -63,8 +63,8 @@ import mage.players.Player;
|
|||
public class BuybackAbility extends StaticAbility implements OptionalAdditionalSourceCosts {
|
||||
|
||||
private static final String keywordText = "Buyback";
|
||||
private static final String reminderTextCost = "<i>(You may {cost} in addition to any other costs as you cast this spell. If you do, put this card into your hand as it resolves.)</i>";
|
||||
private static final String reminderTextMana = "<i>(You may pay an additional {cost} as you cast this spell. If you do, put this card into your hand as it resolves.)</i>";
|
||||
private static final String reminderTextCost = "You may {cost} in addition to any other costs as you cast this spell. If you do, put this card into your hand as it resolves.";
|
||||
private static final String reminderTextMana = "You may pay an additional {cost} as you cast this spell. If you do, put this card into your hand as it resolves.";
|
||||
protected OptionalAdditionalCost buybackCost;
|
||||
|
||||
public BuybackAbility(String manaString) {
|
||||
|
|
|
@ -113,8 +113,9 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
|
|||
reminderText = "As you cast this spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose a new targets for the copy.)";
|
||||
break;
|
||||
}
|
||||
conspireCost = new OptionalAdditionalCostImpl(keywordText, "-", reminderText,
|
||||
new TapTargetCost(new TargetControlledPermanent(2, 2, filter, true)));
|
||||
Cost cost = new TapTargetCost(new TargetControlledPermanent(2, 2, filter, true));
|
||||
cost.setText("");
|
||||
conspireCost = new OptionalAdditionalCostImpl(keywordText, " ", reminderText, cost);
|
||||
addSubAbility(new ConspireTriggeredAbility(conspireId));
|
||||
}
|
||||
|
||||
|
@ -157,10 +158,11 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
|
|||
@Override
|
||||
public void addOptionalAdditionalCosts(Ability ability, Game game) {
|
||||
if (ability instanceof SpellAbility) {
|
||||
Player player = game.getPlayer(controllerId);
|
||||
Player player = game.getPlayer(getControllerId());
|
||||
if (player != null) {
|
||||
resetConspire(ability, game);
|
||||
if (player.chooseUse(Outcome.Benefit, "Pay " + conspireCost.getText(false) + " ?", ability, game)) {
|
||||
if (conspireCost.canPay(ability, getSourceId(), getControllerId(), game)
|
||||
&& player.chooseUse(Outcome.Benefit, "Pay " + conspireCost.getText(false) + " ?", ability, game)) {
|
||||
activateConspire(ability, game);
|
||||
for (Iterator it = ((Costs) conspireCost).iterator(); it.hasNext();) {
|
||||
Cost cost = (Cost) it.next();
|
||||
|
|
|
@ -59,7 +59,7 @@ import mage.players.Player;
|
|||
public class EntwineAbility extends StaticAbility implements OptionalAdditionalModeSourceCosts {
|
||||
|
||||
private static final String keywordText = "Entwine";
|
||||
private static final String reminderText = "<i> (Choose both if you pay the entwine cost.)</i>";
|
||||
private static final String reminderText = "Choose both if you pay the entwine cost.";
|
||||
protected OptionalAdditionalCost additionalCost;
|
||||
|
||||
public EntwineAbility(String manaString) {
|
||||
|
|
|
@ -85,8 +85,8 @@ import mage.players.Player;
|
|||
public class KickerAbility extends StaticAbility implements OptionalAdditionalSourceCosts {
|
||||
|
||||
protected static final String KICKER_KEYWORD = "Kicker";
|
||||
protected static final String KICKER_REMINDER_MANA = "(You may pay an additional {cost} as you cast this spell.)";
|
||||
protected static final String KICKER_REMINDER_COST = "(You may {cost} in addition to any other costs as you cast this spell.)";
|
||||
protected static final String KICKER_REMINDER_MANA = "You may pay an additional {cost} as you cast this spell.";
|
||||
protected static final String KICKER_REMINDER_COST = "You may {cost} in addition to any other costs as you cast this spell.";
|
||||
|
||||
protected Map<String, Integer> activations = new HashMap<>(); // zoneChangeCounter, activations
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ import mage.players.Player;
|
|||
public class ReplicateAbility extends StaticAbility implements OptionalAdditionalSourceCosts {
|
||||
|
||||
private static final String keywordText = "Replicate";
|
||||
private static final String reminderTextMana = "<i>(When you cast this spell, copy it for each time you paid its replicate cost. You may choose new targets for the copies.)</i>";
|
||||
private static final String reminderTextMana = "When you cast this spell, copy it for each time you paid its replicate cost. You may choose new targets for the copies.";
|
||||
protected OptionalAdditionalCost additionalCost;
|
||||
|
||||
public ReplicateAbility(Card card, String manaString) {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.common.DiscardTargetCost;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.SpellAbilityType;
|
||||
|
@ -44,7 +45,9 @@ public class RetraceAbility extends SpellAbility {
|
|||
public RetraceAbility(Card card) {
|
||||
super(card.getManaCost(), card.getName() + " with retrace", Zone.GRAVEYARD, SpellAbilityType.BASE_ALTERNATE);
|
||||
this.getCosts().addAll(card.getSpellAbility().getCosts().copy());
|
||||
this.addCost(new DiscardTargetCost(new TargetCardInHand(new FilterLandCard())));
|
||||
Cost cost = new DiscardTargetCost(new TargetCardInHand(new FilterLandCard()));
|
||||
cost.setText("");
|
||||
this.addCost(cost);
|
||||
this.getEffects().addAll(card.getSpellAbility().getEffects().copy());
|
||||
this.getTargets().addAll(card.getSpellAbility().getTargets().copy());
|
||||
this.getChoices().addAll(card.getSpellAbility().getChoices().copy());
|
||||
|
|
|
@ -40,6 +40,7 @@ import mage.constants.Zone;
|
|||
import mage.counters.Counter;
|
||||
import mage.counters.Counters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
public interface Card extends MageObject {
|
||||
|
||||
|
@ -65,6 +66,8 @@ public interface Card extends MageObject {
|
|||
|
||||
String getTokenSetCode();
|
||||
|
||||
void checkForCountersToAdd(Permanent permanent, Game game);
|
||||
|
||||
void setFaceDown(boolean value, Game game);
|
||||
|
||||
boolean isFaceDown(Game game);
|
||||
|
@ -125,6 +128,8 @@ public interface Card extends MageObject {
|
|||
|
||||
boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId);
|
||||
|
||||
boolean removeFromZone(Game game, Zone fromZone, UUID sourceId);
|
||||
|
||||
boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId);
|
||||
|
||||
boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped);
|
||||
|
|
|
@ -54,8 +54,6 @@ import static mage.constants.Zone.EXILED;
|
|||
import static mage.constants.Zone.GRAVEYARD;
|
||||
import static mage.constants.Zone.HAND;
|
||||
import static mage.constants.Zone.LIBRARY;
|
||||
import static mage.constants.Zone.OUTSIDE;
|
||||
import static mage.constants.Zone.PICK;
|
||||
import static mage.constants.Zone.STACK;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.Counters;
|
||||
|
@ -65,6 +63,7 @@ import mage.game.Game;
|
|||
import mage.game.command.Commander;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
|
@ -342,55 +341,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
Zone fromZone = game.getState().getZone(objectId);
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone, appliedEffects);
|
||||
if (!game.replaceEvent(event)) {
|
||||
if (event.getFromZone() != null) {
|
||||
switch (event.getFromZone()) {
|
||||
case GRAVEYARD:
|
||||
game.getPlayer(ownerId).removeFromGraveyard(this, game);
|
||||
break;
|
||||
case HAND:
|
||||
game.getPlayer(ownerId).removeFromHand(this, game);
|
||||
break;
|
||||
case LIBRARY:
|
||||
game.getPlayer(ownerId).removeFromLibrary(this, game);
|
||||
break;
|
||||
case EXILED:
|
||||
game.getExile().removeCard(this, game);
|
||||
break;
|
||||
case OUTSIDE:
|
||||
game.getPlayer(ownerId).getSideboard().remove(this);
|
||||
break;
|
||||
case COMMAND:
|
||||
game.getState().getCommand().remove((Commander) game.getObject(objectId));
|
||||
break;
|
||||
case STACK:
|
||||
StackObject stackObject = game.getStack().getSpell(getSpellAbility().getId());
|
||||
if (stackObject == null && (this instanceof SplitCard)) { // handle if half of Split cast is on the stack
|
||||
stackObject = game.getStack().getSpell(((SplitCard) this).getLeftHalfCard().getId());
|
||||
if (stackObject == null) {
|
||||
stackObject = game.getStack().getSpell(((SplitCard) this).getRightHalfCard().getId());
|
||||
}
|
||||
}
|
||||
if (stackObject == null) {
|
||||
stackObject = game.getStack().getSpell(getId());
|
||||
}
|
||||
if (stackObject != null) {
|
||||
game.getStack().remove(stackObject);
|
||||
}
|
||||
break;
|
||||
case PICK:
|
||||
case BATTLEFIELD: // for sacrificing permanents or putting to library
|
||||
break;
|
||||
default:
|
||||
Card sourceCard = game.getCard(sourceId);
|
||||
logger.fatal(new StringBuilder("Invalid from zone [").append(fromZone)
|
||||
.append("] for card [").append(this.getName())
|
||||
.append("] to zone [").append(toZone)
|
||||
.append("] source [").append(sourceCard != null ? sourceCard.getName() : "null").append("]").toString());
|
||||
break;
|
||||
}
|
||||
game.rememberLKI(objectId, event.getFromZone(), this);
|
||||
}
|
||||
|
||||
removeFromZone(game, fromZone, sourceId);
|
||||
setFaceDown(false, game);
|
||||
updateZoneChangeCounter(game);
|
||||
switch (event.getToZone()) {
|
||||
|
@ -454,32 +405,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
Card mainCard = getMainCard();
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(mainCard.getId(), ability.getId(), controllerId, fromZone, Zone.STACK);
|
||||
if (!game.replaceEvent(event)) {
|
||||
if (event.getFromZone() != null) {
|
||||
switch (event.getFromZone()) {
|
||||
case GRAVEYARD:
|
||||
game.getPlayer(ownerId).removeFromGraveyard(mainCard, game);
|
||||
break;
|
||||
case HAND:
|
||||
game.getPlayer(ownerId).removeFromHand(mainCard, game);
|
||||
break;
|
||||
case LIBRARY:
|
||||
game.getPlayer(ownerId).removeFromLibrary(mainCard, game);
|
||||
break;
|
||||
case EXILED:
|
||||
game.getExile().removeCard(mainCard, game);
|
||||
break;
|
||||
case OUTSIDE:
|
||||
game.getPlayer(ownerId).getSideboard().remove(mainCard);
|
||||
break;
|
||||
|
||||
case COMMAND:
|
||||
game.getState().getCommand().remove((Commander) game.getObject(mainCard.getId()));
|
||||
break;
|
||||
default:
|
||||
//logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone());
|
||||
}
|
||||
game.rememberLKI(mainCard.getId(), event.getFromZone(), this);
|
||||
}
|
||||
mainCard.removeFromZone(game, fromZone, ability.getSourceId());
|
||||
game.getStack().push(new Spell(this, ability.copy(), controllerId, event.getFromZone()));
|
||||
updateZoneChangeCounter(game);
|
||||
setZone(event.getToZone(), game);
|
||||
|
@ -499,36 +425,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
Zone fromZone = game.getState().getZone(objectId);
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, Zone.EXILED, appliedEffects);
|
||||
if (!game.replaceEvent(event)) {
|
||||
if (fromZone != null) {
|
||||
switch (fromZone) {
|
||||
case GRAVEYARD:
|
||||
game.getPlayer(ownerId).removeFromGraveyard(this, game);
|
||||
break;
|
||||
case HAND:
|
||||
game.getPlayer(ownerId).removeFromHand(this, game);
|
||||
break;
|
||||
case LIBRARY:
|
||||
game.getPlayer(ownerId).removeFromLibrary(this, game);
|
||||
break;
|
||||
case EXILED:
|
||||
game.getExile().removeCard(this, game);
|
||||
break;
|
||||
case STACK:
|
||||
StackObject stackObject = game.getStack().getSpell(getId());
|
||||
if (stackObject != null) {
|
||||
game.getStack().remove(stackObject);
|
||||
}
|
||||
break;
|
||||
case PICK:
|
||||
// nothing to do
|
||||
break;
|
||||
default:
|
||||
MageObject object = game.getObject(sourceId);
|
||||
logger.warn(new StringBuilder("moveToExile, not fully implemented: from = ").append(fromZone).append(" - ").append(object != null ? object.getName() : "null"));
|
||||
}
|
||||
game.rememberLKI(objectId, event.getFromZone(), this);
|
||||
}
|
||||
|
||||
removeFromZone(game, fromZone, sourceId);
|
||||
if (exileId == null) {
|
||||
game.getExile().getPermanentExile().add(this);
|
||||
} else {
|
||||
|
@ -568,37 +465,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
if (facedown) {
|
||||
this.setFaceDown(false, game);
|
||||
}
|
||||
if (fromZone != null) {
|
||||
boolean removed = false;
|
||||
switch (fromZone) {
|
||||
case GRAVEYARD:
|
||||
removed = game.getPlayer(ownerId).removeFromGraveyard(this, game);
|
||||
break;
|
||||
case HAND:
|
||||
removed = game.getPlayer(ownerId).removeFromHand(this, game);
|
||||
break;
|
||||
case LIBRARY:
|
||||
removed = game.getPlayer(ownerId).removeFromLibrary(this, game);
|
||||
break;
|
||||
case EXILED:
|
||||
game.getExile().removeCard(this, game);
|
||||
removed = true;
|
||||
break;
|
||||
case COMMAND:
|
||||
// command object (commander) is only on the stack, so no removing neccessary here
|
||||
removed = true;
|
||||
break;
|
||||
case PICK:
|
||||
removed = true;
|
||||
break;
|
||||
default:
|
||||
logger.warn("putOntoBattlefield, not fully implemented: fromZone=" + fromZone);
|
||||
}
|
||||
game.rememberLKI(objectId, event.getFromZone(), this);
|
||||
if (!removed) {
|
||||
logger.warn("Couldn't find card in fromZone, card=" + getName() + ", fromZone=" + fromZone);
|
||||
}
|
||||
}
|
||||
removeFromZone(game, fromZone, sourceId);
|
||||
updateZoneChangeCounter(game);
|
||||
PermanentCard permanent = new PermanentCard(this, event.getPlayerId(), game);
|
||||
// make sure the controller of all continuous effects of this card are switched to the current controller
|
||||
|
@ -624,7 +491,76 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void checkForCountersToAdd(PermanentCard permanent, Game game) {
|
||||
@Override
|
||||
public boolean removeFromZone(Game game, Zone fromZone, UUID sourceId) {
|
||||
boolean removed = false;
|
||||
MageObject lkiObject = null;
|
||||
switch (fromZone) {
|
||||
case GRAVEYARD:
|
||||
removed = game.getPlayer(ownerId).removeFromGraveyard(this, game);
|
||||
break;
|
||||
case HAND:
|
||||
removed = game.getPlayer(ownerId).removeFromHand(this, game);
|
||||
break;
|
||||
case LIBRARY:
|
||||
removed = game.getPlayer(ownerId).removeFromLibrary(this, game);
|
||||
break;
|
||||
case EXILED:
|
||||
if (game.getExile().getCard(getId(), game) != null) {
|
||||
game.getExile().removeCard(this, game);
|
||||
removed = true;
|
||||
}
|
||||
break;
|
||||
case STACK:
|
||||
StackObject stackObject = game.getStack().getSpell(getSpellAbility().getId());
|
||||
if (stackObject == null && (this instanceof SplitCard)) { // handle if half of Split cast is on the stack
|
||||
stackObject = game.getStack().getSpell(((SplitCard) this).getLeftHalfCard().getId());
|
||||
if (stackObject == null) {
|
||||
stackObject = game.getStack().getSpell(((SplitCard) this).getRightHalfCard().getId());
|
||||
}
|
||||
}
|
||||
if (stackObject == null) {
|
||||
stackObject = game.getStack().getSpell(getId());
|
||||
}
|
||||
if (stackObject != null) {
|
||||
removed = game.getStack().remove(stackObject);
|
||||
lkiObject = stackObject;
|
||||
}
|
||||
break;
|
||||
case COMMAND:
|
||||
lkiObject = (Commander) game.getObject(objectId);
|
||||
if (lkiObject != null) {
|
||||
removed = game.getState().getCommand().remove((Commander) game.getObject(objectId));
|
||||
}
|
||||
break;
|
||||
case OUTSIDE:
|
||||
if (isCopy()) { // copied cards have no need to be removed from a previous zone
|
||||
removed = true;
|
||||
} else if (game.getPlayer(ownerId).getSideboard().contains(this.getId())) {
|
||||
game.getPlayer(ownerId).getSideboard().remove(this.getId());
|
||||
removed = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case PICK: // Pick should no longer be used
|
||||
case BATTLEFIELD: // for sacrificing permanents or putting to library
|
||||
removed = true;
|
||||
break;
|
||||
default:
|
||||
MageObject sourceObject = game.getObject(sourceId);
|
||||
logger.fatal("Invalid from zone [" + fromZone + "] for card [" + this.getIdName()
|
||||
+ "] source [" + (sourceObject != null ? sourceObject.getName() : "null") + "]");
|
||||
break;
|
||||
}
|
||||
game.rememberLKI(objectId, fromZone, lkiObject != null ? lkiObject : this);
|
||||
if (!removed) {
|
||||
logger.warn("Couldn't find card in fromZone, card=" + getIdName() + ", fromZone=" + fromZone);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkForCountersToAdd(Permanent permanent, Game game) {
|
||||
Counters countersToAdd = game.getEnterWithCounters(permanent.getId());
|
||||
if (countersToAdd != null) {
|
||||
for (Counter counter : countersToAdd.values()) {
|
||||
|
|
|
@ -7,24 +7,25 @@ import mage.abilities.Abilities;
|
|||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.counters.Counters;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward
|
||||
*/
|
||||
public class CardState implements Serializable {
|
||||
|
||||
|
||||
protected boolean faceDown;
|
||||
protected Map<String, String> info;
|
||||
protected Counters counters;
|
||||
protected Abilities<Ability> abilities;
|
||||
|
||||
|
||||
private static final Map<String, String> emptyInfo = new HashMap<>();
|
||||
private static final Abilities<Ability> emptyAbilities = new AbilitiesImpl<>();
|
||||
|
||||
|
||||
public CardState() {
|
||||
counters = new Counters();
|
||||
}
|
||||
|
||||
|
||||
public CardState(final CardState state) {
|
||||
this.faceDown = state.faceDown;
|
||||
if (state.info != null) {
|
||||
|
@ -34,7 +35,7 @@ public class CardState implements Serializable {
|
|||
counters = state.counters.copy();
|
||||
if (state.abilities != null) {
|
||||
abilities = new AbilitiesImpl<>();
|
||||
for (Ability ability: state.abilities) {
|
||||
for (Ability ability : state.abilities) {
|
||||
abilities.add(ability.copy());
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +44,7 @@ public class CardState implements Serializable {
|
|||
public CardState copy() {
|
||||
return new CardState(this);
|
||||
}
|
||||
|
||||
|
||||
public void setFaceDown(boolean value) {
|
||||
faceDown = value;
|
||||
}
|
||||
|
@ -66,45 +67,45 @@ public class CardState implements Serializable {
|
|||
info.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Map<String, String> getInfo() {
|
||||
if (info == null) {
|
||||
return emptyInfo;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
public Abilities<Ability> getAbilities() {
|
||||
if (abilities == null) {
|
||||
return emptyAbilities;
|
||||
}
|
||||
return abilities;
|
||||
}
|
||||
|
||||
|
||||
public void addAbility(Ability ability) {
|
||||
if (abilities == null) {
|
||||
abilities = new AbilitiesImpl<>();
|
||||
}
|
||||
abilities.add(ability);
|
||||
for (Ability sub: ability.getSubAbilities()) {
|
||||
for (Ability sub : ability.getSubAbilities()) {
|
||||
abilities.add(sub);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clearAbilities() {
|
||||
if (abilities != null) {
|
||||
for (Ability ability: abilities) {
|
||||
ability.setSourceId(null);
|
||||
ability.setControllerId(null);
|
||||
}
|
||||
// for (Ability ability: abilities) { // Causes problems if temporary (gained) continuous effects are removed
|
||||
// ability.setSourceId(null);
|
||||
// ability.setControllerId(null);
|
||||
// }
|
||||
abilities = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clear() {
|
||||
counters.clear();
|
||||
info = null;
|
||||
clearAbilities();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -364,14 +364,14 @@ public interface Game extends MageItem, Serializable {
|
|||
* This version supports copying of copies of any depth.
|
||||
*
|
||||
* @param copyFromPermanent
|
||||
* @param copyToPermanent
|
||||
* @param copyToPermanentId
|
||||
* @param source
|
||||
* @param applier
|
||||
* @return
|
||||
*/
|
||||
Permanent copyPermanent(Permanent copyFromPermanent, Permanent copyToPermanent, Ability source, ApplyToPermanent applier);
|
||||
Permanent copyPermanent(Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, ApplyToPermanent applier);
|
||||
|
||||
Permanent copyPermanent(Duration duration, Permanent copyFromPermanent, Permanent copyToPermanent, Ability source, ApplyToPermanent applier);
|
||||
Permanent copyPermanent(Duration duration, Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, ApplyToPermanent applier);
|
||||
|
||||
Card copyCard(Card cardToCopy, Ability source, UUID newController);
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ import mage.MageObject;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.common.ChancellorAbility;
|
||||
import mage.abilities.common.GemstoneCavernsAbility;
|
||||
|
@ -77,6 +78,7 @@ import mage.constants.Outcome;
|
|||
import mage.constants.PhaseStep;
|
||||
import mage.constants.PlayerAction;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.counters.Counters;
|
||||
|
@ -1402,12 +1404,12 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Permanent copyPermanent(Permanent copyFromPermanent, Permanent copyToPermanent, Ability source, ApplyToPermanent applier) {
|
||||
return copyPermanent(Duration.Custom, copyFromPermanent, copyToPermanent, source, applier);
|
||||
public Permanent copyPermanent(Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, ApplyToPermanent applier) {
|
||||
return copyPermanent(Duration.Custom, copyFromPermanent, copyToPermanentId, source, applier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Permanent copyPermanent(Duration duration, Permanent copyFromPermanent, Permanent copyToPermanent, Ability source, ApplyToPermanent applier) {
|
||||
public Permanent copyPermanent(Duration duration, Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, ApplyToPermanent applier) {
|
||||
Permanent newBluePrint = null;
|
||||
// handle copies of copies
|
||||
for (Effect effect : getState().getContinuousEffects().getLayeredEffects(this)) {
|
||||
|
@ -1440,7 +1442,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
applier.apply(this, newBluePrint);
|
||||
}
|
||||
|
||||
CopyEffect newEffect = new CopyEffect(duration, newBluePrint, copyToPermanent.getId());
|
||||
CopyEffect newEffect = new CopyEffect(duration, newBluePrint, copyToPermanentId);
|
||||
newEffect.newId();
|
||||
newEffect.setApplier(applier);
|
||||
Ability newAbility = source.copy();
|
||||
|
@ -1686,11 +1688,22 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
SpellAbility spellAbility = perm.getSpellAbility();
|
||||
if (perm.getSpellAbility().getTargets().isEmpty()) {
|
||||
for (Ability ability : perm.getAbilities(this)) {
|
||||
if ((ability instanceof SpellAbility)
|
||||
&& SpellAbilityType.BASE_ALTERNATE.equals(((SpellAbility) ability).getSpellAbilityType())
|
||||
&& !ability.getTargets().isEmpty()) {
|
||||
spellAbility = (SpellAbility) ability;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (spellAbility.getTargets().isEmpty()) {
|
||||
Permanent enchanted = this.getPermanent(perm.getAttachedTo());
|
||||
logger.error("Aura without target: " + perm.getName() + " attached to " + (enchanted == null ? " null" : enchanted.getName()));
|
||||
} else {
|
||||
Target target = perm.getSpellAbility().getTargets().get(0);
|
||||
Target target = spellAbility.getTargets().get(0);
|
||||
if (target instanceof TargetPermanent) {
|
||||
Permanent attachedTo = getPermanent(perm.getAttachedTo());
|
||||
if (attachedTo == null || !attachedTo.getAttachments().contains(perm.getId())) {
|
||||
|
@ -1706,7 +1719,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
Filter auraFilter = perm.getSpellAbility().getTargets().get(0).getFilter();
|
||||
Filter auraFilter = spellAbility.getTargets().get(0).getFilter();
|
||||
if (auraFilter instanceof FilterControlledCreaturePermanent) {
|
||||
if (!((FilterControlledCreaturePermanent) auraFilter).match(attachedTo, perm.getId(), perm.getControllerId(), this)
|
||||
|| attachedTo.cantBeEnchantedBy(perm, this)) {
|
||||
|
@ -1737,7 +1750,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
somethingHappened = true;
|
||||
}
|
||||
} else {
|
||||
Filter auraFilter = perm.getSpellAbility().getTargets().get(0).getFilter();
|
||||
Filter auraFilter = spellAbility.getTargets().get(0).getFilter();
|
||||
if (!auraFilter.match(attachedToPlayer, this) || attachedToPlayer.hasProtectionFrom(perm, this)) {
|
||||
if (movePermanentToGraveyardWithInfo(perm)) {
|
||||
somethingHappened = true;
|
||||
|
|
|
@ -624,7 +624,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
public Permanent getPermanent(UUID permanentId) {
|
||||
if (permanentId != null && battlefield.containsPermanent(permanentId)) {
|
||||
Permanent permanent = battlefield.getPermanent(permanentId);
|
||||
setZone(permanent.getId(), Zone.BATTLEFIELD); // shouldn't this be set anyway? (LevelX2)
|
||||
// setZone(permanent.getId(), Zone.BATTLEFIELD); // shouldn't this be set anyway? (LevelX2)
|
||||
return permanent;
|
||||
}
|
||||
return null;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue