diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java index 525af20c803..3a737ee3964 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java @@ -7,7 +7,7 @@ import mage.client.dialog.PreferencesDialog; import mage.constants.CardType; import mage.constants.MageObjectType; import mage.constants.SubType; -import mage.util.SubTypeList; +import mage.util.SubTypes; import mage.view.CardView; import mage.view.PermanentView; import org.apache.log4j.Logger; @@ -1466,7 +1466,7 @@ public class ModernCardRenderer extends CardRenderer { // Determine which background paint to use from a set of colors // and the current card. - protected static Paint getBackgroundPaint(ObjectColor colors, Collection types, SubTypeList subTypes) { + protected static Paint getBackgroundPaint(ObjectColor colors, Collection types, SubTypes subTypes) { if (subTypes.contains(SubType.VEHICLE)) { return BG_TEXTURE_VEHICLE; } else if (types.contains(CardType.LAND)) { @@ -1493,7 +1493,7 @@ public class ModernCardRenderer extends CardRenderer { // Determine which background image to use from a set of colors // and the current card. - protected static BufferedImage getBackgroundImage(ObjectColor colors, Collection types, SubTypeList subTypes, boolean isExped) { + protected static BufferedImage getBackgroundImage(ObjectColor colors, Collection types, SubTypes subTypes, boolean isExped) { if (subTypes.contains(SubType.VEHICLE)) { return BG_IMG_VEHICLE; } else if (types.contains(CardType.LAND)) { diff --git a/Mage.Common/src/main/java/mage/view/AbilityView.java b/Mage.Common/src/main/java/mage/view/AbilityView.java index 7327ac9eefc..f6d20dfc338 100644 --- a/Mage.Common/src/main/java/mage/view/AbilityView.java +++ b/Mage.Common/src/main/java/mage/view/AbilityView.java @@ -5,7 +5,7 @@ import java.util.EnumSet; import mage.ObjectColor; import mage.abilities.Ability; import mage.constants.SuperType; -import mage.util.SubTypeList; +import mage.util.SubTypes; /** * @author BetaSteward_at_googlemail.com @@ -28,7 +28,7 @@ public class AbilityView extends CardView { this.toughness = ""; this.loyalty = ""; this.cardTypes = new ArrayList<>(); - this.subTypes = new SubTypeList(); + this.subTypes = new SubTypes(); this.superTypes = EnumSet.noneOf(SuperType.class); this.color = new ObjectColor(); this.manaCostLeft = ability.getManaCosts().getSymbols(); diff --git a/Mage.Common/src/main/java/mage/view/CardView.java b/Mage.Common/src/main/java/mage/view/CardView.java index de649000493..d0bee10ac8c 100644 --- a/Mage.Common/src/main/java/mage/view/CardView.java +++ b/Mage.Common/src/main/java/mage/view/CardView.java @@ -29,7 +29,7 @@ import mage.game.stack.StackAbility; import mage.target.Target; import mage.target.Targets; import mage.util.CardUtil; -import mage.util.SubTypeList; +import mage.util.SubTypes; import java.util.*; import java.util.stream.Collectors; @@ -58,7 +58,7 @@ public class CardView extends SimpleCardView { protected String loyalty = ""; protected String startingLoyalty; protected ArrayList cardTypes; - protected SubTypeList subTypes; + protected SubTypes subTypes; protected Set superTypes; protected ObjectColor color; protected ObjectColor frameColor; @@ -165,7 +165,7 @@ public class CardView extends SimpleCardView { this.loyalty = cardView.loyalty; this.startingLoyalty = cardView.startingLoyalty; this.cardTypes = new ArrayList<>(cardView.cardTypes); - this.subTypes = new SubTypeList(cardView.subTypes); + this.subTypes = new SubTypes(cardView.subTypes); this.superTypes = cardView.superTypes; this.color = cardView.color; @@ -552,9 +552,9 @@ public class CardView extends SimpleCardView { this.loyalty = ""; } this.cardTypes = object.getCardType(); - this.subTypes = object.getSubtype(null); + this.subTypes = object.getSubtype(game); this.superTypes = object.getSuperType(); - this.color = object.getColor(null); + this.color = object.getColor(game); this.manaCostLeft = object.getManaCost().getSymbols(); this.manaCostRight = new ArrayList<>(); this.convertedManaCost = object.getManaCost().convertedManaCost(); @@ -596,7 +596,7 @@ public class CardView extends SimpleCardView { } } // Frame color - this.frameColor = object.getFrameColor(null); + this.frameColor = object.getFrameColor(game); // Frame style this.frameStyle = object.getFrameStyle(); // Starting loyalty. Must be extracted from an ability @@ -671,7 +671,7 @@ public class CardView extends SimpleCardView { this.loyalty = ""; this.startingLoyalty = ""; this.cardTypes = new ArrayList<>(); - this.subTypes = new SubTypeList(); + this.subTypes = new SubTypes(); this.superTypes = EnumSet.noneOf(SuperType.class); this.color = new ObjectColor(); this.frameColor = new ObjectColor(); @@ -707,7 +707,7 @@ public class CardView extends SimpleCardView { } - CardView(Token token) { + CardView(Token token, Game game) { super(token.getId(), "", "0", false, "", ""); this.isToken = true; this.id = token.getId(); @@ -720,10 +720,10 @@ public class CardView extends SimpleCardView { this.loyalty = ""; this.startingLoyalty = ""; this.cardTypes = token.getCardType(); - this.subTypes = token.getSubtype(null); + this.subTypes = token.getSubtype(game); this.superTypes = token.getSuperType(); - this.color = token.getColor(null); - this.frameColor = token.getFrameColor(null); + this.color = token.getColor(game); + this.frameColor = token.getFrameColor(game); this.frameStyle = token.getFrameStyle(); this.manaCostLeft = token.getManaCost().getSymbols(); this.manaCostRight = new ArrayList<>(); @@ -816,7 +816,7 @@ public class CardView extends SimpleCardView { return cardTypes; } - public SubTypeList getSubTypes() { + public SubTypes getSubTypes() { return subTypes; } diff --git a/Mage.Common/src/main/java/mage/view/PermanentView.java b/Mage.Common/src/main/java/mage/view/PermanentView.java index c72f910a9b6..28bd992fb5d 100644 --- a/Mage.Common/src/main/java/mage/view/PermanentView.java +++ b/Mage.Common/src/main/java/mage/view/PermanentView.java @@ -6,6 +6,7 @@ import mage.cards.Card; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; +import mage.game.permanent.token.Token; import mage.players.Player; import java.util.ArrayList; @@ -51,7 +52,7 @@ public class PermanentView extends CardView { } this.attachedTo = permanent.getAttachedTo(); if (isToken()) { - original = new CardView(((PermanentToken) permanent).getToken()); + original = new CardView(((PermanentToken) permanent).getToken(), game); original.expansionSetCode = permanent.getExpansionSetCode(); tokenSetCode = original.getTokenSetCode(); tokenDescriptor = original.getTokenDescriptor(); diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java index 361ac57a6a2..355688cbb83 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java @@ -56,7 +56,7 @@ public final class ArtificialScoringSystem { //score + =cardDefinition.getActivations().size()*50; //score += cardDefinition.getManaActivations().size()*80; } else { - if (permanent.getSubtype(game).contains(SubType.EQUIPMENT)) { + if (permanent.hasSubtype(SubType.EQUIPMENT, game)) { score += 100; } } diff --git a/Mage.Sets/src/mage/cards/a/AbsorbIdentity.java b/Mage.Sets/src/mage/cards/a/AbsorbIdentity.java index d24f6167a37..77562763582 100644 --- a/Mage.Sets/src/mage/cards/a/AbsorbIdentity.java +++ b/Mage.Sets/src/mage/cards/a/AbsorbIdentity.java @@ -16,7 +16,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -74,7 +74,7 @@ class AbsorbIdentityEffect extends OneShotEffect { FilterCreaturePermanent filter = new FilterCreaturePermanent("shapeshifter"); filter.add(SubType.SHAPESHIFTER.getPredicate()); for (Permanent copyTo : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) { - game.copyPermanent(Duration.EndOfTurn, copyFrom, copyTo.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, copyFrom, copyTo.getId(), source, new EmptyCopyApplier()); } } return true; diff --git a/Mage.Sets/src/mage/cards/a/AlphaStatus.java b/Mage.Sets/src/mage/cards/a/AlphaStatus.java index ec6fdd63ee6..fa2ca49afab 100644 --- a/Mage.Sets/src/mage/cards/a/AlphaStatus.java +++ b/Mage.Sets/src/mage/cards/a/AlphaStatus.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.DynamicValue; @@ -18,8 +17,9 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Eirkei */ public final class AlphaStatus extends CardImpl { @@ -61,7 +61,7 @@ class AlphaStatusDynamicValue implements DynamicValue { if (enchanted != null) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, game)) { if (!permanent.getId().equals(enchanted.getId())) { - if (enchanted.shareCreatureTypes(permanent, game)) { + if (enchanted.shareCreatureTypes(game, permanent)) { xValue += 2; } } diff --git a/Mage.Sets/src/mage/cards/a/AlpineMoon.java b/Mage.Sets/src/mage/cards/a/AlpineMoon.java index 7ac445e5e5b..4523403eedc 100644 --- a/Mage.Sets/src/mage/cards/a/AlpineMoon.java +++ b/Mage.Sets/src/mage/cards/a/AlpineMoon.java @@ -87,7 +87,7 @@ class AlpineMoonEffect extends ContinuousEffectImpl { // 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects // So the ability removing has to be done before Layer 6 land.removeAllAbilities(source.getSourceId(), game); - land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); break; case AbilityAddingRemovingEffects_6: land.addAbility(new AnyColorManaAbility(), source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/a/AmoeboidChangeling.java b/Mage.Sets/src/mage/cards/a/AmoeboidChangeling.java index 604487800b8..27028090543 100644 --- a/Mage.Sets/src/mage/cards/a/AmoeboidChangeling.java +++ b/Mage.Sets/src/mage/cards/a/AmoeboidChangeling.java @@ -28,8 +28,7 @@ public final class AmoeboidChangeling extends CardImpl { this.toughness = new MageInt(1); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // {tap}: Target creature gains all creature types until end of turn. Ability ability = new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/a/ArcaneAdaptation.java b/Mage.Sets/src/mage/cards/a/ArcaneAdaptation.java index 3069f111d77..ddf7ceb57e3 100644 --- a/Mage.Sets/src/mage/cards/a/ArcaneAdaptation.java +++ b/Mage.Sets/src/mage/cards/a/ArcaneAdaptation.java @@ -1,8 +1,6 @@ package mage.cards.a; -import java.util.Iterator; -import java.util.List; -import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; @@ -21,6 +19,10 @@ import mage.game.stack.Spell; import mage.game.stack.StackObject; import mage.players.Player; +import java.util.Iterator; +import java.util.List; +import java.util.UUID; + /** * @author TheElk801 */ @@ -31,11 +33,12 @@ public final class ArcaneAdaptation extends CardImpl { // As Arcane Adaptation enters the battlefield, choose a creature type. this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.Neutral))); + // Creatures you control are the chosen type in addition to their other types. The same is true for creature spells you control and creature cards you own that aren't on the battlefield. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConspyEffect())); + this.addAbility(new SimpleStaticAbility(new ArcaneAdaptationEffect())); } - public ArcaneAdaptation(final ArcaneAdaptation card) { + private ArcaneAdaptation(final ArcaneAdaptation card) { super(card); } @@ -45,96 +48,94 @@ public final class ArcaneAdaptation extends CardImpl { } } -class ConspyEffect extends ContinuousEffectImpl { +class ArcaneAdaptationEffect extends ContinuousEffectImpl { - public ConspyEffect() { - super(Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "Creatures you control are the chosen type in addition to their other types. The same is true for creature spells you control and creature cards you own that aren't on the battlefield"; + ArcaneAdaptationEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); + staticText = "Creatures you control are the chosen type in addition to their other types. " + + "The same is true for creature spells you control and creature cards you own that aren't on the battlefield"; } - public ConspyEffect(final ConspyEffect effect) { + private ArcaneAdaptationEffect(final ArcaneAdaptationEffect effect) { super(effect); } @Override - public ConspyEffect copy() { - return new ConspyEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Player controller = game.getPlayer(source.getControllerId()); - SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game); - if (controller != null && subType != null) { - // Creature cards you own that aren't on the battlefield - // in graveyard - for (UUID cardId : controller.getGraveyard()) { - Card card = game.getCard(cardId); - if (card != null && card.isCreature() && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); - } - } - // on Hand - for (UUID cardId : controller.getHand()) { - Card card = game.getCard(cardId); - if (card != null && card.isCreature() && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); - } - } - // in Exile - for (Card card : game.getState().getExile().getAllCards(game)) { - if (card.isCreature() && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); - } - } - // in Library (e.g. for Mystical Teachings) - for (Card card : controller.getLibrary().getCards(game)) { - if (card.isOwnedBy(controller.getId()) && card.isCreature() && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); - } - } - // commander in command zone - for (CommandObject commandObject : game.getState().getCommand()) { - if (commandObject instanceof Commander) { - Card card = game.getCard(((Commander) commandObject).getId()); - if (card != null && card.isOwnedBy(controller.getId()) - && card.isCreature() && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); - } - } - } - // creature spells you control - for (Iterator iterator = game.getStack().iterator(); iterator.hasNext(); ) { - StackObject stackObject = iterator.next(); - if (stackObject instanceof Spell - && stackObject.isControlledBy(source.getControllerId()) - && stackObject.isCreature() - && !stackObject.hasSubtype(subType, game)) { - Card card = ((Spell) stackObject).getCard(); - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); - } - } - // creatures you control - List creatures = game.getBattlefield().getAllActivePermanents( - new FilterControlledCreaturePermanent(), source.getControllerId(), game); - for (Permanent creature : creatures) { - if (creature != null) { - creature.addSubType(game, subType); - } - } - return true; - } - - return false; + public ArcaneAdaptationEffect copy() { + return new ArcaneAdaptationEffect(this); } @Override public boolean apply(Game game, Ability source) { - return false; + Player controller = game.getPlayer(source.getControllerId()); + SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game); + if (controller == null || subType == null) { + return false; + } + // Creature cards you own that aren't on the battlefield + // in graveyard + for (UUID cardId : controller.getGraveyard()) { + Card card = game.getCard(cardId); + if (card != null && card.isCreature() && !card.hasSubtype(subType, game)) { + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + } + } + // on Hand + for (UUID cardId : controller.getHand()) { + Card card = game.getCard(cardId); + if (card != null && card.isCreature() && !card.hasSubtype(subType, game)) { + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + } + } + // in Exile + for (Card card : game.getState().getExile().getAllCards(game)) { + if (card.isCreature() && !card.hasSubtype(subType, game)) { + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + } + } + // in Library (e.g. for Mystical Teachings) + for (Card card : controller.getLibrary().getCards(game)) { + if (card.isOwnedBy(controller.getId()) && card.isCreature() && !card.hasSubtype(subType, game)) { + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + } + } + // commander in command zone + for (CommandObject commandObject : game.getState().getCommand()) { + if (commandObject instanceof Commander) { + Card card = game.getCard(((Commander) commandObject).getId()); + if (card != null && card.isOwnedBy(controller.getId()) + && card.isCreature() && !card.hasSubtype(subType, game)) { + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + } + } + } + // creature spells you control + for (Iterator iterator = game.getStack().iterator(); iterator.hasNext(); ) { + StackObject stackObject = iterator.next(); + if (stackObject instanceof Spell + && stackObject.isControlledBy(source.getControllerId()) + && stackObject.isCreature() + && !stackObject.hasSubtype(subType, game)) { + Card card = ((Spell) stackObject).getCard(); + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + } + } + // creatures you control + List creatures = game.getBattlefield().getAllActivePermanents( + new FilterControlledCreaturePermanent(), source.getControllerId(), game); + for (Permanent creature : creatures) { + if (creature != null) { + creature.addSubType(game, subType); + } + } + return true; + } - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; + private void setCreatureSubtype(MageObject object, SubType subtype, Game game) { + if (object == null) { + return; + } + game.getState().getCreateMageObjectAttribute(object, game).getSubtype().add(subtype); } } diff --git a/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java b/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java index a6848d62d51..e3abadcd10b 100644 --- a/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java +++ b/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java @@ -13,7 +13,7 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -46,24 +46,18 @@ public final class ArtisanOfForms extends CardImpl { static Ability createAbility() { Ability ability = new HeroicAbility(new CopyPermanentEffect( StaticFilters.FILTER_PERMANENT_CREATURE, - new ArtisanOfFormsApplyToPermanent(), true + new ArtisanOfFormsCopyApplier(), true ).setText("have {this} become a copy of target creature, except it has this ability"), true); ability.addTarget(new TargetCreaturePermanent()); return ability; } } -class ArtisanOfFormsApplyToPermanent extends ApplyToPermanent { +class ArtisanOfFormsCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.getAbilities().add(ArtisanOfForms.createAbility()); - return true; - } - - @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.addAbility(ArtisanOfForms.createAbility(), source.getSourceId(), game); + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.getAbilities().add(ArtisanOfForms.createAbility()); return true; } } diff --git a/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java b/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java index 07a535b4557..82f8f7130ae 100644 --- a/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java +++ b/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java @@ -89,11 +89,9 @@ class AshayaSoulOfTheWildEffect extends ContinuousEffectImpl { if (!permanent.isLand()) { permanent.addCardType(CardType.LAND); } - if (!permanent.hasSubtype(SubType.FOREST, game)) { - permanent.addSubType(game, SubType.FOREST); - if (!permanent.getAbilities(game).containsClass(GreenManaAbility.class)) { - permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } + permanent.addSubType(game, SubType.FOREST); + if (!permanent.getAbilities(game).containsClass(GreenManaAbility.class)) { + permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); } } return true; diff --git a/Mage.Sets/src/mage/cards/a/Aurification.java b/Mage.Sets/src/mage/cards/a/Aurification.java index 145c46b823e..a0ec8456d78 100644 --- a/Mage.Sets/src/mage/cards/a/Aurification.java +++ b/Mage.Sets/src/mage/cards/a/Aurification.java @@ -19,8 +19,8 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; -import mage.util.SubTypeList; +import java.util.Arrays; import java.util.UUID; /** @@ -44,10 +44,7 @@ public final class Aurification extends CardImpl { this.addAbility(new AddGoldCountersAbility()); // Each creature with a gold counter on it is a Wall in addition to its other creature types and has defender. - SubTypeList subtypes = new SubTypeList(); - subtypes.add(SubType.WALL); - - BecomesSubtypeAllEffect becomesSubtypeAllEffect = new BecomesSubtypeAllEffect(Duration.WhileOnBattlefield, subtypes, filter, false); + BecomesSubtypeAllEffect becomesSubtypeAllEffect = new BecomesSubtypeAllEffect(Duration.WhileOnBattlefield, Arrays.asList(SubType.WALL), filter, false); becomesSubtypeAllEffect.setText(""); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, becomesSubtypeAllEffect)); diff --git a/Mage.Sets/src/mage/cards/a/AvianChangeling.java b/Mage.Sets/src/mage/cards/a/AvianChangeling.java index 3cd09cacaf5..511f873e40e 100644 --- a/Mage.Sets/src/mage/cards/a/AvianChangeling.java +++ b/Mage.Sets/src/mage/cards/a/AvianChangeling.java @@ -22,8 +22,7 @@ public final class AvianChangeling extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); this.addAbility(FlyingAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/cards/b/BakisCurse.java b/Mage.Sets/src/mage/cards/b/BakisCurse.java index df8ee1e5418..f42d7eb4807 100644 --- a/Mage.Sets/src/mage/cards/b/BakisCurse.java +++ b/Mage.Sets/src/mage/cards/b/BakisCurse.java @@ -60,7 +60,7 @@ class BakisCurseEffect extends OneShotEffect { List attachments = creature.getAttachments(); for (UUID attachmentId : attachments) { Permanent attached = game.getPermanent(attachmentId); - if (attached != null && attached.getSubtype(game).contains(SubType.AURA)) { + if (attached != null && attached.hasSubtype(SubType.AURA, game)) { count++; } } diff --git a/Mage.Sets/src/mage/cards/b/BladedBracers.java b/Mage.Sets/src/mage/cards/b/BladedBracers.java index 70498235905..ea691ee5734 100644 --- a/Mage.Sets/src/mage/cards/b/BladedBracers.java +++ b/Mage.Sets/src/mage/cards/b/BladedBracers.java @@ -1,7 +1,7 @@ - package mage.cards.b; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.EquippedHasSubtypeCondition; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.decorator.ConditionalContinuousEffect; @@ -11,8 +11,10 @@ import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.util.SubTypeList; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; import java.util.UUID; @@ -22,27 +24,27 @@ import java.util.UUID; public final class BladedBracers extends CardImpl { private static final String ruleText = "As long as equipped creature is a Human or an Angel, it has vigilance"; + private static final Condition condition = new EquippedHasSubtypeCondition(SubType.HUMAN, SubType.ANGEL); public BladedBracers(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); this.subtype.add(SubType.EQUIPMENT); // Equipped creature gets +1/+1. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 1))); - SubTypeList subTypes = new SubTypeList(); - subTypes.add(SubType.HUMAN); - subTypes.add(SubType.ANGEL); + this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(1, 1))); + // As long as equipped creature is a Human or an Angel, it has vigilance. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, - new ConditionalContinuousEffect( - new GainAbilityAttachedEffect(VigilanceAbility.getInstance(), AttachmentType.EQUIPMENT), - new EquippedHasSubtypeCondition(subTypes), ruleText))); + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new GainAbilityAttachedEffect( + VigilanceAbility.getInstance(), AttachmentType.EQUIPMENT + ), condition, ruleText + ))); // Equip {2} this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2))); } - public BladedBracers(final BladedBracers card) { + private BladedBracers(final BladedBracers card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/b/BladesOfVelisVel.java b/Mage.Sets/src/mage/cards/b/BladesOfVelisVel.java index 4829fbc5912..1e80629ac96 100644 --- a/Mage.Sets/src/mage/cards/b/BladesOfVelisVel.java +++ b/Mage.Sets/src/mage/cards/b/BladesOfVelisVel.java @@ -22,8 +22,7 @@ public final class BladesOfVelisVel extends CardImpl { this.subtype.add(SubType.SHAPESHIFTER); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Up to two target creatures each get +2/+0 and gain all creature types until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(2, 0, Duration.EndOfTurn) diff --git a/Mage.Sets/src/mage/cards/b/BloodMoon.java b/Mage.Sets/src/mage/cards/b/BloodMoon.java index f36a5d1d3e7..69291cf9c87 100644 --- a/Mage.Sets/src/mage/cards/b/BloodMoon.java +++ b/Mage.Sets/src/mage/cards/b/BloodMoon.java @@ -1,6 +1,5 @@ package mage.cards.b; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -13,8 +12,9 @@ import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class BloodMoon extends CardImpl { @@ -71,7 +71,7 @@ public final class BloodMoon extends CardImpl { // 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects // So the ability removing has to be done before Layer 6 // Lands have their mana ability intrinsically, so that is added in layer 4 - land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); land.addSubType(game, SubType.MOUNTAIN); land.removeAllAbilities(source.getSourceId(), game); land.addAbility(new RedManaAbility(), source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/b/BloodlinePretender.java b/Mage.Sets/src/mage/cards/b/BloodlinePretender.java index 64d8abdb06e..1da57f4a724 100644 --- a/Mage.Sets/src/mage/cards/b/BloodlinePretender.java +++ b/Mage.Sets/src/mage/cards/b/BloodlinePretender.java @@ -40,8 +40,7 @@ public final class BloodlinePretender extends CardImpl { this.toughness = new MageInt(2); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // As Bloodline Pretender enters the battlefield, choose a creature type. this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature))); diff --git a/Mage.Sets/src/mage/cards/b/BrudicladTelchorEngineer.java b/Mage.Sets/src/mage/cards/b/BrudicladTelchorEngineer.java index 1a643205f28..96fe10f40f1 100644 --- a/Mage.Sets/src/mage/cards/b/BrudicladTelchorEngineer.java +++ b/Mage.Sets/src/mage/cards/b/BrudicladTelchorEngineer.java @@ -19,7 +19,7 @@ import mage.game.permanent.Permanent; import mage.game.permanent.token.BrudicladTelchorMyrToken; import mage.players.Player; import mage.target.common.TargetControlledPermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; import java.util.UUID; @@ -99,7 +99,7 @@ class BrudicladTelchorEngineerEffect extends OneShotEffect { if (toCopyFromPermanent != null) { for (Permanent toCopyToPermanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { if (!toCopyToPermanent.equals(toCopyFromPermanent)) { - game.copyPermanent(toCopyFromPermanent, toCopyToPermanent.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(toCopyFromPermanent, toCopyToPermanent.getId(), source, new EmptyCopyApplier()); } } return true; diff --git a/Mage.Sets/src/mage/cards/c/CairnWanderer.java b/Mage.Sets/src/mage/cards/c/CairnWanderer.java index 451bc7069d1..281b712fbe2 100644 --- a/Mage.Sets/src/mage/cards/c/CairnWanderer.java +++ b/Mage.Sets/src/mage/cards/c/CairnWanderer.java @@ -30,8 +30,7 @@ public final class CairnWanderer extends CardImpl { this.toughness = new MageInt(4); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // As long as a creature card with flying is in a graveyard, Cairn Wanderer has flying. The same is true for fear, first strike, double strike, deathtouch, haste, landwalk, lifelink, protection, reach, trample, shroud, and vigilance. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CairnWandererEffect())); diff --git a/Mage.Sets/src/mage/cards/c/CallToTheKindred.java b/Mage.Sets/src/mage/cards/c/CallToTheKindred.java index d55a6a13496..fdc656c2b2e 100644 --- a/Mage.Sets/src/mage/cards/c/CallToTheKindred.java +++ b/Mage.Sets/src/mage/cards/c/CallToTheKindred.java @@ -11,7 +11,7 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreatureCard; -import mage.filter.predicate.Predicate; +import mage.filter.predicate.permanent.SharesCreatureTypePredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; @@ -88,7 +88,7 @@ class CallToTheKindredEffect extends OneShotEffect { Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 5)); FilterCreatureCard filter = new FilterCreatureCard(); - filter.add(new CallToTheKindredPredicate(creature)); + filter.add(new SharesCreatureTypePredicate(creature)); if (cards.count(filter, game) > 0) { TargetCard target = new TargetCardInLibrary(0, 1, filter); @@ -103,17 +103,3 @@ class CallToTheKindredEffect extends OneShotEffect { return true; } } - -class CallToTheKindredPredicate implements Predicate { - - private final Permanent permanent; - - CallToTheKindredPredicate(Permanent permanent) { - this.permanent = permanent; - } - - @Override - public boolean apply(Card input, Game game) { - return permanent != null && input != null && permanent.shareCreatureTypes(input, game); - } -} diff --git a/Mage.Sets/src/mage/cards/c/CelestialDawn.java b/Mage.Sets/src/mage/cards/c/CelestialDawn.java index 684e77ff93e..eb63906d5a2 100644 --- a/Mage.Sets/src/mage/cards/c/CelestialDawn.java +++ b/Mage.Sets/src/mage/cards/c/CelestialDawn.java @@ -88,7 +88,7 @@ class CelestialDawnToPlainsEffect extends ContinuousEffectImpl { land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); break; case TypeChangingEffects_4: - land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.removeAllSubTypes(game,SubTypeSet.NonBasicLandType); land.addSubType(game, SubType.PLAINS); break; } diff --git a/Mage.Sets/src/mage/cards/c/CemeteryPuca.java b/Mage.Sets/src/mage/cards/c/CemeteryPuca.java index 3b70f6560f6..67d3fb64225 100644 --- a/Mage.Sets/src/mage/cards/c/CemeteryPuca.java +++ b/Mage.Sets/src/mage/cards/c/CemeteryPuca.java @@ -19,7 +19,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -71,7 +71,7 @@ class CemeteryPucaEffect extends OneShotEffect { if (copyToCreature != null) { Permanent copyFromCreature = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); if (copyFromCreature != null) { - game.copyPermanent(Duration.WhileOnBattlefield, copyFromCreature, copyToCreature.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.WhileOnBattlefield, copyFromCreature, copyToCreature.getId(), source, new EmptyCopyApplier()); ContinuousEffect effect = new GainAbilityTargetEffect(new DiesCreatureTriggeredAbility(new DoIfCostPaid(new CemeteryPucaEffect(), new ManaCostsImpl("{1}")), false, new FilterCreaturePermanent("a creature"), true), Duration.WhileOnBattlefield); effect.setTargetPointer(new FixedTarget(copyToCreature.getId())); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/cards/c/ChameleonColossus.java b/Mage.Sets/src/mage/cards/c/ChameleonColossus.java index d2a7d205bfd..74b097257f4 100644 --- a/Mage.Sets/src/mage/cards/c/ChameleonColossus.java +++ b/Mage.Sets/src/mage/cards/c/ChameleonColossus.java @@ -31,8 +31,7 @@ public final class ChameleonColossus extends CardImpl { this.toughness = new MageInt(4); // Changeling (This card is every creature type at all times.) - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Protection from black this.addAbility(ProtectionAbility.from(ObjectColor.BLACK)); diff --git a/Mage.Sets/src/mage/cards/c/ChangelingBerserker.java b/Mage.Sets/src/mage/cards/c/ChangelingBerserker.java index d718b8fe43a..1c49f1e16ba 100644 --- a/Mage.Sets/src/mage/cards/c/ChangelingBerserker.java +++ b/Mage.Sets/src/mage/cards/c/ChangelingBerserker.java @@ -24,8 +24,7 @@ public final class ChangelingBerserker extends CardImpl { this.toughness = new MageInt(3); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Haste this.addAbility(HasteAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/c/ChangelingHero.java b/Mage.Sets/src/mage/cards/c/ChangelingHero.java index 5265bce967c..2ffb2c5defa 100644 --- a/Mage.Sets/src/mage/cards/c/ChangelingHero.java +++ b/Mage.Sets/src/mage/cards/c/ChangelingHero.java @@ -24,8 +24,7 @@ public final class ChangelingHero extends CardImpl { this.toughness = new MageInt(4); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Champion a creature this.addAbility(new ChampionAbility(this, true)); diff --git a/Mage.Sets/src/mage/cards/c/ChangelingOutcast.java b/Mage.Sets/src/mage/cards/c/ChangelingOutcast.java index 2557d03a256..9de322704c5 100644 --- a/Mage.Sets/src/mage/cards/c/ChangelingOutcast.java +++ b/Mage.Sets/src/mage/cards/c/ChangelingOutcast.java @@ -24,8 +24,7 @@ public final class ChangelingOutcast extends CardImpl { this.toughness = new MageInt(1); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Changeling Outcast can't block and can't be blocked. this.addAbility(new CantBlockAbility()); diff --git a/Mage.Sets/src/mage/cards/c/ChangelingSentinel.java b/Mage.Sets/src/mage/cards/c/ChangelingSentinel.java index 8e532ccce52..0cf2676838f 100644 --- a/Mage.Sets/src/mage/cards/c/ChangelingSentinel.java +++ b/Mage.Sets/src/mage/cards/c/ChangelingSentinel.java @@ -22,8 +22,7 @@ public final class ChangelingSentinel extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); this.addAbility(VigilanceAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/cards/c/ChangelingTitan.java b/Mage.Sets/src/mage/cards/c/ChangelingTitan.java index 3701c9ae751..89fb368999d 100644 --- a/Mage.Sets/src/mage/cards/c/ChangelingTitan.java +++ b/Mage.Sets/src/mage/cards/c/ChangelingTitan.java @@ -23,8 +23,7 @@ public final class ChangelingTitan extends CardImpl { this.toughness = new MageInt(7); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Champion a creature this.addAbility(new ChampionAbility(this, true)); diff --git a/Mage.Sets/src/mage/cards/c/CoatOfArms.java b/Mage.Sets/src/mage/cards/c/CoatOfArms.java index f6801f87cf6..c4213f38a0d 100644 --- a/Mage.Sets/src/mage/cards/c/CoatOfArms.java +++ b/Mage.Sets/src/mage/cards/c/CoatOfArms.java @@ -68,7 +68,7 @@ class CoatOfArmsEffect extends ContinuousEffectImpl { private int getAmount(List permanents, Permanent target, Game game) { int amount = 0; for (Permanent permanent : permanents) { - if (!permanent.getId().equals(target.getId()) && permanent.shareCreatureTypes(target, game)) { + if (!permanent.getId().equals(target.getId()) && permanent.shareCreatureTypes(game, target)) { amount++; } } diff --git a/Mage.Sets/src/mage/cards/c/Conspiracy.java b/Mage.Sets/src/mage/cards/c/Conspiracy.java index 69f6bd22b41..7bddfd69af7 100644 --- a/Mage.Sets/src/mage/cards/c/Conspiracy.java +++ b/Mage.Sets/src/mage/cards/c/Conspiracy.java @@ -1,8 +1,5 @@ package mage.cards.c; -import java.util.Iterator; -import java.util.List; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; @@ -20,7 +17,11 @@ import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.game.stack.StackObject; import mage.players.Player; -import mage.util.SubTypeList; +import mage.util.SubTypes; + +import java.util.Iterator; +import java.util.List; +import java.util.UUID; /** * @author bunchOfDevs @@ -50,16 +51,16 @@ public final class Conspiracy extends CardImpl { static class ConspiracyEffect extends ContinuousEffectImpl { - public ConspiracyEffect() { + private ConspiracyEffect() { super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); staticText = "Creatures you control are the chosen type. The same is " + "true for creature spells you control and creature cards " + "you own that aren't on the battlefield."; - + this.dependendToTypes.add(DependencyType.BecomeCreature); // Opalescence and Starfield of Nyx } - public ConspiracyEffect(final ConspiracyEffect effect) { + private ConspiracyEffect(final ConspiracyEffect effect) { super(effect); } @@ -69,94 +70,77 @@ public final class Conspiracy extends CardImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game); - switch (layer) { - case TypeChangingEffects_4: - if (controller != null && subType != null) { - // Creature cards you own that aren't on the battlefield - // in graveyard - for (UUID cardId : controller.getGraveyard()) { - Card card = game.getCard(cardId); - if (card != null && card.isCreature()) { - setCreatureSubtype(card, subType, game); - } - } - // on Hand - for (UUID cardId : controller.getHand()) { - Card card = game.getCard(cardId); - if (card != null && card.isCreature()) { - setCreatureSubtype(card, subType, game); - } - } - // in Exile - for (Card card : game.getState().getExile().getAllCards(game)) { - if (card.isOwnedBy(controller.getId()) && card.isCreature()) { - setCreatureSubtype(card, subType, game); - } - } - // in Library (e.g. for Mystical Teachings) - for (Card card : controller.getLibrary().getCards(game)) { - if (card.isOwnedBy(controller.getId()) && card.isCreature()) { - setCreatureSubtype(card, subType, game); - } - } - // in command zone - for (CommandObject commandObject : game.getState().getCommand()) { - if (commandObject instanceof Commander) { - Card card = game.getCard(((Commander) commandObject).getId()); - if (card != null && card.isCreature() && card.isOwnedBy(controller.getId())) { - setCreatureSubtype(card, subType, game); - } - } - } - // creature spells you control - for (Iterator iterator = game.getStack().iterator(); iterator.hasNext();) { - StackObject stackObject = iterator.next(); - if (stackObject instanceof Spell - && stackObject.isControlledBy(controller.getId()) - && stackObject.isCreature()) { - setCreatureSubtype(stackObject, subType, game); - setCreatureSubtype(((Spell) stackObject).getCard(), subType, game); - } - } - // creatures you control - List permanents = game.getState().getBattlefield().getAllActivePermanents(controller.getId()); - for (Permanent permanent : permanents) { - if (permanent.isCreature()) { - setCreatureSubtype(permanent, subType, game); - } - } - } - return true; + if (controller == null || subType == null) { + return true; } - return false; + // Creature cards you own that aren't on the battlefield + // in graveyard + for (UUID cardId : controller.getGraveyard()) { + Card card = game.getCard(cardId); + if (card != null && card.isCreature()) { + setCreatureSubtype(card, subType, game); + } + } + // on Hand + for (UUID cardId : controller.getHand()) { + Card card = game.getCard(cardId); + if (card != null && card.isCreature()) { + setCreatureSubtype(card, subType, game); + } + } + // in Exile + for (Card card : game.getState().getExile().getAllCards(game)) { + if (card.isOwnedBy(controller.getId()) && card.isCreature()) { + setCreatureSubtype(card, subType, game); + } + } + // in Library (e.g. for Mystical Teachings) + for (Card card : controller.getLibrary().getCards(game)) { + if (card.isOwnedBy(controller.getId()) && card.isCreature()) { + setCreatureSubtype(card, subType, game); + } + } + // in command zone + for (CommandObject commandObject : game.getState().getCommand()) { + if (commandObject instanceof Commander) { + Card card = game.getCard(((Commander) commandObject).getId()); + if (card != null && card.isCreature() && card.isOwnedBy(controller.getId())) { + setCreatureSubtype(card, subType, game); + } + } + } + // creature spells you control + for (Iterator iterator = game.getStack().iterator(); iterator.hasNext(); ) { + StackObject stackObject = iterator.next(); + if (stackObject instanceof Spell + && stackObject.isControlledBy(controller.getId()) + && stackObject.isCreature()) { + setCreatureSubtype(stackObject, subType, game); + setCreatureSubtype(((Spell) stackObject).getCard(), subType, game); + } + } + // creatures you control + List permanents = game.getState().getBattlefield().getAllActivePermanents(controller.getId()); + for (Permanent permanent : permanents) { + if (permanent.isCreature()) { + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, subType); + } + } + return true; } private void setCreatureSubtype(MageObject object, SubType subtype, Game game) { - if (object != null) { - setChosenSubtype(game.getState() - .getCreateMageObjectAttribute(object, game).getSubtype(), subtype); + if (object == null) { + return; } - } - - private void setChosenSubtype(SubTypeList subtype, SubType choice) { - if (subtype.size() != 1 - || !subtype.contains(choice)) { - subtype.clear(); - subtype.add(choice); - } - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; + SubTypes subTypes = game.getState().getCreateMageObjectAttribute(object, game).getSubtype(); + subTypes.setIsAllCreatureTypes(false); + subTypes.removeAll(SubType.getCreatureTypes()); + subTypes.add(subtype); } } } diff --git a/Mage.Sets/src/mage/cards/c/Conversion.java b/Mage.Sets/src/mage/cards/c/Conversion.java index ac521592730..97d7a64f85d 100644 --- a/Mage.Sets/src/mage/cards/c/Conversion.java +++ b/Mage.Sets/src/mage/cards/c/Conversion.java @@ -1,9 +1,5 @@ package mage.cards.c; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -19,8 +15,12 @@ import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + /** - * * @author LevelX2 */ public final class Conversion extends CardImpl { @@ -75,8 +75,8 @@ public final class Conversion extends CardImpl { for (Permanent land : game.getBattlefield().getAllActivePermanents(CardType.LAND)) { switch (layer) { case TypeChangingEffects_4: - if (land.getSubtype(game).contains(SubType.MOUNTAIN)) { - land.getSubtype(game).removeAll(SubType.getLandTypes()); + if (land.hasSubtype(SubType.MOUNTAIN, game)) { + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); land.addSubType(game, SubType.PLAINS); land.removeAllAbilities(source.getSourceId(), game); land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/c/ConvincingMirage.java b/Mage.Sets/src/mage/cards/c/ConvincingMirage.java index 842c557bf59..96e54fce6de 100644 --- a/Mage.Sets/src/mage/cards/c/ConvincingMirage.java +++ b/Mage.Sets/src/mage/cards/c/ConvincingMirage.java @@ -101,7 +101,7 @@ class ConvincingMirageContinousEffect extends ContinuousEffectImpl { if (land == null) { return false; } - land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); land.addSubType(game, choice); land.removeAllAbilities(source.getSourceId(), game); switch (choice) { diff --git a/Mage.Sets/src/mage/cards/c/CopyArtifact.java b/Mage.Sets/src/mage/cards/c/CopyArtifact.java index 45967d8742b..714e10d99b2 100644 --- a/Mage.Sets/src/mage/cards/c/CopyArtifact.java +++ b/Mage.Sets/src/mage/cards/c/CopyArtifact.java @@ -9,7 +9,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterArtifactPermanent; -import mage.util.functions.CardTypeApplier; +import mage.util.functions.CardTypeCopyApplier; /** * @@ -22,7 +22,7 @@ public final class CopyArtifact extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}"); // You may have Copy Artifact enter the battlefield as a copy of any artifact on the battlefield, except it's an enchantment in addition to its other types. - Effect effect = new CopyPermanentEffect(new FilterArtifactPermanent(), new CardTypeApplier(CardType.ENCHANTMENT)); + Effect effect = new CopyPermanentEffect(new FilterArtifactPermanent(), new CardTypeCopyApplier(CardType.ENCHANTMENT)); effect.setText("as a copy of any artifact on the battlefield, except it's an enchantment in addition to its other types"); this.addAbility(new EntersBattlefieldAbility(effect, true)); } diff --git a/Mage.Sets/src/mage/cards/c/CribSwap.java b/Mage.Sets/src/mage/cards/c/CribSwap.java index 99c599a50da..4b9db935366 100644 --- a/Mage.Sets/src/mage/cards/c/CribSwap.java +++ b/Mage.Sets/src/mage/cards/c/CribSwap.java @@ -28,8 +28,7 @@ public final class CribSwap extends CardImpl { this.subtype.add(SubType.SHAPESHIFTER); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Exile target creature. Its controller creates a 1/1 colorless Shapeshifter creature token with changeling. this.getSpellAbility().addEffect(new ExileTargetEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/c/CrownOfFury.java b/Mage.Sets/src/mage/cards/c/CrownOfFury.java index 3c3a5e57b09..146cb661a8f 100644 --- a/Mage.Sets/src/mage/cards/c/CrownOfFury.java +++ b/Mage.Sets/src/mage/cards/c/CrownOfFury.java @@ -1,8 +1,6 @@ - package mage.cards.c; -import java.util.UUID; - +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -17,26 +15,30 @@ import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.common.FilterOtherCreatureSharingCreatureSubtype; +import mage.filter.predicate.Predicate; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.MageObjectReferencePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author t-schroeder */ public final class CrownOfFury extends CardImpl { public CrownOfFury(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); this.subtype.add(SubType.AURA); - + TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); @@ -69,6 +71,19 @@ public final class CrownOfFury extends CardImpl { class CrownOfFuryEffect extends OneShotEffect { + private static class CrownOfFuryPredicate implements Predicate { + private final Card card; + + private CrownOfFuryPredicate(Card card) { + this.card = card; + } + + @Override + public boolean apply(Card input, Game game) { + return input.shareCreatureTypes(game, card); + } + } + public CrownOfFuryEffect() { super(Outcome.Benefit); this.staticText = "Enchanted creature and other creatures that share a creature type with it get +1/+0 and gain first strike until end of turn."; @@ -94,7 +109,9 @@ class CrownOfFuryEffect extends OneShotEffect { // ... and other creatures that share a creature type with it ... Permanent enchantedCreature = game.getPermanent(source.getSourcePermanentOrLKI(game).getAttachedTo()); - FilterCreaturePermanent filter = new FilterOtherCreatureSharingCreatureSubtype(enchantedCreature, game); + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + filter.add(new CrownOfFuryPredicate(enchantedCreature)); + filter.add(Predicates.not(new MageObjectReferencePredicate(new MageObjectReference(enchantedCreature, game)))); game.addEffect(new BoostAllEffect(1, 0, Duration.EndOfTurn, filter, false), source); game.addEffect(new GainAbilityAllEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, filter), source); diff --git a/Mage.Sets/src/mage/cards/c/CrypticGateway.java b/Mage.Sets/src/mage/cards/c/CrypticGateway.java index 481af3c388c..a57ce6a98de 100644 --- a/Mage.Sets/src/mage/cards/c/CrypticGateway.java +++ b/Mage.Sets/src/mage/cards/c/CrypticGateway.java @@ -150,7 +150,7 @@ class CrypticGatewayPredicate implements Predicate { @Override public boolean apply(Card input, Game game) { for (Permanent permanent : permanents) { - if (!permanent.shareCreatureTypes(input, game)) { + if (!permanent.shareCreatureTypes(game, input)) { return false; } } diff --git a/Mage.Sets/src/mage/cards/c/Cryptoplasm.java b/Mage.Sets/src/mage/cards/c/Cryptoplasm.java index 158b35b27e0..2fd5135608f 100644 --- a/Mage.Sets/src/mage/cards/c/Cryptoplasm.java +++ b/Mage.Sets/src/mage/cards/c/Cryptoplasm.java @@ -17,7 +17,7 @@ import mage.filter.predicate.permanent.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -76,23 +76,14 @@ class CryptoplasmEffect extends OneShotEffect { public boolean apply(Game game, final Ability source) { Permanent creatureToCopy = game.getPermanent(getTargetPointer().getFirst(game, source)); if (creatureToCopy != null) { - ApplyToPermanent applier = new ApplyToPermanent() { + CopyApplier applier = new CopyApplier() { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { Ability upkeepAbility = new BeginningOfUpkeepTriggeredAbility(new CryptoplasmEffect(), TargetController.YOU, true); upkeepAbility.addTarget(new TargetCreaturePermanent()); - permanent.addAbility(upkeepAbility, source.getSourceId(), game); + blueprint.getAbilities().add(upkeepAbility); return true; } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - Ability upkeepAbility = new BeginningOfUpkeepTriggeredAbility(new CryptoplasmEffect(), TargetController.YOU, true); - upkeepAbility.addTarget(new TargetCreaturePermanent()); - mageObject.getAbilities().add(upkeepAbility); - return true; - } - }; game.copyPermanent(creatureToCopy, source.getSourceId(), source, applier); } diff --git a/Mage.Sets/src/mage/cards/c/CrystallineResonance.java b/Mage.Sets/src/mage/cards/c/CrystallineResonance.java index a9f78614e68..828f18ae8e2 100644 --- a/Mage.Sets/src/mage/cards/c/CrystallineResonance.java +++ b/Mage.Sets/src/mage/cards/c/CrystallineResonance.java @@ -12,9 +12,8 @@ import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.predicate.permanent.AnotherPredicate; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -49,7 +48,7 @@ public final class CrystallineResonance extends CardImpl { Ability ability = new CycleControllerTriggeredAbility( new CopyPermanentEffect( StaticFilters.FILTER_PERMANENT_CREATURE, - new CrystallineResonanceApplier(), true + new CrystallineResonanceCopyApplier(), true ).setDuration(Duration.UntilYourNextTurn).setText( "have {this} become a copy of another target permanent until your next turn, " + "except it has this ability" @@ -60,17 +59,11 @@ public final class CrystallineResonance extends CardImpl { } } -class CrystallineResonanceApplier extends ApplyToPermanent { +class CrystallineResonanceCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.getAbilities().add(CrystallineResonance.createAbility()); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.getAbilities().add(CrystallineResonance.createAbility()); + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.getAbilities().add(CrystallineResonance.createAbility()); return true; } } diff --git a/Mage.Sets/src/mage/cards/c/Cytoshape.java b/Mage.Sets/src/mage/cards/c/Cytoshape.java index 9777bd95fec..ef20669c97d 100644 --- a/Mage.Sets/src/mage/cards/c/Cytoshape.java +++ b/Mage.Sets/src/mage/cards/c/Cytoshape.java @@ -16,7 +16,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -78,7 +78,7 @@ class CytoshapeEffect extends OneShotEffect { if (copyFrom != null) { Permanent copyTo = game.getPermanentOrLKIBattlefield(ability.getTargets().get(1).getFirstTarget()); if (copyTo != null) { - game.copyPermanent(Duration.EndOfTurn, copyFrom, copyTo.getId(), ability, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, copyFrom, copyTo.getId(), ability, new EmptyCopyApplier()); } } return true; diff --git a/Mage.Sets/src/mage/cards/d/DacksDuplicate.java b/Mage.Sets/src/mage/cards/d/DacksDuplicate.java index ef7b0408370..07538631f51 100644 --- a/Mage.Sets/src/mage/cards/d/DacksDuplicate.java +++ b/Mage.Sets/src/mage/cards/d/DacksDuplicate.java @@ -1,7 +1,6 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -17,10 +16,11 @@ import mage.constants.SubType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class DacksDuplicate extends CardImpl { @@ -33,7 +33,7 @@ public final class DacksDuplicate extends CardImpl { this.toughness = new MageInt(0); // You may have Dack's Duplicate enter the battlefield as a copy of any creature on the battlefield except it has haste and dethrone. - Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new DacksDuplicateApplyToPermanent()); + Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new DacksDuplicateCopyApplier()); effect.setText("as a copy of any creature on the battlefield except it has haste and dethrone"); this.addAbility(new EntersBattlefieldAbility(effect, true)); } @@ -48,24 +48,15 @@ public final class DacksDuplicate extends CardImpl { } } -class DacksDuplicateApplyToPermanent extends ApplyToPermanent { - +class DacksDuplicateCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { /** * 29/05/2014 The ability of Dack's Duplicate doesn't target the * creature. */ - permanent.addAbility(new DethroneAbility(), source.getSourceId(), game); - permanent.addAbility(HasteAbility.getInstance(), source.getSourceId(), game); + blueprint.getAbilities().add(new DethroneAbility()); + blueprint.getAbilities().add(HasteAbility.getInstance()); return true; } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.getAbilities().add(new DethroneAbility()); - mageObject.getAbilities().add(HasteAbility.getInstance()); - return true; - } - } diff --git a/Mage.Sets/src/mage/cards/d/DescendantsPath.java b/Mage.Sets/src/mage/cards/d/DescendantsPath.java index 16357653c49..444edae83bc 100644 --- a/Mage.Sets/src/mage/cards/d/DescendantsPath.java +++ b/Mage.Sets/src/mage/cards/d/DescendantsPath.java @@ -79,7 +79,7 @@ class DescendantsPathEffect extends OneShotEffect { FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); boolean found = false; for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) { - if (card.shareCreatureTypes(permanent, game)) { + if (card.shareCreatureTypes(game, permanent)) { found = true; break; } diff --git a/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java b/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java index e972261d61c..80a4e75c60f 100644 --- a/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java +++ b/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java @@ -21,7 +21,7 @@ import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; import mage.players.Player; import mage.target.common.TargetCardInGraveyard; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; /** * @@ -83,7 +83,7 @@ class DimirDoppelgangerEffect extends OneShotEffect { controller.moveCards(cardsToExile, Zone.EXILED, source, game); newBluePrint = new PermanentCard(copyFromCard, source.getControllerId(), game); newBluePrint.assignNewId(); - ApplyToPermanent applier = new DimirDoppelgangerApplier(); + CopyApplier applier = new DimirDoppelgangerCopyApplier(); applier.apply(game, newBluePrint, source, dimirDoppelganger.getId()); CopyEffect copyEffect = new CopyEffect(Duration.Custom, newBluePrint, dimirDoppelganger.getId()); copyEffect.newId(); @@ -98,21 +98,13 @@ class DimirDoppelgangerEffect extends OneShotEffect { } } -class DimirDoppelgangerApplier extends ApplyToPermanent { +class DimirDoppelgangerCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DimirDoppelgangerEffect(), new ManaCostsImpl("{1}{U}{B}")); ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card in a graveyard"))); - permanent.getAbilities().add(ability); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DimirDoppelgangerEffect(), new ManaCostsImpl("{1}{U}{B}")); - ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card in a graveyard"))); - mageObject.getAbilities().add(ability); + blueprint.getAbilities().add(ability); return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DrJuliusJumblemorph.java b/Mage.Sets/src/mage/cards/d/DrJuliusJumblemorph.java index b01f8e5f38a..91aeeab5fcd 100644 --- a/Mage.Sets/src/mage/cards/d/DrJuliusJumblemorph.java +++ b/Mage.Sets/src/mage/cards/d/DrJuliusJumblemorph.java @@ -4,6 +4,7 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.continuous.IsAllCreatureTypesSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -33,10 +34,7 @@ public final class DrJuliusJumblemorph extends CardImpl { this.toughness = new MageInt(4); // Dr. Julius Jumblemorph is every creature type (even if this card isn't on the battlefield). - this.setIsAllCreatureTypes(true); - this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect( - "{this} is every creature type (even if this card isn't on the battlefield)." - ))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new IsAllCreatureTypesSourceEffect())); // Whenever a host enters the battlefield under your control, you may search your library and/or graveyard for a card with augment and combine it with that host. If you search your library this way, shuffle it. // TODO: Host currently isn't implemented, so this ability currently would never trigger @@ -46,7 +44,7 @@ public final class DrJuliusJumblemorph extends CardImpl { )); } - public DrJuliusJumblemorph(final DrJuliusJumblemorph card) { + private DrJuliusJumblemorph(final DrJuliusJumblemorph card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/d/Duplicant.java b/Mage.Sets/src/mage/cards/d/Duplicant.java index 2b0b104f57c..48df7b062ab 100644 --- a/Mage.Sets/src/mage/cards/d/Duplicant.java +++ b/Mage.Sets/src/mage/cards/d/Duplicant.java @@ -113,34 +113,32 @@ class DuplicantContinuousEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - if (!permanent.getImprinted().isEmpty()) { - List imprinted = permanent.getImprinted(); - if (imprinted == null || imprinted.isEmpty()) { - return false; - } - Card card = game.getCard(imprinted.get(imprinted.size() - 1)); - if (card != null && card.isCreature()) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.getSubtype(game).addAll(card.getSubtype(game)); - } - - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - permanent.getPower().setValue(card.getPower().getValue()); - permanent.getToughness().setValue(card.getToughness().getValue()); - - } - } - return true; - } - } - + if (permanent == null) { + return false; } - return false; + if (permanent.getImprinted().isEmpty()) { + return false; + } + List imprinted = permanent.getImprinted(); + if (imprinted == null || imprinted.isEmpty()) { + return false; + } + Card card = game.getCard(imprinted.get(imprinted.size() - 1)); + if (card == null || !card.isCreature()) { + return false; + } + switch (layer) { + case TypeChangingEffects_4: + permanent.copySubTypesFrom(game, card, SubTypeSet.CreatureType); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setValue(card.getPower().getValue()); + permanent.getToughness().setValue(card.getToughness().getValue()); + } + } + return true; + } @Override @@ -152,5 +150,4 @@ class DuplicantContinuousEffect extends ContinuousEffectImpl { public boolean hasLayer(Layer layer) { return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4; } - } diff --git a/Mage.Sets/src/mage/cards/e/EarlOfSquirrel.java b/Mage.Sets/src/mage/cards/e/EarlOfSquirrel.java index ce78f61fc1c..e4347744e67 100644 --- a/Mage.Sets/src/mage/cards/e/EarlOfSquirrel.java +++ b/Mage.Sets/src/mage/cards/e/EarlOfSquirrel.java @@ -1,10 +1,7 @@ - package mage.cards.e; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BecomesSubtypeAllEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.keyword.SquirrellinkAbility; @@ -14,20 +11,19 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.constants.TargetController; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TokenPredicate; -import mage.util.SubTypeList; + +import java.util.Arrays; +import java.util.UUID; /** - * * @author spjspj */ public final class EarlOfSquirrel extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creature tokens you control"); - private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("Other squirrels you control"); - + private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("Squirrels you control"); static { filter.add(TokenPredicate.instance); @@ -48,17 +44,17 @@ public final class EarlOfSquirrel extends CardImpl { this.addAbility(SquirrellinkAbility.getInstance()); // Creature tokens you control are Squirrels in addition to their other creature types. - SubTypeList subTypes = new SubTypeList(); - subTypes.add(SubType.SQUIRREL); - Effect effect = new BecomesSubtypeAllEffect(Duration.WhileOnBattlefield, subTypes, filter, false); - effect.setText("Creature tokens you control are Squirrels in addition to their other creature types"); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + this.addAbility(new SimpleStaticAbility(new BecomesSubtypeAllEffect( + Duration.WhileOnBattlefield, Arrays.asList(SubType.SQUIRREL), filter, false + ).setText("Creature tokens you control are Squirrels in addition to their other creature types"))); // Other Squirrels you control get +1/+1. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter2, true))); + this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( + 1, 1, Duration.WhileOnBattlefield, filter2, true + ))); } - public EarlOfSquirrel(final EarlOfSquirrel card) { + private EarlOfSquirrel(final EarlOfSquirrel card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/e/EgoErasure.java b/Mage.Sets/src/mage/cards/e/EgoErasure.java index ecb93a19b4c..f0a470b538a 100644 --- a/Mage.Sets/src/mage/cards/e/EgoErasure.java +++ b/Mage.Sets/src/mage/cards/e/EgoErasure.java @@ -26,8 +26,7 @@ public final class EgoErasure extends CardImpl { this.subtype.add(SubType.SHAPESHIFTER); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); //Creatures target player controls get -2/+0 and lose all creature types until end of turn. this.getSpellAbility().addEffect(new EgoErasureBoostEffect()); diff --git a/Mage.Sets/src/mage/cards/e/ElsewhereFlask.java b/Mage.Sets/src/mage/cards/e/ElsewhereFlask.java index 13fe21ffbd0..8440f071b1a 100644 --- a/Mage.Sets/src/mage/cards/e/ElsewhereFlask.java +++ b/Mage.Sets/src/mage/cards/e/ElsewhereFlask.java @@ -135,7 +135,7 @@ class ElsewhereFlaskContinuousEffect extends ContinuousEffectImpl { it.remove(); continue; } - land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); land.addSubType(game, choice); land.removeAllAbilities(source.getSourceId(), game); switch (choice) { diff --git a/Mage.Sets/src/mage/cards/e/EndemicPlague.java b/Mage.Sets/src/mage/cards/e/EndemicPlague.java index acadec173fd..1b541013b05 100644 --- a/Mage.Sets/src/mage/cards/e/EndemicPlague.java +++ b/Mage.Sets/src/mage/cards/e/EndemicPlague.java @@ -1,9 +1,5 @@ - package mage.cards.e; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.common.SacrificeTargetCost; @@ -13,18 +9,18 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.SubTypeSet; -import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.SharesCreatureTypePredicate; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetControlledCreaturePermanent; -import mage.util.SubTypeList; + +import java.util.UUID; + +import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; /** - * * @author TheElk801 */ public final class EndemicPlague extends CardImpl { @@ -39,7 +35,7 @@ public final class EndemicPlague extends CardImpl { this.getSpellAbility().addEffect(new EndemicPlagueEffect()); } - public EndemicPlague(final EndemicPlague card) { + private EndemicPlague(final EndemicPlague card) { super(card); } @@ -51,40 +47,34 @@ public final class EndemicPlague extends CardImpl { class EndemicPlagueEffect extends OneShotEffect { - public EndemicPlagueEffect() { + EndemicPlagueEffect() { super(Outcome.DestroyPermanent); staticText = "destroy all creatures that share a creature type with the sacrificed creature. They can't be regenerated"; } - public EndemicPlagueEffect(final EndemicPlagueEffect effect) { + private EndemicPlagueEffect(final EndemicPlagueEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - SubTypeList subs = null; - for (Cost cost : source.getCosts()) { - if (cost instanceof SacrificeTargetCost && !((SacrificeTargetCost) cost).getPermanents().isEmpty()) { - subs = ((SacrificeTargetCost) cost).getPermanents().get(0).getSubtype(game); - break; - } - } - if (subs == null) { - return false; - } - List preds = new ArrayList<>(); - for (SubType subType : subs) { - if (subType.getSubTypeSet() == SubTypeSet.CreatureType) { - preds.add(subType.getPredicate()); - } - } - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(Predicates.or(preds)); - new DestroyAllEffect(filter, true).apply(game, source); + if (controller == null) { + return false; } - return true; + Permanent permanent = null; + for (Cost cost : source.getCosts()) { + if (cost instanceof SacrificeTargetCost && !((SacrificeTargetCost) cost).getPermanents().isEmpty()) { + permanent = ((SacrificeTargetCost) cost).getPermanents().get(0); + break; + } + } + if (permanent == null) { + return false; + } + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + filter.add(new SharesCreatureTypePredicate(permanent)); + return new DestroyAllEffect(filter, true).apply(game, source); } @Override diff --git a/Mage.Sets/src/mage/cards/e/EstridsInvocation.java b/Mage.Sets/src/mage/cards/e/EstridsInvocation.java index 938d29dcc8d..a3d6575b671 100644 --- a/Mage.Sets/src/mage/cards/e/EstridsInvocation.java +++ b/Mage.Sets/src/mage/cards/e/EstridsInvocation.java @@ -17,7 +17,7 @@ import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledEnchantmentPermanent; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -33,7 +33,7 @@ public final class EstridsInvocation extends CardImpl { // You may have Estrid's Invocation enter the battlefield as a copy of any enchantment you control, except it gains "At the beginning of your upkeep, you may exile this enchantment. If you do, return it to the battlefield under its owner's control." this.addAbility(new EntersBattlefieldAbility(new CopyPermanentEffect( - filter, new EstridsInvocationApplier() + filter, new EstridsInvocationCopyApplier() ).setText("as a copy of an enchantment you control, except it gains " + "\"At the beginning of your upkeep, " + "you may exile this enchantment. " @@ -52,26 +52,16 @@ public final class EstridsInvocation extends CardImpl { } } -class EstridsInvocationApplier extends ApplyToPermanent { +class EstridsInvocationCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { // At the beginning of your upkeep, you may exile this enchantment. If you do, return it to the battlefield under its owner's control. - permanent.addAbility(new BeginningOfUpkeepTriggeredAbility( - new EstridsInvocationEffect(), TargetController.YOU, true - ), source.getSourceId(), game); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - // At the beginning of your upkeep, you may exile this enchantment. If you do, return it to the battlefield under its owner's control. - mageObject.getAbilities().add(new BeginningOfUpkeepTriggeredAbility( + blueprint.getAbilities().add(new BeginningOfUpkeepTriggeredAbility( new EstridsInvocationEffect(), TargetController.YOU, true )); return true; } - } class EstridsInvocationEffect extends OneShotEffect { diff --git a/Mage.Sets/src/mage/cards/e/EvilTwin.java b/Mage.Sets/src/mage/cards/e/EvilTwin.java index f08e6c3402b..f8240ab9cfd 100644 --- a/Mage.Sets/src/mage/cards/e/EvilTwin.java +++ b/Mage.Sets/src/mage/cards/e/EvilTwin.java @@ -23,7 +23,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -40,7 +40,7 @@ public final class EvilTwin extends CardImpl { this.toughness = new MageInt(0); // You may have Evil Twin enter the battlefield as a copy of any creature on the battlefield, except it has "{U}{B}, {T}: Destroy target creature with the same name as this creature." - Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new EvilTwinApplyToPermanent()); + Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new EvilTwinCopyApplier()); effect.setText("as a copy of any creature on the battlefield, except it has \"{U}{B}, {T}: Destroy target creature with the same name as this creature.\""); this.addAbility(new EntersBattlefieldAbility(effect, true)); @@ -56,7 +56,7 @@ public final class EvilTwin extends CardImpl { } } -class EvilTwinApplyToPermanent extends ApplyToPermanent { +class EvilTwinCopyApplier extends CopyApplier { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with the same name as this creature"); @@ -65,20 +65,11 @@ class EvilTwinApplyToPermanent extends ApplyToPermanent { } @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{U}{B}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent(filter)); - permanent.addAbility(ability, source.getSourceId(), game); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{U}{B}")); - ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); - mageObject.getAbilities().add(ability); + blueprint.getAbilities().add(ability); return true; } diff --git a/Mage.Sets/src/mage/cards/f/FaceOfDivinity.java b/Mage.Sets/src/mage/cards/f/FaceOfDivinity.java index bf17cfb36e3..4e66d1c45ca 100644 --- a/Mage.Sets/src/mage/cards/f/FaceOfDivinity.java +++ b/Mage.Sets/src/mage/cards/f/FaceOfDivinity.java @@ -74,7 +74,7 @@ enum FaceOfDivinityCondition implements Condition { for (UUID id : permanent.getAttachments()) { Permanent otherAura = game.getPermanent(id); if (otherAura != null && !otherAura.getId().equals(currentAura.getId()) - && otherAura.getSubtype(game).contains(SubType.AURA)) { + && otherAura.hasSubtype(SubType.AURA, game)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/f/FacelessHaven.java b/Mage.Sets/src/mage/cards/f/FacelessHaven.java index 41906500c0e..1a1f3ef6eb3 100644 --- a/Mage.Sets/src/mage/cards/f/FacelessHaven.java +++ b/Mage.Sets/src/mage/cards/f/FacelessHaven.java @@ -49,7 +49,7 @@ class FacelessHavenToken extends TokenImpl { FacelessHavenToken() { super("", "4/3 creature with vigilance and all creature types"); cardType.add(CardType.CREATURE); - setIsAllCreatureTypes(true); + subtype.setIsAllCreatureTypes(true); power = new MageInt(4); toughness = new MageInt(3); addAbility(VigilanceAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/f/FacesOfThePast.java b/Mage.Sets/src/mage/cards/f/FacesOfThePast.java index da1f73b3dd7..3d4b6baa28c 100644 --- a/Mage.Sets/src/mage/cards/f/FacesOfThePast.java +++ b/Mage.Sets/src/mage/cards/f/FacesOfThePast.java @@ -62,13 +62,13 @@ class FacesOfThePastEffect extends OneShotEffect { if (controller != null) { if (controller.chooseUse(outcome, "Tap all untapped creatures that share a creature type with " + targetPermanent.getLogName() + "? (Otherwise, untaps all tapped)", source, game)) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, game)) { - if (!permanent.isTapped() && targetPermanent.shareCreatureTypes(permanent, game)) { + if (!permanent.isTapped() && targetPermanent.shareCreatureTypes(game, permanent)) { permanent.tap(source, game); } } } else { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, game)) { - if (permanent.isTapped() && targetPermanent.shareCreatureTypes(permanent, game)) { + if (permanent.isTapped() && targetPermanent.shareCreatureTypes(game, permanent)) { permanent.untap(game); } } diff --git a/Mage.Sets/src/mage/cards/f/FendeepSummoner.java b/Mage.Sets/src/mage/cards/f/FendeepSummoner.java index f22851077da..e8376c55e2d 100644 --- a/Mage.Sets/src/mage/cards/f/FendeepSummoner.java +++ b/Mage.Sets/src/mage/cards/f/FendeepSummoner.java @@ -1,7 +1,6 @@ package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -16,7 +15,8 @@ import mage.constants.Zone; import mage.filter.common.FilterLandPermanent; import mage.game.permanent.token.custom.CreatureToken; import mage.target.common.TargetLandPermanent; -import mage.util.SubTypeList; + +import java.util.UUID; /** * @author anonymous @@ -30,7 +30,7 @@ public final class FendeepSummoner extends CardImpl { } public FendeepSummoner(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); this.subtype.add(SubType.TREEFOLK); this.subtype.add(SubType.SHAMAN); @@ -39,7 +39,7 @@ public final class FendeepSummoner extends CardImpl { // {T}: Up to two target Swamps each become 3/5 Treefolk Warrior creatures in addition to their other types until end of turn. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureTargetEffect( - new CreatureToken(3, 5, "3/5 Treefolk Warrior", new SubTypeList(SubType.TREEFOLK, SubType.WARRIOR)), + new CreatureToken(3, 5, "3/5 Treefolk Warrior", SubType.TREEFOLK, SubType.WARRIOR), false, false, Duration.EndOfTurn), new TapSourceCost()); ability.addTarget(new TargetLandPermanent(0, 2, filter, false)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/f/FireBellyChangeling.java b/Mage.Sets/src/mage/cards/f/FireBellyChangeling.java index e63b834cf52..450e3101390 100644 --- a/Mage.Sets/src/mage/cards/f/FireBellyChangeling.java +++ b/Mage.Sets/src/mage/cards/f/FireBellyChangeling.java @@ -27,8 +27,7 @@ public final class FireBellyChangeling extends CardImpl { this.toughness = new MageInt(1); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // {R}: Fire-Belly Changeling gets +1/+0 until end of turn. Activate this ability no more than twice each turn. this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, diff --git a/Mage.Sets/src/mage/cards/g/GameTrailChangeling.java b/Mage.Sets/src/mage/cards/g/GameTrailChangeling.java index 4238a6deabe..dc08e2fa15f 100644 --- a/Mage.Sets/src/mage/cards/g/GameTrailChangeling.java +++ b/Mage.Sets/src/mage/cards/g/GameTrailChangeling.java @@ -22,8 +22,7 @@ public final class GameTrailChangeling extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); this.addAbility(TrampleAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/cards/g/GhostlyChangeling.java b/Mage.Sets/src/mage/cards/g/GhostlyChangeling.java index e5f5c1b4603..7e909268f56 100644 --- a/Mage.Sets/src/mage/cards/g/GhostlyChangeling.java +++ b/Mage.Sets/src/mage/cards/g/GhostlyChangeling.java @@ -26,8 +26,7 @@ public final class GhostlyChangeling extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl("{1}{B}"))); } diff --git a/Mage.Sets/src/mage/cards/g/Gigantoplasm.java b/Mage.Sets/src/mage/cards/g/Gigantoplasm.java index df6f0f4eaee..f20d8dd570b 100644 --- a/Mage.Sets/src/mage/cards/g/Gigantoplasm.java +++ b/Mage.Sets/src/mage/cards/g/Gigantoplasm.java @@ -23,7 +23,7 @@ import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; /** * @@ -38,7 +38,7 @@ public final class Gigantoplasm extends CardImpl { this.toughness = new MageInt(0); // You may have Gigantoplasm enter the battlefield as a copy of any creature on the battlefield, except it has "{X}: This creature has base power and toughness X/X." - Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new GigantoplasmApplyToPermanent()); + Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new GigantoplasmCopyApplier()); effect.setText("a copy of any creature on the battlefield, except it has \"{X}: This creature has base power and toughness X/X.\""); this.addAbility(new EntersBattlefieldAbility(effect, true)); } @@ -53,25 +53,15 @@ public final class Gigantoplasm extends CardImpl { } } -class GigantoplasmApplyToPermanent extends ApplyToPermanent { +class GigantoplasmCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { DynamicValue variableMana = ManacostVariableValue.instance; Effect effect = new SetPowerToughnessSourceEffect(variableMana, Duration.WhileOnBattlefield, SubLayer.SetPT_7b); effect.setText("This creature has base power and toughness X/X"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); - permanent.getAbilities().add(ability); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - DynamicValue variableMana = ManacostVariableValue.instance; - Effect effect = new SetPowerToughnessSourceEffect(variableMana, Duration.WhileOnBattlefield, SubLayer.SetPT_7b); - effect.setText("This creature has base power and toughness X/X"); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); - mageObject.getAbilities().add(ability); + blueprint.getAbilities().add(ability); return true; } diff --git a/Mage.Sets/src/mage/cards/g/Glaciers.java b/Mage.Sets/src/mage/cards/g/Glaciers.java index 59234594f8f..07ded3d49c4 100644 --- a/Mage.Sets/src/mage/cards/g/Glaciers.java +++ b/Mage.Sets/src/mage/cards/g/Glaciers.java @@ -72,8 +72,8 @@ public final class Glaciers extends CardImpl { switch (layer) { case TypeChangingEffects_4: // the land mana ability is intrinsic, so apply at this layer not layer 6 - if (land.getSubtype(game).contains(SubType.MOUNTAIN)) { - land.getSubtype(game).removeAll(SubType.getLandTypes()); + if (land.hasSubtype(SubType.MOUNTAIN, game)) { + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); land.addSubType(game, SubType.PLAINS); land.removeAllAbilities(source.getSourceId(), game); land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/g/GladewalkerRitualist.java b/Mage.Sets/src/mage/cards/g/GladewalkerRitualist.java index 4b747334e27..15401e582e8 100644 --- a/Mage.Sets/src/mage/cards/g/GladewalkerRitualist.java +++ b/Mage.Sets/src/mage/cards/g/GladewalkerRitualist.java @@ -36,8 +36,7 @@ public final class GladewalkerRitualist extends CardImpl { this.toughness = new MageInt(3); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Whenever another creature named Gladewalker Ritualist enters the battlefield under your control, draw a card. this.addAbility(new EntersBattlefieldControlledTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/g/GlasspoolMimic.java b/Mage.Sets/src/mage/cards/g/GlasspoolMimic.java index 46a43dfb4e1..4403b7faf09 100644 --- a/Mage.Sets/src/mage/cards/g/GlasspoolMimic.java +++ b/Mage.Sets/src/mage/cards/g/GlasspoolMimic.java @@ -13,8 +13,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -36,7 +35,7 @@ public final class GlasspoolMimic extends ModalDoubleFacesCard { // You may have Glasspool Mimic enter the battlefield as a copy of a creature you control, except it's a Shapeshifter Rogue in addition to its other types. this.getLeftHalfCard().addAbility(new EntersBattlefieldAbility( - new CopyPermanentEffect(StaticFilters.FILTER_CONTROLLED_CREATURE, new GlasspoolMimicApplier()), + new CopyPermanentEffect(StaticFilters.FILTER_CONTROLLED_CREATURE, new GlasspoolMimicCopyApplier()), true, null, "You may have {this} enter the battlefield as a copy of " + "a creature you control, except it's a Shapeshifter Rogue in addition to its other types.", "" )); @@ -62,19 +61,11 @@ public final class GlasspoolMimic extends ModalDoubleFacesCard { } } -class GlasspoolMimicApplier extends ApplyToPermanent { +class GlasspoolMimicCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.addSubType(game, SubType.SHAPESHIFTER); - permanent.addSubType(game, SubType.ROGUE); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.addSubType(game, SubType.SHAPESHIFTER); - mageObject.addSubType(game, SubType.ROGUE); + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.addSubType(SubType.SHAPESHIFTER, SubType.ROGUE); return true; } } diff --git a/Mage.Sets/src/mage/cards/g/GodPharaohsGift.java b/Mage.Sets/src/mage/cards/g/GodPharaohsGift.java index f6ea6fa0bf4..dd5391faea0 100644 --- a/Mage.Sets/src/mage/cards/g/GodPharaohsGift.java +++ b/Mage.Sets/src/mage/cards/g/GodPharaohsGift.java @@ -76,14 +76,15 @@ class GodPharaohsGiftEffect extends OneShotEffect { Card cardChosen = game.getCard(target.getFirstTarget()); if (cardChosen != null && cardChosen.moveToExile(exileId, sourceObject.getIdName(), source, game)) { + // create token and modify all attributes permanently (without game usage) EmptyToken token = new EmptyToken(); CardUtil.copyTo(token).from(cardChosen, game); token.removePTCDA(); token.getPower().modifyBaseValue(4); token.getToughness().modifyBaseValue(4); - token.getColor(game).setColor(ObjectColor.BLACK); - token.removeAllCreatureTypes(game); - token.addSubType(game, SubType.ZOMBIE); + token.getColor().setColor(ObjectColor.BLACK); + token.removeAllCreatureTypes(); + token.addSubType(SubType.ZOMBIE); if (token.putOntoBattlefield(1, game, source, source.getControllerId())) { Permanent tokenPermanent = game.getPermanent(token.getLastAddedToken()); if (tokenPermanent != null) { diff --git a/Mage.Sets/src/mage/cards/g/Graveshifter.java b/Mage.Sets/src/mage/cards/g/Graveshifter.java index dc2f3f3e3a0..e7f7f09a771 100644 --- a/Mage.Sets/src/mage/cards/g/Graveshifter.java +++ b/Mage.Sets/src/mage/cards/g/Graveshifter.java @@ -27,8 +27,7 @@ public final class Graveshifter extends CardImpl { this.toughness = new MageInt(2); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // When Graveshifter enters the battlefield, you may return target creature card from your graveyard to your hand. Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); diff --git a/Mage.Sets/src/mage/cards/g/GuardianGladewalker.java b/Mage.Sets/src/mage/cards/g/GuardianGladewalker.java index 19ab91720aa..ae5e98b3d22 100644 --- a/Mage.Sets/src/mage/cards/g/GuardianGladewalker.java +++ b/Mage.Sets/src/mage/cards/g/GuardianGladewalker.java @@ -27,8 +27,7 @@ public final class GuardianGladewalker extends CardImpl { this.toughness = new MageInt(1); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // When Guardian Gladewalker enters the battlefield, put a +1/+1 counter on target creature. Ability ability = new EntersBattlefieldTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/h/HeirloomBlade.java b/Mage.Sets/src/mage/cards/h/HeirloomBlade.java index 6bc6d926334..3b955e11dfd 100644 --- a/Mage.Sets/src/mage/cards/h/HeirloomBlade.java +++ b/Mage.Sets/src/mage/cards/h/HeirloomBlade.java @@ -82,7 +82,7 @@ class HeirloomBladeEffect extends OneShotEffect { Cards otherCards = new CardsImpl(); for (Card card : controller.getLibrary().getCards(game)) { revealed.add(card); - if (card != null && card.isCreature() && equipped.shareCreatureTypes(card, game)) { + if (card != null && card.isCreature() && equipped.shareCreatureTypes(game, card)) { controller.moveCardToHandWithInfo(card, source, game, true); break; } else { diff --git a/Mage.Sets/src/mage/cards/h/Hivestone.java b/Mage.Sets/src/mage/cards/h/Hivestone.java index 8d8929c3941..8f05064fc2b 100644 --- a/Mage.Sets/src/mage/cards/h/Hivestone.java +++ b/Mage.Sets/src/mage/cards/h/Hivestone.java @@ -1,6 +1,5 @@ package mage.cards.h; -import java.util.UUID; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BecomesSubtypeAllEffect; @@ -9,7 +8,9 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; -import mage.util.SubTypeList; + +import java.util.Arrays; +import java.util.UUID; /** * Created by Alexsandr0x. @@ -26,9 +27,7 @@ public final class Hivestone extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // Creatures you control are Slivers in addition to their other creature types. - SubTypeList subTypes = new SubTypeList(); - subTypes.add(SubType.SLIVER); - Effect effect = new BecomesSubtypeAllEffect(Duration.WhileOnBattlefield, subTypes, filter, false); + Effect effect = new BecomesSubtypeAllEffect(Duration.WhileOnBattlefield, Arrays.asList(SubType.SLIVER), filter, false); effect.setText("Creatures you control are Slivers in addition to their other creature types"); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); } diff --git a/Mage.Sets/src/mage/cards/h/HourOfEternity.java b/Mage.Sets/src/mage/cards/h/HourOfEternity.java index 3f9d7eda110..05daae50a66 100644 --- a/Mage.Sets/src/mage/cards/h/HourOfEternity.java +++ b/Mage.Sets/src/mage/cards/h/HourOfEternity.java @@ -90,14 +90,15 @@ class HourOfEternityEffect extends OneShotEffect { controller.moveCardsToExile(cardsToExile, source, game, true, null, ""); for (Card card : cardsToExile) { if (game.getState().getZone(card.getId()) == Zone.EXILED) { + // create token and modify all attributes permanently (without game usage) EmptyToken token = new EmptyToken(); CardUtil.copyTo(token).from(card, game); token.removePTCDA(); token.getPower().modifyBaseValue(4); token.getToughness().modifyBaseValue(4); - token.getColor(game).setColor(ObjectColor.BLACK); - token.removeAllCreatureTypes(game); - token.addSubType(game, SubType.ZOMBIE); + token.getColor().setColor(ObjectColor.BLACK); + token.removeAllCreatureTypes(); + token.addSubType(SubType.ZOMBIE); token.putOntoBattlefield(1, game, source, source.getControllerId()); } } diff --git a/Mage.Sets/src/mage/cards/h/Hydroform.java b/Mage.Sets/src/mage/cards/h/Hydroform.java index 9c85c77e07b..96d8a020e40 100644 --- a/Mage.Sets/src/mage/cards/h/Hydroform.java +++ b/Mage.Sets/src/mage/cards/h/Hydroform.java @@ -43,7 +43,7 @@ class HydroformToken extends TokenImpl { public HydroformToken() { super("", "3/3 Elemental creature with flying"); this.cardType.add(CardType.CREATURE); - this.getSubtype(null).add(SubType.ELEMENTAL); + this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(3); this.toughness = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/i/IllusionaryTerrain.java b/Mage.Sets/src/mage/cards/i/IllusionaryTerrain.java index 27c0a4b5e82..cc1535af076 100644 --- a/Mage.Sets/src/mage/cards/i/IllusionaryTerrain.java +++ b/Mage.Sets/src/mage/cards/i/IllusionaryTerrain.java @@ -19,15 +19,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.ChoiceBasicLandType; import mage.choices.ChoiceImpl; -import mage.constants.CardType; -import mage.constants.DependencyType; -import mage.constants.Duration; -import mage.constants.Layer; +import mage.constants.*; + import static mage.constants.Layer.TypeChangingEffects_4; -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; import mage.players.Player; @@ -93,27 +88,27 @@ class IllusionaryTerrainEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: // the land mana ability is intrinsic, so add it here, not layer 6 - if (land.getSubtype(game).contains(firstChoice)) { - land.getSubtype(game).removeAll(SubType.getLandTypes()); + if (land.hasSubtype(firstChoice, game)) { + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); land.addSubType(game, secondChoice); land.removeAllAbilities(source.getSourceId(), game); - if (land.getSubtype(game).contains(SubType.FOREST)) { + if (land.hasSubtype(SubType.FOREST, game)) { this.dependencyTypes.add(DependencyType.BecomeForest); land.addAbility(new GreenManaAbility(), source.getSourceId(), game); } - if (land.getSubtype(game).contains(SubType.PLAINS)) { + if (land.hasSubtype(SubType.PLAINS, game)) { this.dependencyTypes.add(DependencyType.BecomePlains); land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); } - if (land.getSubtype(game).contains(SubType.MOUNTAIN)) { + if (land.hasSubtype(SubType.MOUNTAIN, game)) { this.dependencyTypes.add(DependencyType.BecomeMountain); land.addAbility(new RedManaAbility(), source.getSourceId(), game); } - if (land.getSubtype(game).contains(SubType.ISLAND)) { + if (land.hasSubtype(SubType.ISLAND, game)) { this.dependencyTypes.add(DependencyType.BecomeIsland); land.addAbility(new BlueManaAbility(), source.getSourceId(), game); } - if (land.getSubtype(game).contains(SubType.SWAMP)) { + if (land.hasSubtype(SubType.SWAMP, game)) { this.dependencyTypes.add(DependencyType.BecomeSwamp); land.addAbility(new BlackManaAbility(), source.getSourceId(), game); } diff --git a/Mage.Sets/src/mage/cards/i/ImpostorOfTheSixthPride.java b/Mage.Sets/src/mage/cards/i/ImpostorOfTheSixthPride.java index bfbb7d01bce..7ac08965303 100644 --- a/Mage.Sets/src/mage/cards/i/ImpostorOfTheSixthPride.java +++ b/Mage.Sets/src/mage/cards/i/ImpostorOfTheSixthPride.java @@ -22,8 +22,7 @@ public final class ImpostorOfTheSixthPride extends CardImpl { this.toughness = new MageInt(1); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); } private ImpostorOfTheSixthPride(final ImpostorOfTheSixthPride card) { diff --git a/Mage.Sets/src/mage/cards/i/InfiniteReflection.java b/Mage.Sets/src/mage/cards/i/InfiniteReflection.java index 50643266bae..fa4b6b6186c 100644 --- a/Mage.Sets/src/mage/cards/i/InfiniteReflection.java +++ b/Mage.Sets/src/mage/cards/i/InfiniteReflection.java @@ -27,7 +27,7 @@ import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -89,7 +89,7 @@ class InfiniteReflectionTriggeredEffect extends OneShotEffect { if (toCopyFromPermanent != null) { for (Permanent toCopyToPermanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { if (!toCopyToPermanent.equals(toCopyFromPermanent) && !(toCopyToPermanent instanceof PermanentToken)) { - game.copyPermanent(toCopyFromPermanent, toCopyToPermanent.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(toCopyFromPermanent, toCopyToPermanent.getId(), source, new EmptyCopyApplier()); } } return true; @@ -129,7 +129,7 @@ class InfiniteReflectionEntersBattlefieldEffect extends ReplacementEffectImpl { if (sourcePermanent != null && toCopyToObject != null && sourcePermanent.getAttachedTo() != null) { Permanent toCopyFromPermanent = game.getPermanent(sourcePermanent.getAttachedTo()); if (toCopyFromPermanent != null) { - game.copyPermanent(toCopyFromPermanent, toCopyToObject.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(toCopyFromPermanent, toCopyToObject.getId(), source, new EmptyCopyApplier()); } } return false; diff --git a/Mage.Sets/src/mage/cards/i/IrregularCohort.java b/Mage.Sets/src/mage/cards/i/IrregularCohort.java index 5d7ed2537e1..18dee4b9756 100644 --- a/Mage.Sets/src/mage/cards/i/IrregularCohort.java +++ b/Mage.Sets/src/mage/cards/i/IrregularCohort.java @@ -24,8 +24,7 @@ public final class IrregularCohort extends CardImpl { this.toughness = new MageInt(2); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // When Irregular Cohort enters the battlefield, create a 2/2 colorless Shapeshifter creature token with changeling. this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ShapeshifterToken()))); diff --git a/Mage.Sets/src/mage/cards/j/JarKaiBattleStance.java b/Mage.Sets/src/mage/cards/j/JarKaiBattleStance.java index a60eedc773b..20a91b6a0a3 100644 --- a/Mage.Sets/src/mage/cards/j/JarKaiBattleStance.java +++ b/Mage.Sets/src/mage/cards/j/JarKaiBattleStance.java @@ -1,7 +1,5 @@ - package mage.cards.j; -import java.util.UUID; import mage.abilities.condition.LockedInCondition; import mage.abilities.condition.common.SourceHasSubtypeCondition; import mage.abilities.decorator.ConditionalContinuousEffect; @@ -14,29 +12,26 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; -import mage.util.SubTypeList; + +import java.util.UUID; /** - * * @author Styxo */ public final class JarKaiBattleStance extends CardImpl { public JarKaiBattleStance(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); // Target creature gains double strike until end of turn. this.getSpellAbility().addEffect(new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - SubTypeList s = new SubTypeList(); - s.add(SubType.JEDI); - s.add(SubType.SITH); + // If that creature is a Jedi or Sith, it also gains trample until end of turn. this.getSpellAbility().addEffect(new ConditionalContinuousEffect( new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), - new LockedInCondition(new SourceHasSubtypeCondition(s)), + new LockedInCondition(new SourceHasSubtypeCondition(SubType.JEDI, SubType.SITH)), "If that creature is a Jedi or Sith, it also gains trample until end of turn")); - } public JarKaiBattleStance(final JarKaiBattleStance card) { diff --git a/Mage.Sets/src/mage/cards/k/KaheeraTheOrphanguard.java b/Mage.Sets/src/mage/cards/k/KaheeraTheOrphanguard.java index e06ce66fda9..a186762ac71 100644 --- a/Mage.Sets/src/mage/cards/k/KaheeraTheOrphanguard.java +++ b/Mage.Sets/src/mage/cards/k/KaheeraTheOrphanguard.java @@ -16,8 +16,9 @@ import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AnotherPredicate; -import mage.util.SubTypeList; +import java.util.Arrays; +import java.util.List; import java.util.Set; import java.util.UUID; @@ -83,7 +84,7 @@ enum KaheeraTheOrphanguardCompanionCondition implements CompanionCondition { return "Each creature card in your starting deck is a Cat, Elemental, Nightmare, Dinosaur or Beast card."; } - private static final SubTypeList subtypes = new SubTypeList( + private static final List subtypes = Arrays.asList( SubType.CAT, SubType.ELEMENTAL, SubType.NIGHTMARE, @@ -92,7 +93,7 @@ enum KaheeraTheOrphanguardCompanionCondition implements CompanionCondition { ); private static boolean checkTypes(Card card) { - return subtypes.stream().anyMatch(subtype -> card.hasSubtype(subtype, null)); + return subtypes.stream().anyMatch(subtype -> card.getSubtype().contains(subtype)); } @Override diff --git a/Mage.Sets/src/mage/cards/k/KondasBanner.java b/Mage.Sets/src/mage/cards/k/KondasBanner.java index 5c48062109a..2d21ceeb477 100644 --- a/Mage.Sets/src/mage/cards/k/KondasBanner.java +++ b/Mage.Sets/src/mage/cards/k/KondasBanner.java @@ -109,7 +109,7 @@ class KondasBannerTypeBoostEffect extends BoostAllEffect { Permanent equipedCreature = game.getPermanent(equipment.getAttachedTo()); if (equipedCreature != null) { for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - if (perm.shareCreatureTypes(equipedCreature, game)) { + if (perm.shareCreatureTypes(game, equipedCreature)) { perm.addPower(power.calculate(game, source, this)); perm.addToughness(toughness.calculate(game, source, this)); diff --git a/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java b/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java index 71cdf748fef..c7240624d93 100644 --- a/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java +++ b/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java @@ -19,7 +19,7 @@ import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; import mage.players.Player; import mage.target.targetpointer.FixedTarget; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; /** * @@ -82,7 +82,7 @@ class LazavDimirMastermindEffect extends OneShotEffect { if (copyFromCard != null) { newBluePrint = new PermanentCard(copyFromCard, source.getControllerId(), game); newBluePrint.assignNewId(); - ApplyToPermanent applier = new LazavDimirMastermindApplier(); + CopyApplier applier = new LazavDimirMastermindCopyApplier(); applier.apply(game, newBluePrint, source, lazavDimirMastermind.getId()); CopyEffect copyEffect = new CopyEffect(Duration.Custom, newBluePrint, lazavDimirMastermind.getId()); copyEffect.newId(); @@ -97,31 +97,18 @@ class LazavDimirMastermindEffect extends OneShotEffect { } } -class LazavDimirMastermindApplier extends ApplyToPermanent { +class LazavDimirMastermindCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { Ability ability = new PutCardIntoGraveFromAnywhereAllTriggeredAbility( new LazavDimirMastermindEffect(), true, new FilterCreatureCard("a creature card"), TargetController.OPPONENT, SetTargetPointer.CARD); - permanent.getAbilities().add(ability); - permanent.setName("Lazav, Dimir Mastermind"); - permanent.addSuperType(SuperType.LEGENDARY); - permanent.getAbilities().add(HexproofAbility.getInstance()); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - Ability ability = new PutCardIntoGraveFromAnywhereAllTriggeredAbility( - new LazavDimirMastermindEffect(), true, - new FilterCreatureCard("a creature card"), - TargetController.OPPONENT, SetTargetPointer.CARD); - mageObject.getAbilities().add(ability); - mageObject.setName("Lazav, Dimir Mastermind"); - mageObject.addSuperType(SuperType.LEGENDARY); - mageObject.getAbilities().add(HexproofAbility.getInstance()); + blueprint.getAbilities().add(ability); + blueprint.setName("Lazav, Dimir Mastermind"); + blueprint.addSuperType(SuperType.LEGENDARY); + blueprint.getAbilities().add(HexproofAbility.getInstance()); return true; } } diff --git a/Mage.Sets/src/mage/cards/l/LazavTheMultifarious.java b/Mage.Sets/src/mage/cards/l/LazavTheMultifarious.java index 5ee5f63379f..87eca308e91 100644 --- a/Mage.Sets/src/mage/cards/l/LazavTheMultifarious.java +++ b/Mage.Sets/src/mage/cards/l/LazavTheMultifarious.java @@ -28,7 +28,7 @@ import mage.game.permanent.PermanentCard; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; import mage.target.targetadjustment.TargetAdjuster; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; /** * @@ -112,7 +112,7 @@ class LazavTheMultifariousEffect extends OneShotEffect { if (copyFromCard != null) { newBluePrint = new PermanentCard(copyFromCard, source.getControllerId(), game); newBluePrint.assignNewId(); - ApplyToPermanent applier = new LazavTheMultifariousApplier(); + CopyApplier applier = new LazavTheMultifariousCopyApplier(); applier.apply(game, newBluePrint, source, lazavTheMultifarious.getId()); CopyEffect copyEffect = new CopyEffect(Duration.Custom, newBluePrint, lazavTheMultifarious.getId()); copyEffect.newId(); @@ -127,31 +127,18 @@ class LazavTheMultifariousEffect extends OneShotEffect { } } -class LazavTheMultifariousApplier extends ApplyToPermanent { +class LazavTheMultifariousCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { Ability ability = new SimpleActivatedAbility( new LazavTheMultifariousEffect(), new ManaCostsImpl("{X}") ); ability.setTargetAdjuster(LazavTheMultifariousAdjuster.instance); - permanent.getAbilities().add(ability); - permanent.setName("Lazav, the Multifarious"); - permanent.addSuperType(SuperType.LEGENDARY); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - Ability ability = new SimpleActivatedAbility( - new LazavTheMultifariousEffect(), - new ManaCostsImpl("{X}") - ); - ability.setTargetAdjuster(LazavTheMultifariousAdjuster.instance); - mageObject.getAbilities().add(ability); - mageObject.setName("Lazav, the Multifarious"); - mageObject.addSuperType(SuperType.LEGENDARY); + blueprint.getAbilities().add(ability); + blueprint.setName("Lazav, the Multifarious"); + blueprint.addSuperType(SuperType.LEGENDARY); return true; } } diff --git a/Mage.Sets/src/mage/cards/l/LiegeOfTheTangle.java b/Mage.Sets/src/mage/cards/l/LiegeOfTheTangle.java index 4359397ae83..2d0c49f8934 100644 --- a/Mage.Sets/src/mage/cards/l/LiegeOfTheTangle.java +++ b/Mage.Sets/src/mage/cards/l/LiegeOfTheTangle.java @@ -2,8 +2,6 @@ package mage.cards.l; -import java.util.Iterator; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.ObjectColor; @@ -20,20 +18,21 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.game.permanent.token.custom.ElementalCreatureToken; import mage.target.Target; import mage.target.common.TargetLandPermanent; +import java.util.Iterator; +import java.util.UUID; + /** - * * @author Loki */ public final class LiegeOfTheTangle extends CardImpl { - public LiegeOfTheTangle (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{6}{G}{G}"); + public LiegeOfTheTangle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{G}{G}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(8); @@ -42,7 +41,7 @@ public final class LiegeOfTheTangle extends CardImpl { this.addAbility(new LiegeOfTheTangleTriggeredAbility()); } - public LiegeOfTheTangle (final LiegeOfTheTangle card) { + public LiegeOfTheTangle(final LiegeOfTheTangle card) { super(card); } @@ -76,7 +75,7 @@ class LiegeOfTheTangleTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; Permanent p = game.getPermanent(event.getSourceId()); return damageEvent.isCombatDamage() && p != null && p.getId().equals(this.getSourceId()); } @@ -101,32 +100,33 @@ class LiegeOfTheTangleEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Iterator it = affectedObjectList.iterator(); it.hasNext();) { + for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { Permanent perm = it.next().getPermanent(game); - if (perm != null) { - if (perm.getCounters(game).getCount(CounterType.AWAKENING) > 0) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - perm.addCardTypes(token.getCardType()); - perm.getSubtype(game).addAll(token.getSubtype(game)); - } - break; - case ColorChangingEffects_5: - if (sublayer == SubLayer.NA) { - perm.getColor(game).setColor(token.getColor(game)); - } - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - perm.getPower().setValue(token.getPower().getValue()); - perm.getToughness().setValue(token.getToughness().getValue()); - } - break; - } - } - } else { + if (perm == null) { it.remove(); + continue; + } + if (perm.getCounters(game).getCount(CounterType.AWAKENING) <= 0) { + continue; + } + switch (layer) { + case TypeChangingEffects_4: + if (sublayer == SubLayer.NA) { + perm.addCardTypes(token.getCardType()); + perm.copySubTypesFrom(game, token); + } + break; + case ColorChangingEffects_5: + if (sublayer == SubLayer.NA) { + perm.getColor(game).setColor(token.getColor(game)); + } + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + perm.getPower().setValue(token.getPower().getValue()); + perm.getToughness().setValue(token.getToughness().getValue()); + } + break; } } return true; @@ -141,7 +141,7 @@ class LiegeOfTheTangleEffect extends ContinuousEffectImpl { public void init(Ability source, Game game) { super.init(source, game); if (this.affectedObjectsSet) { - for (UUID permId: targetPointer.getTargets(game, source)) { + for (UUID permId : targetPointer.getTargets(game, source)) { affectedObjectList.add(new MageObjectReference(permId, game)); } } @@ -154,7 +154,9 @@ class LiegeOfTheTangleEffect extends ContinuousEffectImpl { @Override public boolean hasLayer(Layer layer) { - return layer == Layer.PTChangingEffects_7 || layer == Layer.ColorChangingEffects_5 || layer == layer.TypeChangingEffects_4; + return layer == Layer.PTChangingEffects_7 + || layer == Layer.ColorChangingEffects_5 + || layer == layer.TypeChangingEffects_4; } } diff --git a/Mage.Sets/src/mage/cards/l/LithoformBlight.java b/Mage.Sets/src/mage/cards/l/LithoformBlight.java index 1ec4d1b8877..fa60da1cf24 100644 --- a/Mage.Sets/src/mage/cards/l/LithoformBlight.java +++ b/Mage.Sets/src/mage/cards/l/LithoformBlight.java @@ -82,7 +82,7 @@ class ChangeLandAttachedEffect extends ContinuousEffectImpl { } switch (layer) { case TypeChangingEffects_4: - permanent.getSubtype(game).removeAll(SubType.getLandTypes()); + permanent.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); break; case AbilityAddingRemovingEffects_6: permanent.removeAllAbilities(source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/l/LittjaraGladeWarden.java b/Mage.Sets/src/mage/cards/l/LittjaraGladeWarden.java index bd1a6fe6d4e..30698d54e72 100644 --- a/Mage.Sets/src/mage/cards/l/LittjaraGladeWarden.java +++ b/Mage.Sets/src/mage/cards/l/LittjaraGladeWarden.java @@ -33,8 +33,7 @@ public final class LittjaraGladeWarden extends CardImpl { this.toughness = new MageInt(3); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // {2}{G}, {T}, Exile a creature card from your graveyard: Put two +1/+1 counters on target creature. Activate this ability only any time you could cast a sorcery. Ability ability = new ActivateAsSorceryActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java b/Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java index 7e48a21e79a..d9834d1c1fc 100644 --- a/Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java +++ b/Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java @@ -31,8 +31,7 @@ public final class LittjaraKinseekers extends CardImpl { this.toughness = new MageInt(4); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // When Littjara Kinseekers enters the battlefield, if you control three or more creatures that share a creature type, put a +1/+1 counter on Littjara Kinseekers, then scry 1. Ability ability = new ConditionalInterveningIfTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java b/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java index cd52cc84c36..6a1ffb2d532 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java @@ -77,7 +77,7 @@ public final class MagusOfTheMoon extends CardImpl { // 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects // So the ability removing has to be done before Layer 6 land.removeAllAbilities(source.getSourceId(), game); - land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); land.addSubType(game, SubType.MOUNTAIN); // Mountains have the red mana ability intrinsically so the ability must be added in this layer land.addAbility(new RedManaAbility(), source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/m/ManaEchoes.java b/Mage.Sets/src/mage/cards/m/ManaEchoes.java index d879b3fabf7..4a4de7f7d0b 100644 --- a/Mage.Sets/src/mage/cards/m/ManaEchoes.java +++ b/Mage.Sets/src/mage/cards/m/ManaEchoes.java @@ -65,7 +65,7 @@ class ManaEchoesEffect extends OneShotEffect { if (controller != null && permanent != null) { int foundCreatures = 0; for (Permanent perm : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game)) { - if (permanent.shareCreatureTypes(perm, game)) { + if (permanent.shareCreatureTypes(game, perm)) { foundCreatures++; } } diff --git a/Mage.Sets/src/mage/cards/m/MaskedVandal.java b/Mage.Sets/src/mage/cards/m/MaskedVandal.java index 824c2c23b65..67b70162e88 100644 --- a/Mage.Sets/src/mage/cards/m/MaskedVandal.java +++ b/Mage.Sets/src/mage/cards/m/MaskedVandal.java @@ -40,8 +40,7 @@ public final class MaskedVandal extends CardImpl { this.toughness = new MageInt(3); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // When enters the battlefield, you may exile a creature card from your graveyard. If you do, exile target artifact or enchantment an opponent controls. Ability ability = new EntersBattlefieldAbility( diff --git a/Mage.Sets/src/mage/cards/m/MaskwoodNexus.java b/Mage.Sets/src/mage/cards/m/MaskwoodNexus.java index e65c52e16a4..54bbd662954 100644 --- a/Mage.Sets/src/mage/cards/m/MaskwoodNexus.java +++ b/Mage.Sets/src/mage/cards/m/MaskwoodNexus.java @@ -57,7 +57,7 @@ public final class MaskwoodNexus extends CardImpl { class MaskwoodNexusEffect extends ContinuousEffectImpl { MaskwoodNexusEffect() { - super(Duration.WhileOnBattlefield, Outcome.Benefit); + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); staticText = "Creatures you control are every creature type. " + "The same is true for creature spells you control " + "and creature cards you own that aren't on the battlefield."; @@ -73,7 +73,7 @@ class MaskwoodNexusEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller == null) { return false; @@ -83,26 +83,26 @@ class MaskwoodNexusEffect extends ContinuousEffectImpl { for (UUID cardId : controller.getGraveyard()) { Card card = game.getCard(cardId); if (card != null && card.isCreature()) { - card.setIsAllCreatureTypes(true); + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().setIsAllCreatureTypes(true); } } // on Hand for (UUID cardId : controller.getHand()) { Card card = game.getCard(cardId); if (card != null && card.isCreature()) { - card.setIsAllCreatureTypes(true); + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().setIsAllCreatureTypes(true); } } // in Exile for (Card card : game.getState().getExile().getAllCards(game)) { if (card.isCreature() && card.isOwnedBy(controller.getId())) { - card.setIsAllCreatureTypes(true); + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().setIsAllCreatureTypes(true); } } // in Library (e.g. for Mystical Teachings) for (Card card : controller.getLibrary().getCards(game)) { if (card.isOwnedBy(controller.getId()) && card.isCreature()) { - card.setIsAllCreatureTypes(true); + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().setIsAllCreatureTypes(true); } } // commander in command zone @@ -114,7 +114,7 @@ class MaskwoodNexusEffect extends ContinuousEffectImpl { if (card != null && card.isOwnedBy(controller.getId()) && card.isCreature()) { - card.setIsAllCreatureTypes(true); + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().setIsAllCreatureTypes(true); } } // creature spells you control @@ -124,7 +124,7 @@ class MaskwoodNexusEffect extends ContinuousEffectImpl { && stackObject.isControlledBy(source.getControllerId()) && stackObject.isCreature()) { Card card = ((Spell) stackObject).getCard(); - card.setIsAllCreatureTypes(true); + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().setIsAllCreatureTypes(true); } } // creatures you control @@ -132,16 +132,10 @@ class MaskwoodNexusEffect extends ContinuousEffectImpl { new FilterControlledCreaturePermanent(), source.getControllerId(), game); for (Permanent creature : creatures) { if (creature != null) { - creature.setIsAllCreatureTypes(true); + creature.setIsAllCreatureTypes(game, true); } } return true; } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - } diff --git a/Mage.Sets/src/mage/cards/m/MasterfulReplication.java b/Mage.Sets/src/mage/cards/m/MasterfulReplication.java index eb1a54f1c7b..6fed41c2f38 100644 --- a/Mage.Sets/src/mage/cards/m/MasterfulReplication.java +++ b/Mage.Sets/src/mage/cards/m/MasterfulReplication.java @@ -14,7 +14,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.GolemToken; import mage.target.TargetPermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; import java.util.UUID; @@ -71,7 +71,7 @@ class MasterfulReplicationEffect extends OneShotEffect { } for (Permanent copyToArtifact : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { if (copyToArtifact.isArtifact() && !copyToArtifact.getId().equals(copyFromArtifact.getId())) { - game.copyPermanent(Duration.EndOfTurn, copyFromArtifact, copyToArtifact.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, copyFromArtifact, copyToArtifact.getId(), source, new EmptyCopyApplier()); } } return true; diff --git a/Mage.Sets/src/mage/cards/m/MercurialPretender.java b/Mage.Sets/src/mage/cards/m/MercurialPretender.java index 36145c0c653..dbe837064e1 100644 --- a/Mage.Sets/src/mage/cards/m/MercurialPretender.java +++ b/Mage.Sets/src/mage/cards/m/MercurialPretender.java @@ -13,7 +13,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.util.functions.AbilityApplier; +import mage.util.functions.AbilityCopyApplier; import java.util.UUID; @@ -35,7 +35,7 @@ public final class MercurialPretender extends CardImpl { // You may have Mercurial Pretender enter the battlefield as a copy of any creature you control, // except it has "{2}{U}{U}: Return this creature to its owner's hand." Effect effect = new CopyPermanentEffect(new FilterControlledCreaturePermanent(), - new AbilityApplier(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandSourceEffect(true), new ManaCostsImpl("{2}{U}{U}")))); + new AbilityCopyApplier(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandSourceEffect(true), new ManaCostsImpl("{2}{U}{U}")))); effect.setText(effectText); this.addAbility(new EntersBattlefieldAbility(effect, true)); } diff --git a/Mage.Sets/src/mage/cards/m/MetamorphicAlteration.java b/Mage.Sets/src/mage/cards/m/MetamorphicAlteration.java index 235d4ce49e4..288857e8591 100644 --- a/Mage.Sets/src/mage/cards/m/MetamorphicAlteration.java +++ b/Mage.Sets/src/mage/cards/m/MetamorphicAlteration.java @@ -133,9 +133,7 @@ class MetamorphicAlterationEffect extends ContinuousEffectImpl { permanent.addCardType(cardType); } permanent.removeAllSubTypes(game); - permanent.setIsAllCreatureTypes(copied.isAllCreatureTypes()); - permanent.getSubtype(game).addAll(copied.getSubtype(game)); - permanent.setIsAllCreatureTypes(copied.isAllCreatureTypes()); + permanent.copySubTypesFrom(game, copied); permanent.getColor(game).setColor(copied.getColor(game)); permanent.removeAllAbilities(source.getSourceId(), game); for (Ability ability : copied.getAbilities()) { diff --git a/Mage.Sets/src/mage/cards/m/MirageMirror.java b/Mage.Sets/src/mage/cards/m/MirageMirror.java index ccadfcd18cf..06ea6d41647 100644 --- a/Mage.Sets/src/mage/cards/m/MirageMirror.java +++ b/Mage.Sets/src/mage/cards/m/MirageMirror.java @@ -16,7 +16,7 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -66,7 +66,7 @@ class MirageMirrorCopyEffect extends OneShotEffect { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (sourcePermanent != null && copyFromPermanent != null) { - game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyCopyApplier()); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/m/MirrorEntity.java b/Mage.Sets/src/mage/cards/m/MirrorEntity.java index 8ea0f5324b6..fa76b2f29bb 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorEntity.java +++ b/Mage.Sets/src/mage/cards/m/MirrorEntity.java @@ -32,8 +32,7 @@ public final class MirrorEntity extends CardImpl { this.toughness = new MageInt(1); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // {X}: Until end of turn, creatures you control have base power and toughness X/X and gain all creature types. Ability ability = new SimpleActivatedAbility(new SetPowerToughnessAllEffect( @@ -88,7 +87,7 @@ class MirrorEntityEffect extends ContinuousEffectImpl { it.remove(); // no longer on the battlefield, remove reference to object continue; } - permanent.setIsAllCreatureTypes(true); + permanent.setIsAllCreatureTypes(game, true); } return true; } diff --git a/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java b/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java index 1c421c28976..69c09643314 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java +++ b/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java @@ -19,7 +19,7 @@ import mage.filter.predicate.mageobject.ChosenSubtypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; import java.util.UUID; @@ -77,7 +77,7 @@ class MirrorOfTheForebearsCopyEffect extends OneShotEffect { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (sourcePermanent != null && copyFromPermanent != null) { - game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyCopyApplier()); game.addEffect(new AddCardTypeSourceEffect(Duration.EndOfTurn, CardType.ARTIFACT), source); return true; } diff --git a/Mage.Sets/src/mage/cards/m/Mirrorweave.java b/Mage.Sets/src/mage/cards/m/Mirrorweave.java index 07c32b9a1f1..838e54ac7e5 100644 --- a/Mage.Sets/src/mage/cards/m/Mirrorweave.java +++ b/Mage.Sets/src/mage/cards/m/Mirrorweave.java @@ -17,7 +17,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -77,7 +77,7 @@ class MirrorWeaveEffect extends OneShotEffect { filter.add(Predicates.not(new PermanentIdPredicate(copyFromCreature.getId()))); for (Permanent copyToCreature : game.getBattlefield().getAllActivePermanents(filter, game)) { if (copyToCreature != null) { - game.copyPermanent(Duration.EndOfTurn, copyFromCreature, copyToCreature.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, copyFromCreature, copyToCreature.getId(), source, new EmptyCopyApplier()); } } } diff --git a/Mage.Sets/src/mage/cards/m/MistformUltimus.java b/Mage.Sets/src/mage/cards/m/MistformUltimus.java index d4624294a7b..11090369dd7 100644 --- a/Mage.Sets/src/mage/cards/m/MistformUltimus.java +++ b/Mage.Sets/src/mage/cards/m/MistformUltimus.java @@ -2,7 +2,7 @@ package mage.cards.m; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.continuous.IsAllCreatureTypesSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -26,13 +26,10 @@ public final class MistformUltimus extends CardImpl { this.toughness = new MageInt(3); // Mistform Ultimus is every creature type. - this.setIsAllCreatureTypes(true); - this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect( - "{this} is every creature type (even if this card isn't on the battlefield)." - ))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new IsAllCreatureTypesSourceEffect())); } - public MistformUltimus(final MistformUltimus card) { + private MistformUltimus(final MistformUltimus card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/m/MistformWarchief.java b/Mage.Sets/src/mage/cards/m/MistformWarchief.java index 1702e4c48f7..4d71ee79c51 100644 --- a/Mage.Sets/src/mage/cards/m/MistformWarchief.java +++ b/Mage.Sets/src/mage/cards/m/MistformWarchief.java @@ -1,7 +1,6 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.common.SimpleActivatedAbility; @@ -9,24 +8,24 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.continuous.BecomesChosenCreatureTypeSourceEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; -import mage.constants.SubType; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubTypeSet; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.FilterCard; import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class MistformWarchief extends CardImpl { - private static final FilterCard filter = new FilterCard("Creature spells you cast that share a creature type with {this}"); + private static final FilterCard filter = new FilterCard(); static { filter.add(new MistformWarchiefPredicate()); @@ -41,7 +40,6 @@ public final class MistformWarchief extends CardImpl { // Creature spells you cast that share a creature type with Mistform Warchief cost {1} less to cast. this.addAbility(new SimpleStaticAbility( - Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1) .setText("Creature spells you cast that share a creature type with {this} cost {1} less to cast") )); @@ -50,7 +48,7 @@ public final class MistformWarchief extends CardImpl { this.addAbility(new SimpleActivatedAbility(new BecomesChosenCreatureTypeSourceEffect(), new TapSourceCost())); } - public MistformWarchief(final MistformWarchief card) { + private MistformWarchief(final MistformWarchief card) { super(card); } @@ -60,20 +58,12 @@ public final class MistformWarchief extends CardImpl { } } -class MistformWarchiefPredicate implements ObjectSourcePlayerPredicate> { +class MistformWarchiefPredicate implements ObjectSourcePlayerPredicate> { @Override - public boolean apply(ObjectSourcePlayer input, Game game) { + public boolean apply(ObjectSourcePlayer input, Game game) { MageObject sourceObject = game.getObject(input.getSourceId()); - if (sourceObject != null) { - for (SubType subType : sourceObject.getSubtype(game)) { - if (subType.getSubTypeSet() == SubTypeSet.CreatureType && input.getObject().hasSubtype(subType, game)) { - return true; - } - } - } - return false; - + return sourceObject != null && sourceObject.shareCreatureTypes(game, input.getObject()); } @Override diff --git a/Mage.Sets/src/mage/cards/m/Mistwalker.java b/Mage.Sets/src/mage/cards/m/Mistwalker.java index d34f798fabf..ec12dc22510 100644 --- a/Mage.Sets/src/mage/cards/m/Mistwalker.java +++ b/Mage.Sets/src/mage/cards/m/Mistwalker.java @@ -27,8 +27,7 @@ public final class Mistwalker extends CardImpl { this.toughness = new MageInt(4); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Flying this.addAbility(FlyingAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/m/MizziumTransreliquat.java b/Mage.Sets/src/mage/cards/m/MizziumTransreliquat.java index 298c2f4d8d9..a62a677770b 100644 --- a/Mage.Sets/src/mage/cards/m/MizziumTransreliquat.java +++ b/Mage.Sets/src/mage/cards/m/MizziumTransreliquat.java @@ -15,7 +15,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetArtifactPermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -68,7 +68,7 @@ class MizziumTransreliquatCopyEffect extends OneShotEffect { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (sourcePermanent != null && copyFromPermanent != null) { - game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyCopyApplier()); return true; } return false; @@ -96,7 +96,7 @@ class MizziumTransreliquatCopyAndGainAbilityEffect extends OneShotEffect { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (sourcePermanent != null && copyFromPermanent != null) { - Permanent newPermanent = game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent()); + Permanent newPermanent = game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new EmptyCopyApplier()); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MizziumTransreliquatCopyAndGainAbilityEffect(), new ManaCostsImpl("{1}{U}{R}")); ability.addTarget(new TargetArtifactPermanent()); newPermanent.addAbility(ability, source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/m/MoongloveChangeling.java b/Mage.Sets/src/mage/cards/m/MoongloveChangeling.java index f7115243c58..f2034c6e279 100644 --- a/Mage.Sets/src/mage/cards/m/MoongloveChangeling.java +++ b/Mage.Sets/src/mage/cards/m/MoongloveChangeling.java @@ -24,8 +24,7 @@ public final class MoongloveChangeling extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn), new ColoredManaCost(ColoredManaSymbol.B))); } diff --git a/Mage.Sets/src/mage/cards/m/MoritteOfTheFrost.java b/Mage.Sets/src/mage/cards/m/MoritteOfTheFrost.java index da709cf3142..594b71fecea 100644 --- a/Mage.Sets/src/mage/cards/m/MoritteOfTheFrost.java +++ b/Mage.Sets/src/mage/cards/m/MoritteOfTheFrost.java @@ -15,8 +15,7 @@ import mage.constants.SuperType; import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -35,12 +34,11 @@ public final class MoritteOfTheFrost extends CardImpl { this.toughness = new MageInt(0); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // You may have Moritte of the Frost enter the battlefield as a copy of a permanent you control, except it's legendary and snow in addition to its other types and, if it's a creature, it enters with two additional +1/+1 counters on it and has changeling. this.addAbility(new EntersBattlefieldAbility(new CopyPermanentEffect( - StaticFilters.FILTER_CONTROLLED_PERMANENT, new MoritteOfTheFrostApplier() + StaticFilters.FILTER_CONTROLLED_PERMANENT, new MoritteOfTheFrostCopyApplier() ).setText("as a copy of a permanent you control, except it's legendary and snow in addition to its other types " + "and, if it's a creature, it enters with two additional +1/+1 counters on it and has changeling." ), true)); @@ -56,24 +54,18 @@ public final class MoritteOfTheFrost extends CardImpl { } } -class MoritteOfTheFrostApplier extends ApplyToPermanent { +class MoritteOfTheFrostCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent copyFromBlueprint, Ability source, UUID copyToObjectId) { - return apply(game, (MageObject) copyFromBlueprint, source, copyToObjectId); - } + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.addSuperType(SuperType.LEGENDARY); + blueprint.addSuperType(SuperType.SNOW); - @Override - public boolean apply(Game game, MageObject copyFromBlueprint, Ability source, UUID copyToObjectId) { - copyFromBlueprint.addSuperType(SuperType.LEGENDARY); - copyFromBlueprint.addSuperType(SuperType.SNOW); - - if (!isCopyOfCopy(source, copyToObjectId) && copyFromBlueprint.isCreature()) { - copyFromBlueprint.setIsAllCreatureTypes(true); - copyFromBlueprint.getAbilities().add(ChangelingAbility.getInstance()); - new AddCountersSourceEffect( - CounterType.P1P1.createInstance(2), false - ).apply(game, source); + if (!isCopyOfCopy(source, copyToObjectId) && blueprint.isCreature()) { + blueprint.getAbilities().add(new ChangelingAbility()); + blueprint.getAbilities().add(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(2), false) + )); } return true; } diff --git a/Mage.Sets/src/mage/cards/m/MorophonTheBoundless.java b/Mage.Sets/src/mage/cards/m/MorophonTheBoundless.java index d4fcd5666e4..fd2be913ab0 100644 --- a/Mage.Sets/src/mage/cards/m/MorophonTheBoundless.java +++ b/Mage.Sets/src/mage/cards/m/MorophonTheBoundless.java @@ -40,8 +40,7 @@ public final class MorophonTheBoundless extends CardImpl { this.toughness = new MageInt(6); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // As Morophon, the Boundless enters the battlefield, choose a creature type. this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature))); diff --git a/Mage.Sets/src/mage/cards/m/MothdustChangeling.java b/Mage.Sets/src/mage/cards/m/MothdustChangeling.java index c6f60f80ffb..c78b430e4a3 100644 --- a/Mage.Sets/src/mage/cards/m/MothdustChangeling.java +++ b/Mage.Sets/src/mage/cards/m/MothdustChangeling.java @@ -36,8 +36,7 @@ public final class MothdustChangeling extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new TapTargetCost(new TargetControlledPermanent(filter)))); } diff --git a/Mage.Sets/src/mage/cards/m/Mutavault.java b/Mage.Sets/src/mage/cards/m/Mutavault.java index b579fcc4b94..05dbad7ccb5 100644 --- a/Mage.Sets/src/mage/cards/m/Mutavault.java +++ b/Mage.Sets/src/mage/cards/m/Mutavault.java @@ -46,7 +46,7 @@ class MutavaultToken extends TokenImpl { public MutavaultToken() { super("", "2/2 creature with all creature types"); cardType.add(CardType.CREATURE); - setIsAllCreatureTypes(true); + subtype.setIsAllCreatureTypes(true); power = new MageInt(2); toughness = new MageInt(2); } diff --git a/Mage.Sets/src/mage/cards/m/MyriadLandscape.java b/Mage.Sets/src/mage/cards/m/MyriadLandscape.java index c41e0cd9c40..9aeadac6809 100644 --- a/Mage.Sets/src/mage/cards/m/MyriadLandscape.java +++ b/Mage.Sets/src/mage/cards/m/MyriadLandscape.java @@ -21,9 +21,7 @@ import mage.filter.FilterCard; import mage.filter.predicate.Predicates; import mage.game.Game; import mage.target.common.TargetCardInLibrary; -import mage.util.SubTypeList; -import java.util.Iterator; import java.util.UUID; import java.util.stream.Collectors; @@ -48,7 +46,6 @@ public final class MyriadLandscape extends CardImpl { ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); - } public MyriadLandscape(final MyriadLandscape card) { @@ -75,50 +72,36 @@ class TargetCardInLibrarySharingLandType extends TargetCardInLibrary { filterBasicLandCard.add(SuperType.BASIC.getPredicate()); } - public TargetCardInLibrarySharingLandType(int minNumTargets, int maxNumTargets) { + TargetCardInLibrarySharingLandType(int minNumTargets, int maxNumTargets) { super(minNumTargets, maxNumTargets, filterBasicLandCard); } - public TargetCardInLibrarySharingLandType(final TargetCardInLibrarySharingLandType target) { + private TargetCardInLibrarySharingLandType(final TargetCardInLibrarySharingLandType target) { super(target); } @Override public boolean canTarget(UUID playerId, UUID id, Ability source, Cards cards, Game game) { - if (super.canTarget(playerId, id, source, cards, game)) { - if (!getTargets().isEmpty()) { - // check if new target shares a Land Type - SubTypeList landTypes = new SubTypeList(); - for (UUID landId : getTargets()) { - Card landCard = game.getCard(landId); - if (landCard != null) { - if (landTypes.isEmpty()) { - landTypes.addAll(landCard.getSubtype(game)); - } else { - landTypes.removeIf(next -> !landCard.hasSubtype(next, game)); - } - } - } - Card card = game.getCard(id); - if (card != null && !landTypes.isEmpty()) { - for (Iterator iterator = landTypes.iterator(); iterator.hasNext(); ) { - SubType next = iterator.next(); - if (card.hasSubtype(next, game)) { - return true; - } - } - } - } else { - // first target - return true; - } + if (!super.canTarget(playerId, id, source, cards, game)) { + return false; } - return false; + if (getTargets().isEmpty()) { + // first target + return true; + } + Card card1 = game.getCard(getTargets().get(0)); + Card card2 = game.getCard(id); + return card1 != null + && card2 != null + && card1 + .getSubtype(game) + .stream() + .filter(SubType.getLandTypes()::contains) + .anyMatch(subType -> card2.hasSubtype(subType, game)); } @Override public TargetCardInLibrarySharingLandType copy() { return new TargetCardInLibrarySharingLandType(this); } - } diff --git a/Mage.Sets/src/mage/cards/n/NamelessInversion.java b/Mage.Sets/src/mage/cards/n/NamelessInversion.java index 7191a28e74d..369e4fc3d67 100644 --- a/Mage.Sets/src/mage/cards/n/NamelessInversion.java +++ b/Mage.Sets/src/mage/cards/n/NamelessInversion.java @@ -25,8 +25,7 @@ public final class NamelessInversion extends CardImpl { // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Target creature gets +3/-3 and loses all creature types until end of turn. Effect effect = new BoostTargetEffect(3, -3, Duration.EndOfTurn); diff --git a/Mage.Sets/src/mage/cards/n/NascentMetamorph.java b/Mage.Sets/src/mage/cards/n/NascentMetamorph.java index 7f135eb61fe..3d35080cd41 100644 --- a/Mage.Sets/src/mage/cards/n/NascentMetamorph.java +++ b/Mage.Sets/src/mage/cards/n/NascentMetamorph.java @@ -14,7 +14,7 @@ import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; import mage.players.Player; import mage.target.common.TargetOpponent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; import java.util.UUID; @@ -86,7 +86,7 @@ class NascentMetamorphEffect extends OneShotEffect { if (toCopy != null && permanent != null) { game.copyPermanent(Duration.EndOfTurn, new PermanentCard( toCopy, source.getControllerId(), game - ), permanent.getId(), source, new EmptyApplyToPermanent()); + ), permanent.getId(), source, new EmptyCopyApplier()); } player.revealCards(source, toReveal, game); player.putCardsOnBottomOfLibrary(toReveal, game, source, false); diff --git a/Mage.Sets/src/mage/cards/n/NewBlood.java b/Mage.Sets/src/mage/cards/n/NewBlood.java index 49cf5eea454..2babf0f557e 100644 --- a/Mage.Sets/src/mage/cards/n/NewBlood.java +++ b/Mage.Sets/src/mage/cards/n/NewBlood.java @@ -150,7 +150,7 @@ class ChangeCreatureTypeTargetEffect extends ContinuousEffectImpl { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { if (targetObject.hasSubtype(fromSubType, game)) { - targetObject.getSubtype(game).remove(fromSubType); + targetObject.removeSubType(game, fromSubType); if (!targetObject.hasSubtype(toSubType, game)) { targetObject.addSubType(game, toSubType); } diff --git a/Mage.Sets/src/mage/cards/n/NyleasPresence.java b/Mage.Sets/src/mage/cards/n/NyleasPresence.java index 406fb52f5cd..9d6451b1b1c 100644 --- a/Mage.Sets/src/mage/cards/n/NyleasPresence.java +++ b/Mage.Sets/src/mage/cards/n/NyleasPresence.java @@ -82,8 +82,7 @@ class NyleasPresenceLandTypeEffect extends ContinuousEffectImpl { if (land == null) { return true; } - land.getSubtype(game).removeAll(SubType.getBasicLands()); - land.getSubtype(game).addAll(SubType.getBasicLands()); + land.addSubType(game,SubType.getBasicLands()); land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); land.addAbility(new BlueManaAbility(), source.getSourceId(), game); land.addAbility(new BlackManaAbility(), source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/o/OkoTheTrickster.java b/Mage.Sets/src/mage/cards/o/OkoTheTrickster.java index 3366b1c4e2d..86e1ed6c1b4 100644 --- a/Mage.Sets/src/mage/cards/o/OkoTheTrickster.java +++ b/Mage.Sets/src/mage/cards/o/OkoTheTrickster.java @@ -17,7 +17,7 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; import java.util.UUID; @@ -91,7 +91,7 @@ class OkoTheTricksterCopyEffect extends OneShotEffect { if (sourcePermanent == null || copyFromPermanent == null) { return false; } - game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyCopyApplier()); return true; } } diff --git a/Mage.Sets/src/mage/cards/o/OneWithTheStars.java b/Mage.Sets/src/mage/cards/o/OneWithTheStars.java index 3388b4c1322..9b145c93d3c 100644 --- a/Mage.Sets/src/mage/cards/o/OneWithTheStars.java +++ b/Mage.Sets/src/mage/cards/o/OneWithTheStars.java @@ -87,8 +87,8 @@ class OneWithTheStarsEffect extends ContinuousEffectImpl { if (permanent == null) { return false; } - permanent.setIsAllCreatureTypes(false); - permanent.getSubtype(game).retainAll(SubType.getEnchantmentTypes()); + permanent.setIsAllCreatureTypes(game, false); + permanent.retainAllEnchantmentSubTypes(game); permanent.getCardType().clear(); permanent.addCardType(CardType.ENCHANTMENT); return true; diff --git a/Mage.Sets/src/mage/cards/o/OrvarTheAllForm.java b/Mage.Sets/src/mage/cards/o/OrvarTheAllForm.java index d5b087f42c2..c4c1467081c 100644 --- a/Mage.Sets/src/mage/cards/o/OrvarTheAllForm.java +++ b/Mage.Sets/src/mage/cards/o/OrvarTheAllForm.java @@ -50,8 +50,7 @@ public final class OrvarTheAllForm extends CardImpl { this.toughness = new MageInt(3); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Whenever you cast an instant or sorcery spell, if it targets one or more other permanents you control, create a token that's a copy of one of those permanents. this.addAbility(new ConditionalInterveningIfTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/p/PathOfAncestry.java b/Mage.Sets/src/mage/cards/p/PathOfAncestry.java index ebf879d05a8..651eec27710 100644 --- a/Mage.Sets/src/mage/cards/p/PathOfAncestry.java +++ b/Mage.Sets/src/mage/cards/p/PathOfAncestry.java @@ -98,7 +98,7 @@ class PathOfAncestryTriggeredAbility extends DelayedTriggeredAbility { if (commander == null) { continue; } - if (spell.getCard().shareCreatureTypes(commander, game)) { + if (spell.getCard().shareCreatureTypes(game, commander)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/p/PermeatingMass.java b/Mage.Sets/src/mage/cards/p/PermeatingMass.java index 3a08fd59e45..297215e9449 100644 --- a/Mage.Sets/src/mage/cards/p/PermeatingMass.java +++ b/Mage.Sets/src/mage/cards/p/PermeatingMass.java @@ -13,7 +13,7 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -63,7 +63,7 @@ class PermeatingMassEffect extends OneShotEffect { if (copyTo != null) { Permanent copyFrom = ability.getSourcePermanentOrLKI(game); if (copyFrom != null) { - game.copyPermanent(Duration.Custom, copyFrom, copyTo.getId(), ability, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.Custom, copyFrom, copyTo.getId(), ability, new EmptyCopyApplier()); } } return true; diff --git a/Mage.Sets/src/mage/cards/p/PhantasmalImage.java b/Mage.Sets/src/mage/cards/p/PhantasmalImage.java index de0d842757c..e345bb0fa82 100644 --- a/Mage.Sets/src/mage/cards/p/PhantasmalImage.java +++ b/Mage.Sets/src/mage/cards/p/PhantasmalImage.java @@ -15,8 +15,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -27,22 +26,12 @@ public final class PhantasmalImage extends CardImpl { private static final String effectText = "a copy of any creature on the battlefield, except it's an Illusion in addition to its other types and it has \"When this creature becomes the target of a spell or ability, sacrifice it.\""; - private static final ApplyToPermanent phantasmalImageApplier = new ApplyToPermanent() { + private static final CopyApplier phantasmalImageApplier = new CopyApplier() { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.addSubType(game, SubType.ILLUSION); + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { // Add directly because the created permanent is only used to copy from, so there is no need to add the ability to e.g. TriggeredAbilities - permanent.getAbilities().add(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect())); - //permanent.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect()), game); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.addSubType(game, SubType.ILLUSION); - // Add directly because the created permanent is only used to copy from, so there is no need to add the ability to e.g. TriggeredAbilities - mageObject.getAbilities().add(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect())); - //permanent.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect()), game); + blueprint.addSubType(SubType.ILLUSION); + blueprint.getAbilities().add(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect())); return true; } }; diff --git a/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java b/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java index 17bfef4703c..4e5cb81af1f 100644 --- a/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java +++ b/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java @@ -99,7 +99,7 @@ public final class PhantasmalTerrain extends CardImpl { if (land == null) { return false; } - land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); land.addSubType(game, choice); land.removeAllAbilities(source.getSourceId(), game); switch (choice) { diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianMetamorph.java b/Mage.Sets/src/mage/cards/p/PhyrexianMetamorph.java index ddf5f6177bd..d9cbef4658a 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianMetamorph.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianMetamorph.java @@ -17,8 +17,7 @@ import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; /** * @@ -41,25 +40,19 @@ public final class PhyrexianMetamorph extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(0); - ApplyToPermanent phyrexianMetamorphApplier = new ApplyToPermanent() { + CopyApplier phyrexianMetamorphCopyApplier = new CopyApplier() { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - return apply(game, (MageObject) permanent, source, copyToObjectId); - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - if (!mageObject.isArtifact()) { - mageObject.addCardType(CardType.ARTIFACT); + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + if (!blueprint.isArtifact()) { + blueprint.addCardType(CardType.ARTIFACT); } return true; } - }; // {U/P} ( can be paid with either {U} or 2 life.) // You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types. - Effect effect = new CopyPermanentEffect(filter, phyrexianMetamorphApplier); + Effect effect = new CopyPermanentEffect(filter, phyrexianMetamorphCopyApplier); effect.setText("You may have {this} enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types"); Ability ability = new SimpleStaticAbility(Zone.ALL, new EntersBattlefieldEffect(effect, "", true)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/p/PolymorphousRush.java b/Mage.Sets/src/mage/cards/p/PolymorphousRush.java index db694d8431b..a6b6b2a5e3e 100644 --- a/Mage.Sets/src/mage/cards/p/PolymorphousRush.java +++ b/Mage.Sets/src/mage/cards/p/PolymorphousRush.java @@ -15,7 +15,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; import java.util.UUID; @@ -75,7 +75,7 @@ class PolymorphousRushCopyEffect extends OneShotEffect { for (UUID copyToId : getTargetPointer().getTargets(game, source)) { Permanent copyToCreature = game.getPermanent(copyToId); if (copyToCreature != null) { - game.copyPermanent(Duration.EndOfTurn, copyFromCreature, copyToId, source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, copyFromCreature, copyToId, source, new EmptyCopyApplier()); } } } diff --git a/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java b/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java index 2de51e27b9d..0386ab3b477 100644 --- a/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java +++ b/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java @@ -18,7 +18,7 @@ import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.TokenPredicate; -import mage.util.functions.AbilityApplier; +import mage.util.functions.AbilityCopyApplier; /** * @@ -45,7 +45,7 @@ public final class ProgenitorMimic extends CardImpl { Effect effect = new CreateTokenCopySourceEffect(); effect.setText("create a token that's a copy of this creature"); - AbilityApplier applier = new AbilityApplier( + AbilityCopyApplier applier = new AbilityCopyApplier( new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, false), new SourceMatchesFilterCondition(filter), diff --git a/Mage.Sets/src/mage/cards/p/ProteanThaumaturge.java b/Mage.Sets/src/mage/cards/p/ProteanThaumaturge.java index 241e3f937dc..1439abb2c3f 100644 --- a/Mage.Sets/src/mage/cards/p/ProteanThaumaturge.java +++ b/Mage.Sets/src/mage/cards/p/ProteanThaumaturge.java @@ -16,7 +16,7 @@ import mage.filter.predicate.permanent.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -55,24 +55,18 @@ public final class ProteanThaumaturge extends CardImpl { static Ability createAbility() { Ability ability = new ConstellationAbility(new CopyPermanentEffect( StaticFilters.FILTER_PERMANENT_CREATURE, - new ProteanThaumaturgeApplyToPermanent(), true + new ProteanThaumaturgeCopyApplier(), true ).setText("{this} become a copy of another target creature, except it has this ability"), true, false); ability.addTarget(new TargetPermanent(filter)); return ability; } } -class ProteanThaumaturgeApplyToPermanent extends ApplyToPermanent { +class ProteanThaumaturgeCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.getAbilities().add(ProteanThaumaturge.createAbility()); - return true; - } - - @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.addAbility(ProteanThaumaturge.createAbility(), source.getSourceId(), game); + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.getAbilities().add(ProteanThaumaturge.createAbility()); return true; } } diff --git a/Mage.Sets/src/mage/cards/p/PyreOfHeroes.java b/Mage.Sets/src/mage/cards/p/PyreOfHeroes.java index 1005785eca0..5af2ccc2c0e 100644 --- a/Mage.Sets/src/mage/cards/p/PyreOfHeroes.java +++ b/Mage.Sets/src/mage/cards/p/PyreOfHeroes.java @@ -1,8 +1,5 @@ package mage.cards.p; -import java.util.UUID; - -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.costs.Cost; @@ -19,16 +16,17 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.StaticFilters; -import mage.filter.predicate.Predicate; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.filter.predicate.permanent.SharesCreatureTypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class PyreOfHeroes extends CardImpl { @@ -91,7 +89,7 @@ class PyreOfHeroesEffect extends OneShotEffect { FilterCard filter = new FilterCard("creature card with converted mana cost " + newConvertedCost); filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, newConvertedCost)); filter.add(CardType.CREATURE.getPredicate()); - filter.add(new PyreOfHeroesPredicate(sacrificedPermanent)); + filter.add(new SharesCreatureTypePredicate(sacrificedPermanent)); TargetCardInLibrary target = new TargetCardInLibrary(filter); if (controller.searchLibrary(target, source, game)) { Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); @@ -106,22 +104,3 @@ class PyreOfHeroesEffect extends OneShotEffect { return new PyreOfHeroesEffect(this); } } - -class PyreOfHeroesPredicate implements Predicate { - - private final Permanent sacrificedPermanent; - - public PyreOfHeroesPredicate(Permanent sacrificedPermanent) { - this.sacrificedPermanent = sacrificedPermanent; - } - - @Override - public boolean apply(MageObject input, Game game) { - return input.shareCreatureTypes(sacrificedPermanent, game); - } - - @Override - public String toString() { - return "shares a creature type"; - } -} diff --git a/Mage.Sets/src/mage/cards/q/QuicksilverGargantuan.java b/Mage.Sets/src/mage/cards/q/QuicksilverGargantuan.java index e925ecda970..eee2d279333 100644 --- a/Mage.Sets/src/mage/cards/q/QuicksilverGargantuan.java +++ b/Mage.Sets/src/mage/cards/q/QuicksilverGargantuan.java @@ -13,7 +13,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; /** * @author ayratn @@ -27,7 +27,7 @@ public final class QuicksilverGargantuan extends CardImpl { this.power = new MageInt(7); this.toughness = new MageInt(7); - Ability ability = new EntersBattlefieldAbility(new CopyPermanentEffect(new QuicksilverGargantuanApplyToPermanent()), + Ability ability = new EntersBattlefieldAbility(new CopyPermanentEffect(new QuicksilverGargantuanCopyApplier()), "You may have {this} enter the battlefield as a copy of any creature on the battlefield, except it's 7/7"); this.addAbility(ability); } @@ -42,22 +42,13 @@ public final class QuicksilverGargantuan extends CardImpl { } } -class QuicksilverGargantuanApplyToPermanent extends ApplyToPermanent { +class QuicksilverGargantuanCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.removePTCDA(); - permanent.getPower().modifyBaseValue(7); - permanent.getToughness().modifyBaseValue(7); + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.removePTCDA(); + blueprint.getPower().modifyBaseValue(7); + blueprint.getToughness().modifyBaseValue(7); return true; } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.removePTCDA(); - mageObject.getPower().modifyBaseValue(7); - mageObject.getToughness().modifyBaseValue(7); - return true; - } - } diff --git a/Mage.Sets/src/mage/cards/r/RaiseTheDraugr.java b/Mage.Sets/src/mage/cards/r/RaiseTheDraugr.java index f3a608a89e0..820a24f20d8 100644 --- a/Mage.Sets/src/mage/cards/r/RaiseTheDraugr.java +++ b/Mage.Sets/src/mage/cards/r/RaiseTheDraugr.java @@ -70,7 +70,7 @@ class RaiseTheDraugrTarget extends TargetCardInYourGraveyard { if (targetOne == null || targetTwo == null) { return false; } - return targetOne.shareCreatureTypes(targetTwo, game); + return targetOne.shareCreatureTypes(game, targetTwo); } @Override @@ -94,7 +94,7 @@ class RaiseTheDraugrTarget extends TargetCardInYourGraveyard { if (i <= j) { continue; } - if (cards.get(i).shareCreatureTypes(cards.get(j), game)) { + if (cards.get(i).shareCreatureTypes(game, cards.get(j))) { return true; } } diff --git a/Mage.Sets/src/mage/cards/r/Realmwalker.java b/Mage.Sets/src/mage/cards/r/Realmwalker.java index a46efad7702..b08dc1ac26d 100644 --- a/Mage.Sets/src/mage/cards/r/Realmwalker.java +++ b/Mage.Sets/src/mage/cards/r/Realmwalker.java @@ -35,8 +35,7 @@ public final class Realmwalker extends CardImpl { this.toughness = new MageInt(3); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // As Realmwalker enters the battlefield, choose a creature type. this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.Benefit))); diff --git a/Mage.Sets/src/mage/cards/r/ReinsOfTheVinesteed.java b/Mage.Sets/src/mage/cards/r/ReinsOfTheVinesteed.java index 2ba74f15aad..b90b97ec049 100644 --- a/Mage.Sets/src/mage/cards/r/ReinsOfTheVinesteed.java +++ b/Mage.Sets/src/mage/cards/r/ReinsOfTheVinesteed.java @@ -1,6 +1,5 @@ package mage.cards.r; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.DiesAttachedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -12,17 +11,15 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicate; -import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.SharesCreatureTypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; /** @@ -81,16 +78,10 @@ class ReinsOfTheVinesteedEffect extends OneShotEffect { if (lastStateCreature == null) { return false; } - FilterCreaturePermanent FILTER = new FilterCreaturePermanent(); - StringBuilder sb = new StringBuilder("creature that shares a creature type with the formerly attached creature: "); - List> subtypes = new ArrayList<>(); - for (SubType subtype : lastStateCreature.getSubtype(game)) { - subtypes.add(subtype.getPredicate()); - sb.append(subtype).append(", "); - } - FILTER.add(Predicates.or(subtypes)); - sb.delete(sb.length() - 2, sb.length()); - FILTER.setMessage(sb.toString()); + FilterPermanent FILTER = new FilterCreaturePermanent( + "creature that shares a creature type with " + lastStateCreature.getName() + ); + FILTER.add(new SharesCreatureTypePredicate(lastStateCreature)); TargetPermanent target = new TargetPermanent(FILTER); target.setNotTarget(true); if (controller != null diff --git a/Mage.Sets/src/mage/cards/r/RenegadeDoppelganger.java b/Mage.Sets/src/mage/cards/r/RenegadeDoppelganger.java index 288443705a0..b2c981cc284 100644 --- a/Mage.Sets/src/mage/cards/r/RenegadeDoppelganger.java +++ b/Mage.Sets/src/mage/cards/r/RenegadeDoppelganger.java @@ -15,10 +15,9 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -111,7 +110,7 @@ class RenegadeDoppelgangerEffect extends OneShotEffect { return false; } - game.copyPermanent(Duration.EndOfTurn, targetCreature, permanent.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, targetCreature, permanent.getId(), source, new EmptyCopyApplier()); return false; } } diff --git a/Mage.Sets/src/mage/cards/r/ResplendentMarshal.java b/Mage.Sets/src/mage/cards/r/ResplendentMarshal.java index e5eab14ae54..c8e5d0cd192 100644 --- a/Mage.Sets/src/mage/cards/r/ResplendentMarshal.java +++ b/Mage.Sets/src/mage/cards/r/ResplendentMarshal.java @@ -94,7 +94,7 @@ class ResplendentMarshalEffect extends OneShotEffect { if (controller != null && sourceObject != null && exiledCard != null) { for (Permanent permanent : game.getBattlefield().getActivePermanents( StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE, source.getControllerId(), source.getSourceId(), game)) { - if (permanent.shareCreatureTypes(exiledCard, game)) { + if (permanent.shareCreatureTypes(game, exiledCard)) { permanent.addCounters(CounterType.P1P1.createInstance(), source, game); if (!game.isSimulation()) { game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() diff --git a/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java b/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java index fb8fd6ae0ce..a3c6df6c64a 100644 --- a/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java +++ b/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java @@ -70,7 +70,7 @@ class ReturnFromExtinctionTarget extends TargetCardInYourGraveyard { if (targetOne == null || targetTwo == null) { return false; } - return targetOne.shareCreatureTypes(targetTwo, game); + return targetOne.shareCreatureTypes(game, targetTwo); } @Override @@ -94,7 +94,7 @@ class ReturnFromExtinctionTarget extends TargetCardInYourGraveyard { if (i <= j) { continue; } - if (cards.get(i).shareCreatureTypes(cards.get(j), game)) { + if (cards.get(i).shareCreatureTypes(game, cards.get(j))) { return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SaheeliSublimeArtificer.java b/Mage.Sets/src/mage/cards/s/SaheeliSublimeArtificer.java index 34ea37a1612..fea2ab95b1d 100644 --- a/Mage.Sets/src/mage/cards/s/SaheeliSublimeArtificer.java +++ b/Mage.Sets/src/mage/cards/s/SaheeliSublimeArtificer.java @@ -24,7 +24,7 @@ import mage.game.permanent.token.ServoToken; import mage.target.Target; import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @author TheElk801 @@ -101,7 +101,7 @@ class SaheeliSublimeArtificerEffect extends OneShotEffect { if (copyTo != null) { Permanent copyFrom = game.getPermanentOrLKIBattlefield(source.getTargets().get(1).getFirstTarget()); if (copyFrom != null) { - game.copyPermanent(Duration.EndOfTurn, copyFrom, copyTo.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, copyFrom, copyTo.getId(), source, new EmptyCopyApplier()); ContinuousEffect effect = new AddCardTypeTargetEffect(Duration.EndOfTurn, CardType.ARTIFACT); effect.setTargetPointer(new FixedTarget(copyTo, game)); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/cards/s/SakashimaOfAThousandFaces.java b/Mage.Sets/src/mage/cards/s/SakashimaOfAThousandFaces.java index f07d8ad6efc..5dec8b7ed40 100644 --- a/Mage.Sets/src/mage/cards/s/SakashimaOfAThousandFaces.java +++ b/Mage.Sets/src/mage/cards/s/SakashimaOfAThousandFaces.java @@ -15,7 +15,7 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -35,7 +35,7 @@ public final class SakashimaOfAThousandFaces extends CardImpl { // You may have Sakashima of a Thousand Faces enter the battlefield as a copy of another creature you control, except it has Sakashima of a Thousand Faces's other abilities. this.addAbility(new EntersBattlefieldAbility(new CopyPermanentEffect( - StaticFilters.FILTER_CONTROLLED_A_CREATURE, new SakashimaOfAThousandFacesApplier() + StaticFilters.FILTER_CONTROLLED_A_CREATURE, new SakashimaOfAThousandFacesCopyApplier() ).setText("as a copy of another creature you control, except it has {this}'s other abilities"), true)); // The "legend rule" doesn't apply to permanents you control. @@ -55,19 +55,12 @@ public final class SakashimaOfAThousandFaces extends CardImpl { } } -class SakashimaOfAThousandFacesApplier extends ApplyToPermanent { +class SakashimaOfAThousandFacesCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID targetObjectId) { - permanent.addAbility(new SimpleStaticAbility(new SakashimaOfAThousandFacesEffect()), source.getSourceId(), game); - permanent.addAbility(PartnerAbility.getInstance(), source.getSourceId(), game); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID targetObjectId) { - mageObject.getAbilities().add(new SimpleStaticAbility(new SakashimaOfAThousandFacesEffect())); - mageObject.getAbilities().add(PartnerAbility.getInstance()); + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.getAbilities().add(new SimpleStaticAbility(new SakashimaOfAThousandFacesEffect())); + blueprint.getAbilities().add(PartnerAbility.getInstance()); return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java b/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java index a0e23f4e3db..c06ed0bc159 100644 --- a/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java +++ b/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java @@ -21,8 +21,7 @@ import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; /** * @author LevelX2 @@ -38,7 +37,7 @@ public final class SakashimaTheImpostor extends CardImpl { this.toughness = new MageInt(1); // You may have Sakashima the Impostor enter the battlefield as a copy of any creature on the battlefield, except its name is Sakashima the Impostor, it's legendary in addition to its other types, and it has "{2}{U}{U}: Return Sakashima the Impostor to its owner's hand at the beginning of the next end step." - Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new SakashimaTheImpostorApplier()); + Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new SakashimaTheImpostorCopyApplier()); effect.setText("as a copy of any creature on the battlefield, except its name is Sakashima the Impostor, it's legendary in addition to its other types, and it has \"{2}{U}{U}: Return {this} to its owner's hand at the beginning of the next end step.\""); this.addAbility(new EntersBattlefieldAbility(effect, true)); } @@ -53,27 +52,14 @@ public final class SakashimaTheImpostor extends CardImpl { } } -class SakashimaTheImpostorApplier extends ApplyToPermanent { +class SakashimaTheImpostorCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.addSuperType(SuperType.LEGENDARY); - - permanent.setName("Sakashima the Impostor"); + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.addSuperType(SuperType.LEGENDARY); + blueprint.setName("Sakashima the Impostor"); // {2}{U}{U}: Return Sakashima the Impostor to its owner's hand at the beginning of the next end step - permanent.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, - new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnToHandSourceEffect(true)), false), - new ManaCostsImpl("{2}{U}{U}") - ), source.getSourceId(), game); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.addSuperType(SuperType.LEGENDARY); - mageObject.setName("Sakashima the Impostor"); - // {2}{U}{U}: Return Sakashima the Impostor to its owner's hand at the beginning of the next end step - mageObject.getAbilities().add(new SimpleActivatedAbility(Zone.BATTLEFIELD, + blueprint.getAbilities().add(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnToHandSourceEffect(true)), false), new ManaCostsImpl("{2}{U}{U}") )); diff --git a/Mage.Sets/src/mage/cards/s/SakashimasStudent.java b/Mage.Sets/src/mage/cards/s/SakashimasStudent.java index f833505c69a..586e80b1485 100644 --- a/Mage.Sets/src/mage/cards/s/SakashimasStudent.java +++ b/Mage.Sets/src/mage/cards/s/SakashimasStudent.java @@ -13,7 +13,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.util.functions.AddSubtypeApplier; +import mage.util.functions.AddSubtypeCopyApplier; /** * @@ -33,7 +33,7 @@ public final class SakashimasStudent extends CardImpl { this.addAbility(new NinjutsuAbility(new ManaCostsImpl("{1}{U}"))); // You may have Sakashima's Student enter the battlefield as a copy of any creature on the battlefield, except it's still a Ninja in addition to its other creature types. - Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new AddSubtypeApplier(SubType.NINJA)); + Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new AddSubtypeCopyApplier(SubType.NINJA)); effect.setText("as a copy of any creature on the battlefield, except it's a Ninja in addition to its other creature types"); this.addAbility(new EntersBattlefieldAbility(effect, true)); diff --git a/Mage.Sets/src/mage/cards/s/SakashimasWill.java b/Mage.Sets/src/mage/cards/s/SakashimasWill.java index 1464c12b55c..5edb0fee416 100644 --- a/Mage.Sets/src/mage/cards/s/SakashimasWill.java +++ b/Mage.Sets/src/mage/cards/s/SakashimasWill.java @@ -18,7 +18,7 @@ import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetOpponent; import mage.target.targetpointer.FixedTarget; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; import java.util.UUID; @@ -132,7 +132,7 @@ class SakashimasWillCopyEffect extends OneShotEffect { continue; } game.copyPermanent( - Duration.EndOfTurn, chosenCreature, permanent.getId(), source, new EmptyApplyToPermanent() + Duration.EndOfTurn, chosenCreature, permanent.getId(), source, new EmptyCopyApplier() ); } return true; diff --git a/Mage.Sets/src/mage/cards/s/ShadesBreath.java b/Mage.Sets/src/mage/cards/s/ShadesBreath.java index f1f8aa659ec..04222312869 100644 --- a/Mage.Sets/src/mage/cards/s/ShadesBreath.java +++ b/Mage.Sets/src/mage/cards/s/ShadesBreath.java @@ -13,7 +13,6 @@ import mage.constants.*; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.SubTypeList; import java.util.List; import java.util.UUID; @@ -79,26 +78,26 @@ class ShadesBreathSetColorEffect extends ContinuousEffectImpl { class ShadesBreathSetSubtypeEffect extends ContinuousEffectImpl { - public ShadesBreathSetSubtypeEffect() { + ShadesBreathSetSubtypeEffect() { super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); staticText = "Shade"; } - public ShadesBreathSetSubtypeEffect(final ShadesBreathSetSubtypeEffect effect) { + private ShadesBreathSetSubtypeEffect(final ShadesBreathSetSubtypeEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { - List permanents = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game); + List permanents = game.getBattlefield().getAllActivePermanents( + StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game + ); for (Permanent permanent : permanents) { - if (permanent != null) { - SubTypeList subtype = permanent.getSubtype(game); - if (subtype != null && (subtype.size() != 1 || !subtype.contains(SubType.SHADE))) { - subtype.clear(); - subtype.add(SubType.SHADE); - } + if (permanent == null) { + continue; } + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.SHADE); } return true; } diff --git a/Mage.Sets/src/mage/cards/s/Shapesharer.java b/Mage.Sets/src/mage/cards/s/Shapesharer.java index 5c0c7674c33..f1a59503fee 100644 --- a/Mage.Sets/src/mage/cards/s/Shapesharer.java +++ b/Mage.Sets/src/mage/cards/s/Shapesharer.java @@ -16,7 +16,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @author duncant @@ -35,8 +35,7 @@ public final class Shapesharer extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // {2}{U}: Target Shapeshifter becomes a copy of target creature until your next turn. Ability copyAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, @@ -79,7 +78,7 @@ class ShapesharerEffect extends OneShotEffect { if (copyTo != null) { Permanent copyFrom = game.getPermanentOrLKIBattlefield(ability.getTargets().get(1).getFirstTarget()); if (copyFrom != null) { - game.copyPermanent(Duration.UntilYourNextTurn, copyFrom, copyTo.getId(), ability, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.UntilYourNextTurn, copyFrom, copyTo.getId(), ability, new EmptyCopyApplier()); } } return true; diff --git a/Mage.Sets/src/mage/cards/s/SharedAnimosity.java b/Mage.Sets/src/mage/cards/s/SharedAnimosity.java index f15580f1e82..02ef62d6fe9 100644 --- a/Mage.Sets/src/mage/cards/s/SharedAnimosity.java +++ b/Mage.Sets/src/mage/cards/s/SharedAnimosity.java @@ -4,15 +4,14 @@ import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AttackingPredicate; import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.filter.predicate.permanent.SharesCreatureTypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -69,7 +68,7 @@ class SharedAnimosityEffect extends ContinuousEffectImpl { FilterCreaturePermanent filter = new FilterCreaturePermanent(); filter.add(Predicates.not(new PermanentIdPredicate(this.targetPointer.getFirst(game, source)))); filter.add(AttackingPredicate.instance); - filter.add(new SharedAnimosityPredicate(permanent)); + filter.add(new SharesCreatureTypePredicate(permanent)); power = game.getBattlefield().count(filter, source.getControllerId(), source.getSourceId(), game); } } @@ -89,17 +88,3 @@ class SharedAnimosityEffect extends ContinuousEffectImpl { return "it gets +1/+0 until end of turn for each other attacking creature that shares a creature type with it"; } } - -class SharedAnimosityPredicate implements Predicate { - - private final Permanent permanent; - - SharedAnimosityPredicate(Permanent permanent) { - this.permanent = permanent; - } - - @Override - public boolean apply(Card input, Game game) { - return permanent != null && input != null && permanent.shareCreatureTypes(input, game); - } -} diff --git a/Mage.Sets/src/mage/cards/s/ShieldsOfVelisVel.java b/Mage.Sets/src/mage/cards/s/ShieldsOfVelisVel.java index a276ced613d..ac3185e5739 100644 --- a/Mage.Sets/src/mage/cards/s/ShieldsOfVelisVel.java +++ b/Mage.Sets/src/mage/cards/s/ShieldsOfVelisVel.java @@ -27,8 +27,7 @@ public final class ShieldsOfVelisVel extends CardImpl { this.subtype.add(SubType.SHAPESHIFTER); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); //Creatures target player controls get +0/+1 and gain all creature types until end of turn. this.getSpellAbility().addEffect(new ShieldsOfVelisVelBoostEffect()); @@ -79,7 +78,7 @@ class ShieldsOfVelisVelGainEffect extends ContinuousEffectImpl { for (Iterator it = affectedObjectList.iterator(); it.hasNext();) { Permanent permanent = it.next().getPermanent(game); if (permanent != null) { - permanent.setIsAllCreatureTypes(true); + permanent.setIsAllCreatureTypes(game, true); } else { it.remove(); } diff --git a/Mage.Sets/src/mage/cards/s/SkeletalChangeling.java b/Mage.Sets/src/mage/cards/s/SkeletalChangeling.java index faf91cad887..ca42fb5531a 100644 --- a/Mage.Sets/src/mage/cards/s/SkeletalChangeling.java +++ b/Mage.Sets/src/mage/cards/s/SkeletalChangeling.java @@ -26,8 +26,7 @@ public final class SkeletalChangeling extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // {1}{B}: Regenerate Skeletal Changeling. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{1}{B}"))); } diff --git a/Mage.Sets/src/mage/cards/s/SoulSculptor.java b/Mage.Sets/src/mage/cards/s/SoulSculptor.java index aba2a78b39b..74fcb1f62a2 100644 --- a/Mage.Sets/src/mage/cards/s/SoulSculptor.java +++ b/Mage.Sets/src/mage/cards/s/SoulSculptor.java @@ -89,7 +89,7 @@ class SoulSculptorEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: permanent.getCardType().clear(); - permanent.getSubtype(game).retainAll(SubType.getEnchantmentTypes()); + permanent.retainAllEnchantmentSubTypes(game); permanent.getCardType().add(CardType.ENCHANTMENT); break; case AbilityAddingRemovingEffects_6: diff --git a/Mage.Sets/src/mage/cards/s/SparkDouble.java b/Mage.Sets/src/mage/cards/s/SparkDouble.java index 76447680ebc..70ff4b2f6ea 100644 --- a/Mage.Sets/src/mage/cards/s/SparkDouble.java +++ b/Mage.Sets/src/mage/cards/s/SparkDouble.java @@ -17,8 +17,7 @@ import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -44,7 +43,7 @@ public final class SparkDouble extends CardImpl { // You may have Spark Double enter the battlefield as a copy of a creature or planeswalker you control, // except it enters with an additional +1/+1 counter on it if it’s a creature, // it enters with an additional loyalty counter on it if it’s a planeswalker, and it isn’t legendary if that permanent is legendary. - Effect effect = new CopyPermanentEffect(filter, new SparkDoubleExceptEffectsApplyerToPermanent()); + Effect effect = new CopyPermanentEffect(filter, new SparkDoubleExceptEffectsCopyApplier()); effect.setText("as a copy of a creature or planeswalker you control, " + "except it enters with an additional +1/+1 counter on it if it's a creature, " + "it enters with an additional loyalty counter on it if it's a planeswalker, and it isn't legendary if that permanent is legendary."); @@ -62,15 +61,10 @@ public final class SparkDouble extends CardImpl { } } -class SparkDoubleExceptEffectsApplyerToPermanent extends ApplyToPermanent { +class SparkDoubleExceptEffectsCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent copyFromBlueprint, Ability source, UUID copyToObjectId) { - return apply(game, (MageObject) copyFromBlueprint, source, copyToObjectId); - } - - @Override - public boolean apply(Game game, MageObject copyFromBlueprint, Ability source, UUID copyToObjectId) { + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { // copyToObjectId can be new token outside from game, don't use it // it isn’t legendary if that permanent is legendary @@ -81,7 +75,7 @@ class SparkDoubleExceptEffectsApplyerToPermanent extends ApplyToPermanent { // (2019-05-03) // // So, it's must make changes in blueprint (for farther copyable) - copyFromBlueprint.getSuperType().remove(SuperType.LEGENDARY); + blueprint.getSuperType().remove(SuperType.LEGENDARY); // TODO: Blood Moon problem, can't apply on type changing effects (same as TeferisTimeTwist) // see https://magic.wizards.com/en/articles/archive/feature/war-spark-release-notes-2019-04-19 @@ -96,13 +90,19 @@ class SparkDoubleExceptEffectsApplyerToPermanent extends ApplyToPermanent { // counters only for original card, not copies if (!isCopyOfCopy(source, copyToObjectId)) { // enters with an additional +1/+1 counter on it if it’s a creature - if (copyFromBlueprint.isCreature()) { - new AddCountersSourceEffect(CounterType.P1P1.createInstance(), false).apply(game, source); + if (blueprint.isCreature()) { + blueprint.getAbilities().add(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(), false) + .setText("with an additional +1/+1 counter on it") + )); } // enters with an additional loyalty counter on it if it’s a planeswalker - if (copyFromBlueprint.isPlaneswalker()) { - new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(), false).apply(game, source); + if (blueprint.isPlaneswalker()) { + blueprint.getAbilities().add(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(), false) + .setText("with an additional loyalty counter on it") + )); } } diff --git a/Mage.Sets/src/mage/cards/s/Standardize.java b/Mage.Sets/src/mage/cards/s/Standardize.java index ffed5686509..8061cd1e243 100644 --- a/Mage.Sets/src/mage/cards/s/Standardize.java +++ b/Mage.Sets/src/mage/cards/s/Standardize.java @@ -16,8 +16,8 @@ import mage.constants.SubType; import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; -import mage.util.SubTypeList; +import java.util.Arrays; import java.util.UUID; /** @@ -71,7 +71,7 @@ class StandardizeEffect extends OneShotEffect { if (chosenType != null && !chosenType.isEmpty()) { // ADD TYPE TO TARGET game.addEffect(new BecomesSubtypeAllEffect( - Duration.EndOfTurn, new SubTypeList(SubType.byDescription(chosenType)), + Duration.EndOfTurn, Arrays.asList(SubType.byDescription(chosenType)), StaticFilters.FILTER_PERMANENT_CREATURE, true ), source); return true; diff --git a/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java b/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java index 9e0df8ed14c..8ac020fdeab 100644 --- a/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java +++ b/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java @@ -118,7 +118,7 @@ public final class StarfieldOfNyx extends CardImpl { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { if (!permanent.isCreature() - && !permanent.getSubtype(game).contains(SubType.AURA)) { + && !permanent.hasSubtype(SubType.AURA, game)) { permanent.addCardType(CardType.CREATURE); } } @@ -127,7 +127,7 @@ public final class StarfieldOfNyx extends CardImpl { case PTChangingEffects_7: if (sublayer == SubLayer.SetPT_7b && permanent.isCreature() - && !permanent.getSubtype(game).contains(SubType.AURA)) { + && !permanent.hasSubtype(SubType.AURA, game)) { int manaCost = permanent.getConvertedManaCost(); permanent.getPower().setValue(manaCost); permanent.getToughness().setValue(manaCost); diff --git a/Mage.Sets/src/mage/cards/s/StoneforgeMasterwork.java b/Mage.Sets/src/mage/cards/s/StoneforgeMasterwork.java index 42a0e66a2b8..ffd4453e469 100644 --- a/Mage.Sets/src/mage/cards/s/StoneforgeMasterwork.java +++ b/Mage.Sets/src/mage/cards/s/StoneforgeMasterwork.java @@ -59,7 +59,7 @@ class StoneforgeMasterworkDynamicValue implements DynamicValue { if (equipped != null) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, sourceAbility.getControllerId(), game)) { if (!permanent.getId().equals(equipped.getId())) { - if (equipped.shareCreatureTypes(permanent, game)) { + if (equipped.shareCreatureTypes(game, permanent)) { xValue++; } } diff --git a/Mage.Sets/src/mage/cards/t/TajuruParagon.java b/Mage.Sets/src/mage/cards/t/TajuruParagon.java index ce3403808d1..b0f32651495 100644 --- a/Mage.Sets/src/mage/cards/t/TajuruParagon.java +++ b/Mage.Sets/src/mage/cards/t/TajuruParagon.java @@ -15,7 +15,7 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterCard; -import mage.filter.predicate.Predicate; +import mage.filter.predicate.permanent.SharesCreatureTypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -89,7 +89,7 @@ class TajuruParagonEffect extends OneShotEffect { Permanent permanent = source.getSourcePermanentOrLKI(game); if (permanent != null) { FilterCard filter = new FilterCard("card that shares a creature type with " + permanent.getName()); - filter.add(new TajuruParagonPredicate(permanent)); + filter.add(new SharesCreatureTypePredicate(permanent)); TargetCard target = new TargetCardInLibrary(0, 1, filter); player.choose(outcome, cards, target, game); Card card = game.getCard(target.getFirstTarget()); @@ -102,17 +102,3 @@ class TajuruParagonEffect extends OneShotEffect { return true; } } - -class TajuruParagonPredicate implements Predicate { - - private final Permanent permanent; - - TajuruParagonPredicate(Permanent permanent) { - this.permanent = permanent; - } - - @Override - public boolean apply(Card input, Game game) { - return permanent != null && input != null && permanent.shareCreatureTypes(input, game); - } -} diff --git a/Mage.Sets/src/mage/cards/t/TaureanMauler.java b/Mage.Sets/src/mage/cards/t/TaureanMauler.java index 086ebda27dc..353a8d15d02 100644 --- a/Mage.Sets/src/mage/cards/t/TaureanMauler.java +++ b/Mage.Sets/src/mage/cards/t/TaureanMauler.java @@ -26,8 +26,7 @@ public final class TaureanMauler extends CardImpl { this.toughness = new MageInt(2); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Whenever an opponent casts a spell, you may put a +1/+1 counter on Taurean Mauler. this.addAbility(new SpellCastOpponentTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), true)); diff --git a/Mage.Sets/src/mage/cards/t/Terraformer.java b/Mage.Sets/src/mage/cards/t/Terraformer.java index 9066a84f0d0..b518304606b 100644 --- a/Mage.Sets/src/mage/cards/t/Terraformer.java +++ b/Mage.Sets/src/mage/cards/t/Terraformer.java @@ -138,7 +138,7 @@ class TerraformerContinuousEffect extends ContinuousEffectImpl { it.remove(); continue; } - land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); land.addSubType(game, choice); land.removeAllAbilities(source.getSourceId(), game); switch (choice) { diff --git a/Mage.Sets/src/mage/cards/t/ThespiansStage.java b/Mage.Sets/src/mage/cards/t/ThespiansStage.java index 5b9ca21040d..ba75ac140a6 100644 --- a/Mage.Sets/src/mage/cards/t/ThespiansStage.java +++ b/Mage.Sets/src/mage/cards/t/ThespiansStage.java @@ -16,7 +16,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetLandPermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -69,7 +69,7 @@ class ThespiansStageCopyEffect extends OneShotEffect { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (sourcePermanent != null && copyFromPermanent != null) { - Permanent newPermanent = game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent()); + Permanent newPermanent = game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new EmptyCopyApplier()); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThespiansStageCopyEffect(), new GenericManaCost(2)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetLandPermanent()); diff --git a/Mage.Sets/src/mage/cards/t/TilonallisSkinshifter.java b/Mage.Sets/src/mage/cards/t/TilonallisSkinshifter.java index b49c986e974..c1fdddb99bb 100644 --- a/Mage.Sets/src/mage/cards/t/TilonallisSkinshifter.java +++ b/Mage.Sets/src/mage/cards/t/TilonallisSkinshifter.java @@ -21,7 +21,7 @@ import mage.filter.predicate.permanent.AttackingPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -85,7 +85,7 @@ class TilonallisSkinshifterCopyEffect extends OneShotEffect { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (sourcePermanent != null && copyFromPermanent != null) { - game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent()); + game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyCopyApplier()); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/t/TurtleshellChangeling.java b/Mage.Sets/src/mage/cards/t/TurtleshellChangeling.java index 4571e67a6c5..0016d5138d8 100644 --- a/Mage.Sets/src/mage/cards/t/TurtleshellChangeling.java +++ b/Mage.Sets/src/mage/cards/t/TurtleshellChangeling.java @@ -28,8 +28,7 @@ public final class TurtleshellChangeling extends CardImpl { this.toughness = new MageInt(4); //Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); //{1}{U}: Switch {this}'s power and toughness until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new SwitchPowerToughnessSourceEffect(Duration.EndOfTurn), new ManaCostsImpl("{1}{U}"))); diff --git a/Mage.Sets/src/mage/cards/u/UniversalAutomaton.java b/Mage.Sets/src/mage/cards/u/UniversalAutomaton.java index 735b2f1e825..2bf76268ea0 100644 --- a/Mage.Sets/src/mage/cards/u/UniversalAutomaton.java +++ b/Mage.Sets/src/mage/cards/u/UniversalAutomaton.java @@ -22,8 +22,7 @@ public final class UniversalAutomaton extends CardImpl { this.toughness = new MageInt(1); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); } private UniversalAutomaton(final UniversalAutomaton card) { diff --git a/Mage.Sets/src/mage/cards/u/UnsettledMariner.java b/Mage.Sets/src/mage/cards/u/UnsettledMariner.java index d050604379c..9607ac42096 100644 --- a/Mage.Sets/src/mage/cards/u/UnsettledMariner.java +++ b/Mage.Sets/src/mage/cards/u/UnsettledMariner.java @@ -31,8 +31,7 @@ public final class UnsettledMariner extends CardImpl { this.toughness = new MageInt(2); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Whenever you or a permanent you control becomes the target of a spell or ability an opponent controls, counter that spell or ability unless its controller pays {1}. this.addAbility(new UnsettledMarinerTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java b/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java index 04e3696a361..9c200a7f091 100644 --- a/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java +++ b/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java @@ -19,7 +19,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.EmptyCopyApplier; /** * @@ -75,7 +75,7 @@ class UnstableShapeshifterEffect extends OneShotEffect { Permanent permanent = game.getPermanent(source.getSourceId()); Permanent targetCreature = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); if (targetCreature != null && permanent != null) { - Permanent blueprintPermanent = game.copyPermanent(Duration.Custom, targetCreature, permanent.getId(), source, new EmptyApplyToPermanent()); + Permanent blueprintPermanent = game.copyPermanent(Duration.Custom, targetCreature, permanent.getId(), source, new EmptyCopyApplier()); blueprintPermanent.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new UnstableShapeshifterEffect(), filterAnotherCreature, false, SetTargetPointer.PERMANENT, ""), source.getSourceId(), game); return true; diff --git a/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java b/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java index 986af634752..2be033b66f2 100644 --- a/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java +++ b/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java @@ -80,7 +80,7 @@ public final class UrborgTombOfYawgmoth extends CardImpl { // 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects // So the ability removing has to be done before Layer 6 // Lands have their mana ability intrinsically, so that is added in layer 4 - if (!land.getSubtype(game).contains(SubType.SWAMP)) { + if (!land.hasSubtype(SubType.SWAMP, game)) { land.addSubType(game, SubType.SWAMP); } if (!land.getAbilities().containsRule(new BlackManaAbility())) { diff --git a/Mage.Sets/src/mage/cards/v/ValiantChangeling.java b/Mage.Sets/src/mage/cards/v/ValiantChangeling.java index 5177f12e583..f9ae21df218 100644 --- a/Mage.Sets/src/mage/cards/v/ValiantChangeling.java +++ b/Mage.Sets/src/mage/cards/v/ValiantChangeling.java @@ -35,8 +35,7 @@ public final class ValiantChangeling extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.ALL, new ValiantChangelingCostReductionEffect())); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Double strike this.addAbility(DoubleStrikeAbility.getInstance()); @@ -71,8 +70,7 @@ class ValiantChangelingCostReductionEffect extends CostModificationEffectImpl { for (Permanent permanent : game.getBattlefield().getActivePermanents( StaticFilters.FILTER_CONTROLLED_CREATURE, source.getControllerId(), source.getSourceId(), game )) { - if (permanent.getAbilities().contains(ChangelingAbility.getInstance()) - || permanent.isAllCreatureTypes()) { + if (permanent.isAllCreatureTypes(game)) { reductionAmount = 5; break; } diff --git a/Mage.Sets/src/mage/cards/v/VenomousChangeling.java b/Mage.Sets/src/mage/cards/v/VenomousChangeling.java index 956c7fa3ac9..8647ce94ce4 100644 --- a/Mage.Sets/src/mage/cards/v/VenomousChangeling.java +++ b/Mage.Sets/src/mage/cards/v/VenomousChangeling.java @@ -23,8 +23,7 @@ public final class VenomousChangeling extends CardImpl { this.toughness = new MageInt(3); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Deathtouch this.addAbility(DeathtouchAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/v/VesuvanDoppelganger.java b/Mage.Sets/src/mage/cards/v/VesuvanDoppelganger.java index 540626721f1..f81f9a1fbfd 100644 --- a/Mage.Sets/src/mage/cards/v/VesuvanDoppelganger.java +++ b/Mage.Sets/src/mage/cards/v/VesuvanDoppelganger.java @@ -22,7 +22,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.TargetPermanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; /** * @@ -86,23 +86,14 @@ class VesuvanDoppelgangerCopyEffect extends OneShotEffect { controller.choose(Outcome.Copy, target, source.getSourceId(), game); Permanent copyFromPermanent = game.getPermanent(target.getFirstTarget()); if (copyFromPermanent != null) { - game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new ApplyToPermanent() { + game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new CopyApplier() { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.getColor(game).setColor(sourcePermanent.getColor(game)); - permanent.getAbilities().add(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.getColor().setColor(sourcePermanent.getColor(game)); + blueprint.getAbilities().add(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new VesuvanDoppelgangerCopyEffect(), TargetController.YOU, true, false, rule2)); return true; } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.getColor(game).setColor(sourcePermanent.getColor(game)); - mageObject.getAbilities().add(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, - new VesuvanDoppelgangerCopyEffect(), TargetController.YOU, true, false, rule2)); - return true; - } - }); return true; } diff --git a/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java b/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java index f339bdd59a9..bdb0c91dbc1 100644 --- a/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java +++ b/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java @@ -23,7 +23,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -44,7 +44,7 @@ public final class VesuvanShapeshifter extends CardImpl { this.addAbility(ability); // As Vesuvan Shapeshifter etbs, you may choose another creature. If you do, until Vesuvan Shapeshifter is turned face down, it becomes a copy of that creature - Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new VesuvanShapeShifterFaceUpApplier()); + Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new VesuvanShapeShifterFaceUpCopyApplier()); effect.setText("as a copy of any creature on the battlefield until {this} is turned faced down"); ability = new EntersBattlefieldAbility(effect, true); ability.setWorksFaceDown(false); @@ -69,21 +69,13 @@ public final class VesuvanShapeshifter extends CardImpl { } } -class VesuvanShapeShifterFaceUpApplier extends ApplyToPermanent { +class VesuvanShapeShifterFaceUpCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - Effect effect = new VesuvanShapeshifterFaceDownEffect(); - Ability ability = new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, true); - permanent.getAbilities().add(ability); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - Effect effect = new VesuvanShapeshifterFaceDownEffect(); - Ability ability = new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, true); - mageObject.getAbilities().add(ability); + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.getAbilities().add(new BeginningOfUpkeepTriggeredAbility( + new VesuvanShapeshifterFaceDownEffect(), TargetController.YOU, true + )); return true; } } @@ -118,7 +110,7 @@ class VesuvanShapeshifterEffect extends OneShotEffect { if (controller != null && controller.chooseTarget(Outcome.BecomeCreature, target, source, game) && !target.getTargets().isEmpty()) { Permanent copyFromCreature = game.getPermanentOrLKIBattlefield(target.getFirstTarget()); if (copyFromCreature != null) { - game.copyPermanent(Duration.Custom, copyFromCreature, copyToCreature.getId(), source, new VesuvanShapeShifterFaceUpApplier()); + game.copyPermanent(Duration.Custom, copyFromCreature, copyToCreature.getId(), source, new VesuvanShapeShifterFaceUpCopyApplier()); source.getTargets().clear(); game.getState().processAction(game); // needed to get effects ready if copy happens in replacment and the copied abilities react of the same event (e.g. turn face up) return true; diff --git a/Mage.Sets/src/mage/cards/v/VisionCharm.java b/Mage.Sets/src/mage/cards/v/VisionCharm.java index 73dc1433791..772d63c5157 100644 --- a/Mage.Sets/src/mage/cards/v/VisionCharm.java +++ b/Mage.Sets/src/mage/cards/v/VisionCharm.java @@ -119,7 +119,7 @@ class VisionCharmEffect extends ContinuousEffectImpl { it.remove(); continue; } - land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); land.addSubType(game, targetBasicLandType); land.removeAllAbilities(source.getSourceId(), game); switch (targetBasicLandType) { diff --git a/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java b/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java index 75a3ddd30eb..ccba0479fe2 100644 --- a/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java +++ b/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java @@ -19,7 +19,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import mage.watchers.Watcher; import java.util.HashSet; @@ -41,7 +41,7 @@ public final class VizierOfManyFaces extends CardImpl { this.toughness = new MageInt(0); // You may have Vizier of Many Faces enter the battlefield as a copy of any creature on the battlefield, except if Vizier of Many Faces was embalmed, the token has no mana cost, it's white, and it's a Zombie in addition to its other types. - Effect effect = new CopyPermanentEffect(new VizierOfManyFacesApplyToPermanent()); + Effect effect = new CopyPermanentEffect(new VizierOfManyFacesCopyApplier()); effect.setText("as a copy of any creature on the battlefield, except if {this} was embalmed, the token has no mana cost, it's white, and it's a Zombie in addition to its other types."); this.addAbility(new EntersBattlefieldAbility(effect, true), new EmbalmedThisTurnWatcher()); @@ -59,15 +59,10 @@ public final class VizierOfManyFaces extends CardImpl { } } -class VizierOfManyFacesApplyToPermanent extends ApplyToPermanent { +class VizierOfManyFacesCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - return true; - } - - @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { for (Permanent entering : game.getPermanentsEntering().values()) { if (!entering.getId().equals(copyToObjectId) || !(entering instanceof PermanentToken)) { continue; @@ -81,14 +76,15 @@ class VizierOfManyFacesApplyToPermanent extends ApplyToPermanent { if (!Objects.equals(mor.getSourceId(), originalCardId) || game.getState().getZoneChangeCounter(originalCardId) != mor.getZoneChangeCounter()) { continue; } - permanent.getManaCost().clear(); - permanent.addSubType(game, SubType.ZOMBIE); - permanent.getColor(game).setColor(ObjectColor.WHITE); + blueprint.getManaCost().clear(); + if (!blueprint.getSubtype().contains(SubType.ZOMBIE)) { + blueprint.getSubtype().add(SubType.ZOMBIE); + } + blueprint.getColor().setColor(ObjectColor.WHITE); } } return true; } - } class EmbalmedThisTurnWatcher extends Watcher { diff --git a/Mage.Sets/src/mage/cards/v/VolatileClaws.java b/Mage.Sets/src/mage/cards/v/VolatileClaws.java index 9d06a0c6fbf..720dc0cd483 100644 --- a/Mage.Sets/src/mage/cards/v/VolatileClaws.java +++ b/Mage.Sets/src/mage/cards/v/VolatileClaws.java @@ -73,7 +73,7 @@ class VolatileClawsEffect extends ContinuousEffectImpl { it.remove(); // no longer on the battlefield, remove reference to object continue; } - permanent.setIsAllCreatureTypes(true); + permanent.setIsAllCreatureTypes(game, true); } return true; } diff --git a/Mage.Sets/src/mage/cards/v/VolrathTheShapestealer.java b/Mage.Sets/src/mage/cards/v/VolrathTheShapestealer.java index 880e9a64bc5..1772a12e95a 100644 --- a/Mage.Sets/src/mage/cards/v/VolrathTheShapestealer.java +++ b/Mage.Sets/src/mage/cards/v/VolrathTheShapestealer.java @@ -23,7 +23,7 @@ import mage.game.permanent.PermanentCard; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -101,7 +101,7 @@ class VolrathTheShapestealerEffect extends OneShotEffect { } newBluePrint = new PermanentCard(copyFromCard, source.getControllerId(), game); newBluePrint.assignNewId(); - ApplyToPermanent applier = new VolrathTheShapestealerApplier(); + CopyApplier applier = new VolrathTheShapestealerCopyApplier(); applier.apply(game, newBluePrint, source, volrathTheShapestealer.getId()); CopyEffect copyEffect = new CopyEffect(Duration.UntilYourNextTurn, newBluePrint, volrathTheShapestealer.getId()); copyEffect.newId(); @@ -113,25 +113,16 @@ class VolrathTheShapestealerEffect extends OneShotEffect { } } -class VolrathTheShapestealerApplier extends ApplyToPermanent { +class VolrathTheShapestealerCopyApplier extends CopyApplier { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { Ability ability = new SimpleActivatedAbility(new VolrathTheShapestealerEffect(), new GenericManaCost(1)); ability.addTarget(new TargetPermanent(VolrathTheShapestealer.filter)); - permanent.getAbilities().add(ability); - permanent.getPower().modifyBaseValue(7); - permanent.getToughness().modifyBaseValue(5); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - Ability ability = new SimpleActivatedAbility(new VolrathTheShapestealerEffect(), new GenericManaCost(1)); - ability.addTarget(new TargetPermanent(VolrathTheShapestealer.filter)); - mageObject.getAbilities().add(ability); - mageObject.getPower().modifyBaseValue(7); - mageObject.getToughness().modifyBaseValue(5); + blueprint.getAbilities().add(ability); + blueprint.removePTCDA(); + blueprint.getPower().modifyBaseValue(7); + blueprint.getToughness().modifyBaseValue(5); return true; } } diff --git a/Mage.Sets/src/mage/cards/v/VolrathsShapeshifter.java b/Mage.Sets/src/mage/cards/v/VolrathsShapeshifter.java index 04d4eeef9d1..b43c25e96c8 100644 --- a/Mage.Sets/src/mage/cards/v/VolrathsShapeshifter.java +++ b/Mage.Sets/src/mage/cards/v/VolrathsShapeshifter.java @@ -86,10 +86,7 @@ class VolrathsShapeshifterEffect extends ContinuousEffectImpl { } permanent.removeAllSubTypes(game); - permanent.setIsAllCreatureTypes(card.isAllCreatureTypes()); - for (SubType type : card.getSubtype(game)) { - permanent.addSubType(game, type); - } + permanent.copySubTypesFrom(game, card); permanent.getSuperType().clear(); for (SuperType type : card.getSuperType()) { diff --git a/Mage.Sets/src/mage/cards/v/VoraciousDragon.java b/Mage.Sets/src/mage/cards/v/VoraciousDragon.java index e19550e23f2..532ff9139fe 100644 --- a/Mage.Sets/src/mage/cards/v/VoraciousDragon.java +++ b/Mage.Sets/src/mage/cards/v/VoraciousDragon.java @@ -17,7 +17,6 @@ import mage.constants.SubType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetAnyTarget; -import mage.util.SubTypeList; import java.util.UUID; @@ -40,12 +39,12 @@ public final class VoraciousDragon extends CardImpl { this.addAbility(new DevourAbility(DevourFactor.Devour1)); // When Voracious Dragon enters the battlefield, it deals damage to any target equal to twice the number of Goblins it devoured. - Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(new TwiceDevouredGoblins(), "it"), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(TwiceDevouredGoblins.instance, "it"), false); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } - public VoraciousDragon(final VoraciousDragon card) { + private VoraciousDragon(final VoraciousDragon card) { super(card); } @@ -55,27 +54,31 @@ public final class VoraciousDragon extends CardImpl { } } -class TwiceDevouredGoblins implements DynamicValue { +enum TwiceDevouredGoblins implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { Permanent sourcePermanent = game.getPermanent(sourceAbility.getSourceId()); - if (sourcePermanent != null) { - for (Ability ability : sourcePermanent.getAbilities()) { - if (ability instanceof DevourAbility) { - for (Effect abilityEffect : ability.getEffects()) { - if (abilityEffect instanceof DevourEffect) { - DevourEffect devourEffect = (DevourEffect) abilityEffect; - int amountGoblins = 0; - for (SubTypeList subtypesItem : devourEffect.getSubtypes(game, sourcePermanent.getId())) { - if (subtypesItem.contains(SubType.GOBLIN)) { - ++amountGoblins; - } - } - return amountGoblins * 2; - } + if (sourcePermanent == null) { + return 0; + } + for (Ability ability : sourcePermanent.getAbilities()) { + if (!(ability instanceof DevourAbility)) { + continue; + } + for (Effect abilityEffect : ability.getEffects()) { + if (!(abilityEffect instanceof DevourEffect)) { + continue; + } + DevourEffect devourEffect = (DevourEffect) abilityEffect; + int amountGoblins = 0; + for (Permanent permanent : devourEffect.getDevouredCreatures(game, sourcePermanent.getId())) { + if (permanent.hasSubtype(SubType.GOBLIN, game)) { + ++amountGoblins; } } + return amountGoblins * 2; } } return 0; @@ -83,7 +86,7 @@ class TwiceDevouredGoblins implements DynamicValue { @Override public TwiceDevouredGoblins copy() { - return new TwiceDevouredGoblins(); + return instance; } @Override diff --git a/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java b/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java index ce8d7819e00..ececc544a85 100644 --- a/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java +++ b/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java @@ -26,7 +26,7 @@ import mage.players.Player; import mage.target.Target; import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -106,18 +106,11 @@ class WallOfStolenIdentityCopyEffect extends OneShotEffect { if (copyFromPermanent == null) { return false; } - game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new ApplyToPermanent() { + game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new CopyApplier() { @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.addSubType(game, SubType.WALL); - permanent.getAbilities().add(DefenderAbility.getInstance()); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.addSubType(game, SubType.WALL); - mageObject.getAbilities().add(DefenderAbility.getInstance()); + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.addSubType(SubType.WALL); + blueprint.getAbilities().add(DefenderAbility.getInstance()); return true; } }); diff --git a/Mage.Sets/src/mage/cards/w/WarSpikeChangeling.java b/Mage.Sets/src/mage/cards/w/WarSpikeChangeling.java index 0b9e1bb25e5..c6f430600f4 100644 --- a/Mage.Sets/src/mage/cards/w/WarSpikeChangeling.java +++ b/Mage.Sets/src/mage/cards/w/WarSpikeChangeling.java @@ -24,8 +24,7 @@ public final class WarSpikeChangeling extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new ColoredManaCost(ColoredManaSymbol.R))); } diff --git a/Mage.Sets/src/mage/cards/w/WebweaverChangeling.java b/Mage.Sets/src/mage/cards/w/WebweaverChangeling.java index 58f136aa132..eb8d8608b44 100644 --- a/Mage.Sets/src/mage/cards/w/WebweaverChangeling.java +++ b/Mage.Sets/src/mage/cards/w/WebweaverChangeling.java @@ -28,8 +28,7 @@ public final class WebweaverChangeling extends CardImpl { this.toughness = new MageInt(5); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Reach this.addAbility(ReachAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/w/WeightOfConscience.java b/Mage.Sets/src/mage/cards/w/WeightOfConscience.java index 96a45851fd7..ea3e9654e35 100644 --- a/Mage.Sets/src/mage/cards/w/WeightOfConscience.java +++ b/Mage.Sets/src/mage/cards/w/WeightOfConscience.java @@ -1,5 +1,6 @@ package mage.cards.w; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -11,8 +12,11 @@ import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.SharesCreatureTypePredicate; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -21,10 +25,7 @@ import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; +import java.util.*; /** * @author emerald000 @@ -102,13 +103,14 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { static { filterUntapped.add(Predicates.not(TappedPredicate.instance)); + filterUntapped.add(WeightOfConsciencePredicate.instance); } WeightOfConscienceTarget() { super(2, 2, filterUntapped, true); } - WeightOfConscienceTarget(final WeightOfConscienceTarget target) { + private WeightOfConscienceTarget(final WeightOfConscienceTarget target) { super(target); } @@ -116,28 +118,37 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Player player = game.getPlayer(sourceControllerId); Set possibleTargets = new HashSet<>(0); - if (player != null) { - // Choosing first target - if (this.getTargets().isEmpty()) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) { - for (SubType subtype : permanent.getSubtype(game)) { - if (subtype.getSubTypeSet() == SubTypeSet.CreatureType) { - if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype.toString()), sourceId, sourceControllerId, game, 2)) { - possibleTargets.add(permanent.getId()); - } - } - } + if (player == null) { + return possibleTargets; + } + // Choosing first target + if (this.getTargets().isEmpty()) { + List permanentList = game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game); + if (permanentList.size() < 2) { + return possibleTargets; + } + for (Permanent permanent : permanentList) { + if (permanent.isAllCreatureTypes(game)) { + possibleTargets.add(permanent.getId()); + continue; } - } // Choosing second target - else { - UUID firstTargetId = this.getTargets().get(0); - Permanent firstTargetCreature = game.getPermanent(firstTargetId); - if (firstTargetCreature != null) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) { - if (!permanent.getId().equals(firstTargetId) && firstTargetCreature.shareCreatureTypes(permanent, game)) { - possibleTargets.add(permanent.getId()); - } - } + FilterPermanent filter = filterUntapped.copy(); + filter.add(new SharesCreatureTypePredicate(permanent)); + if (game.getBattlefield().count(filter, sourceId, sourceControllerId, game) > 1) { + possibleTargets.add(permanent.getId()); + } + } + } // Choosing second target + else { + Permanent firstTargetCreature = game.getPermanent(this.getFirstTarget()); + if (firstTargetCreature == null) { + return possibleTargets; + } + FilterPermanent filter = filterUntapped.copy(); + filter.add(new SharesCreatureTypePredicate(firstTargetCreature)); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) { + if (permanent != null) { + possibleTargets.add(permanent.getId()); } } } @@ -148,7 +159,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { for (Permanent permanent1 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) { for (Permanent permanent2 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) { - if (!Objects.equals(permanent1, permanent2) && permanent1.shareCreatureTypes(permanent2, game)) { + if (!Objects.equals(permanent1, permanent2) && permanent1.shareCreatureTypes(game, permanent2)) { return true; } } @@ -158,24 +169,31 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { @Override public boolean canTarget(UUID id, Ability source, Game game) { - if (super.canTarget(id, game)) { - Permanent targetPermanent = game.getPermanent(id); - if (targetPermanent != null) { - if (this.getTargets().isEmpty()) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, source.getControllerId(), source.getSourceId(), game)) { - for (SubType subtype : permanent.getSubtype(game)) { - if (subtype.getSubTypeSet() == SubTypeSet.CreatureType) { - if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype.toString()), source, game, 2)) { - return true; - } - } - } - } - } else { - Permanent firstTarget = game.getPermanent(this.getTargets().get(0)); - return firstTarget != null && firstTarget.shareCreatureTypes(targetPermanent, game); + if (!super.canTarget(id, game)) { + return false; + } + Permanent targetPermanent = game.getPermanent(id); + if (targetPermanent == null) { + return false; + } + if (this.getTargets().isEmpty()) { + List permanentList = game.getBattlefield().getActivePermanents(filterUntapped, source.getControllerId(), source.getSourceId(), game); + if (permanentList.size() < 2) { + return false; + } + for (Permanent permanent : permanentList) { + if (permanent.isAllCreatureTypes(game)) { + return true; + } + FilterPermanent filter = filterUntapped.copy(); + filter.add(new SharesCreatureTypePredicate(permanent)); + if (game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) > 1) { + return true; } } + } else { + Permanent firstTarget = game.getPermanent(this.getTargets().get(0)); + return firstTarget != null && firstTarget.shareCreatureTypes(game, targetPermanent); } return false; } @@ -185,3 +203,17 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { return new WeightOfConscienceTarget(this); } } + +enum WeightOfConsciencePredicate implements Predicate { + instance; + + @Override + public boolean apply(MageObject input, Game game) { + return input.isAllCreatureTypes(game) + || input + .getSubtype(game) + .stream() + .map(SubType::getSubTypeSet) + .anyMatch(SubTypeSet.CreatureType::equals); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WingsOfVelisVel.java b/Mage.Sets/src/mage/cards/w/WingsOfVelisVel.java index 85dd21bbb8b..79570148768 100644 --- a/Mage.Sets/src/mage/cards/w/WingsOfVelisVel.java +++ b/Mage.Sets/src/mage/cards/w/WingsOfVelisVel.java @@ -24,8 +24,7 @@ public final class WingsOfVelisVel extends CardImpl { this.subtype.add(SubType.SHAPESHIFTER); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); // Target creature becomes 4/4, gains all creature types, and gains flying until end of turn. this.getSpellAbility().addEffect(new SetPowerToughnessTargetEffect(4, 4, Duration.EndOfTurn) diff --git a/Mage.Sets/src/mage/cards/w/WoodlandChangeling.java b/Mage.Sets/src/mage/cards/w/WoodlandChangeling.java index 081425f6c86..3f73193784d 100644 --- a/Mage.Sets/src/mage/cards/w/WoodlandChangeling.java +++ b/Mage.Sets/src/mage/cards/w/WoodlandChangeling.java @@ -22,8 +22,7 @@ public final class WoodlandChangeling extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); // Changeling - this.setIsAllCreatureTypes(true); - this.addAbility(ChangelingAbility.getInstance()); + this.addAbility(new ChangelingAbility()); } public WoodlandChangeling(final WoodlandChangeling card) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java index 9404a4dbfab..df0e07b717b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java @@ -459,7 +459,7 @@ public class BestowTest extends CardTestPlayerBase { assertType("Nighthowler", CardType.ENCHANTMENT, true); Permanent nighthowler = getPermanent("Nighthowler"); - Assert.assertFalse("The unattached Nighthowler may not have the aura subtype.", nighthowler.getSubtype(currentGame).contains(SubType.AURA)); + Assert.assertFalse("The unattached Nighthowler may not have the aura subtype.", nighthowler.hasSubtype(SubType.AURA, currentGame)); } @Test diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ChangelingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ChangelingTest.java index a694a6cc216..838fd0c6295 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ChangelingTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ChangelingTest.java @@ -140,7 +140,7 @@ public class ChangelingTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Game-Trail Changeling", 7, 1); assertNotSubtype("Game-Trail Changeling", SubType.SHAPESHIFTER); assertAbility(playerA, "Game-Trail Changeling", HasteAbility.getInstance(), false); - assertAbility(playerA, "Game-Trail Changeling", ChangelingAbility.getInstance(), true); + assertAbility(playerA, "Game-Trail Changeling", new ChangelingAbility(), true); } @Test @@ -159,6 +159,6 @@ public class ChangelingTest extends CardTestPlayerBase { assertSubtype("Game-Trail Changeling", SubType.GOBLIN); assertSubtype("Game-Trail Changeling", SubType.ELF); assertSubtype("Game-Trail Changeling", SubType.SHAPESHIFTER); - assertAbility(playerB, "Game-Trail Changeling", ChangelingAbility.getInstance(), false); + assertAbility(playerB, "Game-Trail Changeling", new ChangelingAbility(), false); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ChangelingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ChangelingTest.java index a27ae3a7f6f..807f29bd8ac 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ChangelingTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ChangelingTest.java @@ -10,7 +10,7 @@ public class ChangelingTest extends CardTestPlayerBase { // Mistform Ultimus is every creature type private static final String ultimus = "Mistform Ultimus"; - // each creature gets +1/+1 for each creature you control that shares a creatureype + // each creature gets +1/+1 for each other creature that shares a creature type with it private static final String coatOfArms = "Coat of Arms"; // all merfolk get +1/+1 private static final String lordOfAtlantis = "Lord of Atlantis"; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java index d011d952b30..a6626ac35f8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java @@ -226,13 +226,13 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase { int mountainTypes = 0; int creatures = 0; for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_LAND, playerA.getId(), currentGame)) { - if (permanent.getSubtype(currentGame).contains(SubType.ISLAND)) { + if (permanent.hasSubtype(SubType.ISLAND, currentGame)) { islandTypes++; } - if (permanent.getSubtype(currentGame).contains(SubType.MOUNTAIN)) { + if (permanent.hasSubtype(SubType.MOUNTAIN, currentGame)) { mountainTypes++; } - if (permanent.getSubtype(currentGame).contains(SubType.SWAMP)) { + if (permanent.hasSubtype(SubType.SWAMP, currentGame)) { swampTypes++; } if (permanent.isCreature()) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/SubTypeChangingEffectsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/SubTypeChangingEffectsTest.java index 31a22dd6f69..57ba62045a9 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/SubTypeChangingEffectsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/SubTypeChangingEffectsTest.java @@ -39,45 +39,45 @@ public class SubTypeChangingEffectsTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Conspiracy", 1); Permanent silvercoatLion = getPermanent("Silvercoat Lion", playerA); - Assert.assertEquals(false, silvercoatLion.getSubtype(currentGame).contains(SubType.CAT)); - Assert.assertEquals(true, silvercoatLion.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertFalse(silvercoatLion.hasSubtype(SubType.CAT, currentGame)); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.ORC, currentGame)); silvercoatLion = getPermanent("Silvercoat Lion", playerB); - Assert.assertEquals(true, silvercoatLion.getSubtype(currentGame).contains(SubType.CAT)); - Assert.assertEquals(false, silvercoatLion.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.CAT, currentGame)); + Assert.assertFalse(silvercoatLion.hasSubtype(SubType.ORC, currentGame)); for (Card card : playerA.getLibrary().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should have ORC type", true, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should not have CAT type", false, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertTrue(card.getName() + " should have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertFalse(card.getName() + " should not have CAT type", card.hasSubtype(SubType.CAT, currentGame)); } } for (Card card : playerB.getLibrary().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertTrue(card.getName() + " should have CAT type", card.hasSubtype(SubType.CAT, currentGame)); } } for (Card card : playerA.getHand().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should have ORC type", true, card.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertTrue(card.getName() + " should have ORC type", card.hasSubtype(SubType.ORC, currentGame)); } } for (Card card : playerB.getHand().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); } } for (Card card : playerA.getGraveyard().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should have ORC type", true, card.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertTrue(card.getName() + " should have ORC type", card.hasSubtype(SubType.ORC, currentGame)); } } for (Card card : playerB.getGraveyard().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); } } @@ -118,27 +118,27 @@ public class SubTypeChangingEffectsTest extends CardTestPlayerBase { assertGraveyardCount(playerB, "Disenchant", 1); Permanent silvercoatLion = getPermanent("Silvercoat Lion", playerA); - Assert.assertEquals(true, silvercoatLion.getSubtype(currentGame).contains(SubType.CAT)); - Assert.assertEquals(false, silvercoatLion.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.CAT, currentGame)); + Assert.assertFalse(silvercoatLion.hasSubtype(SubType.ORC, currentGame)); for (Card card : playerA.getLibrary().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertTrue(card.getName() + " should have CAT type", card.hasSubtype(SubType.CAT, currentGame)); } } for (Card card : playerA.getHand().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertTrue(card.getName() + " should have CAT type", card.hasSubtype(SubType.CAT, currentGame)); } } for (Card card : playerA.getGraveyard().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertTrue(card.getName() + " should have CAT type", card.hasSubtype(SubType.CAT, currentGame)); } } @@ -169,49 +169,49 @@ public class SubTypeChangingEffectsTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Arcane Adaptation", 1); Permanent silvercoatLion = getPermanent("Silvercoat Lion", playerA); - Assert.assertEquals(true, silvercoatLion.getSubtype(currentGame).contains(SubType.CAT)); - Assert.assertEquals(true, silvercoatLion.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.CAT, currentGame)); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.ORC, currentGame)); silvercoatLion = getPermanent("Silvercoat Lion", playerB); - Assert.assertEquals(true, silvercoatLion.getSubtype(currentGame).contains(SubType.CAT)); - Assert.assertEquals(false, silvercoatLion.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.CAT, currentGame)); + Assert.assertFalse(silvercoatLion.hasSubtype(SubType.ORC, currentGame)); for (Card card : playerA.getLibrary().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should have ORC type", true, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertEquals(card.getName() + " should have ORC type", true, card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertEquals(card.getName() + " should have CAT type", true, card.hasSubtype(SubType.CAT, currentGame)); } } for (Card card : playerB.getLibrary().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertEquals(card.getName() + " should not have ORC type", false, card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertEquals(card.getName() + " should have CAT type", true, card.hasSubtype(SubType.CAT, currentGame)); } } for (Card card : playerA.getHand().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should have ORC type", true, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertEquals(card.getName() + " should have ORC type", true, card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertEquals(card.getName() + " should have CAT type", true, card.hasSubtype(SubType.CAT, currentGame)); } } for (Card card : playerB.getHand().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertEquals(card.getName() + " should not have ORC type", false, card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertEquals(card.getName() + " should have CAT type", true, card.hasSubtype(SubType.CAT, currentGame)); } } for (Card card : playerA.getGraveyard().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should have ORC type", true, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertEquals(card.getName() + " should have ORC type", true, card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertEquals(card.getName() + " should have CAT type", true, card.hasSubtype(SubType.CAT, currentGame)); } } for (Card card : playerB.getGraveyard().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertEquals(card.getName() + " should not have ORC type", false, card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertEquals(card.getName() + " should have CAT type", true, card.hasSubtype(SubType.CAT, currentGame)); } } @@ -265,35 +265,35 @@ public class SubTypeChangingEffectsTest extends CardTestPlayerBase { assertGraveyardCount(playerB, "Disenchant", 1); Permanent silvercoatLion = getPermanent("Silvercoat Lion", playerA); - Assert.assertEquals(true, silvercoatLion.getSubtype(currentGame).contains(SubType.CAT)); - Assert.assertEquals(false, silvercoatLion.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.CAT, currentGame)); + Assert.assertFalse(silvercoatLion.hasSubtype(SubType.ORC, currentGame)); Permanent beast = getPermanent("Beast", playerA); - Assert.assertEquals(true, beast.getSubtype(currentGame).contains(SubType.BEAST)); - Assert.assertEquals(false, beast.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertTrue(beast.hasSubtype(SubType.BEAST, currentGame)); + Assert.assertFalse(beast.hasSubtype(SubType.ORC, currentGame)); Permanent wurm = getPermanent("Wurm", playerA); - Assert.assertEquals(true, wurm.getSubtype(currentGame).contains(SubType.WURM)); - Assert.assertEquals(false, wurm.getSubtype(currentGame).contains(SubType.ORC)); + Assert.assertTrue(wurm.hasSubtype(SubType.WURM, currentGame)); + Assert.assertFalse(wurm.hasSubtype(SubType.ORC, currentGame)); for (Card card : playerA.getLibrary().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertEquals(card.getName() + " should not have ORC type", false, card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertEquals(card.getName() + " should have CAT type", true, card.hasSubtype(SubType.CAT, currentGame)); } } for (Card card : playerA.getHand().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertEquals(card.getName() + " should not have ORC type", false, card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertEquals(card.getName() + " should have CAT type", true, card.hasSubtype(SubType.CAT, currentGame)); } } for (Card card : playerA.getGraveyard().getCards(currentGame)) { if (card.isCreature()) { - Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); - Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertEquals(card.getName() + " should not have ORC type", false, card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertEquals(card.getName() + " should have CAT type", true, card.hasSubtype(SubType.CAT, currentGame)); } } @@ -342,4 +342,134 @@ public class SubTypeChangingEffectsTest extends CardTestPlayerBase { assertType("Gingerbrute", CardType.CREATURE, SubType.DRAGON); assertNotSubtype("Gingerbrute", SubType.GOLEM); } + + @Test + public void testMaskwoodNexus() { + addCard(Zone.HAND, playerA, "Maskwood Nexus", 1); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); + + addCard(Zone.HAND, playerA, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion"); + + addCard(Zone.HAND, playerB, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + addCard(Zone.GRAVEYARD, playerB, "Silvercoat Lion"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Maskwood Nexus"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Maskwood Nexus", 1); + + Permanent silvercoatLion = getPermanent("Silvercoat Lion", playerA); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.CAT, currentGame)); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.ORC, currentGame)); + + silvercoatLion = getPermanent("Silvercoat Lion", playerB); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.CAT, currentGame)); + Assert.assertFalse(silvercoatLion.hasSubtype(SubType.ORC, currentGame)); + + for (Card card : playerA.getLibrary().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertTrue(card.getName() + " should have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertTrue(card.getName() + " should have CAT type", card.hasSubtype(SubType.CAT, currentGame)); + } + } + for (Card card : playerB.getLibrary().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertTrue(card.getName() + " should have CAT type", card.hasSubtype(SubType.CAT, currentGame)); + } + } + + for (Card card : playerA.getHand().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertTrue(card.getName() + " should have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + } + } + for (Card card : playerB.getHand().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + } + } + for (Card card : playerA.getGraveyard().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertTrue(card.getName() + " should have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + } + + } + for (Card card : playerB.getGraveyard().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + } + } + } + + @Test + public void testMaskwoodNexus2() { + addCard(Zone.HAND, playerA, "Maskwood Nexus", 1); + addCard(Zone.HAND, playerA, "Shatter", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6); + + addCard(Zone.HAND, playerA, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion"); + + addCard(Zone.HAND, playerB, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + addCard(Zone.GRAVEYARD, playerB, "Silvercoat Lion"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Maskwood Nexus"); + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Shatter", "Maskwood Nexus"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Maskwood Nexus", 1); + + Permanent silvercoatLion = getPermanent("Silvercoat Lion", playerA); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.CAT, currentGame)); + Assert.assertFalse(silvercoatLion.hasSubtype(SubType.ORC, currentGame)); + + silvercoatLion = getPermanent("Silvercoat Lion", playerB); + Assert.assertTrue(silvercoatLion.hasSubtype(SubType.CAT, currentGame)); + Assert.assertFalse(silvercoatLion.hasSubtype(SubType.ORC, currentGame)); + + for (Card card : playerA.getLibrary().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertTrue(card.getName() + " should have CAT type", card.hasSubtype(SubType.CAT, currentGame)); + } + } + for (Card card : playerB.getLibrary().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + Assert.assertTrue(card.getName() + " should have CAT type", card.hasSubtype(SubType.CAT, currentGame)); + } + } + + for (Card card : playerA.getHand().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + } + } + for (Card card : playerB.getHand().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + } + } + for (Card card : playerA.getGraveyard().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + } + + } + for (Card card : playerB.getGraveyard().getCards(currentGame)) { + if (card.isCreature()) { + Assert.assertFalse(card.getName() + " should not have ORC type", card.hasSubtype(SubType.ORC, currentGame)); + } + } + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/LazavDimirMastermindTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/LazavDimirMastermindTest.java index 36bcc01fbed..ab54c107d25 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/LazavDimirMastermindTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/LazavDimirMastermindTest.java @@ -45,7 +45,7 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 3, 2); Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); - Assert.assertTrue(lazav.getSubtype(currentGame).contains(SubType.GRIFFIN)); + Assert.assertTrue(lazav.hasSubtype(SubType.GRIFFIN, currentGame)); Assert.assertTrue("Lazav, Dimir Mastermind must have flying", lazav.getAbilities().contains(FlyingAbility.getInstance())); } @@ -71,8 +71,8 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Lazav, Dimir Mastermind", 1); assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 3, 3); Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); - Assert.assertTrue(lazav.getSubtype(currentGame).contains(SubType.OGRE)); - Assert.assertTrue(lazav.getSubtype(currentGame).contains(SubType.ROGUE)); + Assert.assertTrue(lazav.hasSubtype(SubType.OGRE, currentGame)); + Assert.assertTrue(lazav.hasSubtype(SubType.ROGUE, currentGame)); Permanent gutterSkulk = getPermanent("Gutter Skulk", playerA.getId()); Assert.assertTrue("Gutter Skulk should have deathtouch but hasn't", gutterSkulk.getAbilities().contains(DeathtouchAbility.getInstance())); @@ -111,7 +111,7 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); Assert.assertTrue(lazav.getAbilities().contains(FlyingAbility.getInstance())); - Assert.assertTrue(lazav.getSubtype(currentGame).contains(SubType.SPECTER)); + Assert.assertTrue(lazav.hasSubtype(SubType.SPECTER, currentGame)); Assert.assertTrue(lazav.isLegendary()); assertPermanentCount(playerA, "Silvercoat Lion", 1); @@ -141,7 +141,7 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 2, 2); Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); - Assert.assertTrue(lazav.getSubtype(currentGame).contains(SubType.CAT)); + Assert.assertTrue(lazav.hasSubtype(SubType.CAT, currentGame)); Assert.assertTrue(lazav.isLegendary()); } @@ -186,7 +186,7 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Lazav, Dimir Mastermind", 1); assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 3, 3); Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); - Assert.assertFalse(lazav.getSubtype(currentGame).contains(SubType.GRIFFIN)); // no Griffin type + Assert.assertFalse(lazav.hasSubtype(SubType.GRIFFIN, currentGame)); // no Griffin type Assert.assertFalse("Lazav, Dimir Mastermind must have flying", lazav.getAbilities().contains(FlyingAbility.getInstance())); @@ -222,7 +222,7 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 3, 2); Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); - Assert.assertTrue(lazav.getSubtype(currentGame).contains(SubType.GRIFFIN)); + Assert.assertTrue(lazav.hasSubtype(SubType.GRIFFIN, currentGame)); Assert.assertTrue("Lazav, Dimir Mastermind must have flying", lazav.getAbilities().contains(FlyingAbility.getInstance())); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/SparkDoubleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/SparkDoubleTest.java index 7c3d07f2e40..c624bb7fb1d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/SparkDoubleTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/SparkDoubleTest.java @@ -68,6 +68,7 @@ public class SparkDoubleTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spark Double"); setChoice(playerA, "Yes"); setChoice(playerA, "Ajani, the Greathearted"); + setChoice(playerA, "Ajani, the Greathearted"); // two etb effects (own + copy) setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); @@ -119,6 +120,7 @@ public class SparkDoubleTest extends CardTestPlayerBase { castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Spark Double"); setChoice(playerA, "Yes"); setChoice(playerA, "Gideon, Ally of Zendikar"); + setChoice(playerA, "Gideon, Ally of Zendikar"); // two etb effects (own + copy) setStrictChooseMode(true); setStopAt(1, PhaseStep.END_TURN); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/VolrathsShapshifterTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/VolrathsShapshifterTest.java index f79cf477d34..904dfefaf49 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/VolrathsShapshifterTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/VolrathsShapshifterTest.java @@ -44,7 +44,7 @@ public class VolrathsShapshifterTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Assault Griffin", 3, 2); Permanent shapeshifter = getPermanent("Assault Griffin", playerA.getId()); - Assert.assertTrue(shapeshifter.getSubtype(currentGame).contains(SubType.GRIFFIN)); + Assert.assertTrue(shapeshifter.hasSubtype(SubType.GRIFFIN, currentGame)); Assert.assertTrue("Volrath's Shapeshifter must have flying", shapeshifter.getAbilities().contains(FlyingAbility.getInstance())); Assert.assertTrue("Volrath's Shapeshifter must have {2} : Discard a card", hasShapeshiftersOriginalAbility(shapeshifter)); } @@ -77,7 +77,7 @@ public class VolrathsShapshifterTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Volrath's Shapeshifter", 0, 1); Permanent shapeshifter = getPermanent("Volrath's Shapeshifter", playerA.getId()); - Assert.assertTrue(shapeshifter.getSubtype(currentGame).contains(SubType.SHAPESHIFTER)); + Assert.assertTrue(shapeshifter.hasSubtype(SubType.SHAPESHIFTER, currentGame)); Assert.assertTrue("Volrath's Shapeshifter must have {2} : Discard a card", hasShapeshiftersOriginalAbility(shapeshifter)); } @@ -106,7 +106,7 @@ public class VolrathsShapshifterTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Dutiful Thrull", 1, 1); Permanent shapeshifter = getPermanent("Dutiful Thrull", playerA.getId()); - Assert.assertTrue(shapeshifter.getSubtype(currentGame).contains(SubType.THRULL)); + Assert.assertTrue(shapeshifter.hasSubtype(SubType.THRULL, currentGame)); Assert.assertTrue("Volrath's Shapeshifter must have {2} : Discard a card", hasShapeshiftersOriginalAbility(shapeshifter)); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modaldoublefaces/ModalDoubleFacesCardsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modaldoublefaces/ModalDoubleFacesCardsTest.java index e9e0c112b5f..74dcdeeb8eb 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modaldoublefaces/ModalDoubleFacesCardsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modaldoublefaces/ModalDoubleFacesCardsTest.java @@ -249,7 +249,7 @@ public class ModalDoubleFacesCardsTest extends CardTestPlayerBase { Card card = getHandCards(playerA).get(0); Assert.assertFalse("must be non land", card.isLand()); Assert.assertTrue("must be creature", card.isCreature()); - Assert.assertTrue("must be minotaur", card.getSubtype(currentGame).contains(SubType.MINOTAUR)); + Assert.assertTrue("must be minotaur", card.hasSubtype(SubType.MINOTAUR, currentGame)); Assert.assertEquals("power", 4, card.getPower().getValue()); Assert.assertEquals("toughness", 5, card.getToughness().getValue()); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/LignifyTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/LignifyTest.java index f8820b6d975..d111fb0889b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/LignifyTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/LignifyTest.java @@ -45,7 +45,7 @@ public class LignifyTest extends CardTestPlayerBase { Permanent hivelord = getPermanent("Sliver Hivelord", playerB); - Assert.assertFalse("Sliver Hivelord may not be of subtype Sliver", hivelord.getSubtype(currentGame).contains(SubType.SLIVER)); + Assert.assertFalse("Sliver Hivelord may not be of subtype Sliver", hivelord.hasSubtype(SubType.SLIVER, currentGame)); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/SoulSeparatorTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/SoulSeparatorTest.java index 02eb4769fa5..9fc9834b7b1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/SoulSeparatorTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/SoulSeparatorTest.java @@ -41,7 +41,7 @@ public class SoulSeparatorTest extends CardTestPlayerBase { Permanent saToken = getPermanent("Sylvan Advocate", playerA); Assert.assertTrue(saToken.getAbilities().contains(FlyingAbility.getInstance())); - Assert.assertTrue(saToken.getSubtype(currentGame).contains(SubType.SPIRIT)); + Assert.assertTrue(saToken.hasSubtype(SubType.SPIRIT, currentGame)); Assert.assertTrue(saToken.getAbilities().contains(VigilanceAbility.getInstance())); assertPowerToughness(playerA, "Sylvan Advocate", 1, 1); } @@ -77,7 +77,7 @@ public class SoulSeparatorTest extends CardTestPlayerBase { Permanent treeToken = getPermanent("Tree of Perdition", playerA); Assert.assertTrue(treeToken.getAbilities().contains(FlyingAbility.getInstance())); - Assert.assertTrue(treeToken.getSubtype(currentGame).contains(SubType.SPIRIT)); + Assert.assertTrue(treeToken.hasSubtype(SubType.SPIRIT, currentGame)); Assert.assertTrue(treeToken.getAbilities().contains(DefenderAbility.getInstance())); assertLife(playerA, 20); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/FathomMageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/FathomMageTest.java index 99a884487b4..ec88b1bc393 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/FathomMageTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/FathomMageTest.java @@ -61,7 +61,7 @@ public class FathomMageTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Fathom Mage", 3, 3); Permanent fathomMage = getPermanent("Fathom Mage", playerA); - Assert.assertEquals("Fathom Mage has to be a Mutant", true, fathomMage.getSubtype(currentGame).contains(SubType.MUTANT)); + Assert.assertEquals("Fathom Mage has to be a Mutant", true, fathomMage.hasSubtype(SubType.MUTANT, currentGame)); assertHandCount(playerA, 2); } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index d5e72df385c..20e6d2f2a55 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -1119,7 +1119,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement Permanent found = getPermanent(cardName); Assert.assertTrue("(Battlefield) card type not found (" + cardName + ':' + type + ')', found.getCardType().contains(type)); if (subType != null) { - Assert.assertTrue("(Battlefield) card sub-type not equal (" + cardName + ':' + subType.getDescription() + ')', found.getSubtype(currentGame).contains(subType)); + Assert.assertTrue("(Battlefield) card sub-type not equal (" + cardName + ':' + subType.getDescription() + ')', found.hasSubtype(subType, currentGame)); } } diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 88a0023c320..fde7a68b00e 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -1233,7 +1233,7 @@ public class VerifyCardDataTest { // Remove subtypes that need to be ignored Collection actual = card - .getSubtype(null) + .getSubtype() .stream() .map(SubType::toString) .collect(Collectors.toSet()); @@ -1274,10 +1274,6 @@ public class VerifyCardDataTest { fail(card, "abilities", "card have Multikicker ability, but missing it in rules text"); } - if (card.getAbilities().contains(ChangelingAbility.getInstance()) && !card.isAllCreatureTypes()) { - fail(card, "abilities", "card has Changeling but doesn't have isAllCreatureTypes set to true"); - } - // special check: missing or wrong ability/effect hints Map hints = new HashMap<>(); hints.put(MenaceAbility.class, "can't be blocked except by two or more"); diff --git a/Mage/src/main/java/mage/MageObject.java b/Mage/src/main/java/mage/MageObject.java index 59c99106abe..c1850e822b7 100644 --- a/Mage/src/main/java/mage/MageObject.java +++ b/Mage/src/main/java/mage/MageObject.java @@ -13,10 +13,11 @@ import mage.constants.SubTypeSet; import mage.constants.SuperType; import mage.game.Game; import mage.game.events.ZoneChangeEvent; -import mage.util.SubTypeList; +import mage.util.SubTypes; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Set; @@ -34,7 +35,20 @@ public interface MageObject extends MageItem, Serializable { ArrayList getCardType(); - SubTypeList getSubtype(Game game); + /** + * Return original object's subtypes + * + * @return + */ + SubTypes getSubtype(); + + /** + * Return full subtypes list (from object, from effects) + * + * @param game + * @return + */ + SubTypes getSubtype(Game game); boolean hasSubtype(SubType subtype, Game game); @@ -50,6 +64,8 @@ public interface MageObject extends MageItem, Serializable { boolean hasAbility(Ability ability, Game game); + ObjectColor getColor(); + ObjectColor getColor(Game game); ObjectColor getFrameColor(Game game); @@ -91,7 +107,7 @@ public interface MageObject extends MageItem, Serializable { default boolean isHistoric() { return getCardType().contains(CardType.ARTIFACT) || getSuperType().contains(SuperType.LEGENDARY) - || hasSubtype(SubType.SAGA, null); + || getSubtype().contains(SubType.SAGA); } default boolean isCreature() { @@ -164,23 +180,104 @@ public interface MageObject extends MageItem, Serializable { getCardType().add(cardType); } + /** + * Add subtype temporary, for continuous effects only + * + * @param game + * @param subTypes + */ + default void addSubType(Game game, Collection subTypes) { + for (SubType subType : subTypes) { + addSubType(game, subType); + } + } + + /** + * Add subtype permanently, for one shot effects and tokens setup + * + * @param subTypes + */ + default void addSubType(SubType... subTypes) { + for (SubType subType : subTypes) { + if (subType.canGain(this) + && !getSubtype().contains(subType)) { + getSubtype().add(subType); + } + } + } + + /** + * Add subtype temporary, for continuous effects only + * + * @param game + * @param subTypes + */ default void addSubType(Game game, SubType... subTypes) { for (SubType subType : subTypes) { if (subType.canGain(this) && !hasSubtype(subType, game)) { - getSubtype(game).add(subType); + game.getState().getCreateMageObjectAttribute(this, game).getSubtype().add(subType); + } + } + } + + default void copySubTypesFrom(Game game, MageObject mageObject) { + copySubTypesFrom(game, mageObject, null); + } + + default void copySubTypesFrom(Game game, MageObject mageObject, SubTypeSet subTypeSet) { + if (subTypeSet == SubTypeSet.CreatureType || subTypeSet == null) { + this.setIsAllCreatureTypes(game, mageObject.isAllCreatureTypes(game)); + } + for (SubType subType : mageObject.getSubtype(game)) { + if (subType.getSubTypeSet() == subTypeSet || subTypeSet == null) { + this.addSubType(game, subType); } } } default void removeAllSubTypes(Game game) { - getSubtype(game).clear(); - setIsAllCreatureTypes(false); + removeAllSubTypes(game, null); } - default void removeAllCreatureTypes(Game game) { - getSubtype(game).removeAll(SubType.getCreatureTypes()); + default void removeAllSubTypes(Game game, SubTypeSet subTypeSet) { + if (subTypeSet == null) { + setIsAllCreatureTypes(game, false); + game.getState().getCreateMageObjectAttribute(this, game).getSubtype().clear(); + } else if (subTypeSet == SubTypeSet.CreatureType) { + removeAllCreatureTypes(game); + } else if (subTypeSet == SubTypeSet.NonBasicLandType) { + game.getState().getCreateMageObjectAttribute(this, game).getSubtype().removeAll(SubType.getLandTypes()); + } else { + game.getState().getCreateMageObjectAttribute(this, game).getSubtype().removeAll(SubType.getBySubTypeSet(subTypeSet)); + } + } + + default void retainAllEnchantmentSubTypes(Game game) { + setIsAllCreatureTypes(game, false); + game.getState().getCreateMageObjectAttribute(this, game).getSubtype().retainAll(SubType.getEnchantmentTypes()); + } + + /** + * Remove object's own creature types forever (for copy effects usage) + */ + default void removeAllCreatureTypes() { setIsAllCreatureTypes(false); + getSubtype().removeAll(SubType.getCreatureTypes()); + } + + /** + * Remove object attribute's creature types temporary (for continuous effects usage) + * + * @param game + */ + default void removeAllCreatureTypes(Game game) { + setIsAllCreatureTypes(game, false); + game.getState().getCreateMageObjectAttribute(this, game).getSubtype().removeAll(SubType.getCreatureTypes()); + } + + default void removeSubType(Game game, SubType subType) { + game.getState().getCreateMageObjectAttribute(this, game).getSubtype().remove(subType); } /** @@ -209,19 +306,19 @@ public interface MageObject extends MageItem, Serializable { return false; } - default boolean shareCreatureTypes(Card otherCard, Game game) { + default boolean shareCreatureTypes(Game game, MageObject otherCard) { if (!isCreature() && !isTribal()) { return false; } if (!otherCard.isCreature() && !otherCard.isTribal()) { return false; } - boolean isAllA = this.isAllCreatureTypes(); + boolean isAllA = this.isAllCreatureTypes(game); boolean isAnyA = isAllA || this.getSubtype(game) .stream() .map(SubType::getSubTypeSet) .anyMatch(SubTypeSet.CreatureType::equals); - boolean isAllB = otherCard.isAllCreatureTypes(); + boolean isAllB = otherCard.isAllCreatureTypes(game); boolean isAnyB = isAllB || otherCard .getSubtype(game) .stream() @@ -241,10 +338,18 @@ public interface MageObject extends MageItem, Serializable { .anyMatch(subType -> otherCard.hasSubtype(subType, game))); } - boolean isAllCreatureTypes(); + boolean isAllCreatureTypes(Game game); void setIsAllCreatureTypes(boolean value); + /** + * Change all creature type mark temporary, for continuous effects only + * + * @param game + * @param value + */ + void setIsAllCreatureTypes(Game game, boolean value); + default void addCardTypes(ArrayList cardType) { getCardType().addAll(cardType); } diff --git a/Mage/src/main/java/mage/MageObjectImpl.java b/Mage/src/main/java/mage/MageObjectImpl.java index c2da4643a9d..9b3fa7d8d22 100644 --- a/Mage/src/main/java/mage/MageObjectImpl.java +++ b/Mage/src/main/java/mage/MageObjectImpl.java @@ -1,6 +1,5 @@ package mage; -import java.util.*; import mage.abilities.Abilities; import mage.abilities.AbilitiesImpl; import mage.abilities.Ability; @@ -20,7 +19,9 @@ import mage.game.Game; import mage.game.MageObjectAttribute; import mage.game.events.ZoneChangeEvent; import mage.util.GameLog; -import mage.util.SubTypeList; +import mage.util.SubTypes; + +import java.util.*; public abstract class MageObjectImpl implements MageObject { @@ -32,8 +33,7 @@ public abstract class MageObjectImpl implements MageObject { protected ObjectColor frameColor; protected FrameStyle frameStyle; protected ArrayList cardType = new ArrayList<>(); - protected SubTypeList subtype = new SubTypeList(); - protected boolean isAllCreatureTypes; + protected SubTypes subtype = new SubTypes(); protected Set supertype = EnumSet.noneOf(SuperType.class); protected Abilities abilities; protected String text; @@ -71,8 +71,7 @@ public abstract class MageObjectImpl implements MageObject { toughness = object.toughness.copy(); abilities = object.abilities.copy(); this.cardType.addAll(object.cardType); - this.subtype.addAll(object.subtype); - isAllCreatureTypes = object.isAllCreatureTypes; + this.subtype.copyFrom(object.subtype); supertype.addAll(object.supertype); this.copy = object.copy; this.copyFrom = (object.copyFrom != null ? object.copyFrom.copy() : null); @@ -116,13 +115,18 @@ public abstract class MageObjectImpl implements MageObject { } @Override - public SubTypeList getSubtype(Game game) { + public SubTypes getSubtype() { + return subtype; + } + + @Override + public SubTypes getSubtype(Game game) { if (game != null) { MageObjectAttribute mageObjectAttribute = game.getState().getMageObjectAttribute(getId()); if (mageObjectAttribute != null) { return mageObjectAttribute.getSubtype(); } - } + } return subtype; } @@ -174,6 +178,11 @@ public abstract class MageObjectImpl implements MageObject { } } + @Override + public ObjectColor getColor() { + return color; + } + @Override public ObjectColor getColor(Game game) { if (game != null) { @@ -181,7 +190,7 @@ public abstract class MageObjectImpl implements MageObject { if (mageObjectAttribute != null) { return mageObjectAttribute.getColor(); } - } + } return color; } @@ -240,7 +249,7 @@ public abstract class MageObjectImpl implements MageObject { if (value == null) { return false; } - if (value.getSubTypeSet() == SubTypeSet.CreatureType && isAllCreatureTypes()) { + if (value.getSubTypeSet() == SubTypeSet.CreatureType && isAllCreatureTypes(game)) { return true; } return getSubtype(game).contains(value); @@ -278,13 +287,18 @@ public abstract class MageObjectImpl implements MageObject { } @Override - public boolean isAllCreatureTypes() { - return isAllCreatureTypes; + public boolean isAllCreatureTypes(Game game) { + return this.getSubtype(game).isAllCreatureTypes(); } @Override public void setIsAllCreatureTypes(boolean value) { - isAllCreatureTypes = value && (this.isTribal() || this.isCreature()); + this.getSubtype().setIsAllCreatureTypes(value && (this.isTribal() || this.isCreature())); + } + + @Override + public void setIsAllCreatureTypes(Game game, boolean value) { + this.getSubtype(game).setIsAllCreatureTypes(value && (this.isTribal() || this.isCreature())); } @Override diff --git a/Mage/src/main/java/mage/abilities/abilityword/KinshipAbility.java b/Mage/src/main/java/mage/abilities/abilityword/KinshipAbility.java index c1c7aa687be..ae376ba893e 100644 --- a/Mage/src/main/java/mage/abilities/abilityword/KinshipAbility.java +++ b/Mage/src/main/java/mage/abilities/abilityword/KinshipAbility.java @@ -96,7 +96,7 @@ class KinshipBaseEffect extends OneShotEffect { if (card != null) { Cards cards = new CardsImpl(card); controller.lookAtCards(sourcePermanent.getName(), cards, game); - if (sourcePermanent.shareCreatureTypes(card, game)) { + if (sourcePermanent.shareCreatureTypes(game, card)) { if (controller.chooseUse(outcome, new StringBuilder("Kinship - Reveal ").append(card.getLogName()).append('?').toString(), source, game)) { controller.revealCards(sourcePermanent.getName(), cards, game); for (Effect effect : kinshipEffects) { diff --git a/Mage/src/main/java/mage/abilities/condition/common/EquippedHasSubtypeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/EquippedHasSubtypeCondition.java index cf77814bca2..23c8608d209 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/EquippedHasSubtypeCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/EquippedHasSubtypeCondition.java @@ -7,7 +7,9 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.SubTypeList; + +import java.util.ArrayList; +import java.util.List; /** * Describes condition when equipped permanent has subType @@ -16,35 +18,31 @@ import mage.util.SubTypeList; */ public class EquippedHasSubtypeCondition implements Condition { - private SubTypeList subTypes; // scope = Any + private final List subTypes = new ArrayList<>(); // scope = Any - public EquippedHasSubtypeCondition(SubTypeList subType) { - this.subTypes = subType; - } - - - public EquippedHasSubtypeCondition(SubType subType){ - subTypes = new SubTypeList(); - subTypes.add(subType); + public EquippedHasSubtypeCondition(SubType... subTypes) { + for (SubType subType : subTypes) { + this.subTypes.add(subType); + } } @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); - if (permanent != null && permanent.getAttachedTo() != null) { - Permanent attachedTo = game.getBattlefield().getPermanent(permanent.getAttachedTo()); - if (attachedTo == null) { - attachedTo = (Permanent) game.getLastKnownInformation(permanent.getAttachedTo(), Zone.BATTLEFIELD); - } - if (attachedTo != null) { - - for (SubType s : subTypes) { - if (attachedTo.hasSubtype(s, game)) { - return true; - } - } - + if (permanent == null || permanent.getAttachedTo() == null) { + return false; + } + Permanent attachedTo = game.getBattlefield().getPermanent(permanent.getAttachedTo()); + if (attachedTo == null) { + attachedTo = (Permanent) game.getLastKnownInformation(permanent.getAttachedTo(), Zone.BATTLEFIELD); + } + if (attachedTo == null) { + return false; + } + for (SubType s : subTypes) { + if (attachedTo.hasSubtype(s, game)) { + return true; } } return false; diff --git a/Mage/src/main/java/mage/abilities/condition/common/ProwlCondition.java b/Mage/src/main/java/mage/abilities/condition/common/ProwlCondition.java index 053e17e7778..9b9c13e356f 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/ProwlCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/ProwlCondition.java @@ -3,7 +3,6 @@ package mage.abilities.condition.common; import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.cards.Card; -import mage.constants.SubType; import mage.game.Game; import mage.watchers.common.ProwlWatcher; @@ -20,13 +19,8 @@ public enum ProwlCondition implements Condition { public boolean apply(Game game, Ability source) { ProwlWatcher watcher = game.getState().getWatcher(ProwlWatcher.class); Card card = game.getCard(source.getSourceId()); - if (watcher != null && card != null) { - for (SubType subtype : card.getSubtype(game)) { - if (watcher.hasSubtypeMadeCombatDamage(source.getControllerId(), subtype)) { - return true; - } - } - } - return false; + return watcher != null + && card != null + && watcher.hasSubtypeMadeCombatDamage(source.getControllerId(), card, game); } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/SourceHasSubtypeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SourceHasSubtypeCondition.java index dd8b2ecd3c4..9dc9fcd949f 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/SourceHasSubtypeCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/SourceHasSubtypeCondition.java @@ -5,33 +5,31 @@ import mage.abilities.condition.Condition; import mage.constants.SubType; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.SubTypeList; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** - * * @author Quercitron */ public class SourceHasSubtypeCondition implements Condition { - private final SubTypeList subtypes; + private final List subtypes = new ArrayList<>(); - public SourceHasSubtypeCondition(SubTypeList subtypes) { - this.subtypes = subtypes; - } - - public SourceHasSubtypeCondition(SubType subType){ - subtypes = new SubTypeList(); - subtypes.add(subType); + public SourceHasSubtypeCondition(SubType... subTypes) { + this.subtypes.addAll(Arrays.asList(subTypes)); } @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - for (SubType subtype : subtypes) { - if (permanent.hasSubtype(subtype, game)) { - return true; - } + if (permanent == null) { + return false; + } + for (SubType subtype : subtypes) { + if (permanent.hasSubtype(subtype, game)) { + return true; } } return false; diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestSharedCreatureTypeCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestSharedCreatureTypeCount.java index b2571d27ac7..220399cb10a 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestSharedCreatureTypeCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestSharedCreatureTypeCount.java @@ -1,6 +1,5 @@ package mage.abilities.dynamicvalue.common; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; @@ -34,10 +33,10 @@ public enum GreatestSharedCreatureTypeCount implements DynamicValue { int changelings = permanentList .stream() .filter(Objects::nonNull) - .filter(MageObject::isAllCreatureTypes) + .filter(permanent1 -> permanent1.isAllCreatureTypes(game)) .mapToInt(x -> 1) .sum(); - permanentList.removeIf(MageObject::isAllCreatureTypes); + permanentList.removeIf(permanent1 -> permanent1.isAllCreatureTypes(game)); Map typeMap = new HashMap<>(); permanentList .stream() diff --git a/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java index bbe980d2b8e..1c63d550e6c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java @@ -8,13 +8,14 @@ package mage.abilities.effects.common; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.ReplacementEffectImpl; +import mage.cards.Card; import mage.cards.Cards; import mage.cards.CardsImpl; import mage.constants.Duration; import mage.constants.Outcome; -import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardIdPredicate; import mage.game.Game; @@ -24,9 +25,6 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInHand; -import java.util.ArrayList; -import java.util.List; - /** * Effect for the AmplifyAbility *

@@ -74,6 +72,19 @@ public class AmplifyEffect extends ReplacementEffectImpl { } } + private static class AmplifyPredicate implements Predicate { + private final Card card; + + private AmplifyPredicate(Card card) { + this.card = card; + } + + @Override + public boolean apply(Card input, Game game) { + return input.shareCreatureTypes(game, card); + } + } + public AmplifyEffect(AmplifyFactor amplifyFactor) { super(Duration.EndOfGame, Outcome.BoostCreature); this.amplifyFactor = amplifyFactor; @@ -98,36 +109,31 @@ public class AmplifyEffect extends ReplacementEffectImpl { public boolean replaceEvent(GameEvent event, Ability source, Game game) { Permanent sourceCreature = ((EntersTheBattlefieldEvent) event).getTarget(); Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && sourceCreature != null) { - FilterCreatureCard filter = new FilterCreatureCard("creatures cards to reveal"); - List filterSubtypes = new ArrayList<>(); - for (SubType subtype : sourceCreature.getSubtype(game)) { - filterSubtypes.add(subtype.getPredicate()); - } - if (filterSubtypes.size() > 1) { - filter.add(Predicates.or(filterSubtypes)); - } else if (filterSubtypes.size() == 1) { - filter.add(filterSubtypes.get(0)); - } + if (controller == null || sourceCreature == null) { + return false; + } + FilterCreatureCard filter = new FilterCreatureCard("creatures cards to reveal"); + filter.add(new AmplifyPredicate(sourceCreature)); - // You can’t reveal this card or any other cards that are entering the battlefield at the same time as this card. - filter.add(Predicates.not(new CardIdPredicate(source.getSourceId()))); - for (Permanent enteringPermanent : game.getPermanentsEntering().values()) { - filter.add(Predicates.not(new CardIdPredicate(enteringPermanent.getId()))); - } + // You can’t reveal this card or any other cards that are entering the battlefield at the same time as this card. + filter.add(Predicates.not(new CardIdPredicate(source.getSourceId()))); + for (Permanent enteringPermanent : game.getPermanentsEntering().values()) { + filter.add(Predicates.not(new CardIdPredicate(enteringPermanent.getId()))); + } - if (controller.getHand().count(filter, source.getSourceId(), source.getControllerId(), game) > 0) { - if (controller.chooseUse(outcome, "Reveal cards to Amplify?", source, game)) { - TargetCardInHand target = new TargetCardInHand(0, Integer.MAX_VALUE, filter); - if (controller.chooseTarget(outcome, target, source, game) && !target.getTargets().isEmpty()) { - Cards cards = new CardsImpl(); - cards.addAll(target.getTargets()); - int amountCounters = cards.size() * amplifyFactor.getFactor(); - sourceCreature.addCounters(CounterType.P1P1.createInstance(amountCounters), source, game); - controller.revealCards(sourceCreature.getIdName(), cards, game); - } - } - } + if (controller.getHand().count(filter, source.getSourceId(), source.getControllerId(), game) <= 0) { + return false; + } + if (!controller.chooseUse(outcome, "Reveal cards to Amplify?", source, game)) { + return false; + } + TargetCardInHand target = new TargetCardInHand(0, Integer.MAX_VALUE, filter); + if (controller.chooseTarget(outcome, target, source, game) && !target.getTargets().isEmpty()) { + Cards cards = new CardsImpl(); + cards.addAll(target.getTargets()); + int amountCounters = cards.size() * amplifyFactor.getFactor(); + sourceCreature.addCounters(CounterType.P1P1.createInstance(amountCounters), source, game); + controller.revealCards(sourceCreature.getIdName(), cards, game); } return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java index c857261bac2..4ff4e4bac94 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java @@ -10,7 +10,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; import mage.game.permanent.PermanentToken; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.util.UUID; @@ -25,7 +25,7 @@ public class CopyEffect extends ContinuousEffectImpl { protected MageObject copyFromObject; protected UUID copyToObjectId; - protected ApplyToPermanent applier; + protected CopyApplier applier; public CopyEffect(MageObject copyFromObject, UUID copyToObjectId) { this(Duration.Custom, copyFromObject, copyToObjectId); @@ -105,8 +105,7 @@ public class CopyEffect extends ContinuousEffectImpl { } permanent.removeAllSubTypes(game); - permanent.getSubtype(game).addAll(copyFromObject.getSubtype(game)); - permanent.setIsAllCreatureTypes(copyFromObject.isAllCreatureTypes()); + permanent.copySubTypesFrom(game, copyFromObject); permanent.getSuperType().clear(); for (SuperType type : copyFromObject.getSuperType()) { @@ -165,11 +164,11 @@ public class CopyEffect extends ContinuousEffectImpl { return copyToObjectId; } - public ApplyToPermanent getApplier() { + public CopyApplier getApplier() { return applier; } - public void setApplier(ApplyToPermanent applier) { + public void setApplier(CopyApplier applier) { this.applier = applier; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java index d95d1021bc2..62b1a840f63 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java @@ -16,8 +16,8 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.TargetPermanent; -import mage.util.functions.ApplyToPermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.CopyApplier; +import mage.util.functions.EmptyCopyApplier; import java.util.UUID; @@ -27,7 +27,7 @@ import java.util.UUID; public class CopyPermanentEffect extends OneShotEffect { private final FilterPermanent filter; - private final ApplyToPermanent applier; + private final CopyApplier applier; private final boolean useTargetOfAbility; private Permanent bluePrintPermanent; private Duration duration = Duration.Custom; @@ -36,19 +36,19 @@ public class CopyPermanentEffect extends OneShotEffect { this(StaticFilters.FILTER_PERMANENT_CREATURE); } - public CopyPermanentEffect(ApplyToPermanent applier) { + public CopyPermanentEffect(CopyApplier applier) { this(StaticFilters.FILTER_PERMANENT_CREATURE, applier); } public CopyPermanentEffect(FilterPermanent filter) { - this(filter, new EmptyApplyToPermanent()); + this(filter, new EmptyCopyApplier()); } - public CopyPermanentEffect(FilterPermanent filter, ApplyToPermanent applier) { + public CopyPermanentEffect(FilterPermanent filter, CopyApplier applier) { this(filter, applier, false); } - public CopyPermanentEffect(FilterPermanent filter, ApplyToPermanent applier, boolean useTarget) { + public CopyPermanentEffect(FilterPermanent filter, CopyApplier applier, boolean useTarget) { super(Outcome.Copy); this.applier = applier; this.filter = filter; diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java index 833f89e9992..4f7894c997a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java @@ -32,10 +32,7 @@ public class CopyTokenEffect extends ContinuousEffectImpl { permanent.addCardType(type); } permanent.removeAllSubTypes(game); - for (SubType type : token.getSubtype(game)) { - permanent.addSubType(game, type); - } - permanent.setIsAllCreatureTypes(token.isAllCreatureTypes()); + permanent.copySubTypesFrom(game, token); permanent.getSuperType().clear(); for (SuperType type : token.getSuperType()) { permanent.addSuperType(type); diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java index b0477f5c862..69e9a2f118c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java @@ -17,8 +17,8 @@ import mage.game.permanent.Permanent; import mage.game.permanent.token.EmptyToken; import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; -import mage.util.functions.ApplyToPermanent; -import mage.util.functions.EmptyApplyToPermanent; +import mage.util.functions.CopyApplier; +import mage.util.functions.EmptyCopyApplier; import java.util.ArrayList; import java.util.Arrays; @@ -141,7 +141,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { // can target card or permanent Card copyFrom; - ApplyToPermanent applier = new EmptyApplyToPermanent(); + CopyApplier applier = new EmptyCopyApplier(); if (permanent != null) { // handle copies of copies Permanent copyFromPermanent = permanent; @@ -169,6 +169,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { return false; } + // create token and modify all attributes permanently (without game usage) EmptyToken token = new EmptyToken(); CardUtil.copyTo(token).from(copyFrom, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer) applier.apply(game, token, source, targetId); @@ -200,14 +201,14 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { token.getToughness().modifyBaseValue(tokenToughness); } if (onlySubType != null) { - token.removeAllCreatureTypes(game); - token.addSubType(game, onlySubType); + token.removeAllCreatureTypes(); + token.addSubType(onlySubType); } - if (additionalSubType != null && !token.hasSubtype(additionalSubType, game)) { - token.addSubType(game, additionalSubType); + if (additionalSubType != null) { + token.addSubType(additionalSubType); } if (color != null) { - token.getColor(game).setColor(color); + token.getColor().setColor(color); } additionalAbilities.stream().forEach(token::addAbility); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java index bf226a50b51..bf613364a5d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java @@ -15,7 +15,6 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetControlledCreaturePermanent; -import mage.util.SubTypeList; import java.util.ArrayList; import java.util.Collections; @@ -87,12 +86,12 @@ public class DevourEffect extends ReplacementEffectImpl { if (controller.chooseUse(Outcome.Detriment, "Devour creatures?", source, game)) { controller.chooseTarget(Outcome.Detriment, target, source, game); if (!target.getTargets().isEmpty()) { - List cardSubtypes = new ArrayList<>(); + List creaturesDevoured = new ArrayList<>(); int devouredCreatures = 0; for (UUID targetId : target.getTargets()) { Permanent targetCreature = game.getPermanent(targetId); if (targetCreature != null && targetCreature.sacrifice(source, game)) { - cardSubtypes.add(targetCreature.getSubtype(game)); + creaturesDevoured.add(targetCreature); devouredCreatures++; } } @@ -108,7 +107,7 @@ public class DevourEffect extends ReplacementEffectImpl { amountCounters = devouredCreatures * devourFactor.getFactor(); } creature.addCounters(CounterType.P1P1.createInstance(amountCounters), source, game); - game.getState().setValue(creature.getId().toString() + "devoured", cardSubtypes); + game.getState().setValue(creature.getId().toString() + "devoured", creaturesDevoured); } } @@ -124,10 +123,10 @@ public class DevourEffect extends ReplacementEffectImpl { return sb.toString(); } - public List getSubtypes(Game game, UUID permanentId) { + public List getDevouredCreatures(Game game, UUID permanentId) { Object object = game.getState().getValue(permanentId.toString() + "devoured"); if (object != null) { - return (List) object; + return (List) object; } return Collections.emptyList(); } @@ -135,7 +134,7 @@ public class DevourEffect extends ReplacementEffectImpl { public int getDevouredCreaturesAmount(Game game, UUID permanentId) { Object object = game.getState().getValue(permanentId.toString() + "devoured"); if (object != null) { - return ((List) object).size(); + return ((List) object).size(); } return 0; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java index d7b789d6cae..d73b816f046 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java @@ -42,8 +42,8 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl { return false; } // lands intrictically have the mana ability associated with their type, so added here in layer 4 - permanent.getSubtype(game).removeAll(SubType.getLandTypes()); - permanent.getSubtype(game).addAll(landTypes); + permanent.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); + permanent.addSubType(game, landTypes); permanent.removeAllAbilities(source.getSourceId(), game); for (SubType landType : landTypes) { switch (landType) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java index dd30acc1ff9..ef33949bbc8 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java @@ -117,8 +117,8 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl { // So the ability removing has to be done before Layer 6 land.removeAllAbilities(source.getSourceId(), game); // 305.7 - land.getSubtype(game).removeAll(SubType.getLandTypes()); - land.getSubtype(game).addAll(landTypes); + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); + land.addSubType(game, landTypes); } else { landTypesToAdd.clear(); for (SubType subtype : landTypes) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java index ba392ef745c..df40a86c3f0 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java @@ -104,10 +104,7 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl { if (theyAreStillType != null || loseTypes) { permanent.removeAllCreatureTypes(game); } - for (SubType t : token.getSubtype(game)) { - permanent.addSubType(game, t); - } - permanent.setIsAllCreatureTypes(token.isAllCreatureTypes()); + permanent.copySubTypesFrom(game, token); for (SuperType t : token.getSuperType()) { if (!permanent.getSuperType().contains(t)) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java index 5369d5465a3..18e276333ff 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java @@ -53,85 +53,78 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null) { - Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - for (SuperType t : token.getSuperType()) { - permanent.addSuperType(t); - - } - // card type - switch (loseType) { - case ALL: - case ALL_BUT_COLOR: - permanent.getCardType().clear(); - break; - } - for (CardType t : token.getCardType()) { - permanent.addCardType(t); - } - - // sub type - switch (loseType) { - case ALL: - case ALL_BUT_COLOR: - permanent.removeAllSubTypes(game); - break; - case ABILITIES_SUBTYPE: - permanent.removeAllCreatureTypes(game); - break; - } - for (SubType t : token.getSubtype(game)) { - permanent.addSubType(game, t); - } - } - break; - - case ColorChangingEffects_5: - if (sublayer == SubLayer.NA) { - if (loseType == LoseType.ALL || loseType == LoseType.COLOR) { - permanent.getColor(game).setWhite(false); - permanent.getColor(game).setBlue(false); - permanent.getColor(game).setBlack(false); - permanent.getColor(game).setRed(false); - permanent.getColor(game).setGreen(false); - } - if (token.getColor(game).hasColor()) { - permanent.getColor(game).addColor(token.getColor(game)); - } - } - break; - - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - switch (loseType) { - case ALL: - case ALL_BUT_COLOR: - case ABILITIES: - case ABILITIES_SUBTYPE: - permanent.removeAllAbilities(source.getSourceId(), game); - break; - } - for (Ability ability : token.getAbilities()) { - permanent.addAbility(ability, source.getSourceId(), game); - } - } - break; - - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - permanent.getPower().setValue(token.getPower().getValue()); - permanent.getToughness().setValue(token.getToughness().getValue()); - } - break; - } - } + if (enchantment == null) { + return false; + } + Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); + if (permanent == null) { return true; } - return false; + switch (layer) { + case TypeChangingEffects_4: + for (SuperType t : token.getSuperType()) { + permanent.addSuperType(t); + + } + // card type + switch (loseType) { + case ALL: + case ALL_BUT_COLOR: + permanent.getCardType().clear(); + break; + } + for (CardType t : token.getCardType()) { + permanent.addCardType(t); + } + + // sub type + switch (loseType) { + case ALL: + case ALL_BUT_COLOR: + permanent.removeAllSubTypes(game); + break; + case ABILITIES_SUBTYPE: + permanent.removeAllCreatureTypes(game); + break; + } + permanent.copySubTypesFrom(game, token); + break; + + case ColorChangingEffects_5: + if (loseType == LoseType.ALL || loseType == LoseType.COLOR) { + permanent.getColor(game).setWhite(false); + permanent.getColor(game).setBlue(false); + permanent.getColor(game).setBlack(false); + permanent.getColor(game).setRed(false); + permanent.getColor(game).setGreen(false); + } + if (token.getColor(game).hasColor()) { + permanent.getColor(game).addColor(token.getColor(game)); + } + break; + + case AbilityAddingRemovingEffects_6: + switch (loseType) { + case ALL: + case ALL_BUT_COLOR: + case ABILITIES: + case ABILITIES_SUBTYPE: + permanent.removeAllAbilities(source.getSourceId(), game); + break; + } + for (Ability ability : token.getAbilities()) { + permanent.addAbility(ability, source.getSourceId(), game); + } + break; + + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setValue(token.getPower().getValue()); + permanent.getToughness().setValue(token.getToughness().getValue()); + } + break; + } + return true; } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java index ab88478ab1c..b9c3f839a09 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java @@ -101,12 +101,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements || theyAreStillType == null && permanent.isLand()) { permanent.removeAllCreatureTypes(game); } - if (!token.getSubtype(game).isEmpty()) { - for (SubType subType : token.getSubtype(game)) { - permanent.addSubType(game, subType); - } - } - permanent.setIsAllCreatureTypes(token.isAllCreatureTypes()); + permanent.copySubTypesFrom(game, token); break; case ColorChangingEffects_5: diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java index 630d3013015..462b2ae55ed 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java @@ -87,9 +87,7 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl { if (loseAllAbilities || removeSubtypes) { permanent.removeAllCreatureTypes(game); } - for (SubType t : token.getSubtype(game)) { - permanent.addSubType(game, t); - } + permanent.copySubTypesFrom(game, token); for (SuperType t : token.getSuperType()) { if (!permanent.getSuperType().contains(t)) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java index 68a8b7deead..9fa28ad10ae 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java @@ -5,8 +5,10 @@ import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.SubTypeList; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.UUID; /** @@ -14,22 +16,22 @@ import java.util.UUID; */ public class BecomesCreatureTypeTargetEffect extends ContinuousEffectImpl { - private final SubTypeList subtypes = new SubTypeList(); + private final List subtypes = new ArrayList<>(); private final boolean loseOther; // loses other creature types public BecomesCreatureTypeTargetEffect(Duration duration, SubType subtype) { - this(duration, new SubTypeList(subtype)); + this(duration, Arrays.asList(subtype)); } public BecomesCreatureTypeTargetEffect(Duration duration, SubType subtype, boolean loseOther) { - this(duration, new SubTypeList(subtype), loseOther); + this(duration, Arrays.asList(subtype), loseOther); } - public BecomesCreatureTypeTargetEffect(Duration duration, SubTypeList subtypes) { + public BecomesCreatureTypeTargetEffect(Duration duration, List subtypes) { this(duration, subtypes, true); } - public BecomesCreatureTypeTargetEffect(Duration duration, SubTypeList subtypes, boolean loseOther) { + public BecomesCreatureTypeTargetEffect(Duration duration, List subtypes, boolean loseOther) { super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); this.subtypes.addAll(subtypes); this.staticText = setText(); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesEnchantmentSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesEnchantmentSourceEffect.java index 35d94fe5e95..98e0cf83ba9 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesEnchantmentSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesEnchantmentSourceEffect.java @@ -42,8 +42,8 @@ public class BecomesEnchantmentSourceEffect extends ContinuousEffectImpl impleme } permanent.getCardType().clear(); permanent.getCardType().add(CardType.ENCHANTMENT); - permanent.getSubtype(game).retainAll(SubType.getEnchantmentTypes()); - permanent.setIsAllCreatureTypes(false); + permanent.retainAllEnchantmentSubTypes(game); + permanent.setIsAllCreatureTypes(game, false); return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java index a11f9aeb370..ad2f6806710 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java @@ -12,26 +12,29 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.SubTypeList; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** * @author LevelX2 */ public class BecomesSubtypeAllEffect extends ContinuousEffectImpl { - private final SubTypeList subtypes = new SubTypeList(); + private final List subtypes = new ArrayList<>(); private final boolean loseOther; // loses other subtypes private final FilterCreaturePermanent filter; public BecomesSubtypeAllEffect(Duration duration, SubType subtype) { - this(duration, new SubTypeList(subtype)); + this(duration, Arrays.asList(subtype)); } - public BecomesSubtypeAllEffect(Duration duration, SubTypeList subtypes) { + public BecomesSubtypeAllEffect(Duration duration, List subtypes) { this(duration, subtypes, StaticFilters.FILTER_PERMANENT_CREATURE, true); } - public BecomesSubtypeAllEffect(Duration duration, SubTypeList subtypes, FilterCreaturePermanent filter, boolean loseOther) { + public BecomesSubtypeAllEffect(Duration duration, List subtypes, FilterCreaturePermanent filter, boolean loseOther) { super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); this.subtypes.addAll(subtypes); this.staticText = setText(); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAllCreatureTypesAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAllCreatureTypesAttachedEffect.java index a9473a5103f..cb30e34ab23 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAllCreatureTypesAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAllCreatureTypesAttachedEffect.java @@ -38,7 +38,7 @@ public class GainAllCreatureTypesAttachedEffect extends ContinuousEffectImpl { if (permanent == null) { return false; } - permanent.setIsAllCreatureTypes(true); + permanent.setIsAllCreatureTypes(game, true); return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAllCreatureTypesTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAllCreatureTypesTargetEffect.java index da286872276..016fc758ebc 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAllCreatureTypesTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAllCreatureTypesTargetEffect.java @@ -36,7 +36,7 @@ public class GainAllCreatureTypesTargetEffect extends ContinuousEffectImpl { for (UUID permanentId : targetPointer.getTargets(game, source)) { Permanent target = game.getPermanent(permanentId); if (target != null) { - target.setIsAllCreatureTypes(true); + target.setIsAllCreatureTypes(game, true); affectedTargets++; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/HasSubtypesSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/HasSubtypesSourceEffect.java index 1b444035e24..2f85363577c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/HasSubtypesSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/HasSubtypesSourceEffect.java @@ -5,18 +5,21 @@ import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; import mage.game.Game; -import mage.util.SubTypeList; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** * @author TheElk801 */ public class HasSubtypesSourceEffect extends ContinuousEffectImpl { - private final SubTypeList subtypes = new SubTypeList(); + private final List subtypes = new ArrayList<>(); public HasSubtypesSourceEffect(SubType... subTypes) { super(Duration.EndOfGame, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); - subtypes.add(subTypes); + subtypes.addAll(Arrays.asList(subTypes)); this.staticText = setText(); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/IsAllCreatureTypesSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/IsAllCreatureTypesSourceEffect.java new file mode 100644 index 00000000000..38b3ef6de37 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/IsAllCreatureTypesSourceEffect.java @@ -0,0 +1,40 @@ +package mage.abilities.effects.common.continuous; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.game.Game; + +/** + * @author TheElk801 + */ +public class IsAllCreatureTypesSourceEffect extends ContinuousEffectImpl { + + public IsAllCreatureTypesSourceEffect() { + super(Duration.Custom, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); + this.staticText = "{this} is every creature type (even if this card isn't on the battlefield)."; + } + + private IsAllCreatureTypesSourceEffect(final IsAllCreatureTypesSourceEffect effect) { + super(effect); + } + + @Override + public IsAllCreatureTypesSourceEffect copy() { + return new IsAllCreatureTypesSourceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + MageObject sourceObject = game.getObject(source.getSourceId()); + if (sourceObject == null) { + return false; + } + sourceObject.setIsAllCreatureTypes(game, true); + return true; + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseArtifactTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseArtifactTypeTargetEffect.java index edff38e9663..9a3b33533e7 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseArtifactTypeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseArtifactTypeTargetEffect.java @@ -40,34 +40,19 @@ public class LoseArtifactTypeTargetEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { for (UUID targetId : targetPointer.getTargets(game, source)) { - if (targetId != null) { - Permanent permanent = game.getPermanent(targetId); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.getCardType().remove(CardType.ARTIFACT); - permanent.getSubtype(game).removeAll(SubType.getArtifactTypes()); - } - break; - } - return true; - } + if (targetId == null) { + continue; } + Permanent permanent = game.getPermanent(targetId); + if (permanent == null) { + continue; + } + permanent.getCardType().remove(CardType.ARTIFACT); + permanent.removeAllSubTypes(game, SubTypeSet.ArtifactType); + return true; } return false; } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/SetCardSubtypeAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/SetCardSubtypeAttachedEffect.java index fe82e4e7b02..5979e39f485 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/SetCardSubtypeAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/SetCardSubtypeAttachedEffect.java @@ -5,19 +5,22 @@ import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.SubTypeList; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** * @author nantuko */ public class SetCardSubtypeAttachedEffect extends ContinuousEffectImpl { - private SubTypeList setSubtypes = new SubTypeList(); + private List setSubtypes = new ArrayList<>(); private final AttachmentType attachmentType; public SetCardSubtypeAttachedEffect(Duration duration, AttachmentType attachmentType, SubType... setSubtype) { super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); - this.setSubtypes.add(setSubtype); + this.setSubtypes.addAll(Arrays.asList(setSubtype)); this.attachmentType = attachmentType; this.setText(); } @@ -39,7 +42,7 @@ public class SetCardSubtypeAttachedEffect extends ContinuousEffectImpl { return true; } target.removeAllCreatureTypes(game); - target.getSubtype(game).addAll(setSubtypes); + target.addSubType(game, setSubtypes); return true; } diff --git a/Mage/src/main/java/mage/abilities/keyword/BestowAbility.java b/Mage/src/main/java/mage/abilities/keyword/BestowAbility.java index e9ce835df98..ab10559bd4d 100644 --- a/Mage/src/main/java/mage/abilities/keyword/BestowAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/BestowAbility.java @@ -122,15 +122,16 @@ public class BestowAbility extends SpellAbility { } static public void becomeCreature(Permanent permanent, Game game) { + // permanently changes to the object if (permanent != null) { MageObject basicObject = permanent.getBasicMageObject(game); if (basicObject != null) { - basicObject.getSubtype(null).remove(SubType.AURA); + basicObject.getSubtype().remove(SubType.AURA); if (!basicObject.isCreature()) { basicObject.addCardType(CardType.CREATURE); } } - permanent.getSubtype(null).remove(SubType.AURA); + permanent.getSubtype().remove(SubType.AURA); if (!permanent.isCreature()) { permanent.addCardType(CardType.CREATURE); } @@ -139,8 +140,9 @@ public class BestowAbility extends SpellAbility { } static public void becomeAura(Card card) { + // permanently changes to the object if (card != null) { - card.getSubtype(null).add(SubType.AURA); + card.addSubType(SubType.AURA); card.getCardType().remove(CardType.CREATURE); card.getCardType().add(CardType.ENCHANTMENT); } @@ -173,7 +175,7 @@ class BestowEntersBattlefieldEffect extends ReplacementEffectImpl { if (bestowPermanent != null) { if (bestowPermanent.hasSubtype(SubType.AURA, game)) { MageObject basicObject = bestowPermanent.getBasicMageObject(game); - if (basicObject != null && !basicObject.getSubtype(null).contains(SubType.AURA)) { + if (basicObject != null && !basicObject.getSubtype().contains(SubType.AURA)) { basicObject.getSubtype(null).add(SubType.AURA); basicObject.getCardType().remove(CardType.CREATURE); } diff --git a/Mage/src/main/java/mage/abilities/keyword/ChangelingAbility.java b/Mage/src/main/java/mage/abilities/keyword/ChangelingAbility.java index 7a0ef7dbb1d..2be76663b52 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ChangelingAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ChangelingAbility.java @@ -1,36 +1,27 @@ - - package mage.abilities.keyword; -import mage.abilities.MageSingleton; import mage.abilities.StaticAbility; +import mage.abilities.effects.common.continuous.IsAllCreatureTypesSourceEffect; import mage.constants.Zone; -import java.io.ObjectStreamException; - /** * October 1, 2012 * 702.71. Changeling - * 702.71a Changeling is a characteristic-defining ability. "Changeling" means "This object - * is every creature type." This ability works everywhere, even outside the game. See rule 604.3. - * 702.71b Multiple instances of changeling on the same object are redundant. + * 702.71a Changeling is a characteristic-defining ability. "Changeling" means "This object + * is every creature type." This ability works everywhere, even outside the game. See rule 604.3. + * 702.71b Multiple instances of changeling on the same object are redundant. * * @author nantuko */ -public class ChangelingAbility extends StaticAbility implements MageSingleton { - private static final ChangelingAbility instance = new ChangelingAbility(); +public class ChangelingAbility extends StaticAbility { - private Object readResolve() throws ObjectStreamException { - return instance; + public ChangelingAbility() { + super(Zone.ALL, new IsAllCreatureTypesSourceEffect()); } - public static ChangelingAbility getInstance() { - return instance; - } - - private ChangelingAbility() { - super(Zone.ALL, null); + private ChangelingAbility(final ChangelingAbility ability) { + super(ability); } @Override @@ -40,6 +31,6 @@ public class ChangelingAbility extends StaticAbility implements MageSingleton { @Override public ChangelingAbility copy() { - return instance; + return new ChangelingAbility(this); } } diff --git a/Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java b/Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java index 0beb2103502..8ba79f0a687 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java @@ -51,7 +51,7 @@ public class EmbalmAbility extends ActivatedAbilityImpl { StringBuilder sb = new StringBuilder("Embalm ").append(cost.getText()); sb.append(" (").append(cost.getText()); sb.append(", Exile this card from your graveyard: Create a token that's a copy of it, except it's a white Zombie "); - for (SubType subtype : card.getSubtype(null)) { + for (SubType subtype : card.getSubtype()) { sb.append(subtype).append(" "); } sb.append(" with no mana cost. Embalm only as a sorcery.)"); @@ -84,10 +84,12 @@ class EmbalmEffect extends OneShotEffect { if (controller == null) { return false; } + + // create token and modify all attributes permanently (without game usage) EmptyToken token = new EmptyToken(); CardUtil.copyTo(token).from(card, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer) - token.getColor(game).setColor(ObjectColor.WHITE); - token.addSubType(game, SubType.ZOMBIE); + token.getColor().setColor(ObjectColor.WHITE); + token.addSubType(SubType.ZOMBIE); token.getManaCost().clear(); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.EMBALMED_CREATURE, token.getId(), source, controller.getId())); token.putOntoBattlefield(1, game, source, controller.getId(), false, false, null); diff --git a/Mage/src/main/java/mage/abilities/keyword/EternalizeAbility.java b/Mage/src/main/java/mage/abilities/keyword/EternalizeAbility.java index 92691a7ec2c..4d930718fbb 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EternalizeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EternalizeAbility.java @@ -56,7 +56,7 @@ public class EternalizeAbility extends ActivatedAbilityImpl { StringBuilder sb = new StringBuilder("Eternalize ").append(cost.getText()); sb.append(" (").append(cost.getText()); sb.append(", Exile this card from your graveyard: Create a token that's a copy of it, except it's a 4/4 black Zombie "); - for (SubType subtype : card.getSubtype(null)) { + for (SubType subtype : card.getSubtype()) { sb.append(subtype).append(" "); } sb.append(" with no mana cost. Eternalize only as a sorcery.)"); @@ -89,10 +89,12 @@ class EternalizeEffect extends OneShotEffect { if (controller == null) { return false; } + + // create token and modify all attributes permanently (without game usage) EmptyToken token = new EmptyToken(); CardUtil.copyTo(token).from(card, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer) - token.getColor(game).setColor(ObjectColor.BLACK); - token.addSubType(game, SubType.ZOMBIE); + token.getColor().setColor(ObjectColor.BLACK); + token.addSubType(SubType.ZOMBIE); token.getManaCost().clear(); token.removePTCDA(); token.getPower().modifyBaseValue(4); diff --git a/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java b/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java index 6e7d82d9656..39904a2d41a 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java @@ -285,11 +285,11 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost mageObject.getPower().modifyBaseValue(2); mageObject.getToughness().modifyBaseValue(2); mageObject.getAbilities().clear(); - mageObject.getColor(null).setColor(new ObjectColor()); + mageObject.getColor().setColor(new ObjectColor()); mageObject.setName(""); mageObject.getCardType().clear(); mageObject.addCardType(CardType.CREATURE); - mageObject.getSubtype(null).clear(); + mageObject.getSubtype().clear(); mageObject.getSuperType().clear(); mageObject.getManaCost().clear(); if (mageObject instanceof Permanent) { diff --git a/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java b/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java index 025c6cebcb4..f9cff425b6a 100644 --- a/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java @@ -53,10 +53,7 @@ public class TransformAbility extends SimpleStaticAbility { permanent.addCardType(type); } permanent.removeAllSubTypes(game); - permanent.setIsAllCreatureTypes(sourceCard.isAllCreatureTypes()); - for (SubType type : sourceCard.getSubtype(game)) { - permanent.addSubType(game, type); - } + permanent.copySubTypesFrom(game, sourceCard); permanent.getSuperType().clear(); for (SuperType type : sourceCard.getSuperType()) { permanent.addSuperType(type); diff --git a/Mage/src/main/java/mage/cards/ModalDoubleFacesCard.java b/Mage/src/main/java/mage/cards/ModalDoubleFacesCard.java index 94b919b5768..36861d80d06 100644 --- a/Mage/src/main/java/mage/cards/ModalDoubleFacesCard.java +++ b/Mage/src/main/java/mage/cards/ModalDoubleFacesCard.java @@ -10,7 +10,7 @@ import mage.constants.*; import mage.game.Game; import mage.game.events.ZoneChangeEvent; import mage.util.CardUtil; -import mage.util.SubTypeList; +import mage.util.SubTypes; import java.util.ArrayList; import java.util.EnumSet; @@ -136,9 +136,15 @@ public abstract class ModalDoubleFacesCard extends CardImpl { } @Override - public SubTypeList getSubtype(Game game) { + public SubTypes getSubtype() { // rules: While a double-faced card isn’t on the stack or battlefield, consider only the characteristics of its front face. + // CardImpl's constructor can call some code on init, so you must check left/right before + return leftHalfCard != null ? leftHalfCard.getSubtype() : subtype; + } + @Override + public SubTypes getSubtype(Game game) { + // rules: While a double-faced card isn’t on the stack or battlefield, consider only the characteristics of its front face. // CardImpl's constructor can call some code on init, so you must check left/right before return leftHalfCard != null ? leftHalfCard.getSubtype(game) : subtype; } @@ -240,6 +246,11 @@ public abstract class ModalDoubleFacesCard extends CardImpl { return super.hasAbility(ability, game); } + @Override + public ObjectColor getColor() { + return leftHalfCard.getColor(); + } + @Override public ObjectColor getColor(Game game) { return leftHalfCard.getColor(game); diff --git a/Mage/src/main/java/mage/cards/repository/CardInfo.java b/Mage/src/main/java/mage/cards/repository/CardInfo.java index 0d674bfbc83..a3154258273 100644 --- a/Mage/src/main/java/mage/cards/repository/CardInfo.java +++ b/Mage/src/main/java/mage/cards/repository/CardInfo.java @@ -12,7 +12,7 @@ import mage.cards.mock.MockCard; import mage.cards.mock.MockSplitCard; import mage.constants.*; import mage.util.CardUtil; -import mage.util.SubTypeList; +import mage.util.SubTypes; import org.apache.log4j.Logger; import java.util.*; @@ -162,7 +162,7 @@ public class CardInfo { this.white = card.getColor(null).isWhite(); this.setTypes(card.getCardType()); - this.setSubtypes(card.getSubtype(null).stream().map(SubType::toString).collect(Collectors.toList())); + this.setSubtypes(card.getSubtype().stream().map(SubType::toString).collect(Collectors.toList())); this.setSuperTypes(card.getSuperType()); // mana cost can contains multiple cards (split left/right, modal double faces, card/adventure) @@ -367,8 +367,8 @@ public class CardInfo { this.rules = joinList(rules); } - public final SubTypeList getSubTypes() { - SubTypeList sl = new SubTypeList(); + public final SubTypes getSubTypes() { + SubTypes sl = new SubTypes(); if (subtypes.trim().isEmpty()) { return sl; } diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index cc4aa799630..8c54b9ac24a 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -594,4 +594,8 @@ public enum SubType { public static Set getLandTypes() { return landTypes; } + + public static Set getBySubTypeSet(SubTypeSet subTypeSet) { + return subTypeSetMap.get(subTypeSet); + } } diff --git a/Mage/src/main/java/mage/designations/Designation.java b/Mage/src/main/java/mage/designations/Designation.java index ebabcb7f56c..30263940c51 100644 --- a/Mage/src/main/java/mage/designations/Designation.java +++ b/Mage/src/main/java/mage/designations/Designation.java @@ -18,7 +18,7 @@ import mage.game.Game; import mage.game.events.ZoneChangeEvent; import mage.util.Copyable; import mage.util.GameLog; -import mage.util.SubTypeList; +import mage.util.SubTypes; import java.util.ArrayList; import java.util.EnumSet; @@ -156,8 +156,13 @@ public abstract class Designation implements MageObject, Copyable { } @Override - public SubTypeList getSubtype(Game game) { - return new SubTypeList(); + public SubTypes getSubtype() { + return new SubTypes(); + } + + @Override + public SubTypes getSubtype(Game game) { + return new SubTypes(); } @Override @@ -175,6 +180,11 @@ public abstract class Designation implements MageObject, Copyable { return this.getAbilities().contains(ability); } + @Override + public ObjectColor getColor() { + return emptyColor; + } + @Override public ObjectColor getColor(Game game) { return emptyColor; @@ -245,13 +255,16 @@ public abstract class Designation implements MageObject, Copyable { } @Override - public boolean isAllCreatureTypes() { + public boolean isAllCreatureTypes(Game game) { return false; } @Override public void setIsAllCreatureTypes(boolean value) { + } + @Override + public void setIsAllCreatureTypes(Game game, boolean value) { } @Override diff --git a/Mage/src/main/java/mage/filter/common/FilterOtherCreatureSharingCreatureSubtype.java b/Mage/src/main/java/mage/filter/common/FilterOtherCreatureSharingCreatureSubtype.java deleted file mode 100644 index 8a0443d7676..00000000000 --- a/Mage/src/main/java/mage/filter/common/FilterOtherCreatureSharingCreatureSubtype.java +++ /dev/null @@ -1,44 +0,0 @@ - -package mage.filter.common; - -import java.util.ArrayList; -import java.util.List; - -import mage.constants.SubType; -import mage.constants.SubTypeSet; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.PermanentIdPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; - -/** - * - * @author tschroeder - */ - -public class FilterOtherCreatureSharingCreatureSubtype extends FilterCreaturePermanent { - - public FilterOtherCreatureSharingCreatureSubtype(Permanent creature, Game game) { - super("creature sharing a creature type with " + creature.toString()); - - List subtypePredicates = new ArrayList<>(); - for (SubType subtype : creature.getSubtype(game)) { - if (subtype.getSubTypeSet() == SubTypeSet.CreatureType) { - subtypePredicates.add(subtype.getPredicate()); - } - } - this.add(Predicates.and( - Predicates.or(subtypePredicates), - Predicates.not(new PermanentIdPredicate(creature.getId())) - )); - } - - public FilterOtherCreatureSharingCreatureSubtype(final FilterOtherCreatureSharingCreatureSubtype filter) { - super(filter); - } - - @Override - public FilterOtherCreatureSharingCreatureSubtype copy() { - return new FilterOtherCreatureSharingCreatureSubtype(this); - } -} diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/SharesCreatureTypePredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/SharesCreatureTypePredicate.java new file mode 100644 index 00000000000..59b22fa7434 --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/permanent/SharesCreatureTypePredicate.java @@ -0,0 +1,23 @@ +package mage.filter.predicate.permanent; + +import mage.MageObject; +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author TheElk801 + */ +public class SharesCreatureTypePredicate implements Predicate { + + private final MageObject mageObject; + + public SharesCreatureTypePredicate(Permanent permanent) { + this.mageObject = permanent; + } + + @Override + public boolean apply(MageObject input, Game game) { + return mageObject != null && mageObject.shareCreatureTypes(game, input); + } +} diff --git a/Mage/src/main/java/mage/game/Game.java b/Mage/src/main/java/mage/game/Game.java index f7dd4aa8eb2..5e110d020ee 100644 --- a/Mage/src/main/java/mage/game/Game.java +++ b/Mage/src/main/java/mage/game/Game.java @@ -41,7 +41,7 @@ import mage.players.Player; import mage.players.PlayerList; import mage.players.Players; import mage.util.MessageToClient; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import java.io.Serializable; import java.util.*; @@ -411,9 +411,9 @@ public interface Game extends MageItem, Serializable { * @param applier * @return */ - Permanent copyPermanent(Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, ApplyToPermanent applier); + Permanent copyPermanent(Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, CopyApplier applier); - Permanent copyPermanent(Duration duration, Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, ApplyToPermanent applier); + Permanent copyPermanent(Duration duration, Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, CopyApplier applier); Card copyCard(Card cardToCopy, Ability source, UUID newController); diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 0d44f2c825d..33809cc1e4c 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -66,7 +66,7 @@ import mage.util.CardUtil; import mage.util.GameLog; import mage.util.MessageToClient; import mage.util.RandomUtil; -import mage.util.functions.ApplyToPermanent; +import mage.util.functions.CopyApplier; import mage.watchers.common.*; import org.apache.log4j.Logger; @@ -1651,12 +1651,12 @@ public abstract class GameImpl implements Game, Serializable { } @Override - public Permanent copyPermanent(Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, ApplyToPermanent applier) { + public Permanent copyPermanent(Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, CopyApplier applier) { return copyPermanent(Duration.Custom, copyFromPermanent, copyToPermanentId, source, applier); } @Override - public Permanent copyPermanent(Duration duration, Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, ApplyToPermanent applier) { + public Permanent copyPermanent(Duration duration, Permanent copyFromPermanent, UUID copyToPermanentId, Ability source, CopyApplier applier) { Permanent newBluePrint = null; // handle copies of copies for (Effect effect : getState().getContinuousEffects().getLayeredEffects(this)) { @@ -2231,9 +2231,9 @@ public abstract class GameImpl implements Game, Serializable { Permanent attachment = getPermanent(attachmentId); if (attachment != null && (attachment.isCreature() - || !(attachment.getSubtype(this).contains(SubType.AURA) - || attachment.getSubtype(this).contains(SubType.EQUIPMENT) - || attachment.getSubtype(this).contains(SubType.FORTIFICATION)))) { + || !(attachment.hasSubtype(SubType.AURA, this) + || attachment.hasSubtype(SubType.EQUIPMENT, this) + || attachment.hasSubtype(SubType.FORTIFICATION, this)))) { if (perm.removeAttachment(attachment.getId(), null, this)) { somethingHappened = true; break; diff --git a/Mage/src/main/java/mage/game/MageObjectAttribute.java b/Mage/src/main/java/mage/game/MageObjectAttribute.java index 66da3d0a60c..7ad09f2d1b9 100644 --- a/Mage/src/main/java/mage/game/MageObjectAttribute.java +++ b/Mage/src/main/java/mage/game/MageObjectAttribute.java @@ -1,14 +1,10 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package mage.game; -import java.io.Serializable; import mage.MageObject; import mage.ObjectColor; -import mage.util.SubTypeList; +import mage.util.SubTypes; + +import java.io.Serializable; /** * This class saves changed attributes of mage objects (e.g. in command zone, graveyard, exile or @@ -19,12 +15,11 @@ import mage.util.SubTypeList; public class MageObjectAttribute implements Serializable { protected ObjectColor color; - protected SubTypeList subtype; + protected SubTypes subtype; public MageObjectAttribute(MageObject mageObject, Game game) { - color = mageObject.getColor(null).copy(); - subtype = new SubTypeList(); - subtype.addAll(mageObject.getSubtype(game)); + color = mageObject.getColor().copy(); + subtype = new SubTypes(mageObject.getSubtype(game)); } public MageObjectAttribute(MageObjectAttribute mageObjectAttribute) { @@ -40,7 +35,7 @@ public class MageObjectAttribute implements Serializable { return color; } - public SubTypeList getSubtype() { + public SubTypes getSubtype() { return subtype; } diff --git a/Mage/src/main/java/mage/game/command/Commander.java b/Mage/src/main/java/mage/game/command/Commander.java index fe31f5942ca..b1faaeed7af 100644 --- a/Mage/src/main/java/mage/game/command/Commander.java +++ b/Mage/src/main/java/mage/game/command/Commander.java @@ -18,7 +18,7 @@ import mage.constants.SuperType; import mage.game.Game; import mage.game.events.ZoneChangeEvent; import mage.util.GameLog; -import mage.util.SubTypeList; +import mage.util.SubTypes; import java.util.ArrayList; import java.util.List; @@ -130,7 +130,6 @@ public class Commander implements CommandObject { @Override public void setName(String name) { - } @Override @@ -139,7 +138,12 @@ public class Commander implements CommandObject { } @Override - public SubTypeList getSubtype(Game game) { + public SubTypes getSubtype() { + return sourceObject.getSubtype(); + } + + @Override + public SubTypes getSubtype(Game game) { return sourceObject.getSubtype(game); } @@ -167,6 +171,11 @@ public class Commander implements CommandObject { return otherAbilities != null && otherAbilities.contains(ability); } + @Override + public ObjectColor getColor() { + return sourceObject.getColor(); + } + @Override public ObjectColor getColor(Game game) { return sourceObject.getColor(game); @@ -245,7 +254,7 @@ public class Commander implements CommandObject { } @Override - public boolean isAllCreatureTypes() { + public boolean isAllCreatureTypes(Game game) { return false; } @@ -253,6 +262,10 @@ public class Commander implements CommandObject { public void setIsAllCreatureTypes(boolean value) { } + @Override + public void setIsAllCreatureTypes(Game game, boolean value) { + } + @Override public List getTextParts() { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. diff --git a/Mage/src/main/java/mage/game/command/Emblem.java b/Mage/src/main/java/mage/game/command/Emblem.java index 6ad7a8972cc..2d42604bd9d 100644 --- a/Mage/src/main/java/mage/game/command/Emblem.java +++ b/Mage/src/main/java/mage/game/command/Emblem.java @@ -20,7 +20,7 @@ import mage.constants.SuperType; import mage.game.Game; import mage.game.events.ZoneChangeEvent; import mage.util.GameLog; -import mage.util.SubTypeList; +import mage.util.SubTypes; import java.util.ArrayList; import java.util.EnumSet; @@ -76,7 +76,7 @@ public class Emblem implements CommandObject { this.sourceObject = sourceObject; if (sourceObject instanceof Card) { if (name.isEmpty()) { - name = sourceObject.getSubtype(null).toString(); + name = sourceObject.getSubtype().toString(); } if (expansionSetCodeForImage.isEmpty()) { expansionSetCodeForImage = ((Card) sourceObject).getExpansionSetCode(); @@ -154,8 +154,13 @@ public class Emblem implements CommandObject { } @Override - public SubTypeList getSubtype(Game game) { - return new SubTypeList(); + public SubTypes getSubtype() { + return new SubTypes(); + } + + @Override + public SubTypes getSubtype(Game game) { + return new SubTypes(); } @Override @@ -178,6 +183,11 @@ public class Emblem implements CommandObject { return getAbilities().contains(ability); } + @Override + public ObjectColor getColor() { + return emptyColor; + } + @Override public ObjectColor getColor(Game game) { return emptyColor; @@ -258,13 +268,19 @@ public class Emblem implements CommandObject { throw new UnsupportedOperationException("Unsupported operation"); } - public boolean isAllCreatureTypes() { + @Override + public boolean isAllCreatureTypes(Game game) { return false; } + @Override public void setIsAllCreatureTypes(boolean value) { } + @Override + public void setIsAllCreatureTypes(Game game, boolean value) { + } + public void discardEffects() { for (Ability ability : abilites) { for (Effect effect : ability.getEffects()) { diff --git a/Mage/src/main/java/mage/game/command/Plane.java b/Mage/src/main/java/mage/game/command/Plane.java index ca5b1a03e92..98e75d83d7f 100644 --- a/Mage/src/main/java/mage/game/command/Plane.java +++ b/Mage/src/main/java/mage/game/command/Plane.java @@ -22,7 +22,7 @@ import mage.game.Game; import mage.game.events.ZoneChangeEvent; import mage.util.GameLog; import mage.util.RandomUtil; -import mage.util.SubTypeList; +import mage.util.SubTypes; import java.lang.reflect.Constructor; import java.util.ArrayList; @@ -163,8 +163,13 @@ public class Plane implements CommandObject { } @Override - public SubTypeList getSubtype(Game game) { - return new SubTypeList(); + public SubTypes getSubtype() { + return new SubTypes(); + } + + @Override + public SubTypes getSubtype(Game game) { + return new SubTypes(); } @Override @@ -187,6 +192,11 @@ public class Plane implements CommandObject { return getAbilities().contains(ability); } + @Override + public ObjectColor getColor() { + return emptyColor; + } + @Override public ObjectColor getColor(Game game) { return emptyColor; @@ -267,13 +277,19 @@ public class Plane implements CommandObject { throw new UnsupportedOperationException("Unsupported operation"); } - public boolean isAllCreatureTypes() { + @Override + public boolean isAllCreatureTypes(Game game) { return false; } + @Override public void setIsAllCreatureTypes(boolean value) { } + @Override + public void setIsAllCreatureTypes(Game game, boolean value) { + } + public void discardEffects() { for (Ability ability : abilites) { for (Effect effect : ability.getEffects()) { diff --git a/Mage/src/main/java/mage/game/draft/RateCard.java b/Mage/src/main/java/mage/game/draft/RateCard.java index d2d3608a850..9a27f142d69 100644 --- a/Mage/src/main/java/mage/game/draft/RateCard.java +++ b/Mage/src/main/java/mage/game/draft/RateCard.java @@ -91,9 +91,9 @@ public final class RateCard { type = 15; } else if (card.isCreature()) { type = 10; - } else if (card.getSubtype(null).contains(SubType.EQUIPMENT)) { + } else if (card.getSubtype().contains(SubType.EQUIPMENT)) { type = 8; - } else if (card.getSubtype(null).contains(SubType.AURA)) { + } else if (card.getSubtype().contains(SubType.AURA)) { type = 5; } else if (card.isInstant()) { type = 7; diff --git a/Mage/src/main/java/mage/game/permanent/PermanentCard.java b/Mage/src/main/java/mage/game/permanent/PermanentCard.java index 545b4fa3df5..3e5d5207d56 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentCard.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentCard.java @@ -1,21 +1,20 @@ package mage.game.permanent; -import java.util.UUID; -import javax.annotation.processing.SupportedSourceVersion; -import javax.lang.model.SourceVersion; import mage.MageObject; import mage.abilities.Abilities; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; -import mage.abilities.keyword.EnchantAbility; -import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TransformAbility; import mage.cards.Card; import mage.cards.LevelerCard; import mage.game.Game; import mage.game.events.ZoneChangeEvent; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import java.util.UUID; + /** * @author BetaSteward_at_googlemail.com */ @@ -105,9 +104,7 @@ public class PermanentCard extends PermanentImpl { if (card instanceof PermanentCard) { this.maxLevelCounters = ((PermanentCard) card).maxLevelCounters; } - this.subtype.clear(); - this.subtype.addAll(card.getSubtype(game)); - this.isAllCreatureTypes = card.isAllCreatureTypes(); + this.subtype.copyFrom(card.getSubtype(game)); this.supertype.clear(); supertype.addAll(card.getSuperType()); this.expansionSetCode = card.getExpansionSetCode(); diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index 10f739f4365..05b6500861b 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -1634,6 +1634,11 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { this.createOrder = createOrder; } + @Override + public ObjectColor getColor() { + return color; + } + @Override public ObjectColor getColor(Game game) { return color; diff --git a/Mage/src/main/java/mage/game/permanent/PermanentToken.java b/Mage/src/main/java/mage/game/permanent/PermanentToken.java index 493c87c24dd..aed3e5f9d84 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentToken.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentToken.java @@ -58,6 +58,7 @@ public class PermanentToken extends PermanentImpl { } private void copyFromToken(Token token, Game game, boolean reset) { + // modify all attributes permanently (without game usage) this.name = token.getName(); this.abilities.clear(); if (reset) { @@ -81,9 +82,7 @@ public class PermanentToken extends PermanentImpl { this.frameStyle = token.getFrameStyle(); this.supertype.clear(); this.supertype.addAll(token.getSuperType()); - this.subtype.clear(); - this.subtype.addAll(token.getSubtype(game)); - this.isAllCreatureTypes = token.isAllCreatureTypes(); + this.subtype.copyFrom(token.getSubtype(game)); this.tokenDescriptor = token.getTokenDescriptor(); } diff --git a/Mage/src/main/java/mage/game/permanent/token/CamaridToken.java b/Mage/src/main/java/mage/game/permanent/token/CamaridToken.java index 956fb8b98de..65e698ba919 100644 --- a/Mage/src/main/java/mage/game/permanent/token/CamaridToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/CamaridToken.java @@ -16,8 +16,8 @@ public final class CamaridToken extends TokenImpl { this.getPower().modifyBaseValue(1); this.getToughness().modifyBaseValue(1); this.color.setBlue(true); - this.getSubtype(null).add(SubType.CAMARID); - this.addCardType(CardType.CREATURE); + this.subtype.add(SubType.CAMARID); + this.cardType.add(CardType.CREATURE); } public CamaridToken(final CamaridToken token) { diff --git a/Mage/src/main/java/mage/game/permanent/token/CatWarriorToken.java b/Mage/src/main/java/mage/game/permanent/token/CatWarriorToken.java index 63b4f4c6dd6..02b1bb9572a 100644 --- a/Mage/src/main/java/mage/game/permanent/token/CatWarriorToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/CatWarriorToken.java @@ -27,9 +27,9 @@ public final class CatWarriorToken extends TokenImpl { this.getPower().modifyBaseValue(2); this.getToughness().modifyBaseValue(2); this.color.setGreen(true); - this.getSubtype(null).add(SubType.CAT); - this.getSubtype(null).add(SubType.WARRIOR); - this.addCardType(CardType.CREATURE); + this.subtype.add(SubType.CAT); + this.subtype.add(SubType.WARRIOR); + this.cardType.add(CardType.CREATURE); this.addAbility(new ForestwalkAbility()); } diff --git a/Mage/src/main/java/mage/game/permanent/token/CribSwapShapeshifterWhiteToken.java b/Mage/src/main/java/mage/game/permanent/token/CribSwapShapeshifterWhiteToken.java index 5aa82f27423..24212cb3330 100644 --- a/Mage/src/main/java/mage/game/permanent/token/CribSwapShapeshifterWhiteToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/CribSwapShapeshifterWhiteToken.java @@ -17,8 +17,7 @@ public final class CribSwapShapeshifterWhiteToken extends TokenImpl { subtype.add(SubType.SHAPESHIFTER); power = new MageInt(1); toughness = new MageInt(1); - setIsAllCreatureTypes(true); - addAbility(ChangelingAbility.getInstance()); + addAbility(new ChangelingAbility()); } public CribSwapShapeshifterWhiteToken(final CribSwapShapeshifterWhiteToken token) { diff --git a/Mage/src/main/java/mage/game/permanent/token/NissaSageAnimistToken.java b/Mage/src/main/java/mage/game/permanent/token/NissaSageAnimistToken.java index 9b84eede5e0..582ba58f5d5 100644 --- a/Mage/src/main/java/mage/game/permanent/token/NissaSageAnimistToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/NissaSageAnimistToken.java @@ -14,12 +14,12 @@ public final class NissaSageAnimistToken extends TokenImpl { public NissaSageAnimistToken() { super("Ashaya, the Awoken World", "legendary 4/4 green Elemental creature token named Ashaya, the Awoken World"); this.setOriginalExpansionSetCode("ORI"); - this.addSuperType(SuperType.LEGENDARY); + this.supertype.add(SuperType.LEGENDARY); this.getPower().modifyBaseValue(4); this.getToughness().modifyBaseValue(4); this.color.setGreen(true); - this.getSubtype(null).add(SubType.ELEMENTAL); - this.addCardType(CardType.CREATURE); + this.subtype.add(SubType.ELEMENTAL); + this.cardType.add(CardType.CREATURE); } public NissaSageAnimistToken(final NissaSageAnimistToken token) { diff --git a/Mage/src/main/java/mage/game/permanent/token/RagavanToken.java b/Mage/src/main/java/mage/game/permanent/token/RagavanToken.java index 9e1e6790564..e9fd9cc09f3 100644 --- a/Mage/src/main/java/mage/game/permanent/token/RagavanToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/RagavanToken.java @@ -14,12 +14,12 @@ public final class RagavanToken extends TokenImpl { public RagavanToken() { super("Ragavan", "legendary 2/1 red Monkey creature token named Ragavan"); this.setOriginalExpansionSetCode("AER"); - this.addSuperType(SuperType.LEGENDARY); + this.supertype.add(SuperType.LEGENDARY); this.getPower().modifyBaseValue(2); this.getToughness().modifyBaseValue(1); this.color.setRed(true); - this.getSubtype(null).add(SubType.MONKEY); - this.addCardType(CardType.CREATURE); + this.subtype.add(SubType.MONKEY); + this.cardType.add(CardType.CREATURE); } public RagavanToken(final RagavanToken token) { diff --git a/Mage/src/main/java/mage/game/permanent/token/ShapeshifterBlueToken.java b/Mage/src/main/java/mage/game/permanent/token/ShapeshifterBlueToken.java index 67bddeb14ef..73acb67489c 100644 --- a/Mage/src/main/java/mage/game/permanent/token/ShapeshifterBlueToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/ShapeshifterBlueToken.java @@ -17,8 +17,7 @@ public final class ShapeshifterBlueToken extends TokenImpl { color.setBlue(true); power = new MageInt(2); toughness = new MageInt(2); - setIsAllCreatureTypes(true); - addAbility(ChangelingAbility.getInstance()); + addAbility(new ChangelingAbility()); } private ShapeshifterBlueToken(final ShapeshifterBlueToken token) { diff --git a/Mage/src/main/java/mage/game/permanent/token/ShapeshifterToken.java b/Mage/src/main/java/mage/game/permanent/token/ShapeshifterToken.java index dc9edaa5f10..26f1734143e 100644 --- a/Mage/src/main/java/mage/game/permanent/token/ShapeshifterToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/ShapeshifterToken.java @@ -27,8 +27,7 @@ public final class ShapeshifterToken extends TokenImpl { subtype.add(SubType.SHAPESHIFTER); power = new MageInt(2); toughness = new MageInt(2); - setIsAllCreatureTypes(true); - addAbility(ChangelingAbility.getInstance()); + addAbility(new ChangelingAbility()); } public ShapeshifterToken(final ShapeshifterToken token) { diff --git a/Mage/src/main/java/mage/game/permanent/token/TokenImpl.java b/Mage/src/main/java/mage/game/permanent/token/TokenImpl.java index 5f1dc797f8c..bd42a16551f 100644 --- a/Mage/src/main/java/mage/game/permanent/token/TokenImpl.java +++ b/Mage/src/main/java/mage/game/permanent/token/TokenImpl.java @@ -75,7 +75,6 @@ public abstract class TokenImpl extends MageObjectImpl implements Token { this.expansionSetCodeChecked = token.expansionSetCodeChecked; this.copySourceCard = token.copySourceCard; // will never be changed this.availableImageSetCodes = token.availableImageSetCodes; - this.isAllCreatureTypes = token.isAllCreatureTypes; } @Override diff --git a/Mage/src/main/java/mage/game/permanent/token/WireflyToken.java b/Mage/src/main/java/mage/game/permanent/token/WireflyToken.java index 907ea24ad0b..83dabe7332d 100644 --- a/Mage/src/main/java/mage/game/permanent/token/WireflyToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/WireflyToken.java @@ -16,9 +16,9 @@ public final class WireflyToken extends TokenImpl { this.setOriginalExpansionSetCode("DST"); this.getPower().modifyBaseValue(2); this.getToughness().modifyBaseValue(2); - this.getSubtype(null).add(SubType.INSECT); - this.addCardType(CardType.ARTIFACT); - this.addCardType(CardType.CREATURE); + this.subtype.add(SubType.INSECT); + this.cardType.add(CardType.ARTIFACT); + this.cardType.add(CardType.CREATURE); this.addAbility(FlyingAbility.getInstance()); } diff --git a/Mage/src/main/java/mage/game/permanent/token/custom/CreatureToken.java b/Mage/src/main/java/mage/game/permanent/token/custom/CreatureToken.java index ccb5a1541e6..691a448cb2f 100644 --- a/Mage/src/main/java/mage/game/permanent/token/custom/CreatureToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/custom/CreatureToken.java @@ -6,10 +6,10 @@ import mage.abilities.Ability; import mage.constants.CardType; import mage.constants.SubType; import mage.game.permanent.token.TokenImpl; -import mage.util.SubTypeList; + +import java.util.Arrays; /** - * * @author JayDi85 */ public final class CreatureToken extends TokenImpl { @@ -23,21 +23,17 @@ public final class CreatureToken extends TokenImpl { } public CreatureToken(int power, int toughness, String description) { - this(power, toughness, description, (SubTypeList) null); + this(power, toughness, description, null); } - public CreatureToken(int power, int toughness, String description, SubType extraSubType) { - this(power, toughness, description, new SubTypeList(extraSubType)); - } - - public CreatureToken(int power, int toughness, String description, SubTypeList extraSubTypes) { + public CreatureToken(int power, int toughness, String description, SubType... extraSubTypes) { super("", description); this.cardType.add(CardType.CREATURE); this.power = new MageInt(power); this.toughness = new MageInt(toughness); if (extraSubTypes != null) { - this.subtype.addAll(extraSubTypes); + this.subtype.addAll(Arrays.asList(extraSubTypes)); } } diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index 452a62e7d09..461f3d22ca2 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -34,7 +34,7 @@ import mage.game.permanent.token.EmptyToken; import mage.players.Player; import mage.util.CardUtil; import mage.util.GameLog; -import mage.util.SubTypeList; +import mage.util.SubTypes; /** * @author BetaSteward_at_googlemail.com @@ -253,10 +253,11 @@ public class Spell extends StackObjImpl implements Card { if (ability.getTargets().stillLegal(ability, game)) { boolean bestow = SpellAbilityCastMode.BESTOW.equals(ability.getSpellAbilityCastMode()); if (bestow) { + // before put to play: // Must be removed first time, after that will be removed by continous effect // Otherwise effects like evolve trigger from creature comes into play event card.getCardType().remove(CardType.CREATURE); - if (!card.getSubtype(game).contains(SubType.AURA)) { + if (!card.hasSubtype(SubType.AURA, game)) { card.addSubType(game, SubType.AURA); } } @@ -280,9 +281,11 @@ public class Spell extends StackObjImpl implements Card { // TODO: Find a better way to prevent bestow creatures from being effected by creature affecting abilities Permanent permanent = game.getPermanent(permId); if (permanent instanceof PermanentCard) { + // after put to play: + // restore removed stats (see "before put to play" above) permanent.setSpellAbility(ability); // otherwise spell ability without bestow will be set card.addCardType(CardType.CREATURE); - card.getSubtype(game).remove(SubType.AURA); + card.removeSubType(game, SubType.AURA); } } if (isCopy()) { @@ -312,7 +315,7 @@ public class Spell extends StackObjImpl implements Card { Permanent permanent = game.getPermanent(card.getId()); if (permanent instanceof PermanentCard) { ((PermanentCard) permanent).getCard().addCardType(CardType.CREATURE); - ((PermanentCard) permanent).getCard().getSubtype(game).remove(SubType.AURA); + ((PermanentCard) permanent).getCard().removeSubType(game, SubType.AURA); return true; } } @@ -524,9 +527,14 @@ public class Spell extends StackObjImpl implements Card { } @Override - public SubTypeList getSubtype(Game game) { + public SubTypes getSubtype() { + return card.getSubtype(); + } + + @Override + public SubTypes getSubtype(Game game) { if (SpellAbilityCastMode.BESTOW.equals(this.getSpellAbility().getSpellAbilityCastMode())) { - SubTypeList subtypes = card.getSubtype(game); + SubTypes subtypes = card.getSubtype(game); if (!subtypes.contains(SubType.AURA)) { // do it only once subtypes.add(SubType.AURA); } @@ -538,7 +546,7 @@ public class Spell extends StackObjImpl implements Card { @Override public boolean hasSubtype(SubType subtype, Game game) { if (SpellAbilityCastMode.BESTOW.equals(this.getSpellAbility().getSpellAbilityCastMode())) { // workaround for Bestow (don't like it) - SubTypeList subtypes = card.getSubtype(game); + SubTypes subtypes = card.getSubtype(game); if (!subtypes.contains(SubType.AURA)) { // do it only once subtypes.add(SubType.AURA); } @@ -573,6 +581,11 @@ public class Spell extends StackObjImpl implements Card { return card.hasAbility(ability, game); } + @Override + public ObjectColor getColor() { + return color; + } + @Override public ObjectColor getColor(Game game) { if (game != null) { @@ -1090,7 +1103,7 @@ public class Spell extends StackObjImpl implements Card { } @Override - public boolean isAllCreatureTypes() { + public boolean isAllCreatureTypes(Game game) { return false; } @@ -1098,6 +1111,10 @@ public class Spell extends StackObjImpl implements Card { public void setIsAllCreatureTypes(boolean value) { } + @Override + public void setIsAllCreatureTypes(Game game, boolean value) { + } + @Override public List getTextParts() { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index 1380728a2c6..e98c852fb33 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -30,7 +30,7 @@ import mage.target.Target; import mage.target.Targets; import mage.target.targetadjustment.TargetAdjuster; import mage.util.GameLog; -import mage.util.SubTypeList; +import mage.util.SubTypes; import mage.watchers.Watcher; import java.util.ArrayList; @@ -161,8 +161,13 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public SubTypeList getSubtype(Game game) { - return new SubTypeList(); + public SubTypes getSubtype() { + return new SubTypes(); + } + + @Override + public SubTypes getSubtype(Game game) { + return new SubTypes(); } @Override @@ -185,6 +190,11 @@ public class StackAbility extends StackObjImpl implements Ability { return false; } + @Override + public ObjectColor getColor() { + return emptyColor; + } + @Override public ObjectColor getColor(Game game) { return emptyColor; @@ -604,7 +614,7 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public boolean isAllCreatureTypes() { + public boolean isAllCreatureTypes(Game game) { return false; } @@ -612,6 +622,10 @@ public class StackAbility extends StackObjImpl implements Ability { public void setIsAllCreatureTypes(boolean value) { } + @Override + public void setIsAllCreatureTypes(Game game, boolean value) { + } + @Override public List getTextParts() { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. diff --git a/Mage/src/main/java/mage/target/common/TargetCreaturePermanentWithDifferentTypes.java b/Mage/src/main/java/mage/target/common/TargetCreaturePermanentWithDifferentTypes.java index feedd0a4db8..5ce301c52a7 100644 --- a/Mage/src/main/java/mage/target/common/TargetCreaturePermanentWithDifferentTypes.java +++ b/Mage/src/main/java/mage/target/common/TargetCreaturePermanentWithDifferentTypes.java @@ -37,7 +37,7 @@ public class TargetCreaturePermanentWithDifferentTypes extends TargetCreaturePer Permanent selectedCreature = game.getPermanent(targetId); if (selectedCreature != null && !creature.getId().equals(selectedCreature.getId())) { - if (creature.shareCreatureTypes(selectedCreature, game)) { + if (creature.shareCreatureTypes(game, selectedCreature)) { return false; } } diff --git a/Mage/src/main/java/mage/util/SubTypeList.java b/Mage/src/main/java/mage/util/SubTypeList.java deleted file mode 100644 index a7863b6028d..00000000000 --- a/Mage/src/main/java/mage/util/SubTypeList.java +++ /dev/null @@ -1,34 +0,0 @@ -package mage.util; - -import mage.constants.SubType; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.stream.Collectors; - -public class SubTypeList extends ArrayList { - - public SubTypeList(SubType firstSubType) { - super(); - this.add(firstSubType); - } - - public SubTypeList(SubType... subTypesList) { - super(); - Collections.addAll(this, subTypesList); - } - - public SubTypeList(final SubTypeList list) { - this.addAll(list); - } - - public boolean add(SubType... subTypes) { - return Collections.addAll(this, subTypes); - } - - public boolean removeAll(SubType... subTypes) { - return super.removeAll(Arrays.stream(subTypes) - .collect(Collectors.toList())); - } -} diff --git a/Mage/src/main/java/mage/util/SubTypes.java b/Mage/src/main/java/mage/util/SubTypes.java new file mode 100644 index 00000000000..3b828712dba --- /dev/null +++ b/Mage/src/main/java/mage/util/SubTypes.java @@ -0,0 +1,44 @@ +package mage.util; + +import mage.constants.SubType; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; + +public class SubTypes extends ArrayList { + + private boolean isAllCreatureTypes = false; + + public SubTypes(SubType... subTypes) { + super(); + Collections.addAll(this, subTypes); + } + + public SubTypes(final SubTypes list) { + this.addAll(list); + this.isAllCreatureTypes = list.isAllCreatureTypes; + } + + public boolean add(SubType... subTypes) { + return Collections.addAll(this, subTypes); + } + + public void copyFrom(SubTypes subtypes) { + this.clear(); + this.addAll(subtypes); + this.isAllCreatureTypes = subtypes.isAllCreatureTypes; + } + + public boolean removeAll(SubType... subTypes) { + return super.removeAll(Arrays.asList(subTypes)); + } + + public void setIsAllCreatureTypes(boolean allCreatureTypes) { + isAllCreatureTypes = allCreatureTypes; + } + + public boolean isAllCreatureTypes() { + return isAllCreatureTypes; + } +} diff --git a/Mage/src/main/java/mage/util/functions/AbilityApplier.java b/Mage/src/main/java/mage/util/functions/AbilityApplier.java deleted file mode 100644 index 215ba18200c..00000000000 --- a/Mage/src/main/java/mage/util/functions/AbilityApplier.java +++ /dev/null @@ -1,34 +0,0 @@ - -package mage.util.functions; - -import java.util.UUID; -import mage.MageObject; -import mage.abilities.Ability; -import mage.game.Game; -import mage.game.permanent.Permanent; - -/** - * - * @author LevelX2 - */ -public class AbilityApplier extends ApplyToPermanent { - - private final Ability ability; - - public AbilityApplier(Ability ability) { - this.ability = ability; - } - - @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.addAbility(ability, source.getSourceId(), game); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.getAbilities().add(ability); - return true; - } - -} diff --git a/Mage/src/main/java/mage/util/functions/AbilityCopyApplier.java b/Mage/src/main/java/mage/util/functions/AbilityCopyApplier.java new file mode 100644 index 00000000000..1f370beff8c --- /dev/null +++ b/Mage/src/main/java/mage/util/functions/AbilityCopyApplier.java @@ -0,0 +1,27 @@ +package mage.util.functions; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class AbilityCopyApplier extends CopyApplier { + + private final Ability ability; + + public AbilityCopyApplier(Ability ability) { + this.ability = ability; + } + + @Override + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.getAbilities().add(ability); + return true; + } + +} diff --git a/Mage/src/main/java/mage/util/functions/AddSubtypeApplier.java b/Mage/src/main/java/mage/util/functions/AddSubtypeApplier.java deleted file mode 100644 index 0d762ff8657..00000000000 --- a/Mage/src/main/java/mage/util/functions/AddSubtypeApplier.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package mage.util.functions; - -import mage.MageObject; -import mage.abilities.Ability; -import mage.constants.SubType; -import mage.game.Game; -import mage.game.permanent.Permanent; - -import java.util.UUID; - -/** - * - * @author LevelX2 - */ -public class AddSubtypeApplier extends ApplyToPermanent { - - private final SubType subtype; - - public AddSubtypeApplier(SubType subtype) { - this.subtype = subtype; - } - - @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - if (!permanent.hasSubtype(subtype, game)) { - permanent.addSubType(game, subtype); - } - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - if (!mageObject.hasSubtype(subtype, game)) { - mageObject.addSubType(game, subtype); - } - return true; - } - -} diff --git a/Mage/src/main/java/mage/util/functions/AddSubtypeCopyApplier.java b/Mage/src/main/java/mage/util/functions/AddSubtypeCopyApplier.java new file mode 100644 index 00000000000..a356706871e --- /dev/null +++ b/Mage/src/main/java/mage/util/functions/AddSubtypeCopyApplier.java @@ -0,0 +1,31 @@ +package mage.util.functions; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.constants.SubType; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class AddSubtypeCopyApplier extends CopyApplier { + + private final SubType subtype; + + public AddSubtypeCopyApplier(SubType subtype) { + this.subtype = subtype; + } + + @Override + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + if (!blueprint.getSubtype().contains(subtype)) { + blueprint.getSubtype().add(subtype); + } + return true; + } + +} diff --git a/Mage/src/main/java/mage/util/functions/ApplyToPermanent.java b/Mage/src/main/java/mage/util/functions/ApplyToPermanent.java deleted file mode 100644 index ffde9aeca07..00000000000 --- a/Mage/src/main/java/mage/util/functions/ApplyToPermanent.java +++ /dev/null @@ -1,17 +0,0 @@ -package mage.util.functions; - -import mage.abilities.Ability; -import mage.game.Game; -import mage.game.permanent.Permanent; - -import java.io.Serializable; -import java.util.UUID; - -/** - * @author noxx - */ -public abstract class ApplyToPermanent extends ApplyToMageObject implements Serializable { - - // WARNING: see comments in ApplyToMageObject - public abstract boolean apply(Game game, Permanent permanent, Ability source, UUID targetObjectId); -} diff --git a/Mage/src/main/java/mage/util/functions/CardTypeApplier.java b/Mage/src/main/java/mage/util/functions/CardTypeApplier.java deleted file mode 100644 index 2ca57fb0a2b..00000000000 --- a/Mage/src/main/java/mage/util/functions/CardTypeApplier.java +++ /dev/null @@ -1,34 +0,0 @@ - -package mage.util.functions; - -import java.util.UUID; -import mage.MageObject; -import mage.abilities.Ability; -import mage.constants.CardType; -import mage.game.Game; -import mage.game.permanent.Permanent; - -/** - * - * @author LevelX2 - */ -public class CardTypeApplier extends ApplyToPermanent { - - private final CardType cardType; - - public CardTypeApplier(CardType cardType) { - this.cardType = cardType; - } - - @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.addCardType(cardType); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.addCardType(cardType); - return true; - } -} diff --git a/Mage/src/main/java/mage/util/functions/CardTypeCopyApplier.java b/Mage/src/main/java/mage/util/functions/CardTypeCopyApplier.java new file mode 100644 index 00000000000..3d80a4c0204 --- /dev/null +++ b/Mage/src/main/java/mage/util/functions/CardTypeCopyApplier.java @@ -0,0 +1,28 @@ + +package mage.util.functions; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.constants.CardType; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class CardTypeCopyApplier extends CopyApplier { + + private final CardType cardType; + + public CardTypeCopyApplier(CardType cardType) { + this.cardType = cardType; + } + + @Override + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.addCardType(cardType); + return true; + } +} diff --git a/Mage/src/main/java/mage/util/functions/ApplyToMageObject.java b/Mage/src/main/java/mage/util/functions/CopyApplier.java similarity index 76% rename from Mage/src/main/java/mage/util/functions/ApplyToMageObject.java rename to Mage/src/main/java/mage/util/functions/CopyApplier.java index adbf0828689..4b1892ed31b 100644 --- a/Mage/src/main/java/mage/util/functions/ApplyToMageObject.java +++ b/Mage/src/main/java/mage/util/functions/CopyApplier.java @@ -3,13 +3,17 @@ package mage.util.functions; import mage.MageObject; import mage.abilities.Ability; import mage.game.Game; + +import java.io.Serializable; import java.util.Objects; import java.util.UUID; /** + * Apply additional modifications for blueprint of the copy permanent + * * @author LevelX2 */ -public abstract class ApplyToMageObject { +public abstract class CopyApplier implements Serializable { // WARNING: // 1. Applier uses for copy effects only; @@ -17,8 +21,7 @@ public abstract class ApplyToMageObject { // 3. "source" is the current copy ability and can be different from the original copy ability (copy of copy); // 4. Don't use "source" param at all; // 5. Use isCopyOfCopy() to detect it (some effects can apply to copy of copy, but others can't -- see Spark Double as an example). - // TODO: check all applier implementations - remove source uses, add isCopyOfCopy processing - public abstract boolean apply(Game game, MageObject mageObject, Ability source, UUID targetObjectId); + public abstract boolean apply(Game game, MageObject blueprint, Ability source, UUID targetObjectId); public boolean isCopyOfCopy(Ability source, UUID targetObjectId) { return !Objects.equals(targetObjectId, source.getSourceId()); diff --git a/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java b/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java index 2a27fce4194..5275fd69240 100644 --- a/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java +++ b/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java @@ -63,18 +63,16 @@ public class CopyTokenFunction implements Function { target.setCopySourceCard(source); } + // modify all attributes permanently (without game usage) target.setName(sourceObj.getName()); - target.getColor(null).setColor(sourceObj.getColor(null)); + target.getColor().setColor(sourceObj.getColor()); target.getManaCost().clear(); target.getManaCost().add(sourceObj.getManaCost()); target.getCardType().clear(); for (CardType type : sourceObj.getCardType()) { target.addCardType(type); } - target.getSubtype(null).clear(); - for (SubType type : sourceObj.getSubtype(null)) { - target.getSubtype(null).add(type); - } + target.getSubtype().copyFrom(sourceObj.getSubtype()); target.getSuperType().clear(); for (SuperType type : sourceObj.getSuperType()) { target.addSuperType(type); diff --git a/Mage/src/main/java/mage/util/functions/EmptyApplyToPermanent.java b/Mage/src/main/java/mage/util/functions/EmptyApplyToPermanent.java deleted file mode 100644 index c838a8f7566..00000000000 --- a/Mage/src/main/java/mage/util/functions/EmptyApplyToPermanent.java +++ /dev/null @@ -1,25 +0,0 @@ -package mage.util.functions; - -import java.util.UUID; -import mage.MageObject; -import mage.abilities.Ability; -import mage.game.Game; -import mage.game.permanent.Permanent; - -/** - * @author noxx - */ -public class EmptyApplyToPermanent extends ApplyToPermanent { - - @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - // do nothing - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - return true; - } - -} diff --git a/Mage/src/main/java/mage/util/functions/EmptyCopyApplier.java b/Mage/src/main/java/mage/util/functions/EmptyCopyApplier.java new file mode 100644 index 00000000000..67684565fc8 --- /dev/null +++ b/Mage/src/main/java/mage/util/functions/EmptyCopyApplier.java @@ -0,0 +1,19 @@ +package mage.util.functions; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author noxx + */ +public class EmptyCopyApplier extends CopyApplier { + + @Override + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + return true; + } + +} diff --git a/Mage/src/main/java/mage/watchers/common/ProwlWatcher.java b/Mage/src/main/java/mage/watchers/common/ProwlWatcher.java index 0f89823500b..3ae063170b1 100644 --- a/Mage/src/main/java/mage/watchers/common/ProwlWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/ProwlWatcher.java @@ -1,6 +1,8 @@ package mage.watchers.common; +import mage.cards.Card; import mage.constants.SubType; +import mage.constants.SubTypeSet; import mage.constants.WatcherScope; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; @@ -39,7 +41,7 @@ public class ProwlWatcher extends Watcher { if (creature == null || allSubtypes.contains(creature.getControllerId())) { return; } - if (creature.isAllCreatureTypes()) { + if (creature.isAllCreatureTypes(game)) { allSubtypes.add(creature.getControllerId()); return; } @@ -55,12 +57,16 @@ public class ProwlWatcher extends Watcher { allSubtypes.clear(); } - public boolean hasSubtypeMadeCombatDamage(UUID playerId, SubType subtype) { + public boolean hasSubtypeMadeCombatDamage(UUID playerId, Card card, Game game) { if (allSubtypes.contains(playerId)) { return true; } Set subtypes = damagingSubtypes.get(playerId); - return subtypes != null && subtypes.contains(subtype); + return subtypes != null + && subtypes + .stream() + .filter(subType -> subType.getSubTypeSet() == SubTypeSet.CreatureType) + .anyMatch(subType -> card.hasSubtype(subType, game)); } }