mirror of
https://github.com/correl/mage.git
synced 2024-11-14 19:19:32 +00:00
* Fixed problems of Yixlid Jailer that removed abilities from cards in graveyard permanently (fixes #1147).
This commit is contained in:
parent
893bcbb01f
commit
8854871c15
28 changed files with 248 additions and 180 deletions
|
@ -1,6 +1,8 @@
|
|||
package mage.view;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Abilities;
|
||||
|
@ -26,9 +28,6 @@ import mage.target.Target;
|
|||
import mage.target.Targets;
|
||||
import mage.util.SubTypeList;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -211,8 +210,8 @@ public class CardView extends SimpleCardView {
|
|||
* @param card
|
||||
* @param game
|
||||
* @param controlled is the card view created for the card controller - used
|
||||
* for morph / face down cards to know which player may see information for
|
||||
* the card
|
||||
* for morph / face down cards to know which player may see information for
|
||||
* the card
|
||||
*/
|
||||
public CardView(Card card, Game game, boolean controlled) {
|
||||
this(card, game, controlled, false, false);
|
||||
|
@ -238,12 +237,12 @@ public class CardView extends SimpleCardView {
|
|||
/**
|
||||
* @param card
|
||||
* @param game
|
||||
* @param controlled is the card view created for the card controller - used
|
||||
* for morph / face down cards to know which player may see information for
|
||||
* the card
|
||||
* @param controlled is the card view created for the card controller - used
|
||||
* for morph / face down cards to know which player may see information for
|
||||
* the card
|
||||
* @param showFaceDownCard if true and the card is not on the battlefield,
|
||||
* also a face down card is shown in the view, face down cards will be shown
|
||||
* @param storeZone if true the card zone will be set in the zone attribute.
|
||||
* also a face down card is shown in the view, face down cards will be shown
|
||||
* @param storeZone if true the card zone will be set in the zone attribute.
|
||||
*/
|
||||
public CardView(Card card, Game game, boolean controlled, boolean showFaceDownCard, boolean storeZone) {
|
||||
super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), game != null, card.getTokenDescriptor());
|
||||
|
@ -436,7 +435,7 @@ public class CardView extends SimpleCardView {
|
|||
artRect = ArtRect.SPLIT_FUSED;
|
||||
} else if (spell.getCard() != null) {
|
||||
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 (ty == SpellAbilityType.SPLIT_RIGHT) {
|
||||
artRect = ArtRect.AFTERMATH_BOTTOM;
|
||||
|
@ -470,7 +469,7 @@ public class CardView extends SimpleCardView {
|
|||
this.startingLoyalty = "" + card.getStartingLoyalty();
|
||||
}
|
||||
|
||||
public CardView(MageObject object) {
|
||||
public CardView(MageObject object, Game game) {
|
||||
super(object.getId(), "", "0", false, "", true, "");
|
||||
this.originalCard = null;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package mage.view;
|
||||
|
||||
import java.util.*;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.Effect;
|
||||
|
@ -14,8 +15,6 @@ import mage.game.permanent.PermanentToken;
|
|||
import mage.target.targetpointer.TargetPointer;
|
||||
import mage.util.GameLog;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -102,7 +101,7 @@ public class CardsView extends LinkedHashMap<UUID, CardView> {
|
|||
} else if (isCard) {
|
||||
sourceCardView = new CardView((Card) sourceObject);
|
||||
} else {
|
||||
sourceCardView = new CardView(sourceObject);
|
||||
sourceCardView = new CardView(sourceObject, game);
|
||||
}
|
||||
abilityView = new AbilityView(ability, sourceObject.getName(), sourceCardView);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,11 @@ package mage.view;
|
|||
|
||||
import com.google.gson.Gson;
|
||||
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.abilities.costs.Cost;
|
||||
import mage.cards.Card;
|
||||
|
@ -25,12 +30,6 @@ import mage.players.Player;
|
|||
import mage.watchers.common.CastSpellLastTurnWatcher;
|
||||
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
|
||||
*/
|
||||
|
@ -121,7 +120,7 @@ public class GameView implements Serializable {
|
|||
} else if (object instanceof Designation) {
|
||||
Designation designation = (Designation) game.getObject(object.getId());
|
||||
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 {
|
||||
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) {
|
||||
StackAbility stackAbility = ((StackAbility) object);
|
||||
stackAbility.newId();
|
||||
stack.put(stackObject.getId(), new CardView(stackObject));
|
||||
stack.put(stackObject.getId(), new CardView(stackObject, game));
|
||||
checkPaid(stackObject.getId(), ((StackAbility) stackObject));
|
||||
} else {
|
||||
LOGGER.fatal("Object can't be cast to StackAbility: " + object.getName() + ' ' + object.toString() + ' ' + object.getClass().toString());
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
|
@ -18,11 +21,6 @@ import mage.game.permanent.Permanent;
|
|||
import mage.players.Player;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
|
@ -114,7 +112,7 @@ class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl {
|
|||
|| !card.isOwnedBy(controller.getId())) {
|
||||
return false;
|
||||
}
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
for (Ability ability : card.getAbilities(game)) {
|
||||
if (ability instanceof CyclingAbility) {
|
||||
cardHasCycling = true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
package mage.cards.c;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
|
@ -18,10 +19,6 @@ import mage.game.stack.Spell;
|
|||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
/**
|
||||
* @author magenoxx_at_gmail.com
|
||||
*/
|
||||
|
@ -34,7 +31,7 @@ public final class CastThroughTime extends CardImpl {
|
|||
}
|
||||
|
||||
public CastThroughTime(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{U}{U}{U}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}{U}{U}");
|
||||
|
||||
// Instant and sorcery spells you control have rebound.
|
||||
// (Exile the spell as it resolves if you cast it from your hand. At the beginning of your next upkeep, you may cast that card from exile without paying its mana cost.)
|
||||
|
@ -73,7 +70,7 @@ class GainReboundEffect extends ContinuousEffectImpl {
|
|||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (player != null && permanent != null) {
|
||||
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();) {
|
||||
StackObject stackObject = iterator.next();
|
||||
|
@ -81,19 +78,19 @@ class GainReboundEffect extends ContinuousEffectImpl {
|
|||
Spell spell = (Spell) stackObject;
|
||||
Card card = spell.getCard();
|
||||
if (card != null) {
|
||||
addReboundAbility(card, source, game);
|
||||
addReboundAbility(card, game);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addReboundAbility(Card card, Ability source, Game game) {
|
||||
private void addReboundAbility(Card card, Game 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) {
|
||||
Ability ability = new ReboundAbility();
|
||||
game.getState().addOtherAbility(card, ability);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.d;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -108,7 +107,7 @@ class DarkImpostorContinuousEffect extends ContinuousEffectImpl {
|
|||
for (UUID imprintedId : perm.getImprinted()) {
|
||||
Card card = game.getCard(imprintedId);
|
||||
if (card != null) {
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
for (Ability ability : card.getAbilities(game)) {
|
||||
if (ability instanceof ActivatedAbility) {
|
||||
perm.addAbility(ability.copy(), source.getSourceId(), game);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.d;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -28,8 +27,7 @@ import mage.target.TargetSpell;
|
|||
public final class Delay extends CardImpl {
|
||||
|
||||
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.
|
||||
this.getSpellAbility().addEffect(new DelayEffect());
|
||||
|
@ -71,7 +69,7 @@ class DelayEffect extends OneShotEffect {
|
|||
effect.setTargetPointer(targetPointer);
|
||||
Card card = game.getCard(spell.getSourceId());
|
||||
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);
|
||||
if (controller.moveCardToExileWithInfo(card, exileId, "Suspended cards of " + controller.getLogName(), source.getSourceId(), game, Zone.HAND, true)) {
|
||||
card.addCounters(CounterType.TIME.createInstance(3), source, game);
|
||||
|
@ -79,7 +77,7 @@ class DelayEffect extends OneShotEffect {
|
|||
game.addEffect(new GainSuspendEffect(new MageObjectReference(card, game)), source);
|
||||
}
|
||||
game.informPlayers(controller.getLogName() + " suspends 3 - " + card.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.f;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -15,8 +14,8 @@ import mage.constants.CardType;
|
|||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
|
||||
|
@ -36,7 +35,7 @@ public final class Filth extends CardImpl {
|
|||
}
|
||||
|
||||
public Filth(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
|
||||
this.subtype.add(SubType.INCARNATION);
|
||||
|
||||
this.power = new MageInt(2);
|
||||
|
@ -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.
|
||||
ContinuousEffect effect = new GainAbilityControlledEffect(new SwampwalkAbility(),
|
||||
Duration.WhileOnBattlefield, new FilterCreaturePermanent());
|
||||
Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES);
|
||||
ConditionalContinuousEffect filthEffect = new ConditionalContinuousEffect(effect,
|
||||
new PermanentsOnTheBattlefieldCondition(filter), ruleText);
|
||||
this.addAbility(new SimpleStaticAbility(Zone.GRAVEYARD, filthEffect));
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.h;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -16,11 +15,11 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
|
@ -39,7 +38,7 @@ public final class HavengulLich extends CardImpl {
|
|||
private static final FilterCard filter = new FilterCreatureCard("creature card in a graveyard");
|
||||
|
||||
public HavengulLich(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{B}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{B}");
|
||||
this.subtype.add(SubType.ZOMBIE);
|
||||
this.subtype.add(SubType.WIZARD);
|
||||
|
||||
|
@ -188,7 +187,7 @@ class HavengulLichEffect extends ContinuousEffectImpl {
|
|||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
Card card = game.getCard(cardId);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package mage.cards.j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -20,10 +23,6 @@ import mage.game.Game;
|
|||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
@ -89,7 +88,7 @@ class JhoiraOfTheGhituSuspendEffect extends OneShotEffect {
|
|||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
boolean hasSuspend = card.getAbilities().containsClass(SuspendAbility.class);
|
||||
boolean hasSuspend = card.getAbilities(game).containsClass(SuspendAbility.class);
|
||||
|
||||
UUID exileId = SuspendAbility.getSuspendExileId(controller.getId(), game);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.Objects;
|
||||
|
@ -14,11 +13,11 @@ import mage.cards.Card;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
|
@ -140,7 +139,7 @@ class MairsilThePretenderGainAbilitiesEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
for (Card card : game.getExile().getAllCards(game)) {
|
||||
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) {
|
||||
ActivatedAbility copyAbility = (ActivatedAbility) ability.copy();
|
||||
copyAbility.setMaxActivationsPerTurn(1);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -59,7 +58,7 @@ class MemoryCrystalSpellsCostReductionEffect extends CostModificationEffectImpl
|
|||
|
||||
Card card = game.getCard(abilityToModify.getSourceId());
|
||||
if (card != null) {
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
for (Ability ability : card.getAbilities(game)) {
|
||||
if (ability instanceof BuybackAbility) {
|
||||
if (ability.isActivated()) {
|
||||
int amountToReduce = ((BuybackAbility) ability).reduceCost(2);
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -15,11 +13,11 @@ import mage.cards.Card;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterArtifactCard;
|
||||
import mage.game.Game;
|
||||
|
@ -33,7 +31,7 @@ import mage.target.common.TargetCardInGraveyard;
|
|||
public final class MyrWelder extends CardImpl {
|
||||
|
||||
public MyrWelder(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{3}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}");
|
||||
this.subtype.add(SubType.MYR);
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(4);
|
||||
|
@ -104,12 +102,12 @@ class MyrWelderContinuousEffect extends ContinuousEffectImpl {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent perm = game.getPermanent(source.getSourceId());
|
||||
if (perm != null) {
|
||||
for (UUID imprintedId: perm.getImprinted()) {
|
||||
for (UUID imprintedId : perm.getImprinted()) {
|
||||
Card card = game.getCard(imprintedId);
|
||||
if (card != null) {
|
||||
for (Ability ability: card.getAbilities()) {
|
||||
for (Ability ability : card.getAbilities(game)) {
|
||||
if (ability instanceof ActivatedAbility) {
|
||||
perm.addAbility(ability, game);
|
||||
perm.addAbility(ability, source.getId(), game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.n;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -18,11 +17,11 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
@ -171,7 +170,7 @@ class NarsetTranscendentGainReboundEffect extends ContinuousEffectImpl {
|
|||
if (spell != null) {
|
||||
Card card = spell.getCard();
|
||||
if (card != null) {
|
||||
addReboundAbility(card, source, game);
|
||||
addReboundAbility(card, game);
|
||||
}
|
||||
} else {
|
||||
discard();
|
||||
|
@ -181,9 +180,9 @@ class NarsetTranscendentGainReboundEffect extends ContinuousEffectImpl {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void addReboundAbility(Card card, Ability source, Game game) {
|
||||
private void addReboundAbility(Card card, Game game) {
|
||||
boolean found = false;
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
for (Ability ability : card.getAbilities(game)) {
|
||||
if (ability instanceof ReboundAbility) {
|
||||
found = true;
|
||||
break;
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
|
||||
package mage.cards.n;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
|
@ -66,9 +64,9 @@ public final class NecroticOoze extends CardImpl {
|
|||
if (player != null) {
|
||||
for (Card card : player.getGraveyard().getCards(game)) {
|
||||
if (card.isCreature()) {
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
for (Ability ability : card.getAbilities(game)) {
|
||||
if (ability instanceof ActivatedAbility) {
|
||||
perm.addAbility(ability, game);
|
||||
perm.addAbility(ability, source.getSourceId(), game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package mage.cards.p;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
|
@ -23,10 +26,6 @@ import mage.game.Game;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
|
@ -76,6 +75,7 @@ class PolukranosUnchainedEffect extends OneShotEffect {
|
|||
|
||||
PolukranosUnchainedEffect() {
|
||||
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) {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.s;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -13,11 +12,11 @@ import mage.cards.Card;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
@ -30,7 +29,7 @@ import mage.players.Player;
|
|||
public final class SkillBorrower extends CardImpl {
|
||||
|
||||
public SkillBorrower(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}{U}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}{U}");
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.WIZARD);
|
||||
|
||||
|
@ -53,7 +52,6 @@ public final class SkillBorrower extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class SkillBorrowerAbility extends StaticAbility {
|
||||
|
||||
public SkillBorrowerAbility() {
|
||||
|
@ -71,7 +69,7 @@ class SkillBorrowerAbility extends StaticAbility {
|
|||
|
||||
@Override
|
||||
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() {
|
||||
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) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SkillBorrowerEffect copy() {
|
||||
return new SkillBorrowerEffect(this);
|
||||
|
@ -95,13 +92,13 @@ class SkillBorrowerEffect extends ContinuousEffectImpl {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if(player != null){
|
||||
if (player != null) {
|
||||
Card card = player.getLibrary().getFromTop(game);
|
||||
if(card != null && (card.isCreature() || card.isArtifact())){
|
||||
if (card != null && (card.isCreature() || card.isArtifact())) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if(permanent != null){
|
||||
for(Ability ability : card.getAbilities()){
|
||||
if(ability instanceof ActivatedAbility){
|
||||
if (permanent != null) {
|
||||
for (Ability ability : card.getAbilities(game)) {
|
||||
if (ability instanceof ActivatedAbility) {
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -16,10 +19,6 @@ import mage.game.Game;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
@ -91,7 +90,7 @@ class SoulflayerEffect extends ContinuousEffectImpl implements SourceEffect {
|
|||
if (!card.isCreature()) {
|
||||
continue;
|
||||
}
|
||||
for (Ability cardAbility : card.getAbilities()) {
|
||||
for (Ability cardAbility : card.getAbilities(game)) {
|
||||
if (cardAbility instanceof FlyingAbility) {
|
||||
abilitiesToAdd.add(FlyingAbility.getInstance());
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
|
@ -26,8 +27,6 @@ import mage.players.Player;
|
|||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.watchers.common.AttackedThisTurnWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
|
@ -153,7 +152,7 @@ class TaigamOjutaiMasterGainReboundEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
|
||||
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) {
|
||||
Ability ability = new ReboundAbility();
|
||||
game.getState().addOtherAbility(card, ability);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package mage.cards.v;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -14,8 +15,6 @@ import mage.constants.*;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @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)) {
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
|
||||
package mage.cards.y;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
|
@ -21,7 +19,7 @@ import mage.players.Player;
|
|||
public final class YixlidJailer extends CardImpl {
|
||||
|
||||
public YixlidJailer(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
|
||||
this.subtype.add(SubType.ZOMBIE);
|
||||
this.subtype.add(SubType.WIZARD);
|
||||
|
||||
|
@ -67,14 +65,7 @@ public final class YixlidJailer extends CardImpl {
|
|||
if (player != null) {
|
||||
for (Card card : player.getGraveyard().getCards(game)) {
|
||||
if (card != null) {
|
||||
card.getAbilities(game).clear(); // Will the abilities ever come back????
|
||||
// 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();
|
||||
}
|
||||
card.looseAllAbilities(game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 can’t 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);
|
||||
}
|
||||
}
|
|
@ -5,17 +5,13 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
import mage.abilities.costs.*;
|
||||
import mage.abilities.costs.common.PayLifeCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.*;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.Effects;
|
||||
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.mana.ActivatedManaAbilityImpl;
|
||||
import mage.cards.Card;
|
||||
|
@ -25,7 +21,6 @@ import mage.game.Game;
|
|||
import mage.game.command.Emblem;
|
||||
import mage.game.command.Plane;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ManaEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackAbility;
|
||||
|
@ -952,7 +947,12 @@ public abstract class AbilityImpl implements Ability {
|
|||
return false;
|
||||
}
|
||||
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
|
||||
Abilities<Ability> otherAbilities = game.getState().getAllOtherAbilities(this.getSourceId());
|
||||
return otherAbilities != null && otherAbilities.contains(this);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package mage.cards;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Abilities;
|
||||
|
@ -14,9 +16,6 @@ import mage.game.Game;
|
|||
import mage.game.GameState;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface Card extends MageObject {
|
||||
|
||||
UUID getOwnerId();
|
||||
|
@ -77,15 +76,15 @@ public interface Card extends MageObject {
|
|||
* @param zone
|
||||
* @param sourceId
|
||||
* @param game
|
||||
* @param flag If zone
|
||||
* <ul>
|
||||
* <li>LIBRARY: <ul><li>true - put on top</li><li>false - put on
|
||||
* bottom</li></ul></li>
|
||||
* <li>BATTLEFIELD: <ul><li>true - tapped</li><li>false -
|
||||
* untapped</li></ul></li>
|
||||
* <li>GRAVEYARD: <ul><li>true - not from Battlefield</li><li>false - from
|
||||
* Battlefield</li></ul></li>
|
||||
* </ul>
|
||||
* @param flag If zone
|
||||
* <ul>
|
||||
* <li>LIBRARY: <ul><li>true - put on top</li><li>false - put on
|
||||
* bottom</li></ul></li>
|
||||
* <li>BATTLEFIELD: <ul><li>true - tapped</li><li>false -
|
||||
* untapped</li></ul></li>
|
||||
* <li>GRAVEYARD: <ul><li>true - not from Battlefield</li><li>false - from
|
||||
* Battlefield</li></ul></li>
|
||||
* </ul>
|
||||
* @return true if card was moved to zone
|
||||
*/
|
||||
boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag);
|
||||
|
@ -95,8 +94,8 @@ public interface Card extends MageObject {
|
|||
/**
|
||||
* Moves the card to an exile zone
|
||||
*
|
||||
* @param exileId set to null for generic exile zone
|
||||
* @param name used for exile zone with the specified exileId
|
||||
* @param exileId set to null for generic exile zone
|
||||
* @param name used for exile zone with the specified exileId
|
||||
* @param sourceId
|
||||
* @param game
|
||||
* @return true if card was moved to zone
|
||||
|
@ -132,6 +131,8 @@ public interface Card extends MageObject {
|
|||
|
||||
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 isEffect);
|
||||
|
@ -148,8 +149,8 @@ public interface Card extends MageObject {
|
|||
Card copy();
|
||||
|
||||
/**
|
||||
* @return The main card of a split half card or adventure spell card, otherwise the card itself is
|
||||
* returned
|
||||
* @return The main card of a split half card or adventure spell card,
|
||||
* otherwise the card itself is returned
|
||||
*/
|
||||
Card getMainCard();
|
||||
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
package mage.cards;
|
||||
|
||||
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.MageObjectImpl;
|
||||
import mage.Mana;
|
||||
|
@ -26,13 +32,6 @@ import mage.util.SubTypeList;
|
|||
import mage.watchers.Watcher;
|
||||
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 {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -240,19 +239,12 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
@Override
|
||||
public List<String> getRules(Game game) {
|
||||
try {
|
||||
List<String> rules = getRules();
|
||||
List<String> rules = getAbilities(game).getRules(getName());
|
||||
if (game != null) {
|
||||
// debug state
|
||||
CardState cardState = game.getState().getCardState(objectId);
|
||||
if (cardState != null) {
|
||||
for (String data : cardState.getInfo().values()) {
|
||||
rules.add(data);
|
||||
}
|
||||
for (Ability ability : cardState.getAbilities()) {
|
||||
rules.add(ability.getRule());
|
||||
}
|
||||
for (String data : game.getState().getCardState(objectId).getInfo().values()) {
|
||||
rules.add(data);
|
||||
}
|
||||
|
||||
// ability hints
|
||||
List<String> abilityHints = new ArrayList<>();
|
||||
if (HintUtils.ABILITY_HINTS_ENABLE) {
|
||||
|
@ -267,7 +259,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
|
||||
// restrict hints only for permanents, not cards
|
||||
|
||||
// total hints
|
||||
if (!abilityHints.isEmpty()) {
|
||||
rules.add(HintUtils.HINT_START_MARK);
|
||||
|
@ -301,21 +292,31 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
*/
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities(Game game) {
|
||||
Abilities<Ability> otherAbilities = game.getState().getAllOtherAbilities(objectId);
|
||||
if (otherAbilities == null || otherAbilities.isEmpty()) {
|
||||
CardState cardState = game.getState().getCardState(this.getId());
|
||||
if (!cardState.hasLostAllAbilities() && (cardState.getAbilities() == null || cardState.getAbilities().isEmpty())) {
|
||||
return abilities;
|
||||
}
|
||||
Abilities<Ability> all = new AbilitiesImpl<>();
|
||||
all.addAll(abilities);
|
||||
all.addAll(otherAbilities);
|
||||
if (!cardState.hasLostAllAbilities()) {
|
||||
all.addAll(abilities);
|
||||
}
|
||||
all.addAll(cardState.getAbilities());
|
||||
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
|
||||
*
|
||||
* @param ability
|
||||
*/
|
||||
@Override
|
||||
public void addAbility(Ability ability) {
|
||||
ability.setSourceId(this.getId());
|
||||
abilities.add(ability);
|
||||
|
|
|
@ -18,6 +18,7 @@ public class CardState implements Serializable {
|
|||
protected Map<String, String> info;
|
||||
protected Counters counters;
|
||||
protected Abilities<Ability> abilities;
|
||||
protected boolean lostAllAbilities;
|
||||
|
||||
private static final Map<String, String> emptyInfo = new HashMap<>();
|
||||
private static final Abilities<Ability> emptyAbilities = new AbilitiesImpl<>();
|
||||
|
@ -39,6 +40,7 @@ public class CardState implements Serializable {
|
|||
abilities.add(ability.copy());
|
||||
}
|
||||
}
|
||||
this.lostAllAbilities = state.lostAllAbilities;
|
||||
}
|
||||
|
||||
public CardState copy() {
|
||||
|
@ -90,20 +92,29 @@ public class CardState implements Serializable {
|
|||
abilities.addAll(ability.getSubAbilities());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from applyEffects reset, to reset all layered effects
|
||||
*/
|
||||
public void clearAbilities() {
|
||||
if (abilities != null) {
|
||||
// for (Ability ability: abilities) { // Causes problems if temporary (gained) continuous effects are removed
|
||||
// ability.setSourceId(null);
|
||||
// ability.setControllerId(null);
|
||||
// }
|
||||
abilities = null;
|
||||
}
|
||||
setLostAllAbilities(false);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
counters.clear();
|
||||
info = null;
|
||||
clearAbilities();
|
||||
lostAllAbilities = false;
|
||||
}
|
||||
|
||||
public boolean hasLostAllAbilities() {
|
||||
return lostAllAbilities;
|
||||
}
|
||||
|
||||
public void setLostAllAbilities(boolean lostAllAbilities) {
|
||||
this.lostAllAbilities = lostAllAbilities;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package mage.game;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
|
@ -34,10 +37,6 @@ import mage.util.ThreadLocalStringBuilder;
|
|||
import mage.watchers.Watcher;
|
||||
import mage.watchers.Watchers;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* <p>
|
||||
|
@ -602,7 +601,6 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
// public void addMessage(String message) {
|
||||
// this.messages.add(message);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns a list of all players of the game ignoring range or if a player
|
||||
* 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
|
||||
* returning the other players in turn order.
|
||||
* <p>
|
||||
* Not safe for continuous effects, see rule 800.4k (effects must work until end of turn even after player leaves)
|
||||
* Use Player.InRange() to find active players list at the start of the turn
|
||||
* Not safe for continuous effects, see rule 800.4k (effects must work until
|
||||
* end of turn even after player leaves) Use Player.InRange() to find active
|
||||
* players list at the start of the turn
|
||||
*
|
||||
* @param playerId
|
||||
* @param game
|
||||
|
@ -775,7 +774,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
for (Map.Entry<ZoneChangeData, List<GameEvent>> entry : eventsByKey.entrySet()) {
|
||||
Set<Card> movedCards = new LinkedHashSet<>();
|
||||
Set<PermanentToken> movedTokens = new LinkedHashSet<>();
|
||||
for (Iterator<GameEvent> it = entry.getValue().iterator(); it.hasNext(); ) {
|
||||
for (Iterator<GameEvent> it = entry.getValue().iterator(); it.hasNext();) {
|
||||
GameEvent event = it.next();
|
||||
ZoneChangeEvent castEvent = (ZoneChangeEvent) event;
|
||||
UUID targetId = castEvent.getTargetId();
|
||||
|
@ -1008,7 +1007,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
* @param attachedTo
|
||||
* @param ability
|
||||
* @param copyAbility copies non MageSingleton abilities before adding to
|
||||
* state
|
||||
* state
|
||||
*/
|
||||
public void addOtherAbility(Card attachedTo, Ability ability, boolean copyAbility) {
|
||||
Ability newAbility;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package mage.game.stack;
|
||||
|
||||
import java.util.*;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
|
@ -31,8 +32,6 @@ import mage.players.Player;
|
|||
import mage.util.GameLog;
|
||||
import mage.util.SubTypeList;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -1045,4 +1044,9 @@ public class Spell extends StackObjImpl implements Card {
|
|||
return commandedBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void looseAllAbilities(Game game) {
|
||||
throw new UnsupportedOperationException("Spells should not loose all abilities. Check if this operation is correct.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue