* Fixed problems of Yixlid Jailer that removed abilities from cards in graveyard permanently (fixes #1147).

This commit is contained in:
LevelX2 2020-01-03 15:23:52 +01:00
parent 893bcbb01f
commit 8854871c15
28 changed files with 248 additions and 180 deletions

View file

@ -1,6 +1,8 @@
package mage.view; package mage.view;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import java.util.*;
import java.util.stream.Collectors;
import mage.MageObject; import mage.MageObject;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.Abilities; import mage.abilities.Abilities;
@ -26,9 +28,6 @@ import mage.target.Target;
import mage.target.Targets; import mage.target.Targets;
import mage.util.SubTypeList; import mage.util.SubTypeList;
import java.util.*;
import java.util.stream.Collectors;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -436,7 +435,7 @@ public class CardView extends SimpleCardView {
artRect = ArtRect.SPLIT_FUSED; artRect = ArtRect.SPLIT_FUSED;
} else if (spell.getCard() != null) { } else if (spell.getCard() != null) {
SplitCard wholeCard = ((SplitCardHalf) spell.getCard()).getParentCard(); SplitCard wholeCard = ((SplitCardHalf) spell.getCard()).getParentCard();
Abilities<Ability> aftermathHalfAbilities = wholeCard.getRightHalfCard().getAbilities(); Abilities<Ability> aftermathHalfAbilities = wholeCard.getRightHalfCard().getAbilities(game);
if (aftermathHalfAbilities.stream().anyMatch(ability -> ability instanceof AftermathAbility)) { if (aftermathHalfAbilities.stream().anyMatch(ability -> ability instanceof AftermathAbility)) {
if (ty == SpellAbilityType.SPLIT_RIGHT) { if (ty == SpellAbilityType.SPLIT_RIGHT) {
artRect = ArtRect.AFTERMATH_BOTTOM; artRect = ArtRect.AFTERMATH_BOTTOM;
@ -470,7 +469,7 @@ public class CardView extends SimpleCardView {
this.startingLoyalty = "" + card.getStartingLoyalty(); this.startingLoyalty = "" + card.getStartingLoyalty();
} }
public CardView(MageObject object) { public CardView(MageObject object, Game game) {
super(object.getId(), "", "0", false, "", true, ""); super(object.getId(), "", "0", false, "", true, "");
this.originalCard = null; this.originalCard = null;

View file

@ -1,5 +1,6 @@
package mage.view; package mage.view;
import java.util.*;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
@ -14,8 +15,6 @@ import mage.game.permanent.PermanentToken;
import mage.target.targetpointer.TargetPointer; import mage.target.targetpointer.TargetPointer;
import mage.util.GameLog; import mage.util.GameLog;
import java.util.*;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -102,7 +101,7 @@ public class CardsView extends LinkedHashMap<UUID, CardView> {
} else if (isCard) { } else if (isCard) {
sourceCardView = new CardView((Card) sourceObject); sourceCardView = new CardView((Card) sourceObject);
} else { } else {
sourceCardView = new CardView(sourceObject); sourceCardView = new CardView(sourceObject, game);
} }
abilityView = new AbilityView(ability, sourceObject.getName(), sourceCardView); abilityView = new AbilityView(ability, sourceObject.getName(), sourceCardView);
} }

View file

@ -2,6 +2,11 @@ package mage.view;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.costs.Cost; import mage.abilities.costs.Cost;
import mage.cards.Card; import mage.cards.Card;
@ -25,12 +30,6 @@ import mage.players.Player;
import mage.watchers.common.CastSpellLastTurnWatcher; import mage.watchers.common.CastSpellLastTurnWatcher;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -121,7 +120,7 @@ public class GameView implements Serializable {
} else if (object instanceof Designation) { } else if (object instanceof Designation) {
Designation designation = (Designation) game.getObject(object.getId()); Designation designation = (Designation) game.getObject(object.getId());
if (designation != null) { if (designation != null) {
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, designation.getName(), new CardView(designation))); stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, designation.getName(), new CardView(designation, game)));
} else { } else {
LOGGER.fatal("Designation object not found: " + object.getName() + ' ' + object.toString() + ' ' + object.getClass().toString()); LOGGER.fatal("Designation object not found: " + object.getName() + ' ' + object.toString() + ' ' + object.getClass().toString());
} }
@ -129,7 +128,7 @@ public class GameView implements Serializable {
} else if (object instanceof StackAbility) { } else if (object instanceof StackAbility) {
StackAbility stackAbility = ((StackAbility) object); StackAbility stackAbility = ((StackAbility) object);
stackAbility.newId(); stackAbility.newId();
stack.put(stackObject.getId(), new CardView(stackObject)); stack.put(stackObject.getId(), new CardView(stackObject, game));
checkPaid(stackObject.getId(), ((StackAbility) stackObject)); checkPaid(stackObject.getId(), ((StackAbility) stackObject));
} else { } else {
LOGGER.fatal("Object can't be cast to StackAbility: " + object.getName() + ' ' + object.toString() + ' ' + object.getClass().toString()); LOGGER.fatal("Object can't be cast to StackAbility: " + object.getName() + ' ' + object.toString() + ' ' + object.getClass().toString());

View file

@ -1,5 +1,8 @@
package mage.cards.a; package mage.cards.a;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.ReplacementEffectImpl;
@ -18,11 +21,6 @@ import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.watchers.Watcher; import mage.watchers.Watcher;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
/** /**
* @author jeffwadsworth * @author jeffwadsworth
*/ */
@ -114,7 +112,7 @@ class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl {
|| !card.isOwnedBy(controller.getId())) { || !card.isOwnedBy(controller.getId())) {
return false; return false;
} }
for (Ability ability : card.getAbilities()) { for (Ability ability : card.getAbilities(game)) {
if (ability instanceof CyclingAbility) { if (ability instanceof CyclingAbility) {
cardHasCycling = true; cardHasCycling = true;
} }

View file

@ -1,6 +1,7 @@
package mage.cards.c; package mage.cards.c;
import java.util.Iterator;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.ContinuousEffectImpl;
@ -18,10 +19,6 @@ import mage.game.stack.Spell;
import mage.game.stack.StackObject; import mage.game.stack.StackObject;
import mage.players.Player; import mage.players.Player;
import java.util.Iterator;
import java.util.UUID;
/** /**
* @author magenoxx_at_gmail.com * @author magenoxx_at_gmail.com
*/ */
@ -73,7 +70,7 @@ class GainReboundEffect extends ContinuousEffectImpl {
Permanent permanent = game.getPermanent(source.getSourceId()); Permanent permanent = game.getPermanent(source.getSourceId());
if (player != null && permanent != null) { if (player != null && permanent != null) {
for (Card card : player.getHand().getCards(CastThroughTime.filter, game)) { for (Card card : player.getHand().getCards(CastThroughTime.filter, game)) {
addReboundAbility(card, source, game); addReboundAbility(card, game);
} }
for (Iterator<StackObject> iterator = game.getStack().iterator(); iterator.hasNext();) { for (Iterator<StackObject> iterator = game.getStack().iterator(); iterator.hasNext();) {
StackObject stackObject = iterator.next(); StackObject stackObject = iterator.next();
@ -81,7 +78,7 @@ class GainReboundEffect extends ContinuousEffectImpl {
Spell spell = (Spell) stackObject; Spell spell = (Spell) stackObject;
Card card = spell.getCard(); Card card = spell.getCard();
if (card != null) { if (card != null) {
addReboundAbility(card, source, game); addReboundAbility(card, game);
} }
} }
@ -91,9 +88,9 @@ class GainReboundEffect extends ContinuousEffectImpl {
return false; return false;
} }
private void addReboundAbility(Card card, Ability source, Game game) { private void addReboundAbility(Card card, Game game) {
if (CastThroughTime.filter.match(card, game)) { if (CastThroughTime.filter.match(card, game)) {
boolean found = card.getAbilities().stream().anyMatch(ability -> ability instanceof ReboundAbility); boolean found = card.getAbilities(game).stream().anyMatch(ability -> ability instanceof ReboundAbility);
if (!found) { if (!found) {
Ability ability = new ReboundAbility(); Ability ability = new ReboundAbility();
game.getState().addOtherAbility(card, ability); game.getState().addOtherAbility(card, ability);

View file

@ -1,4 +1,3 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID; import java.util.UUID;
@ -108,7 +107,7 @@ class DarkImpostorContinuousEffect extends ContinuousEffectImpl {
for (UUID imprintedId : perm.getImprinted()) { for (UUID imprintedId : perm.getImprinted()) {
Card card = game.getCard(imprintedId); Card card = game.getCard(imprintedId);
if (card != null) { if (card != null) {
for (Ability ability : card.getAbilities()) { for (Ability ability : card.getAbilities(game)) {
if (ability instanceof ActivatedAbility) { if (ability instanceof ActivatedAbility) {
perm.addAbility(ability.copy(), source.getSourceId(), game); perm.addAbility(ability.copy(), source.getSourceId(), game);
} }

View file

@ -1,4 +1,3 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID; import java.util.UUID;
@ -30,7 +29,6 @@ public final class Delay extends CardImpl {
public Delay(UUID ownerId, CardSetInfo setInfo) { public Delay(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
// Counter target spell. If the spell is countered this way, exile it with three time counters on it instead of putting it into its owner's graveyard. If it doesn't have suspend, it gains suspend. // Counter target spell. If the spell is countered this way, exile it with three time counters on it instead of putting it into its owner's graveyard. If it doesn't have suspend, it gains suspend.
this.getSpellAbility().addEffect(new DelayEffect()); this.getSpellAbility().addEffect(new DelayEffect());
this.getSpellAbility().addTarget(new TargetSpell()); this.getSpellAbility().addTarget(new TargetSpell());
@ -71,7 +69,7 @@ class DelayEffect extends OneShotEffect {
effect.setTargetPointer(targetPointer); effect.setTargetPointer(targetPointer);
Card card = game.getCard(spell.getSourceId()); Card card = game.getCard(spell.getSourceId());
if (card != null && effect.apply(game, source) && game.getState().getZone(card.getId()) == Zone.EXILED) { if (card != null && effect.apply(game, source) && game.getState().getZone(card.getId()) == Zone.EXILED) {
boolean hasSuspend = card.getAbilities().containsClass(SuspendAbility.class); boolean hasSuspend = card.getAbilities(game).containsClass(SuspendAbility.class);
UUID exileId = SuspendAbility.getSuspendExileId(controller.getId(), game); UUID exileId = SuspendAbility.getSuspendExileId(controller.getId(), game);
if (controller.moveCardToExileWithInfo(card, exileId, "Suspended cards of " + controller.getLogName(), source.getSourceId(), game, Zone.HAND, true)) { if (controller.moveCardToExileWithInfo(card, exileId, "Suspended cards of " + controller.getLogName(), source.getSourceId(), game, Zone.HAND, true)) {
card.addCounters(CounterType.TIME.createInstance(3), source, game); card.addCounters(CounterType.TIME.createInstance(3), source, game);

View file

@ -1,4 +1,3 @@
package mage.cards.f; package mage.cards.f;
import java.util.UUID; import java.util.UUID;
@ -15,8 +14,8 @@ import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate;
@ -47,7 +46,7 @@ public final class Filth extends CardImpl {
// As long as Filth is in your graveyard and you control a Swamp, creatures you control have swampwalk. // As long as Filth is in your graveyard and you control a Swamp, creatures you control have swampwalk.
ContinuousEffect effect = new GainAbilityControlledEffect(new SwampwalkAbility(), ContinuousEffect effect = new GainAbilityControlledEffect(new SwampwalkAbility(),
Duration.WhileOnBattlefield, new FilterCreaturePermanent()); Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES);
ConditionalContinuousEffect filthEffect = new ConditionalContinuousEffect(effect, ConditionalContinuousEffect filthEffect = new ConditionalContinuousEffect(effect,
new PermanentsOnTheBattlefieldCondition(filter), ruleText); new PermanentsOnTheBattlefieldCondition(filter), ruleText);
this.addAbility(new SimpleStaticAbility(Zone.GRAVEYARD, filthEffect)); this.addAbility(new SimpleStaticAbility(Zone.GRAVEYARD, filthEffect));

View file

@ -1,4 +1,3 @@
package mage.cards.h; package mage.cards.h;
import java.util.UUID; import java.util.UUID;
@ -16,11 +15,11 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType; import mage.constants.AsThoughEffectType;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Layer; import mage.constants.Layer;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubLayer; import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
@ -188,7 +187,7 @@ class HavengulLichEffect extends ContinuousEffectImpl {
Permanent permanent = game.getPermanent(source.getSourceId()); Permanent permanent = game.getPermanent(source.getSourceId());
Card card = game.getCard(cardId); Card card = game.getCard(cardId);
if (permanent != null && card != null) { if (permanent != null && card != null) {
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.BATTLEFIELD)) { for (ActivatedAbility ability : card.getAbilities(game).getActivatedAbilities(Zone.BATTLEFIELD)) {
permanent.addAbility(ability, source.getSourceId(), game); permanent.addAbility(ability, source.getSourceId(), game);
} }
} }

View file

@ -1,5 +1,8 @@
package mage.cards.j; package mage.cards.j;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObjectReference; import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -20,10 +23,6 @@ import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInHand;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/** /**
* @author LevelX2 * @author LevelX2
*/ */
@ -89,7 +88,7 @@ class JhoiraOfTheGhituSuspendEffect extends OneShotEffect {
if (card == null) { if (card == null) {
return false; return false;
} }
boolean hasSuspend = card.getAbilities().containsClass(SuspendAbility.class); boolean hasSuspend = card.getAbilities(game).containsClass(SuspendAbility.class);
UUID exileId = SuspendAbility.getSuspendExileId(controller.getId(), game); UUID exileId = SuspendAbility.getSuspendExileId(controller.getId(), game);
if (controller.moveCardToExileWithInfo(card, exileId, "Suspended cards of " + controller.getName(), source.getSourceId(), game, Zone.HAND, true)) { if (controller.moveCardToExileWithInfo(card, exileId, "Suspended cards of " + controller.getName(), source.getSourceId(), game, Zone.HAND, true)) {
@ -104,4 +103,3 @@ class JhoiraOfTheGhituSuspendEffect extends OneShotEffect {
return false; return false;
} }
} }

View file

@ -1,4 +1,3 @@
package mage.cards.m; package mage.cards.m;
import java.util.Objects; import java.util.Objects;
@ -14,11 +13,11 @@ import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Layer; import mage.constants.Layer;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubLayer; import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
@ -140,7 +139,7 @@ class MairsilThePretenderGainAbilitiesEffect extends ContinuousEffectImpl {
} }
for (Card card : game.getExile().getAllCards(game)) { for (Card card : game.getExile().getAllCards(game)) {
if (filter.match(card, game) && Objects.equals(card.getOwnerId(), perm.getControllerId())) { if (filter.match(card, game) && Objects.equals(card.getOwnerId(), perm.getControllerId())) {
for (Ability ability : card.getAbilities()) { for (Ability ability : card.getAbilities(game)) {
if (ability instanceof ActivatedAbility) { if (ability instanceof ActivatedAbility) {
ActivatedAbility copyAbility = (ActivatedAbility) ability.copy(); ActivatedAbility copyAbility = (ActivatedAbility) ability.copy();
copyAbility.setMaxActivationsPerTurn(1); copyAbility.setMaxActivationsPerTurn(1);

View file

@ -1,4 +1,3 @@
package mage.cards.m; package mage.cards.m;
import java.util.UUID; import java.util.UUID;
@ -59,7 +58,7 @@ class MemoryCrystalSpellsCostReductionEffect extends CostModificationEffectImpl
Card card = game.getCard(abilityToModify.getSourceId()); Card card = game.getCard(abilityToModify.getSourceId());
if (card != null) { if (card != null) {
for (Ability ability : card.getAbilities()) { for (Ability ability : card.getAbilities(game)) {
if (ability instanceof BuybackAbility) { if (ability instanceof BuybackAbility) {
if (ability.isActivated()) { if (ability.isActivated()) {
int amountToReduce = ((BuybackAbility) ability).reduceCost(2); int amountToReduce = ((BuybackAbility) ability).reduceCost(2);

View file

@ -1,5 +1,3 @@
package mage.cards.m; package mage.cards.m;
import java.util.UUID; import java.util.UUID;
@ -15,11 +13,11 @@ import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Layer; import mage.constants.Layer;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubLayer; import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterArtifactCard; import mage.filter.common.FilterArtifactCard;
import mage.game.Game; import mage.game.Game;
@ -107,9 +105,9 @@ class MyrWelderContinuousEffect extends ContinuousEffectImpl {
for (UUID imprintedId : perm.getImprinted()) { for (UUID imprintedId : perm.getImprinted()) {
Card card = game.getCard(imprintedId); Card card = game.getCard(imprintedId);
if (card != null) { if (card != null) {
for (Ability ability: card.getAbilities()) { for (Ability ability : card.getAbilities(game)) {
if (ability instanceof ActivatedAbility) { if (ability instanceof ActivatedAbility) {
perm.addAbility(ability, game); perm.addAbility(ability, source.getId(), game);
} }
} }
} }

View file

@ -1,4 +1,3 @@
package mage.cards.n; package mage.cards.n;
import java.util.UUID; import java.util.UUID;
@ -18,11 +17,11 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.CardsImpl; import mage.cards.CardsImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Layer; import mage.constants.Layer;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubLayer; import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
@ -171,7 +170,7 @@ class NarsetTranscendentGainReboundEffect extends ContinuousEffectImpl {
if (spell != null) { if (spell != null) {
Card card = spell.getCard(); Card card = spell.getCard();
if (card != null) { if (card != null) {
addReboundAbility(card, source, game); addReboundAbility(card, game);
} }
} else { } else {
discard(); discard();
@ -181,9 +180,9 @@ class NarsetTranscendentGainReboundEffect extends ContinuousEffectImpl {
return false; return false;
} }
private void addReboundAbility(Card card, Ability source, Game game) { private void addReboundAbility(Card card, Game game) {
boolean found = false; boolean found = false;
for (Ability ability : card.getAbilities()) { for (Ability ability : card.getAbilities(game)) {
if (ability instanceof ReboundAbility) { if (ability instanceof ReboundAbility) {
found = true; found = true;
break; break;

View file

@ -1,11 +1,9 @@
package mage.cards.n; package mage.cards.n;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.ActivatedAbility; import mage.abilities.ActivatedAbility;
@ -66,9 +64,9 @@ public final class NecroticOoze extends CardImpl {
if (player != null) { if (player != null) {
for (Card card : player.getGraveyard().getCards(game)) { for (Card card : player.getGraveyard().getCards(game)) {
if (card.isCreature()) { if (card.isCreature()) {
for (Ability ability : card.getAbilities()) { for (Ability ability : card.getAbilities(game)) {
if (ability instanceof ActivatedAbility) { if (ability instanceof ActivatedAbility) {
perm.addAbility(ability, game); perm.addAbility(ability, source.getSourceId(), game);
} }
} }
} }

View file

@ -1,5 +1,8 @@
package mage.cards.p; package mage.cards.p;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
@ -23,10 +26,6 @@ import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/** /**
* @author TheElk801 * @author TheElk801
*/ */
@ -76,6 +75,7 @@ class PolukranosUnchainedEffect extends OneShotEffect {
PolukranosUnchainedEffect() { PolukranosUnchainedEffect() {
super(Outcome.BoostCreature); super(Outcome.BoostCreature);
staticText = "with six +1/+1 counters on it. It escapes with twelve +1/+1 counters on it instead";
} }
private PolukranosUnchainedEffect(final PolukranosUnchainedEffect effect) { private PolukranosUnchainedEffect(final PolukranosUnchainedEffect effect) {

View file

@ -1,4 +1,3 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID; import java.util.UUID;
@ -13,11 +12,11 @@ import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Layer; import mage.constants.Layer;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubLayer; import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -53,7 +52,6 @@ public final class SkillBorrower extends CardImpl {
} }
} }
class SkillBorrowerAbility extends StaticAbility { class SkillBorrowerAbility extends StaticAbility {
public SkillBorrowerAbility() { public SkillBorrowerAbility() {
@ -71,7 +69,7 @@ class SkillBorrowerAbility extends StaticAbility {
@Override @Override
public String getRule() { public String getRule() {
return "As long as the top card of your library is an artifact or creature card, Skill Borrower has all activated abilities of that card"; return "As long as the top card of your library is an artifact or creature card, {this} has all activated abilities of that card";
} }
} }
@ -79,14 +77,13 @@ class SkillBorrowerEffect extends ContinuousEffectImpl {
public SkillBorrowerEffect() { public SkillBorrowerEffect() {
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
staticText = "As long as the top card of your library is an artifact or creature card, Skill Borrower has all activated abilities of that card"; staticText = "As long as the top card of your library is an artifact or creature card, {this} has all activated abilities of that card";
} }
public SkillBorrowerEffect(final SkillBorrowerEffect effect) { public SkillBorrowerEffect(final SkillBorrowerEffect effect) {
super(effect); super(effect);
} }
@Override @Override
public SkillBorrowerEffect copy() { public SkillBorrowerEffect copy() {
return new SkillBorrowerEffect(this); return new SkillBorrowerEffect(this);
@ -100,7 +97,7 @@ class SkillBorrowerEffect extends ContinuousEffectImpl {
if (card != null && (card.isCreature() || card.isArtifact())) { if (card != null && (card.isCreature() || card.isArtifact())) {
Permanent permanent = game.getPermanent(source.getSourceId()); Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) { if (permanent != null) {
for(Ability ability : card.getAbilities()){ for (Ability ability : card.getAbilities(game)) {
if (ability instanceof ActivatedAbility) { if (ability instanceof ActivatedAbility) {
permanent.addAbility(ability, source.getSourceId(), game); permanent.addAbility(ability, source.getSourceId(), game);
} }

View file

@ -1,5 +1,8 @@
package mage.cards.s; package mage.cards.s;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObjectReference; import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -16,10 +19,6 @@ import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** /**
* @author LevelX2 * @author LevelX2
*/ */
@ -91,7 +90,7 @@ class SoulflayerEffect extends ContinuousEffectImpl implements SourceEffect {
if (!card.isCreature()) { if (!card.isCreature()) {
continue; continue;
} }
for (Ability cardAbility : card.getAbilities()) { for (Ability cardAbility : card.getAbilities(game)) {
if (cardAbility instanceof FlyingAbility) { if (cardAbility instanceof FlyingAbility) {
abilitiesToAdd.add(FlyingAbility.getInstance()); abilitiesToAdd.add(FlyingAbility.getInstance());
} }

View file

@ -1,5 +1,6 @@
package mage.cards.t; package mage.cards.t;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility; import mage.abilities.DelayedTriggeredAbility;
@ -26,8 +27,6 @@ import mage.players.Player;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import mage.watchers.common.AttackedThisTurnWatcher; import mage.watchers.common.AttackedThisTurnWatcher;
import java.util.UUID;
/** /**
* @author spjspj * @author spjspj
*/ */
@ -153,7 +152,7 @@ class TaigamOjutaiMasterGainReboundEffect extends ContinuousEffectImpl {
} }
private void addReboundAbility(Card card, Ability source, Game game) { private void addReboundAbility(Card card, Ability source, Game game) {
boolean found = card.getAbilities().stream().anyMatch(ability -> ability instanceof ReboundAbility); boolean found = card.getAbilities(game).stream().anyMatch(ability -> ability instanceof ReboundAbility);
if (!found) { if (!found) {
Ability ability = new ReboundAbility(); Ability ability = new ReboundAbility();
game.getState().addOtherAbility(card, ability); game.getState().addOtherAbility(card, ability);

View file

@ -1,5 +1,6 @@
package mage.cards.v; package mage.cards.v;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
@ -14,8 +15,6 @@ import mage.constants.*;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import java.util.UUID;
/** /**
* @author ImperatorPrime * @author ImperatorPrime
*/ */
@ -98,7 +97,7 @@ class VolrathsShapeshifterEffect extends ContinuousEffectImpl {
} }
for (Ability ability : card.getAbilities()) { for (Ability ability : card.getAbilities(game)) {
if (!permanent.getAbilities().contains(ability)) { if (!permanent.getAbilities().contains(ability)) {
permanent.addAbility(ability, source.getSourceId(), game); permanent.addAbility(ability, source.getSourceId(), game);
} }

View file

@ -1,9 +1,7 @@
package mage.cards.y; package mage.cards.y;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Abilities;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.ContinuousEffectImpl;
@ -67,14 +65,7 @@ public final class YixlidJailer extends CardImpl {
if (player != null) { if (player != null) {
for (Card card : player.getGraveyard().getCards(game)) { for (Card card : player.getGraveyard().getCards(game)) {
if (card != null) { if (card != null) {
card.getAbilities(game).clear(); // Will the abilities ever come back???? card.looseAllAbilities(game);
// TODO: Fix that (LevelX2)
// game.getContinuousEffects().removeGainedEffectsForSource(card.getId());
// game.getState().resetTriggersForSourceId(card.getId());
Abilities abilities = game.getState().getAllOtherAbilities(card.getId());
if (abilities != null) {
abilities.clear();
}
} }
} }
} }

View file

@ -0,0 +1,89 @@
/*
* 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 org.mage.test.cards.continuous;
import mage.abilities.keyword.SwampwalkAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class LoosingAbilitiesTest extends CardTestPlayerBase {
@Test
public void GivingSwampwalkFromGraveyard() {
// Swampwalk
// As long as Filth is in your graveyard and you control a Swamp, creatures you control have swampwalk.
addCard(Zone.GRAVEYARD, playerB, "Filth"); // Creature
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerB, "Silvercoat Lion", 1);
assertAbility(playerB, "Silvercoat Lion", new SwampwalkAbility(), true);
}
/**
* The Card in the graveyard should have no Swampwalk if Yixlid Jailer
* effect was added later
*/
@Test
public void testYixlidJailerRemovesAbilities() {
// Cards in graveyards lose all abilities.
addCard(Zone.HAND, playerA, "Yixlid Jailer"); // Creature 2/1 - {1}{B}
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
// Swampwalk
// As long as Filth is in your graveyard and you control a Swamp, creatures you control have swampwalk.
addCard(Zone.GRAVEYARD, playerB, "Filth");
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yixlid Jailer");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerB, "Silvercoat Lion", 1);
assertAbility(playerB, "Silvercoat Lion", new SwampwalkAbility(), false);
}
// https://github.com/magefree/mage/issues/1147
@Test
public void testYixlidJailerAbilitiesComeBack() {
// Cards in graveyards lose all abilities.
addCard(Zone.HAND, playerA, "Yixlid Jailer"); // Creature 2/1 - {1}{B}
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
// Gravecrawler cant block.
// You may cast Gravecrawler from your graveyard as long as you control a Zombie.
addCard(Zone.GRAVEYARD, playerB, "Gravecrawler");
addCard(Zone.HAND, playerB, "Lightning Bolt", 2);
addCard(Zone.BATTLEFIELD, playerB, "Walking Corpse"); // Creature 2/2 - Zombie
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yixlid Jailer");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", "Yixlid Jailer");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Gravecrawler");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Yixlid Jailer", 1);
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertPermanentCount(playerB, "Gravecrawler", 1);
}
}

View file

@ -5,17 +5,13 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.Mana;
import mage.abilities.costs.*; import mage.abilities.costs.*;
import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.*; import mage.abilities.costs.mana.*;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects; import mage.abilities.effects.Effects;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.effects.mana.DynamicManaEffect;
import mage.abilities.hint.Hint; import mage.abilities.hint.Hint;
import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.Card; import mage.cards.Card;
@ -25,7 +21,6 @@ import mage.game.Game;
import mage.game.command.Emblem; import mage.game.command.Emblem;
import mage.game.command.Plane; import mage.game.command.Plane;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.ManaEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.stack.Spell; import mage.game.stack.Spell;
import mage.game.stack.StackAbility; import mage.game.stack.StackAbility;
@ -952,7 +947,12 @@ public abstract class AbilityImpl implements Ability {
return false; return false;
} }
return ((Permanent) object).isPhasedIn(); return ((Permanent) object).isPhasedIn();
} else if (!object.getAbilities().contains(this)) { } else if (object instanceof Card) {
if (!((Card) object).getAbilities(game).contains(this)) {
return false;
}
return true;
} else if (!object.getAbilities().contains(this)) { // not sure which object it can still be
// check if it's an ability that is temporary gained to a card // check if it's an ability that is temporary gained to a card
Abilities<Ability> otherAbilities = game.getState().getAllOtherAbilities(this.getSourceId()); Abilities<Ability> otherAbilities = game.getState().getAllOtherAbilities(this.getSourceId());
return otherAbilities != null && otherAbilities.contains(this); return otherAbilities != null && otherAbilities.contains(this);

View file

@ -1,5 +1,7 @@
package mage.cards; package mage.cards;
import java.util.List;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.Mana; import mage.Mana;
import mage.abilities.Abilities; import mage.abilities.Abilities;
@ -14,9 +16,6 @@ import mage.game.Game;
import mage.game.GameState; import mage.game.GameState;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import java.util.List;
import java.util.UUID;
public interface Card extends MageObject { public interface Card extends MageObject {
UUID getOwnerId(); UUID getOwnerId();
@ -132,6 +131,8 @@ public interface Card extends MageObject {
void addAbility(Ability ability); void addAbility(Ability ability);
void looseAllAbilities(Game game);
boolean addCounters(Counter counter, Ability source, Game game); boolean addCounters(Counter counter, Ability source, Game game);
boolean addCounters(Counter counter, Ability source, Game game, boolean isEffect); boolean addCounters(Counter counter, Ability source, Game game, boolean isEffect);
@ -148,8 +149,8 @@ public interface Card extends MageObject {
Card copy(); Card copy();
/** /**
* @return The main card of a split half card or adventure spell card, otherwise the card itself is * @return The main card of a split half card or adventure spell card,
* returned * otherwise the card itself is returned
*/ */
Card getMainCard(); Card getMainCard();

View file

@ -1,6 +1,12 @@
package mage.cards; package mage.cards;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.MageObjectImpl; import mage.MageObjectImpl;
import mage.Mana; import mage.Mana;
@ -26,13 +32,6 @@ import mage.util.SubTypeList;
import mage.watchers.Watcher; import mage.watchers.Watcher;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public abstract class CardImpl extends MageObjectImpl implements Card { public abstract class CardImpl extends MageObjectImpl implements Card {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -240,19 +239,12 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
@Override @Override
public List<String> getRules(Game game) { public List<String> getRules(Game game) {
try { try {
List<String> rules = getRules(); List<String> rules = getAbilities(game).getRules(getName());
if (game != null) { if (game != null) {
// debug state // debug state
CardState cardState = game.getState().getCardState(objectId); for (String data : game.getState().getCardState(objectId).getInfo().values()) {
if (cardState != null) {
for (String data : cardState.getInfo().values()) {
rules.add(data); rules.add(data);
} }
for (Ability ability : cardState.getAbilities()) {
rules.add(ability.getRule());
}
}
// ability hints // ability hints
List<String> abilityHints = new ArrayList<>(); List<String> abilityHints = new ArrayList<>();
if (HintUtils.ABILITY_HINTS_ENABLE) { if (HintUtils.ABILITY_HINTS_ENABLE) {
@ -267,7 +259,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
} }
// restrict hints only for permanents, not cards // restrict hints only for permanents, not cards
// total hints // total hints
if (!abilityHints.isEmpty()) { if (!abilityHints.isEmpty()) {
rules.add(HintUtils.HINT_START_MARK); rules.add(HintUtils.HINT_START_MARK);
@ -301,21 +292,31 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
*/ */
@Override @Override
public Abilities<Ability> getAbilities(Game game) { public Abilities<Ability> getAbilities(Game game) {
Abilities<Ability> otherAbilities = game.getState().getAllOtherAbilities(objectId); CardState cardState = game.getState().getCardState(this.getId());
if (otherAbilities == null || otherAbilities.isEmpty()) { if (!cardState.hasLostAllAbilities() && (cardState.getAbilities() == null || cardState.getAbilities().isEmpty())) {
return abilities; return abilities;
} }
Abilities<Ability> all = new AbilitiesImpl<>(); Abilities<Ability> all = new AbilitiesImpl<>();
if (!cardState.hasLostAllAbilities()) {
all.addAll(abilities); all.addAll(abilities);
all.addAll(otherAbilities); }
all.addAll(cardState.getAbilities());
return all; return all;
} }
@Override
public void looseAllAbilities(Game game) {
CardState cardState = game.getState().getCardState(this.getId());
cardState.setLostAllAbilities(true);
cardState.getAbilities().clear();
}
/** /**
* Public in order to support adding abilities to SplitCardHalf's * Public in order to support adding abilities to SplitCardHalf's
* *
* @param ability * @param ability
*/ */
@Override
public void addAbility(Ability ability) { public void addAbility(Ability ability) {
ability.setSourceId(this.getId()); ability.setSourceId(this.getId());
abilities.add(ability); abilities.add(ability);

View file

@ -18,6 +18,7 @@ public class CardState implements Serializable {
protected Map<String, String> info; protected Map<String, String> info;
protected Counters counters; protected Counters counters;
protected Abilities<Ability> abilities; protected Abilities<Ability> abilities;
protected boolean lostAllAbilities;
private static final Map<String, String> emptyInfo = new HashMap<>(); private static final Map<String, String> emptyInfo = new HashMap<>();
private static final Abilities<Ability> emptyAbilities = new AbilitiesImpl<>(); private static final Abilities<Ability> emptyAbilities = new AbilitiesImpl<>();
@ -39,6 +40,7 @@ public class CardState implements Serializable {
abilities.add(ability.copy()); abilities.add(ability.copy());
} }
} }
this.lostAllAbilities = state.lostAllAbilities;
} }
public CardState copy() { public CardState copy() {
@ -90,20 +92,29 @@ public class CardState implements Serializable {
abilities.addAll(ability.getSubAbilities()); abilities.addAll(ability.getSubAbilities());
} }
/**
* Called from applyEffects reset, to reset all layered effects
*/
public void clearAbilities() { public void clearAbilities() {
if (abilities != null) { if (abilities != null) {
// for (Ability ability: abilities) { // Causes problems if temporary (gained) continuous effects are removed
// ability.setSourceId(null);
// ability.setControllerId(null);
// }
abilities = null; abilities = null;
} }
setLostAllAbilities(false);
} }
public void clear() { public void clear() {
counters.clear(); counters.clear();
info = null; info = null;
clearAbilities(); clearAbilities();
lostAllAbilities = false;
}
public boolean hasLostAllAbilities() {
return lostAllAbilities;
}
public void setLostAllAbilities(boolean lostAllAbilities) {
this.lostAllAbilities = lostAllAbilities;
} }
} }

View file

@ -1,5 +1,8 @@
package mage.game; package mage.game;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import mage.MageObject; import mage.MageObject;
import mage.abilities.*; import mage.abilities.*;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
@ -34,10 +37,6 @@ import mage.util.ThreadLocalStringBuilder;
import mage.watchers.Watcher; import mage.watchers.Watcher;
import mage.watchers.Watchers; import mage.watchers.Watchers;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
* <p> * <p>
@ -602,7 +601,6 @@ public class GameState implements Serializable, Copyable<GameState> {
// public void addMessage(String message) { // public void addMessage(String message) {
// this.messages.add(message); // this.messages.add(message);
// } // }
/** /**
* Returns a list of all players of the game ignoring range or if a player * Returns a list of all players of the game ignoring range or if a player
* has lost or left the game. * has lost or left the game.
@ -636,8 +634,9 @@ public class GameState implements Serializable, Copyable<GameState> {
* also setting the playerId to the first/current player of the list. Also * also setting the playerId to the first/current player of the list. Also
* returning the other players in turn order. * returning the other players in turn order.
* <p> * <p>
* Not safe for continuous effects, see rule 800.4k (effects must work until end of turn even after player leaves) * Not safe for continuous effects, see rule 800.4k (effects must work until
* Use Player.InRange() to find active players list at the start of the turn * end of turn even after player leaves) Use Player.InRange() to find active
* players list at the start of the turn
* *
* @param playerId * @param playerId
* @param game * @param game

View file

@ -1,5 +1,6 @@
package mage.game.stack; package mage.game.stack;
import java.util.*;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.Mana; import mage.Mana;
@ -31,8 +32,6 @@ import mage.players.Player;
import mage.util.GameLog; import mage.util.GameLog;
import mage.util.SubTypeList; import mage.util.SubTypeList;
import java.util.*;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -1045,4 +1044,9 @@ public class Spell extends StackObjImpl implements Card {
return commandedBy; return commandedBy;
} }
@Override
public void looseAllAbilities(Game game) {
throw new UnsupportedOperationException("Spells should not loose all abilities. Check if this operation is correct.");
}
} }