mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 03:22:00 -08: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
|
||||
*/
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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,7 +78,7 @@ class GainReboundEffect extends ContinuousEffectImpl {
|
|||
Spell spell = (Spell) stackObject;
|
||||
Card card = spell.getCard();
|
||||
if (card != null) {
|
||||
addReboundAbility(card, source, game);
|
||||
addReboundAbility(card, game);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -91,9 +88,9 @@ class GainReboundEffect extends ContinuousEffectImpl {
|
|||
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;
|
||||
|
|
@ -30,7 +29,6 @@ public final class Delay extends CardImpl {
|
|||
public Delay(UUID ownerId, CardSetInfo setInfo) {
|
||||
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());
|
||||
this.getSpellAbility().addTarget(new TargetSpell());
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -107,9 +105,9 @@ class MyrWelderContinuousEffect 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, 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;
|
||||
|
|
@ -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);
|
||||
|
|
@ -100,7 +97,7 @@ class SkillBorrowerEffect extends ContinuousEffectImpl {
|
|||
if (card != null && (card.isCreature() || card.isArtifact())) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
for(Ability ability : card.getAbilities()){
|
||||
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;
|
||||
|
|
@ -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();
|
||||
|
|
@ -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()) {
|
||||
for (String data : game.getState().getCardState(objectId).getInfo().values()) {
|
||||
rules.add(data);
|
||||
}
|
||||
for (Ability ability : cardState.getAbilities()) {
|
||||
rules.add(ability.getRule());
|
||||
}
|
||||
}
|
||||
|
||||
// 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<>();
|
||||
if (!cardState.hasLostAllAbilities()) {
|
||||
all.addAll(abilities);
|
||||
all.addAll(otherAbilities);
|
||||
}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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…
Add table
Add a link
Reference in a new issue