diff --git a/Mage.Sets/src/mage/cards/a/AgelessSentinels.java b/Mage.Sets/src/mage/cards/a/AgelessSentinels.java index d893d50db0..892e01369a 100644 --- a/Mage.Sets/src/mage/cards/a/AgelessSentinels.java +++ b/Mage.Sets/src/mage/cards/a/AgelessSentinels.java @@ -1,28 +1,22 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BlocksSourceTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.LoseAbilitySourceEffect; -import mage.constants.SubType; import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class AgelessSentinels extends CardImpl { @@ -43,7 +37,7 @@ public final class AgelessSentinels extends CardImpl { // When Ageless Sentinels blocks, it becomes a Bird Giant, and it loses defender. Ability ability = new BlocksSourceTriggeredAbility(new AgelessSentinelsEffect(), false, false, true); Effect effect = new LoseAbilitySourceEffect(DefenderAbility.getInstance(), Duration.WhileOnBattlefield); - effect.setText("and it loses defender"); + effect.setText(", and it loses defender"); ability.addEffect(effect); this.addAbility(ability); } @@ -60,8 +54,8 @@ public final class AgelessSentinels extends CardImpl { private class AgelessSentinelsEffect extends ContinuousEffectImpl { public AgelessSentinelsEffect() { - super(Duration.WhileOnBattlefield, Outcome.BecomeCreature); - staticText = "it becomes a Bird Giant,"; + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature); + staticText = "it becomes a Bird Giant"; } public AgelessSentinelsEffect(final AgelessSentinelsEffect effect) { @@ -74,27 +68,16 @@ public final class AgelessSentinels extends CardImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent == null) { return false; } - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.getSubtype(game).clear(); - permanent.getSubtype(game).add(SubType.BIRD, SubType.GIANT); - } - break; - } + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.BIRD, SubType.GIANT); return true; } - @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.Sets/src/mage/cards/a/AlphaStatus.java b/Mage.Sets/src/mage/cards/a/AlphaStatus.java index 844141280d..ec6fdd63ee 100644 --- a/Mage.Sets/src/mage/cards/a/AlphaStatus.java +++ b/Mage.Sets/src/mage/cards/a/AlphaStatus.java @@ -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.shareSubtypes(permanent, game)) { + if (enchanted.shareCreatureTypes(permanent, game)) { xValue += 2; } } diff --git a/Mage.Sets/src/mage/cards/a/AmoeboidChangeling.java b/Mage.Sets/src/mage/cards/a/AmoeboidChangeling.java index fc593bf849..604487800b 100644 --- a/Mage.Sets/src/mage/cards/a/AmoeboidChangeling.java +++ b/Mage.Sets/src/mage/cards/a/AmoeboidChangeling.java @@ -7,6 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.continuous.GainAllCreatureTypesTargetEffect; import mage.abilities.effects.common.continuous.LoseAllCreatureTypesTargetEffect; import mage.abilities.keyword.ChangelingAbility; import mage.cards.CardImpl; @@ -27,13 +28,13 @@ public final class AmoeboidChangeling extends CardImpl { this.toughness = new MageInt(1); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // {tap}: Target creature gains all creature types until end of turn. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, - new GainAbilityTargetEffect(ChangelingAbility.getInstance(), Duration.EndOfTurn, null, false, Layer.TypeChangingEffects_4, SubLayer.NA), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility( + new GainAllCreatureTypesTargetEffect(Duration.EndOfTurn), new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(ability); // {tap}: Target creature loses all creature types until end of turn. diff --git a/Mage.Sets/src/mage/cards/a/AmorphousAxe.java b/Mage.Sets/src/mage/cards/a/AmorphousAxe.java index 65acf2bc68..6732ef2d53 100644 --- a/Mage.Sets/src/mage/cards/a/AmorphousAxe.java +++ b/Mage.Sets/src/mage/cards/a/AmorphousAxe.java @@ -3,12 +3,10 @@ package mage.cards.a; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.BoostEquippedEffect; -import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; -import mage.abilities.keyword.ChangelingAbility; +import mage.abilities.effects.common.continuous.GainAllCreatureTypesAttachedEffect; import mage.abilities.keyword.EquipAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AttachmentType; import mage.constants.CardType; import mage.constants.SubType; @@ -26,9 +24,7 @@ public final class AmorphousAxe extends CardImpl { // Equipped creature gets +3/+0 and is every creature type. Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(3, 0)); - ability.addEffect(new GainAbilityAttachedEffect( - ChangelingAbility.getInstance(), AttachmentType.EQUIPMENT - ).setText("and is every creature type")); + ability.addEffect(new GainAllCreatureTypesAttachedEffect()); this.addAbility(ability); // Equip {3} diff --git a/Mage.Sets/src/mage/cards/a/ArcaneAdaptation.java b/Mage.Sets/src/mage/cards/a/ArcaneAdaptation.java index fb1a7691d3..a788844dcb 100644 --- a/Mage.Sets/src/mage/cards/a/ArcaneAdaptation.java +++ b/Mage.Sets/src/mage/cards/a/ArcaneAdaptation.java @@ -116,8 +116,8 @@ class ConspyEffect extends ContinuousEffectImpl { List creatures = game.getBattlefield().getAllActivePermanents( new FilterControlledCreaturePermanent(), source.getControllerId(), game); for (Permanent creature : creatures) { - if (creature != null && !creature.hasSubtype(subType, game)) { - creature.getSubtype(game).add(subType); + if (creature != null) { + creature.addSubType(game, subType); } } return true; diff --git a/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java b/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java index 615f5d7e24..54a880253d 100644 --- a/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java +++ b/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java @@ -1,42 +1,37 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.Mana; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.Effect; +import mage.abilities.effects.common.TapSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import static mage.constants.Layer.TypeChangingEffects_4; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author spjspj */ public final class ArixmethesSlumberingIsle extends CardImpl { + private static final Condition condition + = new SourceHasCounterCondition(CounterType.SLUMBER, 1, Integer.MAX_VALUE); + public ArixmethesSlumberingIsle(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); @@ -46,15 +41,18 @@ public final class ArixmethesSlumberingIsle extends CardImpl { this.toughness = new MageInt(12); // Arixmethes, Slumbering Isle enters the battlefield tapped with five slumber counters on it. - this.addAbility(new EntersBattlefieldTappedAbility()); - Effect effect = new AddCountersSourceEffect(CounterType.SLUMBER.createInstance(5)); - this.addAbility(new EntersBattlefieldAbility(effect, "with five slumber counters")); + Ability ability = new EntersBattlefieldAbility( + new TapSourceEffect(true), false, null, + "{this} enters the battlefield tapped with five slumber counters on it", null + ); + ability.addEffect(new AddCountersSourceEffect(CounterType.SLUMBER.createInstance(5))); + this.addAbility(ability); // As long as Arixmethes, Slumbering Isle has a slumber counter on it, it's a land. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( - new ArixmethesIsLandEffect(), - new SourceHasCounterCondition(CounterType.SLUMBER, 1, Integer.MAX_VALUE), - "As long as {this} has a slumber counter on it, it's a land"))); + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new ArixmethesIsLandEffect(), condition, + "As long as {this} has a slumber counter on it, it's a land" + ))); // Whenever you cast a spell, you may remove a slumber counter from Arixmethes. this.addAbility(new SpellCastControllerTriggeredAbility(new RemoveCounterSourceEffect(CounterType.SLUMBER.createInstance(1)), true)); @@ -75,44 +73,28 @@ public final class ArixmethesSlumberingIsle extends CardImpl { class ArixmethesIsLandEffect extends ContinuousEffectImpl { - public ArixmethesIsLandEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); - this.staticText = "As long as {this} has a slumber counter on it, it's a land"; + ArixmethesIsLandEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); } - public ArixmethesIsLandEffect(final ArixmethesIsLandEffect effect) { + private ArixmethesIsLandEffect(final ArixmethesIsLandEffect effect) { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public ArixmethesIsLandEffect copy() { return new ArixmethesIsLandEffect(this); } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); - - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - permanent.getCardType().clear(); - permanent.addCardType(CardType.LAND); - permanent.getSubtype(game).clear(); - break; - } - return true; + if (permanent == null) { + return false; } - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; + permanent.getCardType().clear(); + permanent.addCardType(CardType.LAND); + permanent.removeAllSubTypes(game); + return true; } } diff --git a/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java b/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java index 9f7c16964a..07a535b455 100644 --- a/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java +++ b/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java @@ -90,7 +90,7 @@ class AshayaSoulOfTheWildEffect extends ContinuousEffectImpl { permanent.addCardType(CardType.LAND); } if (!permanent.hasSubtype(SubType.FOREST, game)) { - permanent.getSubtype(game).add(SubType.FOREST); + permanent.addSubType(game, SubType.FOREST); if (!permanent.getAbilities(game).containsClass(GreenManaAbility.class)) { permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); } diff --git a/Mage.Sets/src/mage/cards/a/AshiokNightmareWeaver.java b/Mage.Sets/src/mage/cards/a/AshiokNightmareWeaver.java index bc67e69a24..71a24e4c96 100644 --- a/Mage.Sets/src/mage/cards/a/AshiokNightmareWeaver.java +++ b/Mage.Sets/src/mage/cards/a/AshiokNightmareWeaver.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; @@ -24,8 +23,9 @@ import mage.target.common.TargetOpponent; import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class AshiokNightmareWeaver extends CardImpl { @@ -149,7 +149,7 @@ class AshiokNightmareWeaverPutIntoPlayEffect extends OneShotEffect { class AshiokNightmareWeaverAddTypeEffect extends ContinuousEffectImpl { public AshiokNightmareWeaverAddTypeEffect() { - super(Duration.Custom, Outcome.Neutral); + super(Duration.Custom, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); staticText = "That creature is a Nightmare in addition to its other types"; } @@ -162,34 +162,16 @@ class AshiokNightmareWeaverAddTypeEffect extends ContinuousEffectImpl { return new AshiokNightmareWeaverAddTypeEffect(this); } - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent creature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); - if (creature != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - creature.getSubtype(game).add(SubType.NIGHTMARE); - } - break; - } - return true; - } else { - this.used = true; - } - return false; - } - @Override public boolean apply(Game game, Ability source) { - return false; + Permanent creature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (creature == null) { + this.used = true; + return false; + } + creature.addSubType(game, SubType.NIGHTMARE); + return true; } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } - } class AshiokNightmareWeaverExileAllEffect extends OneShotEffect { diff --git a/Mage.Sets/src/mage/cards/a/AvianChangeling.java b/Mage.Sets/src/mage/cards/a/AvianChangeling.java index f64019816d..3cd09cacaf 100644 --- a/Mage.Sets/src/mage/cards/a/AvianChangeling.java +++ b/Mage.Sets/src/mage/cards/a/AvianChangeling.java @@ -22,6 +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(FlyingAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/cards/b/BladesOfVelisVel.java b/Mage.Sets/src/mage/cards/b/BladesOfVelisVel.java index 997bc35794..4829fbc591 100644 --- a/Mage.Sets/src/mage/cards/b/BladesOfVelisVel.java +++ b/Mage.Sets/src/mage/cards/b/BladesOfVelisVel.java @@ -1,10 +1,7 @@ - package mage.cards.b; -import java.util.UUID; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostTargetEffect; -import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.continuous.GainAllCreatureTypesTargetEffect; import mage.abilities.keyword.ChangelingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -13,26 +10,27 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class BladesOfVelisVel extends CardImpl { public BladesOfVelisVel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.TRIBAL,CardType.INSTANT},"{1}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.TRIBAL, CardType.INSTANT}, "{1}{R}"); this.subtype.add(SubType.SHAPESHIFTER); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); - + // Up to two target creatures each get +2/+0 and gain all creature types until end of turn. - Effect effect = new BoostTargetEffect(2,0, Duration.EndOfTurn); - effect.setText("Up to two target creatures each get +2/+0"); - this.getSpellAbility().addEffect(effect); - effect = new GainAbilityTargetEffect(ChangelingAbility.getInstance(), Duration.EndOfTurn, "and gain all creature types until end of turn"); - this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0,2)); + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 0, Duration.EndOfTurn) + .setText("Up to two target creatures each get +2/+0")); + this.getSpellAbility().addEffect(new GainAllCreatureTypesTargetEffect(Duration.EndOfTurn) + .setText("and gain all creature types until end of turn")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2)); } public BladesOfVelisVel(final BladesOfVelisVel card) { diff --git a/Mage.Sets/src/mage/cards/b/BloodMoon.java b/Mage.Sets/src/mage/cards/b/BloodMoon.java index 1cd11c4e49..f36a5d1d3e 100644 --- a/Mage.Sets/src/mage/cards/b/BloodMoon.java +++ b/Mage.Sets/src/mage/cards/b/BloodMoon.java @@ -72,7 +72,7 @@ public final class BloodMoon extends CardImpl { // 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.getSubtype(game).add(SubType.MOUNTAIN); + land.addSubType(game, SubType.MOUNTAIN); land.removeAllAbilities(source.getSourceId(), game); land.addAbility(new RedManaAbility(), source.getSourceId(), game); break; diff --git a/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java b/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java index 71166b33c8..ce9e0eb92b 100644 --- a/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java +++ b/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java @@ -85,7 +85,7 @@ class BludgeonBrawlAddSubtypeEffect extends ContinuousEffectImpl { List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game); for (Permanent permanent : permanents) { if (permanent != null) { - permanent.getSubtype(game).add(SubType.EQUIPMENT); + permanent.addSubType(game, SubType.EQUIPMENT); affectedPermanents.add(permanent.getId()); } } diff --git a/Mage.Sets/src/mage/cards/b/BronzehideLion.java b/Mage.Sets/src/mage/cards/b/BronzehideLion.java index 98dd760b60..810d851dc7 100644 --- a/Mage.Sets/src/mage/cards/b/BronzehideLion.java +++ b/Mage.Sets/src/mage/cards/b/BronzehideLion.java @@ -144,8 +144,8 @@ class BronzehideLionContinuousEffect extends ContinuousEffectImpl { case TypeChangingEffects_4: lion.getCardType().clear(); lion.addCardType(CardType.ENCHANTMENT); - lion.getSubtype(game).clear(); - lion.getSubtype(game).add(SubType.AURA); + lion.removeAllSubTypes(game); + lion.addSubType(game, SubType.AURA); break; case AbilityAddingRemovingEffects_6: List toRemove = new ArrayList<>(); diff --git a/Mage.Sets/src/mage/cards/c/CairnWanderer.java b/Mage.Sets/src/mage/cards/c/CairnWanderer.java index 335f1f37ea..451bc7069d 100644 --- a/Mage.Sets/src/mage/cards/c/CairnWanderer.java +++ b/Mage.Sets/src/mage/cards/c/CairnWanderer.java @@ -30,6 +30,7 @@ public final class CairnWanderer extends CardImpl { this.toughness = new MageInt(4); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // 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. diff --git a/Mage.Sets/src/mage/cards/c/CallToTheKindred.java b/Mage.Sets/src/mage/cards/c/CallToTheKindred.java index 09694cfa7b..d55a6a1349 100644 --- a/Mage.Sets/src/mage/cards/c/CallToTheKindred.java +++ b/Mage.Sets/src/mage/cards/c/CallToTheKindred.java @@ -1,12 +1,9 @@ - package mage.cards.c; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.keyword.ChangelingAbility; import mage.abilities.keyword.EnchantAbility; import mage.cards.*; import mage.constants.CardType; @@ -15,27 +12,24 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.Predicate; -import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetCard; import mage.target.TargetPermanent; +import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCreaturePermanent; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; /** - * * @author North */ public final class CallToTheKindred extends CardImpl { public CallToTheKindred(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}"); this.subtype.add(SubType.AURA); // Enchant creature @@ -43,6 +37,7 @@ public final class CallToTheKindred extends CardImpl { this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); this.addAbility(new EnchantAbility(auraTarget.getTargetName())); + // At the beginning of your upkeep, you may look at the top five cards of your library. // If you do, you may put a creature card that shares a creature type with enchanted creature from among them onto the battlefield, // then you put the rest of those cards on the bottom of your library in any order. @@ -61,12 +56,14 @@ public final class CallToTheKindred extends CardImpl { class CallToTheKindredEffect extends OneShotEffect { - public CallToTheKindredEffect() { + CallToTheKindredEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "look at the top five cards of your library. If you do, you may put a creature card that shares a creature type with enchanted creature from among them onto the battlefield, then you put the rest of those cards on the bottom of your library in any order"; + this.staticText = "look at the top five cards of your library. If you do, you may put a creature card " + + "that shares a creature type with enchanted creature from among them onto the battlefield, " + + "then you put the rest of those cards on the bottom of your library in any order"; } - public CallToTheKindredEffect(final CallToTheKindredEffect effect) { + private CallToTheKindredEffect(final CallToTheKindredEffect effect) { super(effect); } @@ -90,36 +87,33 @@ class CallToTheKindredEffect extends OneShotEffect { } Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 5)); - controller.lookAtCards(enchantment.getIdName(), cards, game); - FilterCreatureCard filter = new FilterCreatureCard(); + filter.add(new CallToTheKindredPredicate(creature)); - if (!creature.getAbilities().contains(ChangelingAbility.getInstance())) { - StringBuilder sb = new StringBuilder("creature card with at least one subtype from: "); - List> subtypes = new ArrayList<>(); - for (SubType subtype : creature.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()); - } else { - filter.setMessage("creature card that shares a creature type with enchanted creature"); - } - - if (cards.count(filter, game) > 0 && controller.chooseUse(Outcome.DrawCard, "Do you wish to put a creature card onto the battlefield?", source, game)) { - TargetCard target = new TargetCard(Zone.LIBRARY, filter); - - if (controller.choose(Outcome.PutCreatureInPlay, cards, target, game)) { - Card card = cards.get(target.getFirstTarget(), game); - if (card != null) { - cards.remove(card); - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } + if (cards.count(filter, game) > 0) { + TargetCard target = new TargetCardInLibrary(0, 1, filter); + controller.choose(Outcome.PutCreatureInPlay, cards, target, game); + Card card = cards.get(target.getFirstTarget(), game); + if (card != null) { + cards.remove(card); + controller.moveCards(card, Zone.BATTLEFIELD, source, game); } } controller.putCardsOnBottomOfLibrary(cards, game, source, true); 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/CaptivatingVampire.java b/Mage.Sets/src/mage/cards/c/CaptivatingVampire.java index a5b8c7091b..1edbe8ce50 100644 --- a/Mage.Sets/src/mage/cards/c/CaptivatingVampire.java +++ b/Mage.Sets/src/mage/cards/c/CaptivatingVampire.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -21,8 +20,9 @@ import mage.game.permanent.Permanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public final class CaptivatingVampire extends CardImpl { @@ -37,7 +37,7 @@ public final class CaptivatingVampire extends CardImpl { } public CaptivatingVampire(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}"); this.subtype.add(SubType.VAMPIRE); this.power = new MageInt(2); @@ -90,11 +90,7 @@ class CaptivatingVampireEffect extends ContinuousEffectImpl { } break; case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - if (!permanent.hasSubtype(SubType.VAMPIRE, game)) { - permanent.getSubtype(game).add(SubType.VAMPIRE); - } - } + permanent.addSubType(game, SubType.VAMPIRE); break; } return true; diff --git a/Mage.Sets/src/mage/cards/c/CelestialDawn.java b/Mage.Sets/src/mage/cards/c/CelestialDawn.java index 4501d984e5..684e77ff93 100644 --- a/Mage.Sets/src/mage/cards/c/CelestialDawn.java +++ b/Mage.Sets/src/mage/cards/c/CelestialDawn.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageObject; import mage.ObjectColor; import mage.abilities.Ability; @@ -18,14 +16,15 @@ import mage.filter.common.FilterLandPermanent; import mage.filter.common.FilterNonlandPermanent; import mage.game.Game; import mage.game.command.CommandObject; +import mage.game.command.Commander; import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.players.ManaPoolItem; import mage.players.Player; -import mage.game.command.Commander; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class CelestialDawn extends CardImpl { @@ -89,8 +88,8 @@ class CelestialDawnToPlainsEffect extends ContinuousEffectImpl { land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); break; case TypeChangingEffects_4: - land.getSubtype(game).clear(); - land.getSubtype(game).add(SubType.PLAINS); + land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.addSubType(game, SubType.PLAINS); break; } } diff --git a/Mage.Sets/src/mage/cards/c/ChameleonColossus.java b/Mage.Sets/src/mage/cards/c/ChameleonColossus.java index 283e0dce68..d2a7d205bf 100644 --- a/Mage.Sets/src/mage/cards/c/ChameleonColossus.java +++ b/Mage.Sets/src/mage/cards/c/ChameleonColossus.java @@ -31,6 +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()); // Protection from black diff --git a/Mage.Sets/src/mage/cards/c/ChangelingBerserker.java b/Mage.Sets/src/mage/cards/c/ChangelingBerserker.java index b6ad46c5c2..d718b8fe43 100644 --- a/Mage.Sets/src/mage/cards/c/ChangelingBerserker.java +++ b/Mage.Sets/src/mage/cards/c/ChangelingBerserker.java @@ -24,6 +24,7 @@ public final class ChangelingBerserker extends CardImpl { this.toughness = new MageInt(3); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // Haste diff --git a/Mage.Sets/src/mage/cards/c/ChangelingHero.java b/Mage.Sets/src/mage/cards/c/ChangelingHero.java index f767161223..5265bce967 100644 --- a/Mage.Sets/src/mage/cards/c/ChangelingHero.java +++ b/Mage.Sets/src/mage/cards/c/ChangelingHero.java @@ -24,6 +24,7 @@ public final class ChangelingHero extends CardImpl { this.toughness = new MageInt(4); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // Champion a creature diff --git a/Mage.Sets/src/mage/cards/c/ChangelingOutcast.java b/Mage.Sets/src/mage/cards/c/ChangelingOutcast.java index fbbedddbb0..2557d03a25 100644 --- a/Mage.Sets/src/mage/cards/c/ChangelingOutcast.java +++ b/Mage.Sets/src/mage/cards/c/ChangelingOutcast.java @@ -24,6 +24,7 @@ public final class ChangelingOutcast extends CardImpl { this.toughness = new MageInt(1); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // Changeling Outcast can't block and can't be blocked. diff --git a/Mage.Sets/src/mage/cards/c/ChangelingSentinel.java b/Mage.Sets/src/mage/cards/c/ChangelingSentinel.java index 08bd56e16f..8e532ccce5 100644 --- a/Mage.Sets/src/mage/cards/c/ChangelingSentinel.java +++ b/Mage.Sets/src/mage/cards/c/ChangelingSentinel.java @@ -22,6 +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(VigilanceAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/cards/c/ChangelingTitan.java b/Mage.Sets/src/mage/cards/c/ChangelingTitan.java index 76d8915027..3701c9ae75 100644 --- a/Mage.Sets/src/mage/cards/c/ChangelingTitan.java +++ b/Mage.Sets/src/mage/cards/c/ChangelingTitan.java @@ -23,6 +23,7 @@ public final class ChangelingTitan extends CardImpl { this.toughness = new MageInt(7); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // Champion a creature diff --git a/Mage.Sets/src/mage/cards/c/ChimericCoils.java b/Mage.Sets/src/mage/cards/c/ChimericCoils.java index a553b4c1ae..a1473cf34b 100644 --- a/Mage.Sets/src/mage/cards/c/ChimericCoils.java +++ b/Mage.Sets/src/mage/cards/c/ChimericCoils.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; @@ -15,17 +13,18 @@ import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author Plopman */ public final class ChimericCoils extends CardImpl { public ChimericCoils(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); // {X}{1}: Chimeric Coils becomes an X/X Construct artifact creature. Sacrifice it at the beginning of thhe next end step. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChimericCoilsEffect(), new ManaCostsImpl("{X}{1}")); + Ability ability = new SimpleActivatedAbility(new ChimericCoilsEffect(), new ManaCostsImpl("{X}{1}")); ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeSourceEffect()))); this.addAbility(ability); } @@ -43,8 +42,8 @@ public final class ChimericCoils extends CardImpl { class ChimericCoilsEffect extends ContinuousEffectImpl { public ChimericCoilsEffect() { - super(Duration.EndOfTurn, Outcome.BecomeCreature); - setText(); + super(Duration.Custom, Outcome.BecomeCreature); + staticText = "{this} becomes an X/X Construct artifact creature"; } public ChimericCoilsEffect(final ChimericCoilsEffect effect) { @@ -59,24 +58,28 @@ class ChimericCoilsEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.addCardType(CardType.CREATURE); - permanent.getSubtype(game).add(SubType.CONSTRUCT); - } - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - int xValue = source.getManaCostsToPay().getX(); - permanent.getPower().setValue(xValue); - permanent.getToughness().setValue(xValue); - } - } - return true; + if (permanent == null) { + return false; } - return false; + switch (layer) { + case TypeChangingEffects_4: + if (!permanent.isArtifact()) { + permanent.addCardType(CardType.ARTIFACT); + } + if (!permanent.isCreature()) { + permanent.addCardType(CardType.CREATURE); + } + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.CONSTRUCT); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + int xValue = source.getManaCostsToPay().getX(); + permanent.getPower().setValue(xValue); + permanent.getToughness().setValue(xValue); + } + } + return true; } @Override @@ -84,10 +87,6 @@ class ChimericCoilsEffect extends ContinuousEffectImpl { return false; } - private void setText() { - staticText = duration.toString() + " {this} becomes an X/X Construct artifact creature"; - } - @Override public boolean hasLayer(Layer layer) { return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4; diff --git a/Mage.Sets/src/mage/cards/c/ChimericStaff.java b/Mage.Sets/src/mage/cards/c/ChimericStaff.java index b7046aeb8c..5be3990d58 100644 --- a/Mage.Sets/src/mage/cards/c/ChimericStaff.java +++ b/Mage.Sets/src/mage/cards/c/ChimericStaff.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -12,17 +10,18 @@ import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author Backfir3 */ public final class ChimericStaff extends CardImpl { public ChimericStaff(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // {X}: Chimeric Staff becomes an X/X Construct artifact creature until end of turn. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChimericStaffEffect(), new ManaCostsImpl("{X}"))); + this.addAbility(new SimpleActivatedAbility(new ChimericStaffEffect(), new ManaCostsImpl("{X}"))); } public ChimericStaff(final ChimericStaff card) { @@ -39,7 +38,7 @@ class ChimericStaffEffect extends ContinuousEffectImpl { public ChimericStaffEffect() { super(Duration.EndOfTurn, Outcome.BecomeCreature); - setText(); + staticText = "{this} becomes an X/X Construct artifact creature until end of turn"; } public ChimericStaffEffect(final ChimericStaffEffect effect) { @@ -54,26 +53,28 @@ class ChimericStaffEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.addCardType(CardType.CREATURE); - permanent.getSubtype(game).add(SubType.CONSTRUCT); - } - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - int xValue = source.getManaCostsToPay().getX(); - if (xValue != 0) { - permanent.getPower().setValue(xValue); - permanent.getToughness().setValue(xValue); - } - } - } - return true; + if (permanent == null) { + return false; } - return false; + switch (layer) { + case TypeChangingEffects_4: + if (!permanent.isArtifact()) { + permanent.addCardType(CardType.ARTIFACT); + } + if (!permanent.isCreature()) { + permanent.addCardType(CardType.CREATURE); + } + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.CONSTRUCT); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + int xValue = source.getManaCostsToPay().getX(); + permanent.getPower().setValue(xValue); + permanent.getToughness().setValue(xValue); + } + } + return true; } @Override @@ -81,10 +82,6 @@ class ChimericStaffEffect extends ContinuousEffectImpl { return false; } - private void setText() { - staticText = duration.toString() + " {this} becomes an X/X Construct artifact creature"; - } - @Override public boolean hasLayer(Layer layer) { return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4; diff --git a/Mage.Sets/src/mage/cards/c/CoatOfArms.java b/Mage.Sets/src/mage/cards/c/CoatOfArms.java index 0a33e6ab69..f6801f87cf 100644 --- a/Mage.Sets/src/mage/cards/c/CoatOfArms.java +++ b/Mage.Sets/src/mage/cards/c/CoatOfArms.java @@ -1,28 +1,26 @@ package mage.cards.c; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.keyword.ChangelingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; 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; /** - * * @author North */ public final class CoatOfArms extends CardImpl { public CoatOfArms(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); // Each creature gets +1/+1 for each other creature on the battlefield that shares at least one creature type with it. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CoatOfArmsEffect())); @@ -40,7 +38,7 @@ public final class CoatOfArms extends CardImpl { class CoatOfArmsEffect extends ContinuousEffectImpl { - public CoatOfArmsEffect() { + public CoatOfArmsEffect() { super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); this.staticText = "Each creature gets +1/+1 for each other creature on the battlefield that shares at least one creature type with it"; } @@ -56,7 +54,9 @@ class CoatOfArmsEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - List permanents = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game); + List permanents = game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game + ); for (Permanent permanent : permanents) { int amount = getAmount(permanents, permanent, game); permanent.addPower(amount); @@ -67,20 +67,9 @@ class CoatOfArmsEffect extends ContinuousEffectImpl { private int getAmount(List permanents, Permanent target, Game game) { int amount = 0; - SubTypeList targetSubtype = target.getSubtype(game); - if (target.getAbilities().contains(ChangelingAbility.getInstance()) || target.isAllCreatureTypes()) { - return permanents.size() - 1; - } for (Permanent permanent : permanents) { - if (!permanent.getId().equals(target.getId())) { - for (SubType subtype : targetSubtype) { - if (subtype.getSubTypeSet() == SubTypeSet.CreatureType) { - if (permanent.hasSubtype(subtype, game)) { - amount++; - break; - } - } - } + if (!permanent.getId().equals(target.getId()) && permanent.shareCreatureTypes(target, game)) { + amount++; } } return amount; diff --git a/Mage.Sets/src/mage/cards/c/Conversion.java b/Mage.Sets/src/mage/cards/c/Conversion.java index afd4397c6a..ac52159273 100644 --- a/Mage.Sets/src/mage/cards/c/Conversion.java +++ b/Mage.Sets/src/mage/cards/c/Conversion.java @@ -77,7 +77,7 @@ public final class Conversion extends CardImpl { case TypeChangingEffects_4: if (land.getSubtype(game).contains(SubType.MOUNTAIN)) { land.getSubtype(game).removeAll(SubType.getLandTypes()); - land.getSubtype(game).add(SubType.PLAINS); + land.addSubType(game, SubType.PLAINS); land.removeAllAbilities(source.getSourceId(), game); land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); break; diff --git a/Mage.Sets/src/mage/cards/c/ConvincingMirage.java b/Mage.Sets/src/mage/cards/c/ConvincingMirage.java index 4254a33a64..842c557bf5 100644 --- a/Mage.Sets/src/mage/cards/c/ConvincingMirage.java +++ b/Mage.Sets/src/mage/cards/c/ConvincingMirage.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; @@ -18,8 +16,9 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; +import java.util.UUID; + /** - * * @author North */ public final class ConvincingMirage extends CardImpl { @@ -32,8 +31,10 @@ public final class ConvincingMirage extends CardImpl { TargetPermanent auraTarget = new TargetLandPermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + // As Convincing Mirage enters the battlefield, choose a basic land type. this.addAbility(new AsEntersBattlefieldAbility(new ChooseBasicLandTypeEffect(Outcome.Neutral))); + // Enchanted land is the chosen type. Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); @@ -53,7 +54,7 @@ public final class ConvincingMirage extends CardImpl { class ConvincingMirageContinousEffect extends ContinuousEffectImpl { public ConvincingMirageContinousEffect() { - super(Duration.WhileOnBattlefield, Outcome.Neutral); + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); staticText = "Enchanted land is the chosen type"; } @@ -67,53 +68,59 @@ class ConvincingMirageContinousEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent enchantment = game.getPermanent(source.getSourceId()); + public void init(Ability source, Game game) { + super.init(source, game); SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY)); - if (enchantment != null && enchantment.getAttachedTo() != null && choice != null) { - Permanent land = game.getPermanent(enchantment.getAttachedTo()); - if (land != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - land.getSubtype(game).clear(); - land.getSubtype(game).add(choice); - } - break; - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - land.getAbilities().clear(); - if (choice.equals(SubType.FOREST)) { - land.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.PLAINS)) { - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.MOUNTAIN)) { - land.addAbility(new RedManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.ISLAND)) { - land.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.SWAMP)) { - land.addAbility(new BlackManaAbility(), source.getSourceId(), game); - } - } - break; - } - return true; - } + switch (choice) { + case FOREST: + dependencyTypes.add(DependencyType.BecomeForest); + break; + case PLAINS: + dependencyTypes.add(DependencyType.BecomePlains); + break; + case MOUNTAIN: + dependencyTypes.add(DependencyType.BecomeMountain); + break; + case ISLAND: + dependencyTypes.add(DependencyType.BecomeIsland); + break; + case SWAMP: + dependencyTypes.add(DependencyType.BecomeSwamp); + break; } - return false; } @Override public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; + Permanent enchantment = game.getPermanent(source.getSourceId()); + SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY)); + if (enchantment == null || enchantment.getAttachedTo() == null || choice == null) { + return false; + } + Permanent land = game.getPermanent(enchantment.getAttachedTo()); + if (land == null) { + return false; + } + land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.addSubType(game, choice); + land.removeAllAbilities(source.getSourceId(), game); + switch (choice) { + case FOREST: + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); + break; + case PLAINS: + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + break; + case MOUNTAIN: + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + break; + case ISLAND: + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + break; + case SWAMP: + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + break; + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/c/CreepingRenaissance.java b/Mage.Sets/src/mage/cards/c/CreepingRenaissance.java index 57c5648c7e..486f01c731 100644 --- a/Mage.Sets/src/mage/cards/c/CreepingRenaissance.java +++ b/Mage.Sets/src/mage/cards/c/CreepingRenaissance.java @@ -1,25 +1,26 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlashbackAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.Choice; -import mage.choices.ChoiceImpl; +import mage.choices.ChoiceCardType; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.TimingRule; import mage.constants.Zone; +import mage.filter.FilterCard; import mage.game.Game; import mage.players.Player; +import java.util.Arrays; +import java.util.UUID; +import java.util.stream.Collectors; + /** - * * @author nantuko */ public final class CreepingRenaissance extends CardImpl { @@ -58,40 +59,27 @@ class CreepingRenaissanceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Choice typeChoice = new ChoiceImpl(); - typeChoice.setMessage("Choose permanent type"); - - typeChoice.getChoices().add(CardType.ARTIFACT.toString()); - typeChoice.getChoices().add(CardType.CREATURE.toString()); - typeChoice.getChoices().add(CardType.ENCHANTMENT.toString()); - typeChoice.getChoices().add(CardType.LAND.toString()); - typeChoice.getChoices().add(CardType.PLANESWALKER.toString()); - - if (controller.choose(Outcome.ReturnToHand, typeChoice, game)) { - String typeName = typeChoice.getChoice(); - CardType chosenType = null; - for (CardType cardType : CardType.values()) { - if (cardType.toString().equals(typeName)) { - chosenType = cardType; - } - } - if (chosenType != null) { - for (Card card : controller.getGraveyard().getCards(game)) { - if (card.getCardType().contains(chosenType)) { - card.moveToZone(Zone.HAND, source.getSourceId(), game, false); - } - } - return true; - } - } + if (controller == null) { + return false; } - return false; + Choice typeChoice = new ChoiceCardType(true, Arrays.stream(CardType.values()).filter(CardType::isPermanentType).collect(Collectors.toList())); + typeChoice.setMessage("Choose a permanent type"); + + if (!controller.choose(Outcome.ReturnToHand, typeChoice, game)) { + return false; + } + String typeName = typeChoice.getChoice(); + CardType chosenType = CardType.fromString(typeChoice.getChoice()); + if (chosenType == null) { + return false; + } + FilterCard filter = new FilterCard(chosenType.toString().toLowerCase() + " card"); + filter.add(chosenType.getPredicate()); + return controller.moveCards(controller.getGraveyard().getCards(filter, source.getSourceId(), controller.getId(), game), Zone.HAND, source, game); } @Override public CreepingRenaissanceEffect copy() { return new CreepingRenaissanceEffect(this); } - } diff --git a/Mage.Sets/src/mage/cards/c/CribSwap.java b/Mage.Sets/src/mage/cards/c/CribSwap.java index 671bc13ae5..42ad6318a2 100644 --- a/Mage.Sets/src/mage/cards/c/CribSwap.java +++ b/Mage.Sets/src/mage/cards/c/CribSwap.java @@ -28,6 +28,7 @@ public final class CribSwap extends CardImpl { this.subtype.add(SubType.SHAPESHIFTER); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // Exile target creature. Its controller creates a 1/1 colorless Shapeshifter creature token with changeling. this.getSpellAbility().addEffect(new ExileTargetEffect()); diff --git a/Mage.Sets/src/mage/cards/c/CrypticGateway.java b/Mage.Sets/src/mage/cards/c/CrypticGateway.java index de3c4d4ac7..9db7c1b83d 100644 --- a/Mage.Sets/src/mage/cards/c/CrypticGateway.java +++ b/Mage.Sets/src/mage/cards/c/CrypticGateway.java @@ -1,52 +1,40 @@ - package mage.cards.c; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect; -import mage.abilities.keyword.ChangelingAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetControlledPermanent; -import java.util.ArrayList; -import java.util.List; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; /** - * * @author spjspj */ public final class CrypticGateway extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); - - static { - filter.add(Predicates.not(TappedPredicate.instance)); - } - - TargetControlledPermanent target; - public CrypticGateway(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); // Tap two untapped creatures you control: You may put a creature card from your hand that shares a creature type with each creature tapped this way onto the battlefield. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CrypticGatewayEffect(), new CrypticGatewayCost(new TargetControlledPermanent(filter)))); + this.addAbility(new SimpleActivatedAbility(new CrypticGatewayEffect(), new CrypticGatewayCost())); } public CrypticGateway(final CrypticGateway card) { @@ -61,29 +49,28 @@ public final class CrypticGateway extends CardImpl { class CrypticGatewayCost extends CostImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); - private UUID targetCreatureId = null; - private UUID targetCreatureId2 = null; - - TargetControlledPermanent target; + private static final FilterControlledCreaturePermanent filter + = new FilterControlledCreaturePermanent("untapped creatures you control"); static { filter.add(Predicates.not(TappedPredicate.instance)); } - public CrypticGatewayCost(TargetControlledPermanent target) { - this.target = target; + private final TargetControlledPermanent target = new TargetControlledPermanent(2, filter); + private CrypticGatewayPredicate predicate; + + public CrypticGatewayCost() { this.text = "Tap two untapped creatures you control"; } public CrypticGatewayCost(final CrypticGatewayCost cost) { super(cost); - this.target = cost.target.copy(); } @Override public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { int numTargets = 0; + Set permanents = new HashSet<>(); while (numTargets < 2 && target.choose(Outcome.Tap, controllerId, sourceId, game)) { for (UUID targetId : target.getTargets()) { Permanent permanent = game.getPermanent(targetId); @@ -94,16 +81,13 @@ class CrypticGatewayCost extends CostImpl { if (paid) { numTargets++; target.clearChosen(); - } - for (Effect effect : ability.getEffects()) { - if (targetCreatureId == null) { - targetCreatureId = permanent.getId(); - } else if (targetCreatureId2 == null) { - targetCreatureId2 = permanent.getId(); - } + permanents.add(permanent); } } } + if (paid) { + this.predicate = new CrypticGatewayPredicate(permanents); + } return paid; } @@ -112,18 +96,14 @@ class CrypticGatewayCost extends CostImpl { return target.canChoose(controllerId, game); } + public CrypticGatewayPredicate getPredicate() { + return predicate; + } + @Override public CrypticGatewayCost copy() { return new CrypticGatewayCost(this); } - - public UUID getTargetCreatureId() { - return targetCreatureId; - } - - public UUID getTargetCreatureId2() { - return targetCreatureId2; - } } class CrypticGatewayEffect extends OneShotEffect { @@ -147,59 +127,33 @@ class CrypticGatewayEffect extends OneShotEffect { if (source.getCosts() == null) { return false; } - FilterCard filter = new FilterCreatureCard("creature card from your hand that shares a creature type with each creature tapped this way"); - for (Cost cost : source.getCosts()) { if (cost instanceof CrypticGatewayCost) { - UUID id = ((CrypticGatewayCost) cost).getTargetCreatureId(); - UUID id2 = ((CrypticGatewayCost) cost).getTargetCreatureId2(); - Permanent creature = game.getPermanentOrLKIBattlefield(id); - Permanent creature2 = game.getPermanentOrLKIBattlefield(id2); - - if (creature == null || creature2 == null) { - return false; - } - - boolean commonSubType = false; - boolean changeling = false; - boolean changeling2 = false; - if (creature.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature.isAllCreatureTypes()) { - changeling = true; - } - if (creature2.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature2.isAllCreatureTypes()) { - changeling2 = true; - } - - List subtypes = new ArrayList<>(); - - for (SubType subtype : creature.getSubtype(game)) { - if (creature2.hasSubtype(subtype, game) || changeling2) { - subtypes.add(subtype.getPredicate()); - commonSubType = true; - } - } - - for (SubType subtype : creature2.getSubtype(game)) { - if (creature.hasSubtype(subtype, game) || changeling) { - subtypes.add(subtype.getPredicate()); - commonSubType = true; - } - } - - if (changeling && changeling2) { - filter = new FilterCreatureCard("creature card from your hand that shares a creature type with each creature tapped this way"); - } else if (commonSubType) { - filter.add(Predicates.or(subtypes)); - } - - if (commonSubType) { - PutCardFromHandOntoBattlefieldEffect putIntoPlay = new PutCardFromHandOntoBattlefieldEffect(filter); - putIntoPlay.apply(game, source); - } + Predicate predicate = ((CrypticGatewayCost) cost).getPredicate(); + filter.add(predicate); + return new PutCardFromHandOntoBattlefieldEffect(filter).apply(game, source); } } - return false; } } + +class CrypticGatewayPredicate implements Predicate { + + private final Set permanents = new HashSet<>(); + + CrypticGatewayPredicate(Set permanents) { + this.permanents.addAll(permanents); + } + + @Override + public boolean apply(Card input, Game game) { + for (Permanent permanent : permanents) { + if (!permanent.shareCreatureTypes(input, game)) { + return false; + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DescendantsPath.java b/Mage.Sets/src/mage/cards/d/DescendantsPath.java index 92445e71ac..16357653c4 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.shareSubtypes(permanent, game)) { + if (card.shareCreatureTypes(permanent, game)) { found = true; break; } diff --git a/Mage.Sets/src/mage/cards/d/DrJuliusJumblemorph.java b/Mage.Sets/src/mage/cards/d/DrJuliusJumblemorph.java index eb47860166..b01f8e5f38 100644 --- a/Mage.Sets/src/mage/cards/d/DrJuliusJumblemorph.java +++ b/Mage.Sets/src/mage/cards/d/DrJuliusJumblemorph.java @@ -1,20 +1,31 @@ - package mage.cards.d; -import java.util.UUID; import mage.MageInt; -import mage.abilities.keyword.ChangelingAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.InfoEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ComparisonType; import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; + +import java.util.UUID; /** - * * @author vereena42 & L_J */ public final class DrJuliusJumblemorph extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("a host"); + + static { + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, -1)); + } + public DrJuliusJumblemorph(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{W}"); this.addSuperType(SuperType.LEGENDARY); @@ -22,10 +33,17 @@ 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.addAbility(ChangelingAbility.getInstance()); - + 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)." + ))); + // 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 + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + new InfoEffect("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."), filter + )); } public DrJuliusJumblemorph(final DrJuliusJumblemorph card) { diff --git a/Mage.Sets/src/mage/cards/d/Dragonshift.java b/Mage.Sets/src/mage/cards/d/Dragonshift.java index 368a83fec5..990d8147b4 100644 --- a/Mage.Sets/src/mage/cards/d/Dragonshift.java +++ b/Mage.Sets/src/mage/cards/d/Dragonshift.java @@ -48,7 +48,7 @@ public final class Dragonshift extends CardImpl { .withColor("UR") .withSubType(SubType.DRAGON) .withAbility(FlyingAbility.getInstance()), - null, filter, Duration.EndOfTurn, true)); + null, filter, Duration.EndOfTurn, true, false, true)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DragonsoulKnight.java b/Mage.Sets/src/mage/cards/d/DragonsoulKnight.java index 86d66d5d9d..50185afaf9 100644 --- a/Mage.Sets/src/mage/cards/d/DragonsoulKnight.java +++ b/Mage.Sets/src/mage/cards/d/DragonsoulKnight.java @@ -1,7 +1,6 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -19,14 +18,15 @@ import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class DragonsoulKnight extends CardImpl { public DragonsoulKnight(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.KNIGHT); @@ -37,12 +37,12 @@ public final class DragonsoulKnight extends CardImpl { this.addAbility(FirstStrikeAbility.getInstance()); // {W}{U}{B}{R}{G}: Until end of turn, Dragonsoul Knight becomes a Dragon, gets +5/+3, and gains flying and trample. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DragonsoulKnightEffect(), new ManaCostsImpl("{W}{U}{B}{R}{G}")); + Ability ability = new SimpleActivatedAbility(new DragonsoulKnightEffect(), new ManaCostsImpl("{W}{U}{B}{R}{G}")); Effect effect = new BoostSourceEffect(5, 3, Duration.EndOfTurn); - effect.setText("gets +5/+3"); + effect.setText(", gets +5/+3"); ability.addEffect(effect); effect = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn); - effect.setText("and gains flying"); + effect.setText(", and gains flying"); ability.addEffect(effect); effect = new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); effect.setText("and trample"); @@ -60,14 +60,14 @@ public final class DragonsoulKnight extends CardImpl { return new DragonsoulKnight(this); } - private class DragonsoulKnightEffect extends ContinuousEffectImpl { + private static class DragonsoulKnightEffect extends ContinuousEffectImpl { - public DragonsoulKnightEffect() { - super(Duration.EndOfTurn, Outcome.BecomeCreature); - setText(); + private DragonsoulKnightEffect() { + super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature); + staticText = "Until end of turn, {this} becomes a Dragon"; } - public DragonsoulKnightEffect(final DragonsoulKnightEffect effect) { + private DragonsoulKnightEffect(final DragonsoulKnightEffect effect) { super(effect); } @@ -77,34 +77,14 @@ public final class DragonsoulKnight extends CardImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent == null) { return false; } - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.getSubtype(game).clear(); - permanent.getSubtype(game).add(SubType.DRAGON); - } - break; - } + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.DRAGON); return true; } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - private void setText() { - staticText = "Until end of turn, {this} becomes a Dragon, "; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } } } diff --git a/Mage.Sets/src/mage/cards/d/DralnusCrusade.java b/Mage.Sets/src/mage/cards/d/DralnusCrusade.java index 343baac0ba..7750a505ae 100755 --- a/Mage.Sets/src/mage/cards/d/DralnusCrusade.java +++ b/Mage.Sets/src/mage/cards/d/DralnusCrusade.java @@ -16,7 +16,6 @@ import mage.game.permanent.Permanent; import java.util.UUID; /** - * * @author brikr */ public final class DralnusCrusade extends CardImpl { @@ -53,9 +52,7 @@ class DralnusCrusadeEffect extends ContinuousEffectImpl { for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE_GOBLINS, source.getControllerId(), source.getSourceId(), game)) { switch (layer) { case TypeChangingEffects_4: - if (!permanent.hasSubtype(SubType.ZOMBIE, game)) { - permanent.getSubtype(game).add(SubType.ZOMBIE); - } + permanent.addSubType(game, SubType.ZOMBIE); break; case ColorChangingEffects_5: permanent.getColor(game).setColor(ObjectColor.BLACK); diff --git a/Mage.Sets/src/mage/cards/d/DranaTheLastBloodchief.java b/Mage.Sets/src/mage/cards/d/DranaTheLastBloodchief.java index d10f51dd1c..5f29275b3e 100644 --- a/Mage.Sets/src/mage/cards/d/DranaTheLastBloodchief.java +++ b/Mage.Sets/src/mage/cards/d/DranaTheLastBloodchief.java @@ -123,9 +123,7 @@ class DranaTheLastBloodchiefSubtypeEffect extends ContinuousEffectImpl { public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent creature = mor.getPermanent(game); if (creature != null) { - if (!creature.hasSubtype(SubType.VAMPIRE, game)) { - creature.getSubtype(game).add(SubType.VAMPIRE); - } + creature.addSubType(game, SubType.VAMPIRE); return true; } else { this.used = true; diff --git a/Mage.Sets/src/mage/cards/e/EgoErasure.java b/Mage.Sets/src/mage/cards/e/EgoErasure.java index 3f7d2fba9a..ecb93a19b4 100644 --- a/Mage.Sets/src/mage/cards/e/EgoErasure.java +++ b/Mage.Sets/src/mage/cards/e/EgoErasure.java @@ -26,6 +26,7 @@ public final class EgoErasure extends CardImpl { this.subtype.add(SubType.SHAPESHIFTER); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); //Creatures target player controls get -2/+0 and lose all creature types until end of turn. @@ -76,7 +77,7 @@ class EgoErasureLoseEffect extends ContinuousEffectImpl { for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { Permanent permanent = it.next().getPermanent(game); if (permanent != null) { - permanent.getSubtype(game).retainAll(SubType.getLandTypes()); + permanent.removeAllCreatureTypes(game); } else { it.remove(); } diff --git a/Mage.Sets/src/mage/cards/e/ElsewhereFlask.java b/Mage.Sets/src/mage/cards/e/ElsewhereFlask.java index 0b4b0442c9..13fe21ffbd 100644 --- a/Mage.Sets/src/mage/cards/e/ElsewhereFlask.java +++ b/Mage.Sets/src/mage/cards/e/ElsewhereFlask.java @@ -1,8 +1,5 @@ - package mage.cards.e; -import java.util.Iterator; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -17,14 +14,15 @@ import mage.cards.CardSetInfo; import mage.choices.Choice; import mage.choices.ChoiceBasicLandType; import mage.constants.*; -import mage.filter.common.FilterControlledLandPermanent; -import mage.filter.common.FilterControlledPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.Iterator; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class ElsewhereFlask extends CardImpl { @@ -36,7 +34,7 @@ public final class ElsewhereFlask extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1))); // Sacrifice Elsewhere Flask: Choose a basic land type. Each land you control becomes that type until end of turn. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ElsewhereFlaskEffect(), new SacrificeSourceCost())); + this.addAbility(new SimpleActivatedAbility(new ElsewhereFlaskEffect(), new SacrificeSourceCost())); } public ElsewhereFlask(final ElsewhereFlask card) { @@ -80,13 +78,11 @@ class ElsewhereFlaskEffect extends OneShotEffect { class ElsewhereFlaskContinuousEffect extends ContinuousEffectImpl { - private static final FilterControlledPermanent filter = new FilterControlledLandPermanent(); - - public ElsewhereFlaskContinuousEffect() { - super(Duration.EndOfTurn, Outcome.Neutral); + ElsewhereFlaskContinuousEffect() { + super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); } - public ElsewhereFlaskContinuousEffect(final ElsewhereFlaskContinuousEffect effect) { + private ElsewhereFlaskContinuousEffect(final ElsewhereFlaskContinuousEffect effect) { super(effect); } @@ -98,64 +94,68 @@ class ElsewhereFlaskContinuousEffect extends ContinuousEffectImpl { @Override public void init(Ability source, Game game) { super.init(source, game); - if (this.affectedObjectsSet) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { - affectedObjectList.add(new MageObjectReference(permanent, game)); - } - } - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "_ElsewhereFlask")); - if (choice != null) { - for (Iterator it = affectedObjectList.iterator(); it.hasNext();) { - Permanent land = it.next().getPermanent(game); - if (land != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - land.getSubtype(game).clear(); - land.getSubtype(game).add(choice); - } - break; - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - land.getAbilities().clear(); - if (choice.equals(SubType.FOREST)) { - land.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.PLAINS)) { - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.MOUNTAIN)) { - land.addAbility(new RedManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.ISLAND)) { - land.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.SWAMP)) { - land.addAbility(new BlackManaAbility(), source.getSourceId(), game); - } - } - break; - } - } else { - it.remove(); - } - } - return true; + switch (choice) { + case FOREST: + dependencyTypes.add(DependencyType.BecomeForest); + break; + case PLAINS: + dependencyTypes.add(DependencyType.BecomePlains); + break; + case MOUNTAIN: + dependencyTypes.add(DependencyType.BecomeMountain); + break; + case ISLAND: + dependencyTypes.add(DependencyType.BecomeIsland); + break; + case SWAMP: + dependencyTypes.add(DependencyType.BecomeSwamp); + break; + } + if (this.affectedObjectsSet) { + game.getBattlefield() + .getActivePermanents( + StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, + source.getControllerId(), source.getSourceId(), game + ).stream() + .map(permanent -> new MageObjectReference(permanent, game)) + .forEach(affectedObjectList::add); } - return false; } @Override public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; + SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "_ElsewhereFlask")); + if (choice == null) { + return false; + } + for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { + Permanent land = it.next().getPermanent(game); + if (land == null) { + it.remove(); + continue; + } + land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.addSubType(game, choice); + land.removeAllAbilities(source.getSourceId(), game); + switch (choice) { + case FOREST: + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); + break; + case PLAINS: + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + break; + case MOUNTAIN: + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + break; + case ISLAND: + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + break; + case SWAMP: + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + break; + } + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/e/EnchantedEvening.java b/Mage.Sets/src/mage/cards/e/EnchantedEvening.java index 940296f503..a31e066c4e 100644 --- a/Mage.Sets/src/mage/cards/e/EnchantedEvening.java +++ b/Mage.Sets/src/mage/cards/e/EnchantedEvening.java @@ -1,19 +1,18 @@ package mage.cards.e; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.Effect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class EnchantedEvening extends CardImpl { @@ -22,11 +21,7 @@ public final class EnchantedEvening extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W/U}{W/U}"); // All permanents are enchantments in addition to their other types. - Effect effect = new EnchangedEveningEffect(CardType.ENCHANTMENT, - Duration.WhileOnBattlefield, new FilterPermanent()); - effect.setText("All permanents are enchantments in addition to their other types"); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); - + this.addAbility(new SimpleStaticAbility(new EnchangedEveningEffect())); } public EnchantedEvening(final EnchantedEvening card) { @@ -39,31 +34,27 @@ public final class EnchantedEvening extends CardImpl { } // need to be enclosed class for dependent check of continuous effects - static class EnchangedEveningEffect extends ContinuousEffectImpl { + private static class EnchangedEveningEffect extends ContinuousEffectImpl { - private final CardType addedCardType; - private final FilterPermanent filter; - - public EnchangedEveningEffect(CardType addedCardType, Duration duration, FilterPermanent filter) { - super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); - this.addedCardType = addedCardType; - this.filter = filter; + private EnchangedEveningEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); this.dependencyTypes.add(DependencyType.EnchantmentAddingRemoving); this.dependencyTypes.add(DependencyType.AuraAddingRemoving); + this.staticText = "All permanents are enchantments in addition to their other types"; } - public EnchangedEveningEffect(final EnchangedEveningEffect effect) { + private EnchangedEveningEffect(final EnchangedEveningEffect effect) { super(effect); - this.addedCardType = effect.addedCardType; - this.filter = effect.filter; } @Override public boolean apply(Game game, Ability source) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, game)) { - if (permanent != null - && !permanent.getCardType().contains(addedCardType)) { - permanent.addCardType(addedCardType); + for (Permanent permanent : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_PERMANENT, source.getControllerId(), + source.getSourceId(), game + )) { + if (permanent != null) { + permanent.addCardType(CardType.ENCHANTMENT); } } return true; diff --git a/Mage.Sets/src/mage/cards/e/EverythingamajigC.java b/Mage.Sets/src/mage/cards/e/EverythingamajigC.java index 7a331d7a2e..e6c37f1f67 100644 --- a/Mage.Sets/src/mage/cards/e/EverythingamajigC.java +++ b/Mage.Sets/src/mage/cards/e/EverythingamajigC.java @@ -9,8 +9,8 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.mana.ManaEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.abilities.effects.mana.ManaEffect; import mage.abilities.hint.common.MyTurnHint; import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.cards.CardImpl; @@ -127,7 +127,7 @@ class ChimericStaffEffect extends ContinuousEffectImpl { public ChimericStaffEffect() { super(Duration.EndOfTurn, Outcome.BecomeCreature); - setText(); + staticText = "{this} becomes an X/X Construct artifact creature until end of turn"; } public ChimericStaffEffect(final ChimericStaffEffect effect) { @@ -142,26 +142,28 @@ class ChimericStaffEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.addCardType(CardType.CREATURE); - permanent.getSubtype(game).add(SubType.CONSTRUCT); - } - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - int xValue = source.getManaCostsToPay().getX(); - if (xValue != 0) { - permanent.getPower().setValue(xValue); - permanent.getToughness().setValue(xValue); - } - } - } - return true; + if (permanent == null) { + return false; } - return false; + switch (layer) { + case TypeChangingEffects_4: + if (!permanent.isArtifact()) { + permanent.addCardType(CardType.ARTIFACT); + } + if (!permanent.isCreature()) { + permanent.addCardType(CardType.CREATURE); + } + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.CONSTRUCT); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + int xValue = source.getManaCostsToPay().getX(); + permanent.getPower().setValue(xValue); + permanent.getToughness().setValue(xValue); + } + } + return true; } @Override @@ -169,10 +171,6 @@ class ChimericStaffEffect extends ContinuousEffectImpl { return false; } - private void setText() { - staticText = duration.toString() + " {this} becomes an X/X Construct artifact creature"; - } - @Override public boolean hasLayer(Layer layer) { return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4; diff --git a/Mage.Sets/src/mage/cards/f/FacesOfThePast.java b/Mage.Sets/src/mage/cards/f/FacesOfThePast.java index 518012e91c..77fde7971c 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.shareSubtypes(permanent, game)) { + if (!permanent.isTapped() && targetPermanent.shareCreatureTypes(permanent, game)) { permanent.tap(game); } } } else { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, game)) { - if (permanent.isTapped() && targetPermanent.shareSubtypes(permanent, game)) { + if (permanent.isTapped() && targetPermanent.shareCreatureTypes(permanent, game)) { permanent.untap(game); } } diff --git a/Mage.Sets/src/mage/cards/f/FireBellyChangeling.java b/Mage.Sets/src/mage/cards/f/FireBellyChangeling.java index 2ee6cb5a13..e63b834cf5 100644 --- a/Mage.Sets/src/mage/cards/f/FireBellyChangeling.java +++ b/Mage.Sets/src/mage/cards/f/FireBellyChangeling.java @@ -27,6 +27,7 @@ public final class FireBellyChangeling extends CardImpl { this.toughness = new MageInt(1); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // {R}: Fire-Belly Changeling gets +1/+0 until end of turn. Activate this ability no more than twice each turn. diff --git a/Mage.Sets/src/mage/cards/g/GameTrailChangeling.java b/Mage.Sets/src/mage/cards/g/GameTrailChangeling.java index 6315d0e345..4238a6deab 100644 --- a/Mage.Sets/src/mage/cards/g/GameTrailChangeling.java +++ b/Mage.Sets/src/mage/cards/g/GameTrailChangeling.java @@ -22,6 +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(TrampleAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/cards/g/GhostlyChangeling.java b/Mage.Sets/src/mage/cards/g/GhostlyChangeling.java index 0f29fb3083..e5f5c1b460 100644 --- a/Mage.Sets/src/mage/cards/g/GhostlyChangeling.java +++ b/Mage.Sets/src/mage/cards/g/GhostlyChangeling.java @@ -26,6 +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 SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl("{1}{B}"))); } diff --git a/Mage.Sets/src/mage/cards/g/Glaciers.java b/Mage.Sets/src/mage/cards/g/Glaciers.java index dd24f30067..59234594f8 100644 --- a/Mage.Sets/src/mage/cards/g/Glaciers.java +++ b/Mage.Sets/src/mage/cards/g/Glaciers.java @@ -74,7 +74,7 @@ public final class Glaciers extends CardImpl { // 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()); - land.getSubtype(game).add(SubType.PLAINS); + land.addSubType(game, SubType.PLAINS); land.removeAllAbilities(source.getSourceId(), game); land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); break; diff --git a/Mage.Sets/src/mage/cards/g/GlasspoolMimic.java b/Mage.Sets/src/mage/cards/g/GlasspoolMimic.java index ffd0f24364..d8af57674e 100644 --- a/Mage.Sets/src/mage/cards/g/GlasspoolMimic.java +++ b/Mage.Sets/src/mage/cards/g/GlasspoolMimic.java @@ -54,15 +54,15 @@ class GlasspoolMimicApplier extends ApplyToPermanent { @Override public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.getSubtype(game).add(SubType.SHAPESHIFTER); - permanent.getSubtype(game).add(SubType.ROGUE); + 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.getSubtype(game).add(SubType.SHAPESHIFTER); - mageObject.getSubtype(game).add(SubType.ROGUE); + mageObject.addSubType(game, SubType.SHAPESHIFTER); + mageObject.addSubType(game, 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 8ada8cfce8..df45a74c2c 100644 --- a/Mage.Sets/src/mage/cards/g/GodPharaohsGift.java +++ b/Mage.Sets/src/mage/cards/g/GodPharaohsGift.java @@ -88,8 +88,8 @@ class GodPharaohsGiftEffect extends OneShotEffect { token.getPower().modifyBaseValue(4); token.getToughness().modifyBaseValue(4); token.getColor(game).setColor(ObjectColor.BLACK); - token.getSubtype(game).clear(); - token.getSubtype(game).add(SubType.ZOMBIE); + token.removeAllCreatureTypes(game); + token.addSubType(game, SubType.ZOMBIE); if (token.putOntoBattlefield(1, game, source.getSourceId(), 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 279b8397c0..dc2f3f3e3a 100644 --- a/Mage.Sets/src/mage/cards/g/Graveshifter.java +++ b/Mage.Sets/src/mage/cards/g/Graveshifter.java @@ -27,6 +27,7 @@ public final class Graveshifter extends CardImpl { this.toughness = new MageInt(2); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // When Graveshifter enters the battlefield, you may return target creature card from your graveyard to your hand. diff --git a/Mage.Sets/src/mage/cards/g/GrimoireOfTheDead.java b/Mage.Sets/src/mage/cards/g/GrimoireOfTheDead.java index 4c56f63411..6312618db8 100644 --- a/Mage.Sets/src/mage/cards/g/GrimoireOfTheDead.java +++ b/Mage.Sets/src/mage/cards/g/GrimoireOfTheDead.java @@ -1,9 +1,6 @@ package mage.cards.g; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.DiscardTargetCost; @@ -24,14 +21,17 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInHand; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author BetaSteward */ public final class GrimoireOfTheDead extends CardImpl { public GrimoireOfTheDead(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); addSuperType(SuperType.LEGENDARY); // {1}, {tap}, Discard a card: Put a study counter on Grimoire of the Dead. @@ -121,14 +121,10 @@ class GrimoireOfTheDeadEffect2 extends ContinuousEffectImpl { if (permanent != null) { switch (layer) { case ColorChangingEffects_5: - if (sublayer == SubLayer.NA) { - permanent.getColor(game).setBlack(true); - } + permanent.getColor(game).setBlack(true); break; case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.getSubtype(game).add(SubType.ZOMBIE); - } + permanent.addSubType(game, SubType.ZOMBIE); break; } return true; diff --git a/Mage.Sets/src/mage/cards/h/HeirloomBlade.java b/Mage.Sets/src/mage/cards/h/HeirloomBlade.java index 65edc738a5..7a87d4de45 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.shareSubtypes(card, game)) { + if (card != null && card.isCreature() && equipped.shareCreatureTypes(card, game)) { controller.moveCardToHandWithInfo(card, source.getSourceId(), game, true); break; } else { diff --git a/Mage.Sets/src/mage/cards/h/HourOfEternity.java b/Mage.Sets/src/mage/cards/h/HourOfEternity.java index 918d40620d..dea482bda9 100644 --- a/Mage.Sets/src/mage/cards/h/HourOfEternity.java +++ b/Mage.Sets/src/mage/cards/h/HourOfEternity.java @@ -97,8 +97,8 @@ class HourOfEternityEffect extends OneShotEffect { token.getPower().modifyBaseValue(4); token.getToughness().modifyBaseValue(4); token.getColor(game).setColor(ObjectColor.BLACK); - token.getSubtype(game).clear(); - token.getSubtype(game).add(SubType.ZOMBIE); + token.removeAllCreatureTypes(game); + token.addSubType(game, SubType.ZOMBIE); token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); } } diff --git a/Mage.Sets/src/mage/cards/i/IllusionaryTerrain.java b/Mage.Sets/src/mage/cards/i/IllusionaryTerrain.java index 5fd36bb4ea..27c0a4b5e8 100644 --- a/Mage.Sets/src/mage/cards/i/IllusionaryTerrain.java +++ b/Mage.Sets/src/mage/cards/i/IllusionaryTerrain.java @@ -95,7 +95,7 @@ class IllusionaryTerrainEffect extends ContinuousEffectImpl { // 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()); - land.getSubtype(game).add(secondChoice); + land.addSubType(game, secondChoice); land.removeAllAbilities(source.getSourceId(), game); if (land.getSubtype(game).contains(SubType.FOREST)) { this.dependencyTypes.add(DependencyType.BecomeForest); diff --git a/Mage.Sets/src/mage/cards/i/ImpostorOfTheSixthPride.java b/Mage.Sets/src/mage/cards/i/ImpostorOfTheSixthPride.java index 94e82f36d8..bfbb7d01bc 100644 --- a/Mage.Sets/src/mage/cards/i/ImpostorOfTheSixthPride.java +++ b/Mage.Sets/src/mage/cards/i/ImpostorOfTheSixthPride.java @@ -22,6 +22,7 @@ public final class ImpostorOfTheSixthPride extends CardImpl { this.toughness = new MageInt(1); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/cards/i/IrregularCohort.java b/Mage.Sets/src/mage/cards/i/IrregularCohort.java index 4b7d95621f..5d7ed2537e 100644 --- a/Mage.Sets/src/mage/cards/i/IrregularCohort.java +++ b/Mage.Sets/src/mage/cards/i/IrregularCohort.java @@ -24,6 +24,7 @@ public final class IrregularCohort extends CardImpl { this.toughness = new MageInt(2); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // When Irregular Cohort enters the battlefield, create a 2/2 colorless Shapeshifter creature token with changeling. diff --git a/Mage.Sets/src/mage/cards/k/KondasBanner.java b/Mage.Sets/src/mage/cards/k/KondasBanner.java index fbe583449a..5c48062109 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.shareSubtypes(equipedCreature, game)) { + if (perm.shareCreatureTypes(equipedCreature, game)) { perm.addPower(power.calculate(game, source, this)); perm.addToughness(toughness.calculate(game, source, this)); diff --git a/Mage.Sets/src/mage/cards/l/LifeAndLimb.java b/Mage.Sets/src/mage/cards/l/LifeAndLimb.java index c48d4df326..e1ea3d82cd 100644 --- a/Mage.Sets/src/mage/cards/l/LifeAndLimb.java +++ b/Mage.Sets/src/mage/cards/l/LifeAndLimb.java @@ -70,18 +70,13 @@ class LifeAndLimbEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: permanent.addCardType(CardType.CREATURE); - if (!permanent.hasSubtype(SubType.SAPROLING, game)) { - permanent.getSubtype(game).add(SubType.SAPROLING); - } - - // land abilities are intrinsic, so add them here, not in layer 6 - if (!permanent.hasSubtype(SubType.FOREST, game)) { - permanent.getSubtype(game).add(SubType.FOREST); - if (!permanent.getAbilities(game).containsClass(GreenManaAbility.class)) { - permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } - } permanent.addCardType(CardType.LAND); + permanent.addSubType(game, SubType.SAPROLING); + // land abilities are intrinsic, so add them here, not in layer 6 + permanent.addSubType(game, SubType.FOREST); + if (!permanent.getAbilities(game).containsClass(GreenManaAbility.class)) { + permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); + } break; case ColorChangingEffects_5: permanent.getColor(game).setColor(ObjectColor.GREEN); diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java b/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java index d68dba2bd4..cd52cc84c3 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java @@ -78,7 +78,7 @@ public final class MagusOfTheMoon extends CardImpl { // So the ability removing has to be done before Layer 6 land.removeAllAbilities(source.getSourceId(), game); land.getSubtype(game).removeAll(SubType.getLandTypes()); - land.getSubtype(game).add(SubType.MOUNTAIN); + 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); break; diff --git a/Mage.Sets/src/mage/cards/m/ManaEchoes.java b/Mage.Sets/src/mage/cards/m/ManaEchoes.java index 0e266ad925..d879b3fabf 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.shareSubtypes(perm, game)) { + if (permanent.shareCreatureTypes(perm, game)) { foundCreatures++; } } diff --git a/Mage.Sets/src/mage/cards/m/MephidrossVampire.java b/Mage.Sets/src/mage/cards/m/MephidrossVampire.java index e782a5f888..06b7ad6358 100644 --- a/Mage.Sets/src/mage/cards/m/MephidrossVampire.java +++ b/Mage.Sets/src/mage/cards/m/MephidrossVampire.java @@ -86,9 +86,7 @@ class MephidrossVampireEffect extends ContinuousEffectImpl { creature.addAbility(new DealsDamageToACreatureTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false, false, false), source.getSourceId(), game); break; case TypeChangingEffects_4: - if (!creature.hasSubtype(SubType.VAMPIRE, game)) { - creature.getSubtype(game).add(SubType.VAMPIRE); - } + creature.addSubType(game, SubType.VAMPIRE); break; } } diff --git a/Mage.Sets/src/mage/cards/m/MetamorphicAlteration.java b/Mage.Sets/src/mage/cards/m/MetamorphicAlteration.java index ee046ca105..235d4ce49e 100644 --- a/Mage.Sets/src/mage/cards/m/MetamorphicAlteration.java +++ b/Mage.Sets/src/mage/cards/m/MetamorphicAlteration.java @@ -74,20 +74,21 @@ class ChooseACreature extends OneShotEffect { if (sourceObject == null) { sourceObject = game.getObject(source.getSourceId()); } - if (controller != null - && sourceObject != null) { - Target target = new TargetCreaturePermanent(); - target.setNotTarget(true); - if (target.canChoose(source.getSourceId(), controller.getId(), game)) { - controller.choose(Outcome.Copy, target, source.getSourceId(), game); - Permanent chosenPermanent = game.getPermanent(target.getFirstTarget()); - if (chosenPermanent != null) { - game.getState().setValue(source.getSourceId().toString() + INFO_KEY, chosenPermanent.copy()); - } - } + if (controller == null + || sourceObject == null) { + return false; + } + Target target = new TargetCreaturePermanent(); + target.setNotTarget(true); + if (!target.canChoose(source.getSourceId(), controller.getId(), game)) { return true; } - return false; + controller.choose(Outcome.Copy, target, source.getSourceId(), game); + Permanent chosenPermanent = game.getPermanent(target.getFirstTarget()); + if (chosenPermanent != null) { + game.getState().setValue(source.getSourceId().toString() + INFO_KEY, chosenPermanent.copy()); + } + return true; } @Override @@ -108,46 +109,41 @@ class MetamorphicAlterationEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { Permanent enchantment = game.getPermanent(source.getSourceId()); Permanent copied = (Permanent) game.getState().getValue(source.getSourceId().toString() + ChooseACreature.INFO_KEY); - if (enchantment != null - && copied != null) { - Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); - if (permanent != null - && layer == Layer.CopyEffects_1) { - permanent.setName(copied.getName()); - permanent.getManaCost().clear(); - permanent.getManaCost().addAll(copied.getManaCost()); - permanent.setExpansionSetCode(copied.getExpansionSetCode()); - permanent.getSuperType().clear(); - for (SuperType t : copied.getSuperType()) { - permanent.addSuperType(t); - } - permanent.getCardType().clear(); - for (CardType cardType : copied.getCardType()) { - permanent.addCardType(cardType); - } - permanent.getSubtype(game).retainAll(SubType.getLandTypes()); - for (SubType subType : copied.getSubtype(game)) { - permanent.getSubtype(game).add(subType); - } - permanent.getColor(game).setColor(copied.getColor(game)); - permanent.removeAllAbilities(source.getSourceId(), game); - for (Ability ability : copied.getAbilities()) { - permanent.addAbility(ability, source.getSourceId(), game); - } - permanent.getPower().setValue(copied.getPower().getBaseValue()); - permanent.getToughness().setValue(copied.getToughness().getBaseValue()); - return true; - } + if (enchantment == null + || copied == null) { + return false; } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; + Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); + if (permanent == null) { + return false; + } + permanent.setName(copied.getName()); + permanent.getManaCost().clear(); + permanent.getManaCost().addAll(copied.getManaCost()); + permanent.setExpansionSetCode(copied.getExpansionSetCode()); + permanent.getSuperType().clear(); + for (SuperType t : copied.getSuperType()) { + permanent.addSuperType(t); + } + permanent.getCardType().clear(); + for (CardType cardType : copied.getCardType()) { + permanent.addCardType(cardType); + } + permanent.removeAllSubTypes(game); + permanent.setIsAllCreatureTypes(copied.isAllCreatureTypes()); + permanent.getSubtype(game).addAll(copied.getSubtype(game)); + permanent.setIsAllCreatureTypes(copied.isAllCreatureTypes()); + permanent.getColor(game).setColor(copied.getColor(game)); + permanent.removeAllAbilities(source.getSourceId(), game); + for (Ability ability : copied.getAbilities()) { + permanent.addAbility(ability, source.getSourceId(), game); + } + permanent.getPower().setValue(copied.getPower().getBaseValue()); + permanent.getToughness().setValue(copied.getToughness().getBaseValue()); + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/m/MirrorEntity.java b/Mage.Sets/src/mage/cards/m/MirrorEntity.java index 9174db87c9..8ea0f5324b 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorEntity.java +++ b/Mage.Sets/src/mage/cards/m/MirrorEntity.java @@ -1,52 +1,46 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.VariableManaCost; -import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.ManacostVariableValue; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.continuous.SetPowerToughnessAllEffect; import mage.abilities.keyword.ChangelingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.SubLayer; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.Iterator; +import java.util.UUID; /** - * * @author Plopman */ public final class MirrorEntity extends CardImpl { - static private FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Creatures you control"); - public MirrorEntity(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); this.subtype.add(SubType.SHAPESHIFTER); this.power = new MageInt(1); this.toughness = new MageInt(1); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); + // {X}: Until end of turn, creatures you control have base power and toughness X/X and gain all creature types. - DynamicValue variableMana = ManacostVariableValue.instance; - Effect effect = new SetPowerToughnessAllEffect(variableMana, variableMana, Duration.EndOfTurn, filter, true); - effect.setText("Until end of turn, creatures you control have base power and toughness X/X"); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new VariableManaCost()); - effect = new GainAbilityAllEffect(ChangelingAbility.getInstance(), Duration.EndOfTurn, filter, false, Layer.TypeChangingEffects_4, SubLayer.NA); - effect.setText("and gain all creature types"); - ability.addEffect(effect); + Ability ability = new SimpleActivatedAbility(new SetPowerToughnessAllEffect( + ManacostVariableValue.instance, ManacostVariableValue.instance, + Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES, true + ).setText("Until end of turn, creatures you control have base power and toughness X/X"), new VariableManaCost()); + ability.addEffect(new MirrorEntityEffect()); this.addAbility(ability); } @@ -59,3 +53,43 @@ public final class MirrorEntity extends CardImpl { return new MirrorEntity(this); } } + +class MirrorEntityEffect extends ContinuousEffectImpl { + + MirrorEntityEffect() { + super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); + staticText = "and gain all creature types"; + } + + private MirrorEntityEffect(final MirrorEntityEffect effect) { + super(effect); + } + + @Override + public MirrorEntityEffect copy() { + return new MirrorEntityEffect(this); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + for (Permanent perm : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_CREATURES, source.getControllerId(), source.getSourceId(), game + )) { + affectedObjectList.add(new MageObjectReference(perm, game)); + } + } + + @Override + public boolean apply(Game game, Ability source) { + for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { + Permanent permanent = it.next().getPermanent(game); + if (permanent == null) { + it.remove(); // no longer on the battlefield, remove reference to object + continue; + } + permanent.setIsAllCreatureTypes(true); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/m/MistformUltimus.java b/Mage.Sets/src/mage/cards/m/MistformUltimus.java index 375a434a35..d4624294a7 100644 --- a/Mage.Sets/src/mage/cards/m/MistformUltimus.java +++ b/Mage.Sets/src/mage/cards/m/MistformUltimus.java @@ -1,31 +1,35 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; -import mage.abilities.keyword.ChangelingAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.InfoEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; +import mage.constants.Zone; + +import java.util.UUID; /** - * * @author vereena42 */ public final class MistformUltimus extends CardImpl { public MistformUltimus(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); - + this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.ILLUSION); this.power = new MageInt(3); this.toughness = new MageInt(3); // Mistform Ultimus is every creature type. - this.addAbility(ChangelingAbility.getInstance()); + 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)." + ))); } public MistformUltimus(final MistformUltimus card) { diff --git a/Mage.Sets/src/mage/cards/m/MoongloveChangeling.java b/Mage.Sets/src/mage/cards/m/MoongloveChangeling.java index ef32aee047..f7115243c5 100644 --- a/Mage.Sets/src/mage/cards/m/MoongloveChangeling.java +++ b/Mage.Sets/src/mage/cards/m/MoongloveChangeling.java @@ -24,6 +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 SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn), new ColoredManaCost(ColoredManaSymbol.B))); } diff --git a/Mage.Sets/src/mage/cards/m/MorophonTheBoundless.java b/Mage.Sets/src/mage/cards/m/MorophonTheBoundless.java index c8064c745c..b18b28ea8c 100644 --- a/Mage.Sets/src/mage/cards/m/MorophonTheBoundless.java +++ b/Mage.Sets/src/mage/cards/m/MorophonTheBoundless.java @@ -40,6 +40,7 @@ public final class MorophonTheBoundless extends CardImpl { this.toughness = new MageInt(6); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // As Morophon, the Boundless enters the battlefield, choose a creature type. diff --git a/Mage.Sets/src/mage/cards/m/MothdustChangeling.java b/Mage.Sets/src/mage/cards/m/MothdustChangeling.java index 6f276339b1..c6f60f80ff 100644 --- a/Mage.Sets/src/mage/cards/m/MothdustChangeling.java +++ b/Mage.Sets/src/mage/cards/m/MothdustChangeling.java @@ -36,6 +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 SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new TapTargetCost(new TargetControlledPermanent(filter)))); } diff --git a/Mage.Sets/src/mage/cards/n/NamelessInversion.java b/Mage.Sets/src/mage/cards/n/NamelessInversion.java index 8ad30fe242..7191a28e74 100644 --- a/Mage.Sets/src/mage/cards/n/NamelessInversion.java +++ b/Mage.Sets/src/mage/cards/n/NamelessInversion.java @@ -25,6 +25,7 @@ public final class NamelessInversion extends CardImpl { // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // Target creature gets +3/-3 and loses all creature types until end of turn. diff --git a/Mage.Sets/src/mage/cards/n/Necromancy.java b/Mage.Sets/src/mage/cards/n/Necromancy.java index 50d87e1e83..d0522b0c22 100644 --- a/Mage.Sets/src/mage/cards/n/Necromancy.java +++ b/Mage.Sets/src/mage/cards/n/Necromancy.java @@ -1,7 +1,6 @@ package mage.cards.n; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -29,8 +28,9 @@ import mage.target.Target; import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Necromancy extends CardImpl { @@ -175,18 +175,12 @@ class NecromancyChangeAbilityEffect extends ContinuousEffectImpl implements Sour if (permanent != null) { switch (layer) { case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - if (!permanent.hasSubtype(SubType.AURA, game)) { - permanent.getSubtype(game).add(SubType.AURA); - } - } + permanent.addSubType(game, SubType.AURA); break; case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - permanent.addAbility(newAbility, source.getSourceId(), game); - permanent.getSpellAbility().getTargets().clear(); - permanent.getSpellAbility().getTargets().add(target); - } + permanent.addAbility(newAbility, source.getSourceId(), game); + permanent.getSpellAbility().getTargets().clear(); + permanent.getSpellAbility().getTargets().add(target); } return true; } diff --git a/Mage.Sets/src/mage/cards/n/NewBlood.java b/Mage.Sets/src/mage/cards/n/NewBlood.java index 4361a19ef0..49cf5eea45 100644 --- a/Mage.Sets/src/mage/cards/n/NewBlood.java +++ b/Mage.Sets/src/mage/cards/n/NewBlood.java @@ -152,7 +152,7 @@ class ChangeCreatureTypeTargetEffect extends ContinuousEffectImpl { if (targetObject.hasSubtype(fromSubType, game)) { targetObject.getSubtype(game).remove(fromSubType); if (!targetObject.hasSubtype(toSubType, game)) { - targetObject.getSubtype(game).add(toSubType); + targetObject.addSubType(game, toSubType); } } break; diff --git a/Mage.Sets/src/mage/cards/n/NimDeathmantle.java b/Mage.Sets/src/mage/cards/n/NimDeathmantle.java index 6198990341..3e0dac4573 100644 --- a/Mage.Sets/src/mage/cards/n/NimDeathmantle.java +++ b/Mage.Sets/src/mage/cards/n/NimDeathmantle.java @@ -39,17 +39,23 @@ public final class NimDeathmantle extends CardImpl { this.subtype.add(SubType.EQUIPMENT); // Equipped creature gets +2/+2, has intimidate, and is a black Zombie. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(IntimidateAbility.getInstance(), AttachmentType.EQUIPMENT))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SetCardColorAttachedEffect(ObjectColor.BLACK, Duration.WhileOnBattlefield, AttachmentType.EQUIPMENT))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SetCardSubtypeAttachedEffect(Duration.WhileOnBattlefield, AttachmentType.EQUIPMENT, SubType.ZOMBIE))); + Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(2, 2)); + ability.addEffect(new GainAbilityAttachedEffect( + IntimidateAbility.getInstance(), AttachmentType.EQUIPMENT + ).setText(", has intimidate")); + ability.addEffect(new SetCardColorAttachedEffect( + ObjectColor.BLACK, Duration.WhileOnBattlefield, AttachmentType.EQUIPMENT + ).setText(", and is")); + ability.addEffect(new SetCardSubtypeAttachedEffect( + Duration.WhileOnBattlefield, AttachmentType.EQUIPMENT, SubType.ZOMBIE + ).setText("black Zombie").concatBy("a")); + this.addAbility(ability); // Whenever a nontoken creature is put into your graveyard from the battlefield, you may pay {4}. If you do, return that card to the battlefield and attach Nim Deathmantle to it. this.addAbility(new NimDeathmantleTriggeredAbility()); // Equip {4} this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(4))); - } public NimDeathmantle(final NimDeathmantle card) { @@ -93,7 +99,7 @@ class NimDeathmantleTriggeredAbility extends TriggeredAbilityImpl { && !(permanent instanceof PermanentToken) && permanent.isCreature()) { - getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game) +1)); + getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game) + 1)); return true; } return false; @@ -124,8 +130,8 @@ class NimDeathmantleEffect extends OneShotEffect { Permanent equipment = game.getPermanent(source.getSourceId()); if (controller != null && equipment != null) { if (controller.chooseUse(Outcome.Benefit, equipment.getName() + " - Pay " + cost.getText() + '?', source, game)) { - cost.clearPaid(); - if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) { + cost.clearPaid(); + if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) { UUID target = targetPointer.getFirst(game, source); if (target != null) { Card card = game.getCard(target); diff --git a/Mage.Sets/src/mage/cards/n/NyleasPresence.java b/Mage.Sets/src/mage/cards/n/NyleasPresence.java index 14cb39ed09..406fb52f5c 100644 --- a/Mage.Sets/src/mage/cards/n/NyleasPresence.java +++ b/Mage.Sets/src/mage/cards/n/NyleasPresence.java @@ -1,6 +1,5 @@ package mage.cards.n; -import mage.Mana; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -17,8 +16,6 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; /** @@ -30,18 +27,18 @@ public final class NyleasPresence extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); this.subtype.add(SubType.AURA); - // Enchant land TargetPermanent auraTarget = new TargetLandPermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + // When Nylea's Presence enters the battlefield, draw a card. this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1))); - // Enchanted land is every basic land type in addition to its other types. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NyleasPresenceLandTypeEffect())); + // Enchanted land is every basic land type in addition to its other types. + this.addAbility(new SimpleStaticAbility(new NyleasPresenceLandTypeEffect())); } public NyleasPresence(final NyleasPresence card) { @@ -56,22 +53,18 @@ public final class NyleasPresence extends CardImpl { class NyleasPresenceLandTypeEffect extends ContinuousEffectImpl { - protected List landTypes = new ArrayList<>(); - public NyleasPresenceLandTypeEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); - landTypes.addAll(SubType.getBasicLands()); + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); this.staticText = "Enchanted land is every basic land type in addition to its other types"; + dependencyTypes.add(DependencyType.BecomePlains); + dependencyTypes.add(DependencyType.BecomeIsland); + dependencyTypes.add(DependencyType.BecomeSwamp); + dependencyTypes.add(DependencyType.BecomeMountain); + dependencyTypes.add(DependencyType.BecomeForest); } public NyleasPresenceLandTypeEffect(final NyleasPresenceLandTypeEffect effect) { super(effect); - this.landTypes.addAll(effect.landTypes); - } - - @Override - public boolean apply(Game game, Ability source) { - return false; } @Override @@ -80,52 +73,22 @@ class NyleasPresenceLandTypeEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null && enchantment.getAttachedTo() != null) { - Permanent land = game.getPermanent(enchantment.getAttachedTo()); - if (land != null) { - switch (layer) { - case AbilityAddingRemovingEffects_6: - Mana mana = new Mana(); - for (Ability ability : land.getAbilities()) { - if (ability instanceof BasicManaAbility) { - for (Mana netMana : ((BasicManaAbility) ability).getNetMana(game)) { - mana.add(netMana); - } - } - } - if (mana.getGreen() == 0 && landTypes.contains(SubType.FOREST)) { - land.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } - if (mana.getRed() == 0 && landTypes.contains(SubType.MOUNTAIN)) { - land.addAbility(new RedManaAbility(), source.getSourceId(), game); - } - if (mana.getBlue() == 0 && landTypes.contains(SubType.ISLAND)) { - land.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - if (mana.getWhite() == 0 && landTypes.contains(SubType.PLAINS)) { - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - } - if (mana.getBlack() == 0 && landTypes.contains(SubType.SWAMP)) { - land.addAbility(new BlackManaAbility(), source.getSourceId(), game); - } - break; - case TypeChangingEffects_4: - for (SubType subtype : landTypes) { - if (!land.hasSubtype(subtype, game)) { - land.getSubtype(game).add(subtype); - } - } - break; - } - } + if (enchantment == null || enchantment.getAttachedTo() == null) { + return true; } + Permanent land = game.getPermanent(enchantment.getAttachedTo()); + if (land == null) { + return true; + } + land.getSubtype(game).removeAll(SubType.getBasicLands()); + land.getSubtype(game).addAll(SubType.getBasicLands()); + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); return true; } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; - } } diff --git a/Mage.Sets/src/mage/cards/o/OneWithTheStars.java b/Mage.Sets/src/mage/cards/o/OneWithTheStars.java index 168757c057..3388b4c132 100644 --- a/Mage.Sets/src/mage/cards/o/OneWithTheStars.java +++ b/Mage.Sets/src/mage/cards/o/OneWithTheStars.java @@ -87,6 +87,8 @@ class OneWithTheStarsEffect extends ContinuousEffectImpl { if (permanent == null) { return false; } + permanent.setIsAllCreatureTypes(false); + permanent.getSubtype(game).retainAll(SubType.getEnchantmentTypes()); permanent.getCardType().clear(); permanent.addCardType(CardType.ENCHANTMENT); return true; diff --git a/Mage.Sets/src/mage/cards/o/OpalTitan.java b/Mage.Sets/src/mage/cards/o/OpalTitan.java index bbbbc452f7..58ad41edcf 100644 --- a/Mage.Sets/src/mage/cards/o/OpalTitan.java +++ b/Mage.Sets/src/mage/cards/o/OpalTitan.java @@ -1,6 +1,5 @@ package mage.cards.o; -import java.util.UUID; import mage.MageObjectReference; import mage.ObjectColor; import mage.abilities.Ability; @@ -13,23 +12,16 @@ import mage.abilities.effects.common.continuous.SourceEffect; import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.DependencyType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SetTargetPointer; -import mage.constants.SubLayer; -import mage.constants.SubType; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterSpell; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.Spell; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class OpalTitan extends CardImpl { @@ -98,7 +90,8 @@ class OpalTitanBecomesCreatureEffect extends ContinuousEffectImpl implements Sou if (sublayer == SubLayer.NA) { permanent.getCardType().clear(); permanent.addCardType(CardType.CREATURE); - permanent.getSubtype(game).add(SubType.GIANT); + permanent.removeAllSubTypes(game); + permanent.addSubType(game, SubType.GIANT); } break; case AbilityAddingRemovingEffects_6: diff --git a/Mage.Sets/src/mage/cards/p/ParagonOfTheAmesha.java b/Mage.Sets/src/mage/cards/p/ParagonOfTheAmesha.java index 29e40dd933..6fe3812635 100644 --- a/Mage.Sets/src/mage/cards/p/ParagonOfTheAmesha.java +++ b/Mage.Sets/src/mage/cards/p/ParagonOfTheAmesha.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -19,14 +17,15 @@ import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class ParagonOfTheAmesha extends CardImpl { public ParagonOfTheAmesha(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.KNIGHT); @@ -37,18 +36,17 @@ public final class ParagonOfTheAmesha extends CardImpl { this.addAbility(FirstStrikeAbility.getInstance()); // {W}{U}{B}{R}{G}: Until end of turn, Paragon of the Amesha becomes an Angel, gets +3/+3, and gains flying and lifelink. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ParagonOfTheAmeshaEffect(), new ManaCostsImpl("{W}{U}{B}{R}{G}")); + Ability ability = new SimpleActivatedAbility(new ParagonOfTheAmeshaEffect(), new ManaCostsImpl("{W}{U}{B}{R}{G}")); Effect effect = new BoostSourceEffect(3, 3, Duration.EndOfTurn); - effect.setText("gets +3/+3,"); + effect.setText(", gets +3/+3"); ability.addEffect(effect); effect = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn); - effect.setText("and gains flying"); + effect.setText(", and gains flying"); ability.addEffect(effect); effect = new GainAbilitySourceEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn); effect.setText("and lifelink"); ability.addEffect(effect); this.addAbility(ability); - } public ParagonOfTheAmesha(final ParagonOfTheAmesha card) { @@ -62,12 +60,12 @@ public final class ParagonOfTheAmesha extends CardImpl { private static class ParagonOfTheAmeshaEffect extends ContinuousEffectImpl { - public ParagonOfTheAmeshaEffect() { - super(Duration.EndOfTurn, Outcome.BecomeCreature); - setText(); + private ParagonOfTheAmeshaEffect() { + super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature); + staticText = "Until end of turn, {this} becomes an Angel"; } - public ParagonOfTheAmeshaEffect(final ParagonOfTheAmeshaEffect effect) { + private ParagonOfTheAmeshaEffect(final ParagonOfTheAmeshaEffect effect) { super(effect); } @@ -77,34 +75,14 @@ public final class ParagonOfTheAmesha extends CardImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent == null) { return false; } - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.getSubtype(game).clear(); - permanent.getSubtype(game).add(SubType.ANGEL); - } - break; - } + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.ANGEL); return true; } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - private void setText() { - staticText = "Until end of turn, {this} becomes an Angel, "; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } } } diff --git a/Mage.Sets/src/mage/cards/p/PathOfAncestry.java b/Mage.Sets/src/mage/cards/p/PathOfAncestry.java index 8b4085a101..ee0be6c447 100644 --- a/Mage.Sets/src/mage/cards/p/PathOfAncestry.java +++ b/Mage.Sets/src/mage/cards/p/PathOfAncestry.java @@ -5,23 +5,18 @@ import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.keyword.ScryEffect; -import mage.abilities.keyword.ChangelingAbility; import mage.abilities.mana.CommanderColorIdentityManaAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.SubType; -import mage.constants.SubTypeSet; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.players.Player; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; /** @@ -92,8 +87,7 @@ class PathOfAncestryTriggeredAbility extends DelayedTriggeredAbility { return false; } Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell == null || (spell.getSubtype(game).isEmpty() - && !spell.hasAbility(ChangelingAbility.getInstance(), game))) { + if (spell == null) { return false; } Player player = game.getPlayer(getControllerId()); @@ -101,7 +95,6 @@ class PathOfAncestryTriggeredAbility extends DelayedTriggeredAbility { return false; } boolean isAllA = false; - Set subTypeSet = new HashSet<>(); for (UUID commanderId : game.getCommandersIds(player)) { Card commander = game.getPermanent(commanderId); if (commander == null) { @@ -110,19 +103,11 @@ class PathOfAncestryTriggeredAbility extends DelayedTriggeredAbility { if (commander == null) { continue; } - if (commander.isAllCreatureTypes() - || commander.hasAbility(ChangelingAbility.getInstance(), game)) { - isAllA = true; - break; + if (spell.getCard().shareCreatureTypes(commander, game)) { + return true; } - subTypeSet.addAll(commander.getSubtype(game)); } - subTypeSet.removeIf(subType -> subType.getSubTypeSet() != SubTypeSet.CreatureType); - if (subTypeSet.isEmpty() && !isAllA) { - return false; - } - return spell.hasAbility(ChangelingAbility.getInstance(), game) - || spell.getSubtype(game).stream().anyMatch(subTypeSet::contains); + return false; } @Override diff --git a/Mage.Sets/src/mage/cards/p/PhantasmalImage.java b/Mage.Sets/src/mage/cards/p/PhantasmalImage.java index 9c0b2db68f..de0d842757 100644 --- a/Mage.Sets/src/mage/cards/p/PhantasmalImage.java +++ b/Mage.Sets/src/mage/cards/p/PhantasmalImage.java @@ -30,9 +30,7 @@ public final class PhantasmalImage extends CardImpl { private static final ApplyToPermanent phantasmalImageApplier = new ApplyToPermanent() { @Override public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - if (!permanent.hasSubtype(SubType.ILLUSION, game)) { - permanent.getSubtype(game).add(SubType.ILLUSION); - } + permanent.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 permanent.getAbilities().add(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect())); //permanent.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect()), game); @@ -41,9 +39,7 @@ public final class PhantasmalImage extends CardImpl { @Override public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - if (!mageObject.hasSubtype(SubType.ILLUSION, game)) { - mageObject.getSubtype(game).add(SubType.ILLUSION); - } + 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); diff --git a/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java b/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java index 76b23c0cae..17bfef4703 100644 --- a/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java +++ b/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java @@ -1,6 +1,5 @@ package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; @@ -8,28 +7,18 @@ import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.ChooseBasicLandTypeEffect; import mage.abilities.keyword.EnchantAbility; -import mage.abilities.mana.BlackManaAbility; -import mage.abilities.mana.BlueManaAbility; -import mage.abilities.mana.GreenManaAbility; -import mage.abilities.mana.RedManaAbility; -import mage.abilities.mana.WhiteManaAbility; +import mage.abilities.mana.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.DependencyType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; +import java.util.UUID; + /** - * * @author Quercitron */ public final class PhantasmalTerrain extends CardImpl { @@ -60,14 +49,14 @@ public final class PhantasmalTerrain extends CardImpl { return new PhantasmalTerrain(this); } - class PhantasmalTerrainContinuousEffect extends ContinuousEffectImpl { + private static class PhantasmalTerrainContinuousEffect extends ContinuousEffectImpl { - public PhantasmalTerrainContinuousEffect() { - super(Duration.WhileOnBattlefield, Outcome.Neutral); - this.staticText = "enchanted land is the chosen type"; + private PhantasmalTerrainContinuousEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); + staticText = "Enchanted land is the chosen type"; } - public PhantasmalTerrainContinuousEffect(final PhantasmalTerrainContinuousEffect effect) { + private PhantasmalTerrainContinuousEffect(final PhantasmalTerrainContinuousEffect effect) { super(effect); } @@ -77,72 +66,60 @@ public final class PhantasmalTerrain extends CardImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent enchantment = game.getPermanent(source.getSourceId()); - SubType choice = SubType.byDescription((String) game.getState() - .getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY)); - if (choice != null) { - if (choice.equals(SubType.MOUNTAIN)) { - dependencyTypes.add(DependencyType.BecomeMountain); - } - if (choice.equals(SubType.FOREST)) { + public void init(Ability source, Game game) { + super.init(source, game); + SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY)); + switch (choice) { + case FOREST: dependencyTypes.add(DependencyType.BecomeForest); - } - if (choice.equals(SubType.SWAMP)) { - dependencyTypes.add(DependencyType.BecomeSwamp); - } - if (choice.equals(SubType.ISLAND)) { - dependencyTypes.add(DependencyType.BecomeIsland); - } - if (choice.equals(SubType.PLAINS)) { + break; + case PLAINS: dependencyTypes.add(DependencyType.BecomePlains); - } + break; + case MOUNTAIN: + dependencyTypes.add(DependencyType.BecomeMountain); + break; + case ISLAND: + dependencyTypes.add(DependencyType.BecomeIsland); + break; + case SWAMP: + dependencyTypes.add(DependencyType.BecomeSwamp); + break; } - if (enchantment != null - && enchantment.getAttachedTo() != null - && choice != null) { - Permanent land = game.getPermanent(enchantment.getAttachedTo()); - if (land != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - land.getSubtype(game).clear(); - land.getSubtype(game).add(choice); - land.removeAllAbilities(source.getSourceId(), game); - - // land ability is intrinsic, so apply at this layer, not layer 6 - if (choice.equals(SubType.FOREST)) { - land.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.PLAINS)) { - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.MOUNTAIN)) { - land.addAbility(new RedManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.ISLAND)) { - land.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.SWAMP)) { - land.addAbility(new BlackManaAbility(), source.getSourceId(), game); - } - } - break; - } - 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; + Permanent enchantment = game.getPermanent(source.getSourceId()); + SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY)); + if (enchantment == null || enchantment.getAttachedTo() == null || choice == null) { + return false; + } + Permanent land = game.getPermanent(enchantment.getAttachedTo()); + if (land == null) { + return false; + } + land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.addSubType(game, choice); + land.removeAllAbilities(source.getSourceId(), game); + switch (choice) { + case FOREST: + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); + break; + case PLAINS: + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + break; + case MOUNTAIN: + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + break; + case ISLAND: + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + break; + case SWAMP: + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + break; + } + return true; } } } diff --git a/Mage.Sets/src/mage/cards/p/PolymorphistsJest.java b/Mage.Sets/src/mage/cards/p/PolymorphistsJest.java index dd721287a3..2f56d29046 100644 --- a/Mage.Sets/src/mage/cards/p/PolymorphistsJest.java +++ b/Mage.Sets/src/mage/cards/p/PolymorphistsJest.java @@ -1,39 +1,32 @@ package mage.cards.p; -import java.util.Iterator; -import java.util.UUID; import mage.MageObjectReference; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.SubType; -import mage.filter.common.FilterCreaturePermanent; +import mage.constants.*; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPlayer; +import java.util.Iterator; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class PolymorphistsJest extends CardImpl { public PolymorphistsJest(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{U}"); // Until end of turn, each creature target player controls loses all abilities and becomes a blue Frog with base power and toughness 1/1. this.getSpellAbility().addEffect(new PolymorphistsJestEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); - } public PolymorphistsJest(final PolymorphistsJest card) { @@ -48,8 +41,6 @@ public final class PolymorphistsJest extends CardImpl { class PolymorphistsJestEffect extends ContinuousEffectImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - public PolymorphistsJestEffect() { super(Duration.EndOfTurn, Outcome.BecomeCreature); staticText = "Until end of turn, each creature target player controls loses all abilities and becomes a blue Frog with base power and toughness 1/1"; @@ -68,46 +59,40 @@ class PolymorphistsJestEffect extends ContinuousEffectImpl { public void init(Ability source, Game game) { super.init(source, game); if (this.affectedObjectsSet) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, getTargetPointer().getFirst(game, source), game)) { - affectedObjectList.add(new MageObjectReference(permanent, game)); - } + game.getBattlefield() + .getActivePermanents( + StaticFilters.FILTER_CONTROLLED_CREATURE, + getTargetPointer().getFirst(game, source), source.getSourceId(), game + ).stream() + .map(permanent -> new MageObjectReference(permanent, game)) + .forEach(affectedObjectList::add); } } @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 permanent = it.next().getPermanent(game); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.getSubtype(game).clear(); - permanent.getSubtype(game).add(SubType.FROG); - } - - break; - case ColorChangingEffects_5: - if (sublayer == SubLayer.NA) { - permanent.getColor(game).setBlack(false); - permanent.getColor(game).setGreen(false); - permanent.getColor(game).setBlue(false); - permanent.getColor(game).setWhite(false); - permanent.getColor(game).setBlack(false); - permanent.getColor(game).setColor(ObjectColor.BLUE); - } - break; - case AbilityAddingRemovingEffects_6: - permanent.removeAllAbilities(source.getSourceId(), game); - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - permanent.getPower().setValue(1); - permanent.getToughness().setValue(1); - } - } - } else { + if (permanent == null) { it.remove(); + continue; + } + switch (layer) { + case TypeChangingEffects_4: + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.FROG); + break; + case ColorChangingEffects_5: + permanent.getColor(game).setColor(ObjectColor.BLUE); + break; + case AbilityAddingRemovingEffects_6: + permanent.removeAllAbilities(source.getSourceId(), game); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setValue(1); + permanent.getToughness().setValue(1); + } } } return true; @@ -120,7 +105,10 @@ class PolymorphistsJestEffect extends ContinuousEffectImpl { @Override public boolean hasLayer(Layer layer) { - return layer == Layer.PTChangingEffects_7 || layer == Layer.ColorChangingEffects_5 || layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; + return layer == Layer.PTChangingEffects_7 + || layer == Layer.ColorChangingEffects_5 + || layer == Layer.AbilityAddingRemovingEffects_6 + || layer == Layer.TypeChangingEffects_4; } } diff --git a/Mage.Sets/src/mage/cards/r/Realmwright.java b/Mage.Sets/src/mage/cards/r/Realmwright.java index a7bb10453c..f3b15d9426 100644 --- a/Mage.Sets/src/mage/cards/r/Realmwright.java +++ b/Mage.Sets/src/mage/cards/r/Realmwright.java @@ -1,35 +1,22 @@ - package mage.cards.r; -import java.util.List; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.ChooseBasicLandTypeEffect; -import mage.abilities.mana.BlackManaAbility; -import mage.abilities.mana.BlueManaAbility; -import mage.abilities.mana.GreenManaAbility; -import mage.abilities.mana.RedManaAbility; -import mage.abilities.mana.WhiteManaAbility; +import mage.abilities.mana.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; -import mage.filter.common.FilterControlledLandPermanent; +import mage.constants.*; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class Realmwright extends CardImpl { @@ -46,7 +33,7 @@ public final class Realmwright extends CardImpl { this.addAbility(new AsEntersBattlefieldAbility(new ChooseBasicLandTypeEffect(Outcome.Neutral))); // Lands you control are the chosen type in addition to their other types. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new RealmwrightEffect2())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new RealmwrightEffect())); } public Realmwright(final Realmwright card) { @@ -59,111 +46,81 @@ public final class Realmwright extends CardImpl { } } -class RealmwrightEffect2 extends ContinuousEffectImpl { +class RealmwrightEffect extends ContinuousEffectImpl { - public RealmwrightEffect2() { - super(Duration.WhileOnBattlefield, Outcome.Neutral); + public RealmwrightEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); staticText = "Lands you control are the chosen type in addition to their other types"; } - public RealmwrightEffect2(final RealmwrightEffect2 effect) { + public RealmwrightEffect(final RealmwrightEffect effect) { super(effect); } @Override - public RealmwrightEffect2 copy() { - return new RealmwrightEffect2(this); + public RealmwrightEffect copy() { + return new RealmwrightEffect(this); } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Player you = game.getPlayer(source.getControllerId()); - List lands = game.getBattlefield().getAllActivePermanents(new FilterControlledLandPermanent(), source.getControllerId(), game); + public void init(Ability source, Game game) { + super.init(source, game); SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY)); - if (you != null && choice != null) { - for (Permanent land : lands) { - if (land != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA && !land.hasSubtype(choice, game)) { - land.getSubtype(game).add(choice); - } - break; - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - boolean addAbility = true; - if (choice.equals(SubType.FOREST)) { - for (Ability existingAbility : land.getAbilities()) { - if (existingAbility instanceof GreenManaAbility) { - addAbility = false; - break; - } - } - if (addAbility) { - land.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } - } - if (choice.equals(SubType.PLAINS)) { - for (Ability existingAbility : land.getAbilities()) { - if (existingAbility instanceof WhiteManaAbility) { - addAbility = false; - break; - } - } - if (addAbility) { - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - } - } - if (choice.equals(SubType.MOUNTAIN)) { - for (Ability existingAbility : land.getAbilities()) { - if (existingAbility instanceof RedManaAbility) { - addAbility = false; - break; - } - } - if (addAbility) { - land.addAbility(new RedManaAbility(), source.getSourceId(), game); - } - } - if (choice.equals(SubType.ISLAND)) { - for (Ability existingAbility : land.getAbilities()) { - if (existingAbility instanceof BlueManaAbility) { - addAbility = false; - break; - } - } - if (addAbility) { - land.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - } - if (choice.equals(SubType.SWAMP)) { - for (Ability existingAbility : land.getAbilities()) { - if (existingAbility instanceof BlackManaAbility) { - addAbility = false; - break; - } - } - if (addAbility) { - land.addAbility(new BlackManaAbility(), source.getSourceId(), game); - } - } - } - break; - } - } - } - return true; + switch (choice) { + case PLAINS: + dependencyTypes.add(DependencyType.BecomePlains); + break; + case ISLAND: + dependencyTypes.add(DependencyType.BecomeIsland); + break; + case SWAMP: + dependencyTypes.add(DependencyType.BecomeSwamp); + break; + case MOUNTAIN: + dependencyTypes.add(DependencyType.BecomeMountain); + break; + case FOREST: + dependencyTypes.add(DependencyType.BecomeForest); + break; } - return false; } @Override public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; + SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY)); + if (choice == null) { + return false; + } + Ability ability; + switch (choice) { + case PLAINS: + ability = new WhiteManaAbility(); + break; + case ISLAND: + ability = new BlueManaAbility(); + break; + case SWAMP: + ability = new BlackManaAbility(); + break; + case MOUNTAIN: + ability = new RedManaAbility(); + break; + case FOREST: + ability = new GreenManaAbility(); + break; + default: + ability = null; + } + for (Permanent land : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, + source.getControllerId(), source.getSourceId(), game + )) { + if (land == null || land.hasSubtype(choice, game)) { + continue; + } + land.addSubType(game, choice); + land.addAbility(ability, source.getSourceId(), game); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java b/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java index 6a3f7ce162..fb8fd6ae0c 100644 --- a/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java +++ b/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java @@ -4,21 +4,18 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; -import mage.abilities.keyword.ChangelingAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.SubTypeSet; import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; -import java.util.HashSet; -import java.util.Set; +import java.util.List; import java.util.UUID; +import java.util.stream.Collectors; /** * @author TheElk801 @@ -73,12 +70,11 @@ class ReturnFromExtinctionTarget extends TargetCardInYourGraveyard { if (targetOne == null || targetTwo == null) { return false; } - return targetOne.shareSubtypes(targetTwo, game); + return targetOne.shareCreatureTypes(targetTwo, game); } @Override public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { - Set subTypes = new HashSet<>(); MageObject targetSource = game.getObject(sourceId); Player player = game.getPlayer(sourceControllerId); if (player == null) { @@ -87,22 +83,21 @@ class ReturnFromExtinctionTarget extends TargetCardInYourGraveyard { if (targetSource == null) { return false; } - for (Card card : player.getGraveyard().getCards(filter, sourceId, sourceControllerId, game)) { - if (card.isAllCreatureTypes() || card.hasAbility(ChangelingAbility.getInstance(), game)) { - if (!subTypes.isEmpty()) { - return true; - } else { - subTypes.addAll(SubType.getCreatureTypes()); + List cards = player.getGraveyard().getCards( + filter, sourceId, sourceControllerId, game + ).stream().collect(Collectors.toList()); + if (cards.size() < 2) { + return false; + } + for (int i = 0; i < cards.size(); i++) { + for (int j = 0; j < cards.size(); j++) { + if (i <= j) { + continue; } - continue; - } - for (SubType subType : card.getSubtype(game)) { - if (subType.getSubTypeSet() == SubTypeSet.CreatureType && subTypes.contains(subType)) { + if (cards.get(i).shareCreatureTypes(cards.get(j), game)) { return true; } } - subTypes.addAll(card.getSubtype(game)); - subTypes.removeIf((SubType st) -> (st.getSubTypeSet() != SubTypeSet.CreatureType)); } return false; } diff --git a/Mage.Sets/src/mage/cards/r/RunedStalactite.java b/Mage.Sets/src/mage/cards/r/RunedStalactite.java index 34a54ffa55..e76431ecfb 100644 --- a/Mage.Sets/src/mage/cards/r/RunedStalactite.java +++ b/Mage.Sets/src/mage/cards/r/RunedStalactite.java @@ -1,38 +1,33 @@ - package mage.cards.r; -import java.util.UUID; +import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; -import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; -import mage.abilities.keyword.ChangelingAbility; +import mage.abilities.effects.common.continuous.GainAllCreatureTypesAttachedEffect; import mage.abilities.keyword.EquipAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AttachmentType; import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class RunedStalactite extends CardImpl { public RunedStalactite(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 and is every creature type. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1,1))); - Effect effect = new GainAbilityAttachedEffect(ChangelingAbility.getInstance(), AttachmentType.EQUIPMENT, Duration.WhileOnBattlefield); - effect.setText("Equipped creature is every creature type (Changeling)"); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(1, 1)); + ability.addEffect(new GainAllCreatureTypesAttachedEffect()); + this.addAbility(ability); + // Equip {2} this.addAbility(new EquipAbility(Outcome.BoostCreature, new ManaCostsImpl("{2}"))); } diff --git a/Mage.Sets/src/mage/cards/s/SarkhanTheDragonspeaker.java b/Mage.Sets/src/mage/cards/s/SarkhanTheDragonspeaker.java index 49b3957b0a..95ef7f0563 100644 --- a/Mage.Sets/src/mage/cards/s/SarkhanTheDragonspeaker.java +++ b/Mage.Sets/src/mage/cards/s/SarkhanTheDragonspeaker.java @@ -91,8 +91,8 @@ class SarkhanTheDragonspeakerEffect extends ContinuousEffectImpl { if (sublayer == SubLayer.NA) { permanent.getCardType().clear(); permanent.addCardType(CardType.CREATURE); - permanent.getSubtype(game).clear(); - permanent.getSubtype(game).add(SubType.DRAGON); + permanent.removeAllSubTypes(game); + permanent.addSubType(game, SubType.DRAGON); permanent.getSuperType().clear(); permanent.addSuperType(SuperType.LEGENDARY); } diff --git a/Mage.Sets/src/mage/cards/s/SarkhanTheMasterless.java b/Mage.Sets/src/mage/cards/s/SarkhanTheMasterless.java index d8b4c335ed..844679b467 100644 --- a/Mage.Sets/src/mage/cards/s/SarkhanTheMasterless.java +++ b/Mage.Sets/src/mage/cards/s/SarkhanTheMasterless.java @@ -127,8 +127,8 @@ class SarkhanTheMasterlessBecomeDragonEffect extends ContinuousEffectImpl { if (sublayer == SubLayer.NA) { permanent.getCardType().clear(); permanent.addCardType(CardType.CREATURE); - permanent.getSubtype(game).clear(); - permanent.getSubtype(game).add(SubType.DRAGON); + permanent.removeAllSubTypes(game); + permanent.addSubType(game, SubType.DRAGON); } break; case ColorChangingEffects_5: diff --git a/Mage.Sets/src/mage/cards/s/SealockMonster.java b/Mage.Sets/src/mage/cards/s/SealockMonster.java index 3857660822..773a8e07d8 100644 --- a/Mage.Sets/src/mage/cards/s/SealockMonster.java +++ b/Mage.Sets/src/mage/cards/s/SealockMonster.java @@ -1,48 +1,49 @@ - package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BecomesMonstrousSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.combat.CantAttackUnlessDefenderControllsPermanent; +import mage.abilities.effects.common.continuous.AddCardSubTypeTargetEffect; import mage.abilities.keyword.MonstrosityAbility; -import mage.abilities.mana.BlueManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterLandPermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.Target; import mage.target.common.TargetLandPermanent; import java.util.UUID; /** - * * @author LevelX2 */ public final class SealockMonster extends CardImpl { + private static final FilterPermanent filter = new FilterLandPermanent(SubType.ISLAND, "an Island"); + public SealockMonster(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); this.subtype.add(SubType.OCTOPUS); this.power = new MageInt(5); this.toughness = new MageInt(5); // Sealock Monster can't attack unless defending player controls an Island. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackUnlessDefenderControllsPermanent(new FilterLandPermanent(SubType.ISLAND,"an Island")))); - // {5}{U}{U}: Monstrosity 3. - this.addAbility(new MonstrosityAbility("{5}{U}{U}",3)); - // When Sealock Monster becomes monstrous, target land becomes an island in addition to its other types. - Ability ability = new BecomesMonstrousSourceTriggeredAbility(new SealockMonsterBecomesIslandTargetEffect()); - Target target = new TargetLandPermanent(); - ability.addTarget(target); - this.addAbility(ability); + this.addAbility(new SimpleStaticAbility(new CantAttackUnlessDefenderControllsPermanent(filter))); + // {5}{U}{U}: Monstrosity 3. + this.addAbility(new MonstrosityAbility("{5}{U}{U}", 3)); + + // When Sealock Monster becomes monstrous, target land becomes an island in addition to its other types. + Ability ability = new BecomesMonstrousSourceTriggeredAbility( + new AddCardSubTypeTargetEffect(SubType.ISLAND, Duration.EndOfTurn) + ); + ability.addTarget(new TargetLandPermanent()); + this.addAbility(ability); } public SealockMonster(final SealockMonster card) { @@ -54,56 +55,3 @@ public final class SealockMonster extends CardImpl { return new SealockMonster(this); } } - -class SealockMonsterBecomesIslandTargetEffect extends ContinuousEffectImpl { - - private static Ability islandAbility = new BlueManaAbility(); - - public SealockMonsterBecomesIslandTargetEffect() { - super(Duration.EndOfGame, Outcome.Detriment); - this.staticText = "target land becomes an island in addition to its other types"; - - } - - public SealockMonsterBecomesIslandTargetEffect(final SealockMonsterBecomesIslandTargetEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public SealockMonsterBecomesIslandTargetEffect copy() { - return new SealockMonsterBecomesIslandTargetEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (UUID targetPermanent : targetPointer.getTargets(game, source)) { - Permanent land = game.getPermanent(targetPermanent); - if (land != null) { - switch (layer) { - case AbilityAddingRemovingEffects_6: - if (!land.getAbilities().containsRule(islandAbility)) { - land.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - break; - case TypeChangingEffects_4: - if (!land.hasSubtype(SubType.ISLAND, game)) { - land.getSubtype(game).add(SubType.ISLAND); - } - break; - } - } - } - return true; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; - } - -} diff --git a/Mage.Sets/src/mage/cards/s/Shapesharer.java b/Mage.Sets/src/mage/cards/s/Shapesharer.java index fbca5f79ed..5c0c7674c3 100644 --- a/Mage.Sets/src/mage/cards/s/Shapesharer.java +++ b/Mage.Sets/src/mage/cards/s/Shapesharer.java @@ -35,6 +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()); // {2}{U}: Target Shapeshifter becomes a copy of target creature until your next turn. diff --git a/Mage.Sets/src/mage/cards/s/SharedAnimosity.java b/Mage.Sets/src/mage/cards/s/SharedAnimosity.java index 01624774ee..f15580f1e8 100644 --- a/Mage.Sets/src/mage/cards/s/SharedAnimosity.java +++ b/Mage.Sets/src/mage/cards/s/SharedAnimosity.java @@ -1,12 +1,10 @@ - package mage.cards.s; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.keyword.ChangelingAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -18,21 +16,20 @@ import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; /** - * * @author Plopman */ public final class SharedAnimosity extends CardImpl { public SharedAnimosity(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // Whenever a creature you control attacks, it gets +1/+0 until end of turn for each other attacking creature that shares a creature type with it. - this.addAbility(new AttacksCreatureYouControlTriggeredAbility(new SharedAnimosityEffect(), false, true)); + this.addAbility(new AttacksCreatureYouControlTriggeredAbility( + new SharedAnimosityEffect(), false, true) + ); } public SharedAnimosity(final SharedAnimosity card) { @@ -51,7 +48,7 @@ class SharedAnimosityEffect extends ContinuousEffectImpl { public SharedAnimosityEffect() { super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - + } public SharedAnimosityEffect(final SharedAnimosityEffect effect) { @@ -69,29 +66,11 @@ class SharedAnimosityEffect extends ContinuousEffectImpl { super.init(source, game); Permanent permanent = game.getPermanent(this.targetPointer.getFirst(game, source)); if (permanent != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent(); filter.add(Predicates.not(new PermanentIdPredicate(this.targetPointer.getFirst(game, source)))); filter.add(AttackingPredicate.instance); - boolean allCreatureTypes = false; - if (permanent.isAllCreatureTypes()) { - allCreatureTypes = true; - } else { - for(Ability ability : permanent.getAbilities()){ - if(ability instanceof ChangelingAbility){ - allCreatureTypes = true; - } - } - } - if(!allCreatureTypes){ - List> predicateList = new ArrayList<>(); - for(SubType subtype : permanent.getSubtype(game)){ - predicateList.add(subtype.getPredicate()); - } - filter.add(Predicates.or(predicateList)); - } - - power = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game).size(); + filter.add(new SharedAnimosityPredicate(permanent)); + power = game.getBattlefield().count(filter, source.getControllerId(), source.getSourceId(), game); } } @@ -110,3 +89,17 @@ 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 edc7d925e2..a276ced613 100644 --- a/Mage.Sets/src/mage/cards/s/ShieldsOfVelisVel.java +++ b/Mage.Sets/src/mage/cards/s/ShieldsOfVelisVel.java @@ -27,6 +27,7 @@ public final class ShieldsOfVelisVel extends CardImpl { this.subtype.add(SubType.SHAPESHIFTER); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); //Creatures target player controls get +0/+1 and gain all creature types until end of turn. @@ -78,7 +79,7 @@ class ShieldsOfVelisVelGainEffect extends ContinuousEffectImpl { for (Iterator it = affectedObjectList.iterator(); it.hasNext();) { Permanent permanent = it.next().getPermanent(game); if (permanent != null) { - permanent.addAbility(ChangelingAbility.getInstance(), source.getSourceId(), game); + permanent.setIsAllCreatureTypes(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 f58165c582..faf91cad88 100644 --- a/Mage.Sets/src/mage/cards/s/SkeletalChangeling.java +++ b/Mage.Sets/src/mage/cards/s/SkeletalChangeling.java @@ -26,6 +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()); // {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/SlumberingTora.java b/Mage.Sets/src/mage/cards/s/SlumberingTora.java index c91c47e1cc..e56691992c 100644 --- a/Mage.Sets/src/mage/cards/s/SlumberingTora.java +++ b/Mage.Sets/src/mage/cards/s/SlumberingTora.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; @@ -17,23 +16,24 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCardInHand; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SlumberingTora extends CardImpl { private static final FilterCard filter = new FilterCard("Spirit or Arcane card"); - + static { - filter.add(Predicates.or(SubType.SPIRIT.getPredicate(),SubType.ARCANE.getPredicate())); - } + filter.add(Predicates.or(SubType.SPIRIT.getPredicate(), SubType.ARCANE.getPredicate())); + } public SlumberingTora(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // {2}, Discard a Spirit or Arcane card: Slumbering Tora becomes an X/X Cat artifact creature until end of turn, // where X is the discarded card's converted mana cost. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SlumberingToraEffect(), new ManaCostsImpl("{2}")); + Ability ability = new SimpleActivatedAbility(new SlumberingToraEffect(), new ManaCostsImpl("{2}")); ability.addCost(new DiscardTargetCost(new TargetCardInHand(filter))); this.addAbility(ability); } @@ -46,15 +46,18 @@ public final class SlumberingTora extends CardImpl { public SlumberingTora copy() { return new SlumberingTora(this); } - + private static class SlumberingToraEffect extends ContinuousEffectImpl { - public SlumberingToraEffect() { + private int convManaCosts = 0; + + private SlumberingToraEffect() { super(Duration.EndOfTurn, Outcome.BecomeCreature); - setText(); + staticText = "{this} becomes an X/X Cat artifact creature until end of turn, " + + "where X is the discarded card's converted mana cost"; } - public SlumberingToraEffect(final SlumberingToraEffect effect) { + private SlumberingToraEffect(final SlumberingToraEffect effect) { super(effect); } @@ -63,33 +66,36 @@ public final class SlumberingTora extends CardImpl { return new SlumberingToraEffect(this); } + @Override + public void init(Ability source, Game game) { + super.init(source, game); + for (Cost cost : source.getCosts()) { + if (cost instanceof DiscardTargetCost && !((DiscardTargetCost) cost).getCards().isEmpty()) { + convManaCosts = ((DiscardTargetCost) cost).getCards().get(0).getConvertedManaCost(); + return; + } + } + } + @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.addCardType(CardType.CREATURE); - permanent.getSubtype(game).add(SubType.CAT); - } - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - int convManaCosts = 0; - for (Cost cost: source.getCosts()) { - if (cost instanceof DiscardTargetCost && !((DiscardTargetCost) cost).getCards().isEmpty()) { - convManaCosts = ((DiscardTargetCost)cost).getCards().get(0).getConvertedManaCost(); - break; - } - } - permanent.getPower().setValue(convManaCosts); - permanent.getToughness().setValue(convManaCosts); - } - } - return true; + if (permanent == null) { + return false; } - return false; + switch (layer) { + case TypeChangingEffects_4: + permanent.addCardType(CardType.ARTIFACT); + permanent.addCardType(CardType.CREATURE); + permanent.addSubType(game, SubType.CAT); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setValue(convManaCosts); + permanent.getToughness().setValue(convManaCosts); + } + } + return true; } @Override @@ -97,14 +103,9 @@ public final class SlumberingTora extends CardImpl { return false; } - private void setText() { - staticText = "{this} becomes an X/X Cat artifact creature until end of turn, where X is the discarded card's converted mana cost"; - } - @Override public boolean hasLayer(Layer layer) { return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4; } } - } diff --git a/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java b/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java index 8c9b34ca57..4d29690f3f 100644 --- a/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java +++ b/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java @@ -1,6 +1,5 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -9,20 +8,14 @@ import mage.abilities.keyword.EnchantAbility; import mage.abilities.mana.GreenManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.DependencyType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.SubType; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SongOfTheDryads extends CardImpl { @@ -40,7 +33,6 @@ public final class SongOfTheDryads extends CardImpl { // Enchanted permanent is a colorless Forest land. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BecomesColorlessForestLandEffect())); - } public SongOfTheDryads(final SongOfTheDryads card) { @@ -55,13 +47,13 @@ public final class SongOfTheDryads extends CardImpl { class BecomesColorlessForestLandEffect extends ContinuousEffectImpl { - public BecomesColorlessForestLandEffect() { + BecomesColorlessForestLandEffect() { super(Duration.WhileOnBattlefield, Outcome.Detriment); this.staticText = "Enchanted permanent is a colorless Forest land"; dependencyTypes.add(DependencyType.BecomeForest); } - public BecomesColorlessForestLandEffect(final BecomesColorlessForestLandEffect effect) { + private BecomesColorlessForestLandEffect(final BecomesColorlessForestLandEffect effect) { super(effect); } @@ -78,38 +70,36 @@ class BecomesColorlessForestLandEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null && enchantment.getAttachedTo() != null) { - Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); - if (permanent != null) { - switch (layer) { - case ColorChangingEffects_5: - permanent.getColor(game).setWhite(false); - permanent.getColor(game).setGreen(false); - permanent.getColor(game).setBlack(false); - permanent.getColor(game).setBlue(false); - permanent.getColor(game).setRed(false); - break; - case AbilityAddingRemovingEffects_6: - permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); - break; - case TypeChangingEffects_4: - permanent.removeAllAbilities(source.getSourceId(), game); - permanent.getCardType().clear(); - permanent.addCardType(CardType.LAND); - permanent.getSubtype(game).clear(); - permanent.getSubtype(game).add(SubType.FOREST); - break; - } - return true; - } + if (enchantment == null || enchantment.getAttachedTo() == null) { + return false; } - return false; + Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); + if (permanent == null) { + return false; + } + switch (layer) { + case ColorChangingEffects_5: + permanent.getColor(game).setWhite(false); + permanent.getColor(game).setGreen(false); + permanent.getColor(game).setBlack(false); + permanent.getColor(game).setBlue(false); + permanent.getColor(game).setRed(false); + break; + case TypeChangingEffects_4: + permanent.getCardType().clear(); + permanent.addCardType(CardType.LAND); + permanent.removeAllSubTypes(game); + permanent.addSubType(game, SubType.FOREST); + permanent.removeAllAbilities(source.getSourceId(), game); + permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); + break; + } + return true; } @Override public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 - || layer == Layer.ColorChangingEffects_5 + return layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4; } } diff --git a/Mage.Sets/src/mage/cards/s/SorinVengefulBloodlord.java b/Mage.Sets/src/mage/cards/s/SorinVengefulBloodlord.java index 8d6261aaa6..526d6c4f76 100644 --- a/Mage.Sets/src/mage/cards/s/SorinVengefulBloodlord.java +++ b/Mage.Sets/src/mage/cards/s/SorinVengefulBloodlord.java @@ -95,7 +95,7 @@ enum SorinVengefulBloodlordAdjuster implements TargetAdjuster { class SorinVengefulBloodlordEffect extends ContinuousEffectImpl { SorinVengefulBloodlordEffect() { super(Duration.Custom, Outcome.Neutral); - staticText = "That creature is a vampire in addition to its other types"; + staticText = "That creature is a Vampire in addition to its other types"; } private SorinVengefulBloodlordEffect(final SorinVengefulBloodlordEffect effect) { @@ -119,11 +119,7 @@ class SorinVengefulBloodlordEffect extends ContinuousEffectImpl { } } if (creature != null) { - if (sublayer == SubLayer.NA) { - if (!creature.hasSubtype(SubType.VAMPIRE, game)) { - creature.getSubtype(game).add(SubType.VAMPIRE); - } - } + creature.addSubType(game, SubType.VAMPIRE); return true; } else { this.used = true; diff --git a/Mage.Sets/src/mage/cards/s/SoulSculptor.java b/Mage.Sets/src/mage/cards/s/SoulSculptor.java index 710fe7cc5c..aba2a78b39 100644 --- a/Mage.Sets/src/mage/cards/s/SoulSculptor.java +++ b/Mage.Sets/src/mage/cards/s/SoulSculptor.java @@ -1,6 +1,5 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; @@ -10,29 +9,22 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.DependencyType; -import mage.constants.Duration; -import mage.constants.Layer; -import static mage.constants.Layer.TypeChangingEffects_4; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.StackObject; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class SoulSculptor extends CardImpl { - final String rule = "Target creature becomes an enchantment and loses all abilities until a player casts a creature spell."; + private static final String rule = "Target creature becomes an enchantment and loses all abilities until a player casts a creature spell."; public SoulSculptor(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); @@ -42,7 +34,7 @@ public final class SoulSculptor extends CardImpl { this.toughness = new MageInt(1); // {1}{W}, {tap}: Target creature becomes an enchantment and loses all abilities until a player casts a creature spell. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new SoulSculptorEffect(), SoulSculptorCondition.instance, rule), new ManaCostsImpl("{1}{W}")); + Ability ability = new SimpleActivatedAbility(new ConditionalContinuousEffect(new SoulSculptorEffect(), SoulSculptorCondition.instance, rule), new ManaCostsImpl("{1}{W}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); @@ -90,27 +82,23 @@ class SoulSculptorEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent permanent = affectedObjectList.get(0).getPermanent(game); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.getCardType().clear(); - permanent.getSubtype(game).clear(); - if (!permanent.getCardType().contains(CardType.ENCHANTMENT)) { - permanent.getCardType().add(CardType.ENCHANTMENT); - } - } - break; - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - permanent.getAbilities().clear(); - } - break; - } - return true; + if (permanent == null) { + this.discard(); + return false; } - this.discard(); - return false; + switch (layer) { + case TypeChangingEffects_4: + permanent.getCardType().clear(); + permanent.getSubtype(game).retainAll(SubType.getEnchantmentTypes()); + permanent.getCardType().add(CardType.ENCHANTMENT); + break; + case AbilityAddingRemovingEffects_6: + if (sublayer == SubLayer.NA) { + permanent.getAbilities().clear(); + } + break; + } + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/s/Standardize.java b/Mage.Sets/src/mage/cards/s/Standardize.java index b11eea4b55..ffed568650 100644 --- a/Mage.Sets/src/mage/cards/s/Standardize.java +++ b/Mage.Sets/src/mage/cards/s/Standardize.java @@ -1,10 +1,7 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BecomesSubtypeAllEffect; @@ -16,8 +13,12 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.SubType; +import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; +import mage.util.SubTypeList; + +import java.util.UUID; /** * @author EvilGeek @@ -69,8 +70,10 @@ class StandardizeEffect extends OneShotEffect { chosenType = typeChoice.getChoice(); if (chosenType != null && !chosenType.isEmpty()) { // ADD TYPE TO TARGET - ContinuousEffect effect = new BecomesSubtypeAllEffect(Duration.EndOfTurn, SubType.byDescription(chosenType)); - game.addEffect(effect, source); + game.addEffect(new BecomesSubtypeAllEffect( + Duration.EndOfTurn, new SubTypeList(SubType.byDescription(chosenType)), + StaticFilters.FILTER_PERMANENT_CREATURE, true + ), source); return true; } diff --git a/Mage.Sets/src/mage/cards/s/StoneforgeMasterwork.java b/Mage.Sets/src/mage/cards/s/StoneforgeMasterwork.java index cf49576bbd..42a0e66a2b 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.shareSubtypes(permanent, game)) { + if (equipped.shareCreatureTypes(permanent, game)) { xValue++; } } diff --git a/Mage.Sets/src/mage/cards/s/StoneworkPackbeast.java b/Mage.Sets/src/mage/cards/s/StoneworkPackbeast.java index 360c5461bf..1327ee5efe 100644 --- a/Mage.Sets/src/mage/cards/s/StoneworkPackbeast.java +++ b/Mage.Sets/src/mage/cards/s/StoneworkPackbeast.java @@ -4,6 +4,7 @@ import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.continuous.HasSubtypesSourceEffect; import mage.abilities.mana.AnyColorManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -22,16 +23,12 @@ public final class StoneworkPackbeast extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}"); this.subtype.add(SubType.BEAST); - this.subtype.add(SubType.CLERIC); - this.subtype.add(SubType.ROGUE); - this.subtype.add(SubType.WARRIOR); - this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); this.toughness = new MageInt(1); // Stonework Packbeast is also a Cleric, Rogue, Warrior, and Wizard. this.addAbility(new SimpleStaticAbility( - Zone.ALL, new InfoEffect("{this} is also a Cleric, Rogue, Warrior, and Wizard") + Zone.ALL, new HasSubtypesSourceEffect(SubType.CLERIC, SubType.ROGUE, SubType.WARRIOR, SubType.WIZARD) )); // {2}: Add one mana of any color. diff --git a/Mage.Sets/src/mage/cards/s/StormtideLeviathan.java b/Mage.Sets/src/mage/cards/s/StormtideLeviathan.java index 0c46713eaf..80a77f0a8f 100644 --- a/Mage.Sets/src/mage/cards/s/StormtideLeviathan.java +++ b/Mage.Sets/src/mage/cards/s/StormtideLeviathan.java @@ -1,6 +1,5 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -11,28 +10,23 @@ import mage.abilities.keyword.IslandwalkAbility; import mage.abilities.mana.BlueManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.DependencyType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public final class StormtideLeviathan extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures without flying or islandwalk"); + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("Creatures without flying or islandwalk"); static { filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); @@ -48,12 +42,12 @@ public final class StormtideLeviathan extends CardImpl { // Islandwalk (This creature can't be blocked as long as defending player controls an Island.) this.addAbility(new IslandwalkAbility()); - // All lands are Islands in addition to their other types. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new StormtideLeviathanEffect())); - // Creatures without flying or islandwalk can't attack. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, - new CantAttackAnyPlayerAllEffect(Duration.WhileOnBattlefield, filter))); + // All lands are Islands in addition to their other types. + this.addAbility(new SimpleStaticAbility(new StormtideLeviathanEffect())); + + // Creatures without flying or islandwalk can't attack. + this.addAbility(new SimpleStaticAbility(new CantAttackAnyPlayerAllEffect(Duration.WhileOnBattlefield, filter))); } public StormtideLeviathan(final StormtideLeviathan card) { @@ -67,13 +61,13 @@ public final class StormtideLeviathan extends CardImpl { class StormtideLeviathanEffect extends ContinuousEffectImpl { - public StormtideLeviathanEffect() { - super(Duration.WhileOnBattlefield, Outcome.Neutral); + private StormtideLeviathanEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); staticText = "All lands are Islands in addition to their other types"; this.dependencyTypes.add(DependencyType.BecomeIsland); } - public StormtideLeviathanEffect(final StormtideLeviathanEffect effect) { + private StormtideLeviathanEffect(final StormtideLeviathanEffect effect) { super(effect); } @@ -83,32 +77,17 @@ public final class StormtideLeviathan extends CardImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { for (Permanent land : game.getBattlefield().getActivePermanents( - new FilterLandPermanent(), source.getControllerId(), game)) { - switch (layer) { - case TypeChangingEffects_4: - // land abilities are intrinsic, so add them here, not in layer 6 - if (!land.hasSubtype(SubType.ISLAND, game)) { - land.getSubtype(game).add(SubType.ISLAND); - if (!land.getAbilities(game).containsClass(BlueManaAbility.class)) { - land.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - } - break; + StaticFilters.FILTER_LAND, source.getControllerId(), game + )) { + // land abilities are intrinsic, so add them here, not in layer 6 + land.addSubType(game, SubType.ISLAND); + if (!land.getAbilities(game).containsClass(BlueManaAbility.class)) { + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); } } return true; } - - @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.Sets/src/mage/cards/t/TajuruParagon.java b/Mage.Sets/src/mage/cards/t/TajuruParagon.java index 3f0ca8bbad..ce3403808d 100644 --- a/Mage.Sets/src/mage/cards/t/TajuruParagon.java +++ b/Mage.Sets/src/mage/cards/t/TajuruParagon.java @@ -7,11 +7,13 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.InfoEffect; -import mage.abilities.keyword.ChangelingAbility; +import mage.abilities.effects.common.continuous.HasSubtypesSourceEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.*; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.Predicate; import mage.game.Game; @@ -31,16 +33,12 @@ public final class TajuruParagon extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); this.subtype.add(SubType.ELF); - this.subtype.add(SubType.CLERIC); - this.subtype.add(SubType.ROGUE); - this.subtype.add(SubType.WARRIOR); - this.subtype.add(SubType.WIZARD); this.power = new MageInt(3); this.toughness = new MageInt(2); // Tajuru Paragon is also a Cleric, Rogue, Warrior, and Wizard. this.addAbility(new SimpleStaticAbility( - Zone.ALL, new InfoEffect("{this} is also a Cleric, Rogue, Warrior, and Wizard") + Zone.ALL, new HasSubtypesSourceEffect(SubType.CLERIC, SubType.ROGUE, SubType.WARRIOR, SubType.WIZARD) )); // Kicker {3} @@ -115,27 +113,6 @@ class TajuruParagonPredicate implements Predicate { @Override public boolean apply(Card input, Game game) { - boolean isAllA = permanent.isAllCreatureTypes() - || permanent.hasAbility(ChangelingAbility.getInstance(), game); - boolean isAnyA = isAllA || permanent.getSubtype(game) - .stream() - .map(SubType::getSubTypeSet) - .anyMatch(SubTypeSet.CreatureType::equals); - boolean isAllB = input.isAllCreatureTypes() - || input.hasAbility(ChangelingAbility.getInstance(), game); - boolean isAnyB = isAllB || input - .getSubtype(game) - .stream() - .map(SubType::getSubTypeSet) - .anyMatch(SubTypeSet.CreatureType::equals); - if (isAllA) { - return isAllB || isAnyB; - } - return isAnyA - && (isAllB || permanent - .getSubtype(game) - .stream() - .filter(subType -> subType.getSubTypeSet() == SubTypeSet.CreatureType) - .anyMatch(subType -> input.hasSubtype(subType, 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 5dc202dfb0..086ebda27d 100644 --- a/Mage.Sets/src/mage/cards/t/TaureanMauler.java +++ b/Mage.Sets/src/mage/cards/t/TaureanMauler.java @@ -26,6 +26,7 @@ public final class TaureanMauler extends CardImpl { this.toughness = new MageInt(2); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // Whenever an opponent casts a spell, you may put a +1/+1 counter on Taurean Mauler. diff --git a/Mage.Sets/src/mage/cards/t/Terraformer.java b/Mage.Sets/src/mage/cards/t/Terraformer.java index f65370e2fb..9066a84f0d 100644 --- a/Mage.Sets/src/mage/cards/t/Terraformer.java +++ b/Mage.Sets/src/mage/cards/t/Terraformer.java @@ -1,8 +1,6 @@ package mage.cards.t; -import java.util.Iterator; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; @@ -10,30 +8,21 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; -import mage.abilities.mana.BlackManaAbility; -import mage.abilities.mana.BlueManaAbility; -import mage.abilities.mana.GreenManaAbility; -import mage.abilities.mana.RedManaAbility; -import mage.abilities.mana.WhiteManaAbility; +import mage.abilities.mana.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.Choice; import mage.choices.ChoiceBasicLandType; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; -import mage.filter.common.FilterControlledLandPermanent; -import mage.filter.common.FilterControlledPermanent; +import mage.constants.*; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.Iterator; +import java.util.UUID; + /** - * * @author emerald000 */ public final class Terraformer extends CardImpl { @@ -46,7 +35,7 @@ public final class Terraformer extends CardImpl { this.toughness = new MageInt(2); // {1}: Choose a basic land type. Each land you control becomes that type until end of turn. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TerraformerEffect(), new GenericManaCost(1))); + this.addAbility(new SimpleActivatedAbility(new TerraformerEffect(), new GenericManaCost(1))); } public Terraformer(final Terraformer card) { @@ -66,7 +55,7 @@ class TerraformerEffect extends OneShotEffect { this.staticText = "Choose a basic land type. Each land you control becomes that type until end of turn"; } - TerraformerEffect(final TerraformerEffect effect) { + private TerraformerEffect(final TerraformerEffect effect) { super(effect); } @@ -92,13 +81,11 @@ class TerraformerEffect extends OneShotEffect { class TerraformerContinuousEffect extends ContinuousEffectImpl { - private static final FilterControlledPermanent filter = new FilterControlledLandPermanent(); - TerraformerContinuousEffect() { - super(Duration.EndOfTurn, Outcome.Neutral); + super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); } - TerraformerContinuousEffect(final TerraformerContinuousEffect effect) { + private TerraformerContinuousEffect(final TerraformerContinuousEffect effect) { super(effect); } @@ -110,64 +97,68 @@ class TerraformerContinuousEffect extends ContinuousEffectImpl { @Override public void init(Ability source, Game game) { super.init(source, game); - if (this.affectedObjectsSet) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { - affectedObjectList.add(new MageObjectReference(permanent, game)); - } - } - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "_Terraformer")); - if (choice != null) { - for (Iterator it = affectedObjectList.iterator(); it.hasNext();) { - Permanent land = it.next().getPermanent(game); - if (land != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - land.getSubtype(game).clear(); - land.getSubtype(game).add(choice); - } - break; - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - land.getAbilities().clear(); - if (choice.equals(SubType.FOREST)) { - land.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.PLAINS)) { - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.MOUNTAIN)) { - land.addAbility(new RedManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.ISLAND)) { - land.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - if (choice.equals(SubType.SWAMP)) { - land.addAbility(new BlackManaAbility(), source.getSourceId(), game); - } - } - break; - } - } else { - it.remove(); - } - } - return true; + switch (choice) { + case FOREST: + dependencyTypes.add(DependencyType.BecomeForest); + break; + case PLAINS: + dependencyTypes.add(DependencyType.BecomePlains); + break; + case MOUNTAIN: + dependencyTypes.add(DependencyType.BecomeMountain); + break; + case ISLAND: + dependencyTypes.add(DependencyType.BecomeIsland); + break; + case SWAMP: + dependencyTypes.add(DependencyType.BecomeSwamp); + break; + } + if (this.affectedObjectsSet) { + game.getBattlefield() + .getActivePermanents( + StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, + source.getControllerId(), source.getSourceId(), game + ).stream() + .map(permanent -> new MageObjectReference(permanent, game)) + .forEach(affectedObjectList::add); } - return false; } @Override public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; + SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "_ElsewhereFlask")); + if (choice == null) { + return false; + } + for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { + Permanent land = it.next().getPermanent(game); + if (land == null) { + it.remove(); + continue; + } + land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.addSubType(game, choice); + land.removeAllAbilities(source.getSourceId(), game); + switch (choice) { + case FOREST: + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); + break; + case PLAINS: + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + break; + case MOUNTAIN: + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + break; + case ISLAND: + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + break; + case SWAMP: + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + break; + } + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java b/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java index a0980c9bec..ebe6ac12fd 100644 --- a/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java +++ b/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java @@ -1,41 +1,38 @@ - package mage.cards.t; -import java.util.UUID; -import mage.MageInt; -import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.VariableManaCost; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.common.continuous.SourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; import mage.abilities.keyword.DefenderAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; + +import java.util.UUID; /** - * - * @author cbt33 + * @author TheElk801 */ public final class TestamentOfFaith extends CardImpl { public TestamentOfFaith(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}"); // {X}: Testament of Faith becomes an X/X Wall creature with defender in addition to its other types until end of turn. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TestamentOfFaithBecomesCreatureSourceEffect(new TestamentOfFaithToken(), "enchantment", Duration.EndOfTurn), new VariableManaCost())); + Ability ability = new SimpleActivatedAbility(new SetPowerToughnessSourceEffect( + ManacostVariableValue.instance, Duration.EndOfTurn, SubLayer.SetPT_7b + ).setText("{this} becomes an X/X"), new VariableManaCost()); + ability.addEffect(new TestamentOfFaithEffect()); + ability.addEffect(new GainAbilitySourceEffect( + DefenderAbility.getInstance(), Duration.EndOfTurn + ).setText("with defender in addition to its other types until end of turn")); + this.addAbility(ability); } public TestamentOfFaith(final TestamentOfFaith card) { @@ -48,121 +45,30 @@ public final class TestamentOfFaith extends CardImpl { } } -class TestamentOfFaithBecomesCreatureSourceEffect extends ContinuousEffectImpl implements SourceEffect { +class TestamentOfFaithEffect extends ContinuousEffectImpl { - protected Token token; - protected String type; - protected int zoneChangeCounter; - - public TestamentOfFaithBecomesCreatureSourceEffect(Token token, String type, Duration duration) { - super(duration, Outcome.BecomeCreature); - this.token = token; - this.type = type; - setText(); + TestamentOfFaithEffect() { + super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature); + staticText = "Wall creature"; } - public TestamentOfFaithBecomesCreatureSourceEffect(final TestamentOfFaithBecomesCreatureSourceEffect effect) { + private TestamentOfFaithEffect(final TestamentOfFaithEffect effect) { super(effect); - this.token = effect.token.copy(); - this.type = effect.type; } @Override - public TestamentOfFaithBecomesCreatureSourceEffect copy() { - return new TestamentOfFaithBecomesCreatureSourceEffect(this); - } - - @Override - public void init(Ability source, Game game) { - super.init(source, game); - this.getAffectedObjects().add(new MageObjectReference(source.getSourceId(), game)); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent = affectedObjectList.get(0).getPermanent(game); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - if (!token.getCardType().isEmpty()) { - for (CardType t : token.getCardType()) { - if (!permanent.getCardType().contains(t)) { - permanent.addCardType(t); - } - } - } - if (type != null && type.isEmpty() || type == null) { - permanent.getSubtype(game).clear(); - } - if (!token.getSubtype(game).isEmpty()) { - permanent.getSubtype(game).addAll(token.getSubtype(game)); - } - } - break; - case ColorChangingEffects_5: - if (sublayer == SubLayer.NA) { - if (token.getColor(game).hasColor()) { - permanent.getColor(game).setColor(token.getColor(game)); - } - } - break; - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - if (!token.getAbilities().isEmpty()) { - for (Ability ability: token.getAbilities()) { - permanent.addAbility(ability, source.getSourceId(), game); - } - } - } - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - MageInt power = new MageInt(source.getManaCosts().getVariableCosts().get(0).getAmount()); - MageInt toughness = new MageInt(source.getManaCosts().getVariableCosts().get(0).getAmount()); - permanent.getPower().setValue(power.getValue()); - permanent.getToughness().setValue(toughness.getValue()); - } - } - return true; - } else { - if (duration == Duration.Custom) { - this.discard(); - } - } - return false; + public TestamentOfFaithEffect copy() { + return new TestamentOfFaithEffect(this); } @Override public boolean apply(Game game, Ability source) { - return false; + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + return false; + } + permanent.addCardType(CardType.CREATURE); + permanent.addSubType(game, SubType.WALL); + return true; } - - private void setText() { - staticText = "{this} becomes an X/X Wall creature with defender in addition to its other types until end of turn"; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.PTChangingEffects_7 || layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4; - } - } - - -class TestamentOfFaithToken extends TokenImpl { - TestamentOfFaithToken() { - super("Wall", "X/X Wall creature with defender"); - cardType.add(CardType.CREATURE); - this.subtype.add(SubType.WALL); - color.setWhite(true); - this.addAbility(DefenderAbility.getInstance()); - } - public TestamentOfFaithToken(final TestamentOfFaithToken token) { - super(token); - } - - public TestamentOfFaithToken copy() { - return new TestamentOfFaithToken(this); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/TezzeretCruelMachinist.java b/Mage.Sets/src/mage/cards/t/TezzeretCruelMachinist.java index c47ecd602a..503a85bc48 100644 --- a/Mage.Sets/src/mage/cards/t/TezzeretCruelMachinist.java +++ b/Mage.Sets/src/mage/cards/t/TezzeretCruelMachinist.java @@ -141,7 +141,7 @@ class TezzeretCruelMachinistCardTypeEffect extends AddCardTypeTargetEffect { case TypeChangingEffects_4: target.getSuperType().clear(); target.getCardType().clear(); - target.getSubtype(game).clear(); + target.removeAllSubTypes(game); target.addCardType(CardType.ARTIFACT); target.addCardType(CardType.CREATURE); break; diff --git a/Mage.Sets/src/mage/cards/t/TezzeretTheSeeker.java b/Mage.Sets/src/mage/cards/t/TezzeretTheSeeker.java index bf93fc6fb6..4784689d15 100644 --- a/Mage.Sets/src/mage/cards/t/TezzeretTheSeeker.java +++ b/Mage.Sets/src/mage/cards/t/TezzeretTheSeeker.java @@ -134,7 +134,6 @@ class TezzeretTheSeekerEffect3 extends ContinuousEffectImpl { if (!permanent.isCreature()) { permanent.addCardType(CardType.CREATURE); } - permanent.getSubtype(game).clear(); } break; case PTChangingEffects_7: diff --git a/Mage.Sets/src/mage/cards/t/TheAntiquitiesWar.java b/Mage.Sets/src/mage/cards/t/TheAntiquitiesWar.java index 4f125fbec7..bc13743dea 100644 --- a/Mage.Sets/src/mage/cards/t/TheAntiquitiesWar.java +++ b/Mage.Sets/src/mage/cards/t/TheAntiquitiesWar.java @@ -98,7 +98,6 @@ class TheAntiquitiesWarEffect extends ContinuousEffectImpl { if (!permanent.isCreature()) { permanent.addCardType(CardType.CREATURE); } - permanent.getSubtype(game).clear(); } break; case PTChangingEffects_7: diff --git a/Mage.Sets/src/mage/cards/t/TurtleshellChangeling.java b/Mage.Sets/src/mage/cards/t/TurtleshellChangeling.java index a2780fbfe5..4571e67a6c 100644 --- a/Mage.Sets/src/mage/cards/t/TurtleshellChangeling.java +++ b/Mage.Sets/src/mage/cards/t/TurtleshellChangeling.java @@ -28,6 +28,7 @@ public final class TurtleshellChangeling extends CardImpl { this.toughness = new MageInt(4); //Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); //{1}{U}: Switch {this}'s power and toughness until end of turn. diff --git a/Mage.Sets/src/mage/cards/u/UniversalAutomaton.java b/Mage.Sets/src/mage/cards/u/UniversalAutomaton.java index 74f505881a..735b2f1e82 100644 --- a/Mage.Sets/src/mage/cards/u/UniversalAutomaton.java +++ b/Mage.Sets/src/mage/cards/u/UniversalAutomaton.java @@ -22,6 +22,7 @@ public final class UniversalAutomaton extends CardImpl { this.toughness = new MageInt(1); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/cards/u/UnsettledMariner.java b/Mage.Sets/src/mage/cards/u/UnsettledMariner.java index dcc22cf871..d050604379 100644 --- a/Mage.Sets/src/mage/cards/u/UnsettledMariner.java +++ b/Mage.Sets/src/mage/cards/u/UnsettledMariner.java @@ -31,6 +31,7 @@ public final class UnsettledMariner extends CardImpl { this.toughness = new MageInt(2); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // 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}. diff --git a/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java b/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java index 5e4f2e852b..986af63475 100644 --- a/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java +++ b/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java @@ -81,7 +81,7 @@ public final class UrborgTombOfYawgmoth extends CardImpl { // 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)) { - land.getSubtype(game).add(SubType.SWAMP); + land.addSubType(game, SubType.SWAMP); } if (!land.getAbilities().containsRule(new BlackManaAbility())) { land.addAbility(new BlackManaAbility(), source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/u/UrsineChampion.java b/Mage.Sets/src/mage/cards/u/UrsineChampion.java index 32847388d8..ef47de2301 100644 --- a/Mage.Sets/src/mage/cards/u/UrsineChampion.java +++ b/Mage.Sets/src/mage/cards/u/UrsineChampion.java @@ -1,26 +1,20 @@ package mage.cards.u; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class UrsineChampion extends CardImpl { @@ -53,14 +47,14 @@ public final class UrsineChampion extends CardImpl { return new UrsineChampion(this); } - private class UrsineChampionEffect extends ContinuousEffectImpl { + private static class UrsineChampionEffect extends ContinuousEffectImpl { - public UrsineChampionEffect() { - super(Duration.EndOfTurn, Outcome.BecomeCreature); - setText(); + private UrsineChampionEffect() { + super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature); + staticText = "and becomes a Bear Berserker until end of turn"; } - public UrsineChampionEffect(final UrsineChampionEffect effect) { + private UrsineChampionEffect(final UrsineChampionEffect effect) { super(effect); } @@ -70,35 +64,14 @@ public final class UrsineChampion extends CardImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent == null) { return false; } - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.getSubtype(game).clear(); - permanent.getSubtype(game).add(SubType.BEAR); - permanent.getSubtype(game).add(SubType.BERSERKER); - } - break; - } + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.BEAR, SubType.BERSERKER); return true; } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - private void setText() { - staticText = "and becomes a Bear Berserker until end of turn"; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } } } diff --git a/Mage.Sets/src/mage/cards/v/ValiantChangeling.java b/Mage.Sets/src/mage/cards/v/ValiantChangeling.java index e562dd6e0c..5177f12e58 100644 --- a/Mage.Sets/src/mage/cards/v/ValiantChangeling.java +++ b/Mage.Sets/src/mage/cards/v/ValiantChangeling.java @@ -35,6 +35,7 @@ public final class ValiantChangeling extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.ALL, new ValiantChangelingCostReductionEffect())); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // Double strike diff --git a/Mage.Sets/src/mage/cards/v/VeiledSentry.java b/Mage.Sets/src/mage/cards/v/VeiledSentry.java index 933b8aaca4..a625f8f072 100644 --- a/Mage.Sets/src/mage/cards/v/VeiledSentry.java +++ b/Mage.Sets/src/mage/cards/v/VeiledSentry.java @@ -1,6 +1,5 @@ package mage.cards.v; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; @@ -9,24 +8,16 @@ import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import static mage.constants.Layer.PTChangingEffects_7; -import static mage.constants.Layer.TypeChangingEffects_4; -import mage.constants.Outcome; -import mage.constants.SetTargetPointer; -import mage.constants.SubLayer; -import mage.constants.SubType; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterSpell; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.Spell; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class VeiledSentry extends CardImpl { @@ -79,15 +70,10 @@ class VeiledSentryEffect extends ContinuousEffectImpl { } switch (layer) { case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - veiledSentry.getCardType().clear(); - if (!veiledSentry.isCreature()) { - veiledSentry.addCardType(CardType.CREATURE); - } - if (!veiledSentry.getSubtype(game).contains(SubType.ILLUSION)) { - veiledSentry.getSubtype(game).add(SubType.ILLUSION); - } - } + veiledSentry.getCardType().clear(); + veiledSentry.removeAllSubTypes(game); + veiledSentry.addCardType(CardType.CREATURE); + veiledSentry.addSubType(game, SubType.ILLUSION); break; case PTChangingEffects_7: diff --git a/Mage.Sets/src/mage/cards/v/VenomousChangeling.java b/Mage.Sets/src/mage/cards/v/VenomousChangeling.java index eec819e708..956c7fa3ac 100644 --- a/Mage.Sets/src/mage/cards/v/VenomousChangeling.java +++ b/Mage.Sets/src/mage/cards/v/VenomousChangeling.java @@ -23,6 +23,7 @@ public final class VenomousChangeling extends CardImpl { this.toughness = new MageInt(3); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // Deathtouch diff --git a/Mage.Sets/src/mage/cards/v/VeteranAdventurer.java b/Mage.Sets/src/mage/cards/v/VeteranAdventurer.java index 10f54a1c83..b5da4fa64d 100644 --- a/Mage.Sets/src/mage/cards/v/VeteranAdventurer.java +++ b/Mage.Sets/src/mage/cards/v/VeteranAdventurer.java @@ -3,7 +3,7 @@ package mage.cards.v; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.common.PartyCount; -import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.continuous.HasSubtypesSourceEffect; import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect; import mage.abilities.hint.common.PartyCountHint; import mage.abilities.keyword.VigilanceAbility; @@ -24,15 +24,13 @@ public final class VeteranAdventurer extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}"); this.subtype.add(SubType.HUMAN); - this.subtype.add(SubType.CLERIC); - this.subtype.add(SubType.ROGUE); - this.subtype.add(SubType.WARRIOR); - this.subtype.add(SubType.WIZARD); this.power = new MageInt(5); this.toughness = new MageInt(5); // Veteran Adventurer is also a Cleric, Rogue, Warrior, and Wizard. - this.addAbility(new SimpleStaticAbility(new InfoEffect("{this} is also a Cleric, Rogue, Warrior, and Wizard"))); + this.addAbility(new SimpleStaticAbility( + Zone.ALL, new HasSubtypesSourceEffect(SubType.CLERIC, SubType.ROGUE, SubType.WARRIOR, SubType.WIZARD) + )); // This spell costs {1} less to cast for each creature in your party. this.addAbility(new SimpleStaticAbility( diff --git a/Mage.Sets/src/mage/cards/v/VisionCharm.java b/Mage.Sets/src/mage/cards/v/VisionCharm.java index 9d8920bbd0..73dc143379 100644 --- a/Mage.Sets/src/mage/cards/v/VisionCharm.java +++ b/Mage.Sets/src/mage/cards/v/VisionCharm.java @@ -1,19 +1,13 @@ package mage.cards.v; -import java.util.Iterator; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.PhaseOutTargetEffect; import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect; -import mage.abilities.mana.BlackManaAbility; -import mage.abilities.mana.BlueManaAbility; -import mage.abilities.mana.GreenManaAbility; -import mage.abilities.mana.RedManaAbility; -import mage.abilities.mana.WhiteManaAbility; +import mage.abilities.mana.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.Choice; @@ -28,8 +22,10 @@ import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetArtifactPermanent; +import java.util.Iterator; +import java.util.UUID; + /** - * * @author tre3qwerty */ public final class VisionCharm extends CardImpl { @@ -42,18 +38,15 @@ public final class VisionCharm extends CardImpl { this.getSpellAbility().addTarget(new TargetPlayer()); // or choose a land type and a basic land type. Each land of the first chosen type becomes the second chosen type until end of turn; - Mode mode = new Mode(); - mode.addEffect(new VisionCharmEffect()); - this.getSpellAbility().addMode(mode); + this.getSpellAbility().addMode(new Mode(new VisionCharmEffect())); // or target artifact phases out. - mode = new Mode(); - mode.addEffect(new PhaseOutTargetEffect()); + Mode mode = new Mode(new PhaseOutTargetEffect()); mode.addTarget(new TargetArtifactPermanent()); this.getSpellAbility().addMode(mode); } - public VisionCharm(final VisionCharm card) { + private VisionCharm(final VisionCharm card) { super(card); } @@ -68,12 +61,12 @@ class VisionCharmEffect extends ContinuousEffectImpl { private String targetLandType; private SubType targetBasicLandType; - public VisionCharmEffect() { - super(Duration.EndOfTurn, Outcome.Neutral); + VisionCharmEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); staticText = "Choose a land type and a basic land type. Each land of the first chosen type becomes the second chosen type until end of turn."; } - public VisionCharmEffect(final VisionCharmEffect effect) { + private VisionCharmEffect(final VisionCharmEffect effect) { super(effect); targetLandType = effect.targetLandType; targetBasicLandType = effect.targetBasicLandType; @@ -119,51 +112,35 @@ class VisionCharmEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - // TODO fix to use SubType enum - for (Iterator it = affectedObjectList.iterator(); it.hasNext();) { + public boolean apply(Game game, Ability source) { + for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { Permanent land = it.next().getPermanent(game); - if (land != null) { - switch (layer) { - case TypeChangingEffects_4: - land.getSubtype(game).clear(); - land.getSubtype(game).add(targetBasicLandType); - break; - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - land.getAbilities().clear(); - if (targetBasicLandType.equals(SubType.FOREST)) { - land.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } - if (targetBasicLandType.equals(SubType.PLAINS)) { - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - } - if (targetBasicLandType.equals(SubType.MOUNTAIN)) { - land.addAbility(new RedManaAbility(), source.getSourceId(), game); - } - if (targetBasicLandType.equals(SubType.ISLAND)) { - land.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - if (targetBasicLandType.equals(SubType.SWAMP)) { - land.addAbility(new BlackManaAbility(), source.getSourceId(), game); - } - } - } - } else { + if (land == null) { it.remove(); + continue; + } + land.getSubtype(game).removeAll(SubType.getLandTypes()); + land.addSubType(game, targetBasicLandType); + land.removeAllAbilities(source.getSourceId(), game); + switch (targetBasicLandType) { + case FOREST: + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); + break; + case PLAINS: + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + break; + case MOUNTAIN: + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + break; + case ISLAND: + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + break; + case SWAMP: + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + break; } } return true; } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; - } } diff --git a/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java b/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java index e449f79c6d..75a3ddd30e 100644 --- a/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java +++ b/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java @@ -47,7 +47,6 @@ public final class VizierOfManyFaces extends CardImpl { // Embalm {3}{U}{U} this.addAbility(new EmbalmAbility(new ManaCostsImpl("{3}{U}{U}"), this)); - } public VizierOfManyFaces(final VizierOfManyFaces card) { @@ -70,21 +69,21 @@ class VizierOfManyFacesApplyToPermanent extends ApplyToPermanent { @Override public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { for (Permanent entering : game.getPermanentsEntering().values()) { - if (entering.getId().equals(copyToObjectId) && entering instanceof PermanentToken) { - UUID originalCardId = ((PermanentToken) entering).getToken().getCopySourceCard().getId(); - EmbalmedThisTurnWatcher watcher = game.getState().getWatcher(EmbalmedThisTurnWatcher.class); - if (watcher != null) { - for (MageObjectReference mor : watcher.getEmbalmedThisTurnCards()) { - if (Objects.equals(mor.getSourceId(), originalCardId) && game.getState().getZoneChangeCounter(originalCardId) == mor.getZoneChangeCounter()) { - permanent.getManaCost().clear(); - if (!permanent.hasSubtype(SubType.ZOMBIE, game)) { - permanent.getSubtype(game).add(SubType.ZOMBIE); - } - permanent.getColor(game).setColor(ObjectColor.WHITE); - - } - } + if (!entering.getId().equals(copyToObjectId) || !(entering instanceof PermanentToken)) { + continue; + } + UUID originalCardId = ((PermanentToken) entering).getToken().getCopySourceCard().getId(); + EmbalmedThisTurnWatcher watcher = game.getState().getWatcher(EmbalmedThisTurnWatcher.class); + if (watcher == null) { + continue; + } + for (MageObjectReference mor : watcher.getEmbalmedThisTurnCards()) { + 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); } } return true; @@ -117,5 +116,4 @@ class EmbalmedThisTurnWatcher extends Watcher { super.reset(); embalmedThisTurnTokens.clear(); } - } diff --git a/Mage.Sets/src/mage/cards/v/VolatileClaws.java b/Mage.Sets/src/mage/cards/v/VolatileClaws.java index a336762c30..9d06a0c6fb 100644 --- a/Mage.Sets/src/mage/cards/v/VolatileClaws.java +++ b/Mage.Sets/src/mage/cards/v/VolatileClaws.java @@ -1,14 +1,17 @@ package mage.cards.v; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.continuous.BoostControlledEffect; -import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; -import mage.abilities.keyword.ChangelingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; +import mage.constants.*; import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import java.util.Iterator; import java.util.UUID; /** @@ -23,10 +26,7 @@ public final class VolatileClaws extends CardImpl { this.getSpellAbility().addEffect(new BoostControlledEffect( 2, 0, Duration.EndOfTurn ).setText("until end of turn, creatures you control get +2/+0")); - this.getSpellAbility().addEffect(new GainAbilityControlledEffect( - ChangelingAbility.getInstance(), Duration.EndOfTurn, - StaticFilters.FILTER_PERMANENT_CREATURE - ).setText("and gain all creature types")); + this.getSpellAbility().addEffect(new VolatileClawsEffect()); } private VolatileClaws(final VolatileClaws card) { @@ -38,3 +38,43 @@ public final class VolatileClaws extends CardImpl { return new VolatileClaws(this); } } + +class VolatileClawsEffect extends ContinuousEffectImpl { + + VolatileClawsEffect() { + super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); + staticText = "and gain all creature types"; + } + + private VolatileClawsEffect(final VolatileClawsEffect effect) { + super(effect); + } + + @Override + public VolatileClawsEffect copy() { + return new VolatileClawsEffect(this); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + for (Permanent perm : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_CREATURES, source.getControllerId(), source.getSourceId(), game + )) { + affectedObjectList.add(new MageObjectReference(perm, game)); + } + } + + @Override + public boolean apply(Game game, Ability source) { + for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { + Permanent permanent = it.next().getPermanent(game); + if (permanent == null) { + it.remove(); // no longer on the battlefield, remove reference to object + continue; + } + permanent.setIsAllCreatureTypes(true); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/v/VolrathsShapeshifter.java b/Mage.Sets/src/mage/cards/v/VolrathsShapeshifter.java index a2d7f98248..04d4eeef9d 100644 --- a/Mage.Sets/src/mage/cards/v/VolrathsShapeshifter.java +++ b/Mage.Sets/src/mage/cards/v/VolrathsShapeshifter.java @@ -1,6 +1,5 @@ package mage.cards.v; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -15,6 +14,8 @@ import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** * @author ImperatorPrime */ @@ -84,11 +85,10 @@ class VolrathsShapeshifterEffect extends ContinuousEffectImpl { permanent.addCardType(type); } - permanent.getSubtype(game).clear(); + permanent.removeAllSubTypes(game); + permanent.setIsAllCreatureTypes(card.isAllCreatureTypes()); for (SubType type : card.getSubtype(game)) { - if (!permanent.hasSubtype(type, game)) { - permanent.getSubtype(game).add(type); - } + permanent.addSubType(game, type); } permanent.getSuperType().clear(); diff --git a/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java b/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java index 842336238c..845850f9fa 100644 --- a/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java +++ b/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java @@ -3,28 +3,32 @@ package mage.cards.w; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.keyword.DefenderAbility; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.TargetPermanent; -import mage.util.functions.ApplyToPermanent; -import java.util.UUID; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousRuleModifyingEffect; import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; +import mage.util.functions.ApplyToPermanent; + +import java.util.UUID; /** * @author TheElk801 @@ -46,11 +50,8 @@ public final class WallOfStolenIdentity extends CardImpl { // You may have Wall of Stolen Identity enter the battlefield as a copy of any creature on the battlefield, except it's a wall in addition to its other types and it has defender. When you do, tap the copied creature and it doesn't untap during its controller's untap step for as long as you control Wall of Stolen Identity. Ability ability = new SimpleStaticAbility( - Zone.BATTLEFIELD, - new EntersBattlefieldEffect( - new WallOfStolenIdentityCopyEffect(), - rule, - true)); + new EntersBattlefieldEffect(new WallOfStolenIdentityCopyEffect(), rule, true) + ); this.addAbility(ability); } @@ -86,53 +87,54 @@ class WallOfStolenIdentityCopyEffect extends OneShotEffect { permanent = game.getPermanentEntering(source.getSourceId()); } final Permanent sourcePermanent = permanent; - if (controller != null - && sourcePermanent != null) { - Target target = new TargetPermanent(new FilterCreaturePermanent("target creature (you copy from)")); - target.setRequired(true); - if (source instanceof SimpleStaticAbility) { - target = new TargetPermanent(new FilterCreaturePermanent("creature (you copy from)")); - target.setRequired(false); - target.setNotTarget(true); - } - if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) { - 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() { - @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - permanent.getSubtype(game).add(SubType.WALL); - permanent.getAbilities().add(DefenderAbility.getInstance()); - return true; - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.getSubtype(game).add(SubType.WALL); - mageObject.getAbilities().add(DefenderAbility.getInstance()); - return true; - } - - }); - - copyFromPermanent.tap(game); - // Incredibly, you can't just add a fixed target to a continuousrulemodifyingeffect, thus the workaround. - ContinuousRuleModifyingEffect effect = new DontUntapInControllersUntapStepSourceEffect(); - Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); - ContinuousEffect effect2 = new GainAbilityTargetEffect(ability, Duration.Custom); - ConditionalContinuousEffect conditionalEffect = new ConditionalContinuousEffect( - effect2, new WallOfStolenIdentityCondition( - source, - source.getControllerId(), - sourcePermanent.getZoneChangeCounter(game)), ""); - conditionalEffect.setTargetPointer(new FixedTarget(target.getFirstTarget())); - game.addEffect(conditionalEffect, source); - return true; - } - } + if (controller == null + || sourcePermanent == null) { + return false; } - return false; + Target target = new TargetPermanent(new FilterCreaturePermanent("target creature (you copy from)")); + target.setRequired(true); + if (source instanceof SimpleStaticAbility) { + target = new TargetPermanent(new FilterCreaturePermanent("creature (you copy from)")); + target.setRequired(false); + target.setNotTarget(true); + } + if (!target.canChoose(source.getSourceId(), source.getControllerId(), game)) { + return false; + } + controller.choose(Outcome.Copy, target, source.getSourceId(), game); + Permanent copyFromPermanent = game.getPermanent(target.getFirstTarget()); + if (copyFromPermanent == null) { + return false; + } + game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new ApplyToPermanent() { + @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()); + return true; + } + }); + + copyFromPermanent.tap(game); + // Incredibly, you can't just add a fixed target to a continuousrulemodifyingeffect, thus the workaround. + ContinuousRuleModifyingEffect effect = new DontUntapInControllersUntapStepSourceEffect(); + Ability ability = new SimpleStaticAbility(effect); + ContinuousEffect effect2 = new GainAbilityTargetEffect(ability, Duration.Custom); + ConditionalContinuousEffect conditionalEffect = new ConditionalContinuousEffect( + effect2, new WallOfStolenIdentityCondition( + source, + source.getControllerId(), + sourcePermanent.getZoneChangeCounter(game)), ""); + conditionalEffect.setTargetPointer(new FixedTarget(target.getFirstTarget())); + game.addEffect(conditionalEffect, source); + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/w/WarSpikeChangeling.java b/Mage.Sets/src/mage/cards/w/WarSpikeChangeling.java index 2be2e23584..0b9e1bb25e 100644 --- a/Mage.Sets/src/mage/cards/w/WarSpikeChangeling.java +++ b/Mage.Sets/src/mage/cards/w/WarSpikeChangeling.java @@ -24,6 +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 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 e96b7e72e4..58f136aa13 100644 --- a/Mage.Sets/src/mage/cards/w/WebweaverChangeling.java +++ b/Mage.Sets/src/mage/cards/w/WebweaverChangeling.java @@ -28,6 +28,7 @@ public final class WebweaverChangeling extends CardImpl { this.toughness = new MageInt(5); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // Reach diff --git a/Mage.Sets/src/mage/cards/w/WeightOfConscience.java b/Mage.Sets/src/mage/cards/w/WeightOfConscience.java index 73e09126cb..49f6d7c665 100644 --- a/Mage.Sets/src/mage/cards/w/WeightOfConscience.java +++ b/Mage.Sets/src/mage/cards/w/WeightOfConscience.java @@ -134,7 +134,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { Permanent firstTargetCreature = game.getPermanent(firstTargetId); if (firstTargetCreature != null) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { - if (!permanent.getId().equals(firstTargetId) && firstTargetCreature.shareSubtypes(permanent, game)) { + if (!permanent.getId().equals(firstTargetId) && firstTargetCreature.shareCreatureTypes(permanent, game)) { possibleTargets.add(permanent.getId()); } } @@ -148,7 +148,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { for (Permanent permanent1 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { for (Permanent permanent2 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { - if (!Objects.equals(permanent1, permanent2) && permanent1.shareSubtypes(permanent2, game)) { + if (!Objects.equals(permanent1, permanent2) && permanent1.shareCreatureTypes(permanent2, game)) { return true; } } @@ -173,7 +173,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { } } else { Permanent firstTarget = game.getPermanent(this.getTargets().get(0)); - if (firstTarget != null && firstTarget.shareSubtypes(targetPermanent, game)) { + if (firstTarget != null && firstTarget.shareCreatureTypes(targetPermanent, game)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/w/WildwoodScourge.java b/Mage.Sets/src/mage/cards/w/WildwoodScourge.java index 737b4d5b49..a67d78efe1 100644 --- a/Mage.Sets/src/mage/cards/w/WildwoodScourge.java +++ b/Mage.Sets/src/mage/cards/w/WildwoodScourge.java @@ -33,7 +33,7 @@ public final class WildwoodScourge extends CardImpl { this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance()))); // Whenever one or more +1/+1 counters are put on another non-Hydra creature you control, put a +1/+1 counter on Wildwood Scourge. - this.addAbility(new EnduringScalelordTriggeredAbility()); + this.addAbility(new WildwoodScourgeTriggeredAbility()); } private WildwoodScourge(final WildwoodScourge card) { @@ -46,19 +46,19 @@ public final class WildwoodScourge extends CardImpl { } } -class EnduringScalelordTriggeredAbility extends TriggeredAbilityImpl { +class WildwoodScourgeTriggeredAbility extends TriggeredAbilityImpl { - EnduringScalelordTriggeredAbility() { + WildwoodScourgeTriggeredAbility() { super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false); } - private EnduringScalelordTriggeredAbility(final EnduringScalelordTriggeredAbility ability) { + private WildwoodScourgeTriggeredAbility(final WildwoodScourgeTriggeredAbility ability) { super(ability); } @Override - public EnduringScalelordTriggeredAbility copy() { - return new EnduringScalelordTriggeredAbility(this); + public WildwoodScourgeTriggeredAbility copy() { + return new WildwoodScourgeTriggeredAbility(this); } @Override @@ -73,11 +73,11 @@ class EnduringScalelordTriggeredAbility extends TriggeredAbilityImpl { if (permanent == null) { permanent = game.getPermanentEntering(event.getTargetId()); } - return (permanent != null + return permanent != null && !event.getTargetId().equals(this.getSourceId()) && permanent.isCreature() - && !permanent.getSubtype(game).contains(SubType.HYDRA) - && permanent.isControlledBy(this.getControllerId())); + && !permanent.hasSubtype(SubType.HYDRA, game) + && permanent.isControlledBy(this.getControllerId()); } return false; } diff --git a/Mage.Sets/src/mage/cards/w/WingsOfVelisVel.java b/Mage.Sets/src/mage/cards/w/WingsOfVelisVel.java index 87cb49aa9c..85dd21bbb8 100644 --- a/Mage.Sets/src/mage/cards/w/WingsOfVelisVel.java +++ b/Mage.Sets/src/mage/cards/w/WingsOfVelisVel.java @@ -1,47 +1,40 @@ - package mage.cards.w; -import java.util.UUID; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.continuous.GainAllCreatureTypesTargetEffect; import mage.abilities.effects.common.continuous.SetPowerToughnessTargetEffect; import mage.abilities.keyword.ChangelingAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.SubLayer; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class WingsOfVelisVel extends CardImpl { public WingsOfVelisVel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.TRIBAL,CardType.INSTANT},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.TRIBAL, CardType.INSTANT}, "{1}{U}"); this.subtype.add(SubType.SHAPESHIFTER); // Changeling + this.setIsAllCreatureTypes(true); this.addAbility(ChangelingAbility.getInstance()); // 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) + .setText("Target creature becomes 4/4")); + this.getSpellAbility().addEffect(new GainAllCreatureTypesTargetEffect(Duration.EndOfTurn) + .setText(", gains all creature types")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn) + .setText(", and gains flying until end of turn")); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - Effect effect = new SetPowerToughnessTargetEffect(4, 4, Duration.EndOfTurn); - effect.setText("Target creature becomes 4/4"); - this.getSpellAbility().addEffect(effect); - - effect = new GainAbilityTargetEffect(ChangelingAbility.getInstance(), Duration.EndOfTurn, null, false, Layer.TypeChangingEffects_4, SubLayer.NA); - effect.setText(", gains all creature types"); - this.getSpellAbility().addEffect(effect); - - effect = new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn); - effect.setText(", and gains flying until end of turn"); - this.getSpellAbility().addEffect(effect); } public WingsOfVelisVel(final WingsOfVelisVel card) { diff --git a/Mage.Sets/src/mage/cards/w/WishfulMerfolk.java b/Mage.Sets/src/mage/cards/w/WishfulMerfolk.java index 0badf53c39..92dc12451e 100644 --- a/Mage.Sets/src/mage/cards/w/WishfulMerfolk.java +++ b/Mage.Sets/src/mage/cards/w/WishfulMerfolk.java @@ -15,7 +15,6 @@ import mage.game.permanent.Permanent; import java.util.UUID; /** - * * @author jmharmon */ @@ -32,7 +31,7 @@ public final class WishfulMerfolk extends CardImpl { this.addAbility(DefenderAbility.getInstance()); // {1}{U}: Wishful Merfolk loses defender and becomes a Human until end of turn. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new WishfulMerfolkEffect(), new ManaCostsImpl("{1}{U}"))); + this.addAbility(new SimpleActivatedAbility(new WishfulMerfolkEffect(), new ManaCostsImpl("{1}{U}"))); } public WishfulMerfolk(final WishfulMerfolk card) { @@ -64,23 +63,19 @@ class WishfulMerfolkEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - switch (layer) { - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - permanent.removeAbility(DefenderAbility.getInstance(), source.getSourceId(), game); - } - break; - case TypeChangingEffects_4: - if (permanent.getSubtype(game).contains(SubType.MERFOLK)) { - permanent.getSubtype(game).clear(); - permanent.getSubtype(game).add(SubType.HUMAN); - } - break; - } - return true; + if (permanent == null) { + return false; } - return false; + switch (layer) { + case AbilityAddingRemovingEffects_6: + permanent.removeAbility(DefenderAbility.getInstance(), source.getSourceId(), game); + break; + case TypeChangingEffects_4: + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.HUMAN); + break; + } + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/w/WoodlandChangeling.java b/Mage.Sets/src/mage/cards/w/WoodlandChangeling.java index c475a823e8..081425f6c8 100644 --- a/Mage.Sets/src/mage/cards/w/WoodlandChangeling.java +++ b/Mage.Sets/src/mage/cards/w/WoodlandChangeling.java @@ -22,6 +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()); } diff --git a/Mage.Sets/src/mage/cards/x/Xenograft.java b/Mage.Sets/src/mage/cards/x/Xenograft.java index 2e08278a7a..cce12a2e17 100644 --- a/Mage.Sets/src/mage/cards/x/Xenograft.java +++ b/Mage.Sets/src/mage/cards/x/Xenograft.java @@ -1,8 +1,6 @@ package mage.cards.x; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; @@ -15,8 +13,10 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; +import java.util.UUID; + /** - * * @author North */ public final class Xenograft extends CardImpl { @@ -54,16 +54,16 @@ class XenograftAddSubtypeEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game); - if (subType != null) { - List permanents = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game); - for (Permanent permanent : permanents) { - if (permanent != null && !permanent.hasSubtype(subType, game)) { - permanent.getSubtype(game).add(subType); - } - } - return true; + if (subType == null) { + return false; } - return false; + List permanents = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game); + for (Permanent permanent : permanents) { + if (permanent != null) { + permanent.addSubType(game, subType); + } + } + return true; } @Override 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 1c745fb409..a694a6cc21 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 @@ -2,7 +2,10 @@ package org.mage.test.cards.abilities.keywords; import mage.abilities.Ability; +import mage.abilities.keyword.ChangelingAbility; +import mage.abilities.keyword.HasteAbility; import mage.constants.PhaseStep; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.permanent.Permanent; import org.junit.Assert; @@ -10,7 +13,6 @@ import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * * @author LevelX2 */ public class ChangelingTest extends CardTestPlayerBase { @@ -80,7 +82,7 @@ public class ChangelingTest extends CardTestPlayerBase { /** * NOTE: As of 05/06/2017 this test is failing due to a bug in code. * See issue #3316 - * + *

* Kaseto, Orochi Archmage do not give Chameleon Colossus +2/+2 , even though Chameleon Colossus should have the "snake" type */ @Test @@ -103,10 +105,10 @@ public class ChangelingTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Chameleon Colossus"); /* Nessian Asp {4}{G} - 4/5 - * Creature — Snake - * Reach - * {6}{G}: Monstrosity 4. (If this creature isn't monstrous, put four +1/+1 counters on it and it becomes monstrous.) - */ + * Creature — Snake + * Reach + * {6}{G}: Monstrosity 4. (If this creature isn't monstrous, put four +1/+1 counters on it and it becomes monstrous.) + */ addCard(Zone.BATTLEFIELD, playerA, "Nessian Asp"); @@ -122,4 +124,41 @@ public class ChangelingTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Chameleon Colossus", 6, 6); } + + @Test + public void testLoseAllCreatureTypes() { + addCard(Zone.BATTLEFIELD, playerA, "Game-Trail Changeling"); + addCard(Zone.BATTLEFIELD, playerA, "Goblin Chieftain"); + addCard(Zone.HAND, playerA, "Nameless Inversion"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nameless Inversion", "Game-Trail Changeling"); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + // Should have no creature types but still have the Changeling ability + 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); + } + + @Test + public void testLoseAbilities() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + addCard(Zone.BATTLEFIELD, playerB, "Game-Trail Changeling"); + addCard(Zone.HAND, playerA, "Merfolk Trickster"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Merfolk Trickster"); + addTarget(playerA, "Game-Trail Changeling"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertTapped("Game-Trail Changeling", true); + 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); + } } 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 c57888e58c..a27ae3a7f6 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 @@ -1,5 +1,6 @@ package org.mage.test.cards.continuous; +import mage.constants.CardType; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Test; @@ -8,29 +9,33 @@ import org.mage.test.serverside.base.CardTestPlayerBase; public class ChangelingTest extends CardTestPlayerBase { // Mistform Ultimus is every creature type - private final String ultimus = "Mistform Ultimus"; + private static final String ultimus = "Mistform Ultimus"; // each creature gets +1/+1 for each creature you control that shares a creatureype - private final String coatOfArms = "Coat of Arms"; + private static final String coatOfArms = "Coat of Arms"; // all merfolk get +1/+1 - private final String lordOfAtlantis = "Lord of Atlantis"; + private static final String lordOfAtlantis = "Lord of Atlantis"; // all illusions get +1/+1 - private final String lordOfUnreal = "Lord of the Unreal"; + private static final String lordOfUnreal = "Lord of the Unreal"; // mutavault becomes a token that is all creature types - private final String mutavault = "Mutavault"; - + private static final String mutavault = "Mutavault"; + // vehicles have no creature type + private static final String copter = "Smuggler's Copter"; // 2/2 changeling - private final String woodlandChangeling = "Woodland Changeling"; + private static final String woodlandChangeling = "Woodland Changeling"; @Test - public void coatOfArmsTest(){ + public void coatOfArmsTest() { addCard(Zone.BATTLEFIELD, playerA, ultimus); addCard(Zone.BATTLEFIELD, playerA, coatOfArms); addCard(Zone.BATTLEFIELD, playerA, lordOfAtlantis); addCard(Zone.BATTLEFIELD, playerA, lordOfUnreal); addCard(Zone.BATTLEFIELD, playerA, mutavault); + addCard(Zone.BATTLEFIELD, playerA, copter); addCard(Zone.BATTLEFIELD, playerA, woodlandChangeling, 2); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}: Until end of turn {this} becomes"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Crew"); + setChoice(playerA, ultimus); setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); execute(); @@ -54,10 +59,15 @@ public class ChangelingTest extends CardTestPlayerBase { coat of arms: +5 */ assertPowerToughness(playerA, mutavault, 9, 9); + /* + smuggler's copter; +3 + */ + assertType(copter, CardType.CREATURE, true); + assertPowerToughness(playerA, copter, 3, 3); } @Test - public void testMetallicMimicChangelingTrigger(){ + public void testMetallicMimicChangelingTrigger() { // all creatures with the chosen subtype come into play with a +1/+1 counter final String mimic = "Metallic Mimic"; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/GainAbilityDependenciesTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/GainAbilityDependenciesTest.java index 78e4bf1abc..c2eb044474 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/GainAbilityDependenciesTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/GainAbilityDependenciesTest.java @@ -82,7 +82,6 @@ public class GainAbilityDependenciesTest extends CardTestPlayerBase { // equip activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {3}", "Elephant"); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); - checkAbility("must have all type ability", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Elephant", ChangelingAbility.class, true); // attack with +1 token attack(3, playerA, "Elephant", playerB); 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 2f21399ae6..31a22dd6f6 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 @@ -1,6 +1,7 @@ package org.mage.test.cards.continuous; import mage.cards.Card; +import mage.constants.CardType; import mage.constants.PhaseStep; import mage.constants.SubType; import mage.constants.Zone; @@ -296,6 +297,49 @@ public class SubTypeChangingEffectsTest extends CardTestPlayerBase { } } + } + @Test + public void testKeepOtherTypes() { + // Dragonshift (2013-04-15) + // Each affected creature will lose all other colors and creature types and be only red, blue, and a Dragon. + // Each will retain any other types it may have had, such as artifact. + addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 3); + addCard(Zone.BATTLEFIELD, playerA, "Gingerbrute"); + addCard(Zone.HAND, playerA, "Dragonshift"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dragonshift", "Gingerbrute"); + + setStopAt(1, PhaseStep.END_TURN); + + execute(); + + // Food is an artifact subtype and should not be removed + assertType("Gingerbrute", CardType.ARTIFACT, SubType.FOOD); + // Golem is a creature subtype and should be removed + assertType("Gingerbrute", CardType.CREATURE, SubType.DRAGON); + assertNotSubtype("Gingerbrute", SubType.GOLEM); + } + + @Test + public void testKeepOtherTypes2() { + // Dragonshift (2013-04-15) + // Each affected creature will lose all other colors and creature types and be only red, blue, and a Dragon. + // Each will retain any other types it may have had, such as artifact. + addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 7); + addCard(Zone.BATTLEFIELD, playerA, "Gingerbrute"); + addCard(Zone.HAND, playerA, "Dragonshift"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dragonshift with overload"); + + setStopAt(1, PhaseStep.END_TURN); + + execute(); + + // Food is an artifact subtype and should not be removed + assertType("Gingerbrute", CardType.ARTIFACT, SubType.FOOD); + // Golem is a creature subtype and should be removed + assertType("Gingerbrute", CardType.CREATURE, SubType.DRAGON); + assertNotSubtype("Gingerbrute", SubType.GOLEM); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java index 4cb9d4a3cd..12e66f80fb 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java @@ -1,25 +1,25 @@ package org.mage.test.cards.copy; +import mage.abilities.common.BecomesTargetTriggeredAbility; import mage.abilities.keyword.IndestructibleAbility; import mage.abilities.keyword.LifelinkAbility; import mage.constants.PhaseStep; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.permanent.Permanent; import org.junit.Assert; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; +import static org.junit.Assert.*; + /** * @author noxx - * + *

* Card: You may have {this} enter the battlefield as a copy of any creature on * the battlefield, except it's an Illusion in addition to its other types and * it gains "When this creature becomes the target of a spell or ability, * sacrifice it." - * */ public class PhantasmalImageTest extends CardTestPlayerBase { @@ -130,6 +130,7 @@ public class PhantasmalImageTest extends CardTestPlayerBase { // CardTestPlayerAPIImpl.assertPowerToughness:351->CardTestPlayerAPIImpl.assertPowerToughness:337 // There is no such creature under player's control with specified power&toughness, player=PlayerA, // cardName=Ravager of the Fells (found similar: 1, one of them: power=8 toughness=8) + /** * Tests copying already transformed creature Makes sure it still has "When * this creature becomes the target of a spell or ability, sacrifice it" @@ -313,7 +314,6 @@ public class PhantasmalImageTest extends CardTestPlayerBase { * the "When this creature becomes the target of a spell or ability, * sacrifice it." ability. I did not pay attention to see if it failed to * become an illusion too. - * */ @Test public void testCopiedFrostTitan() { @@ -426,13 +426,13 @@ public class PhantasmalImageTest extends CardTestPlayerBase { /** * Action Game State 1 -----------------> Game State 2 (On 'field) (Move to * GY) (In graveyard) - * + *

* LTB abilities such as Persist are expceptional in that they trigger based * on their existence and state of objects before the event (Game State 1, * when the card is on the battlefield) rather than after (Game State 2, * when the card is in the graveyard). It doesn't matter that the LTB * ability doesn't exist in Game State 2. [CR 603.6d] - * + *

* 603.6d Normally, objects that exist immediately after an event are * checked to see if the event matched any trigger conditions. Continuous * effects that exist at that time are used to determine what the trigger @@ -446,13 +446,12 @@ public class PhantasmalImageTest extends CardTestPlayerBase { * planeswalks away from a plane will trigger based on their existence, and * the appearance of objects, prior to the event rather than afterward. The * game has to “look back in time” to determine if these abilities trigger. - * + *

* Example: Two creatures are on the battlefield along with an artifact that * has the ability “Whenever a creature dies, you gain 1 life.” Someone * plays a spell that destroys all artifacts, creatures, and enchantments. * The artifact's ability triggers twice, even though the artifact goes to * its owner's graveyard at the same time as the creatures. - * */ @Test public void testPersist() { @@ -549,7 +548,7 @@ public class PhantasmalImageTest extends CardTestPlayerBase { * battlefield. 12:29: Phantasmal Image [466] died 12:29: HipSomHap puts a * Wurm [7d0] token onto the battlefield 12:29: HipSomHap puts a Wurm [186] * token onto the battlefield - * + *

* To the best of my knowledge, the Phantasmal Image [466], which entered * the battlefield as a Wurmcoil Engine, should grant tokens through the * Dies-trigger as well, right? @@ -610,4 +609,69 @@ public class PhantasmalImageTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Elemental", 1); } + + @Test + public void testAnimatedArtifact() { + addCard(Zone.BATTLEFIELD, playerB, "Chimeric Staff"); + addCard(Zone.BATTLEFIELD, playerB, "Island", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + addCard(Zone.HAND, playerA, "Phantasmal Image"); + + setChoice(playerB, "X=1"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{X}"); + + setChoice(playerA, "Chimeric Staff"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Phantasmal Image"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertAllCommandsUsed(); + + Permanent staffA = getPermanent("Chimeric Staff", playerA); + assertTrue("Phantasmal Image should be an artifact", staffA.isArtifact()); + assertTrue("Phantasmal Image should not be a creature", !staffA.isCreature()); + assertTrue("Phantasmal Image should not be an Illusion", !staffA.hasSubtype(SubType.ILLUSION, currentGame)); + assertTrue("Phantasmal Image should not be a Construct", !staffA.hasSubtype(SubType.CONSTRUCT, currentGame)); + assertTrue("Phantasmal Image should have the sacrifice trigger", staffA.getAbilities(currentGame).containsClass(BecomesTargetTriggeredAbility.class)); + + Permanent staffB = getPermanent("Chimeric Staff", playerB); + assertTrue("Chimeric Staff should be an artifact", staffB.isArtifact()); + assertTrue("Chimeric Staff should be a creature", staffB.isCreature()); + assertTrue("Chimeric Staff should be a Construct", staffB.hasSubtype(SubType.CONSTRUCT, currentGame)); + } + + @Test + public void testAnimatedTribal() { + addCard(Zone.BATTLEFIELD, playerB, "Cloak and Dagger"); + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + addCard(Zone.HAND, playerA, "Karn's Touch"); + addCard(Zone.HAND, playerA, "Phantasmal Image"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Karn's Touch", "Cloak and Dagger"); + + setChoice(playerA, "Cloak and Dagger"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Phantasmal Image"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertAllCommandsUsed(); + + Permanent cloakA = getPermanent("Cloak and Dagger", playerA); + assertTrue("Phantasmal Image should be an artifact", cloakA.isArtifact()); + assertTrue("Phantasmal Image should be tribal", cloakA.isTribal()); + assertTrue("Phantasmal Image should not be a creature", !cloakA.isCreature()); + assertTrue("Phantasmal Image should be a Rogue", cloakA.hasSubtype(SubType.ROGUE, currentGame)); + assertTrue("Phantasmal Image should be an Illusion", cloakA.hasSubtype(SubType.ILLUSION, currentGame)); + assertTrue("Phantasmal Image should be an Equipment", cloakA.hasSubtype(SubType.EQUIPMENT, currentGame)); + assertTrue("Phantasmal Image should have the sacrifice trigger", cloakA.getAbilities(currentGame).containsClass(BecomesTargetTriggeredAbility.class)); + + Permanent cloakB = getPermanent("Cloak and Dagger", playerB); + assertTrue("Cloak and Dagger should be an artifact", cloakB.isArtifact()); + assertTrue("Cloak and Dagger should be a creature", cloakB.isCreature()); + assertTrue("Cloak and Dagger should be tribal", cloakB.isTribal()); + assertTrue("Cloak and Dagger should be a Rogue", cloakB.hasSubtype(SubType.ROGUE, currentGame)); + assertTrue("Cloak and Dagger should be an Equipment", cloakB.hasSubtype(SubType.EQUIPMENT, currentGame)); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/lgn/MistformUltimusTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/lgn/MistformUltimusTest.java new file mode 100644 index 0000000000..cdaca04442 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/lgn/MistformUltimusTest.java @@ -0,0 +1,42 @@ +package org.mage.test.cards.single.lgn; + +import mage.abilities.keyword.HasteAbility; +import mage.constants.PhaseStep; +import mage.constants.SubType; +import mage.constants.Zone; +import org.junit.Ignore; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author TheElk801 + */ +public class MistformUltimusTest extends CardTestPlayerBase { + + private static final String ultimus = "Mistform Ultimus"; + private static final String chieftain = "Goblin Chieftain"; + private static final String gametrail = "Game-Trail Changeling"; + private static final String inversion = "Nameless Inversion"; + + @Test + public void testMistformUltimus() { + addCard(Zone.BATTLEFIELD, playerA, ultimus); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertSubtype(ultimus, SubType.GOBLIN); + } + + @Test + public void testGoblinChieftain() { + addCard(Zone.BATTLEFIELD, playerA, ultimus); + addCard(Zone.BATTLEFIELD, playerA, chieftain); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPowerToughness(playerA, ultimus, 4, 4); + assertAbility(playerA, ultimus, HasteAbility.getInstance(), true); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/thb/OneWithTheStarsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/thb/OneWithTheStarsTest.java new file mode 100644 index 0000000000..8f7dcb3859 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/thb/OneWithTheStarsTest.java @@ -0,0 +1,103 @@ +package org.mage.test.cards.single.thb; + +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.abilities.mana.AnyColorManaAbility; +import mage.constants.CardType; +import mage.constants.PhaseStep; +import mage.constants.SubType; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author TheElk801 + */ + +public class OneWithTheStarsTest extends CardTestPlayerBase { + + private static final String stars = "One with the Stars"; + private static final String knight = "Dragonsoul Knight"; + private static final String brute = "Gingerbrute"; + private static final String shrine = "Honden of Cleansing Fire"; + private static final String blossom = "Bitterblossom"; + + private void makeRainbowLand(int count) { + for (int i = 0; i < count; i++) { + addCustomCardWithAbility( + "Rainbow", playerA, new AnyColorManaAbility(), + null, CardType.LAND, "", Zone.BATTLEFIELD + ); + } + } + + @Test + public void testDragonsoulKnight() { + addCard(Zone.HAND, playerA, stars); + addCard(Zone.BATTLEFIELD, playerA, knight); + makeRainbowLand(9); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, stars, knight); + + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{W}{U}"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertType(knight, CardType.ENCHANTMENT, true); + assertType(knight, CardType.CREATURE, false); + assertNotSubtype(knight, SubType.HUMAN); + assertNotSubtype(knight, SubType.KNIGHT); + assertNotSubtype(knight, SubType.DRAGON); + assertAbility(playerA, knight, FlyingAbility.getInstance(), true); + assertAbility(playerA, knight, TrampleAbility.getInstance(), true); + } + + @Test + public void testGingerbrute() { + addCard(Zone.HAND, playerA, stars); + addCard(Zone.BATTLEFIELD, playerA, brute); + makeRainbowLand(4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, stars, brute); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertType(brute, CardType.ENCHANTMENT, true); + assertType(brute, CardType.ARTIFACT, false); + assertType(brute, CardType.CREATURE, false); + assertNotSubtype(brute, SubType.GOLEM); + assertNotSubtype(brute, SubType.FOOD); + } + + @Test + public void testShrine() { + addCard(Zone.HAND, playerA, stars); + addCard(Zone.BATTLEFIELD, playerA, shrine); + makeRainbowLand(4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, stars, shrine); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertType(shrine, CardType.ENCHANTMENT, SubType.SHRINE); + } + + @Test + public void testBitterblossom() { + addCard(Zone.HAND, playerA, stars); + addCard(Zone.BATTLEFIELD, playerA, blossom); + makeRainbowLand(4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, stars, blossom); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertType(blossom, CardType.ENCHANTMENT, true); + assertType(blossom, CardType.TRIBAL, false); + assertNotSubtype(blossom, SubType.FAERIE); + } +} 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 67b1ce7e49..a96a3a437d 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 @@ -1116,7 +1116,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement //Assert.assertNotEquals("", cardName); Permanent found = getPermanent(cardName); if (subType != null) { - Assert.assertFalse("(Battlefield) card sub-type equal (" + cardName + ':' + subType.getDescription() + ')', found.getSubtype(currentGame).contains(subType)); + Assert.assertFalse("(Battlefield) card sub-type equal (" + cardName + ':' + subType.getDescription() + ')', found.hasSubtype(subType, currentGame)); } } @@ -1130,7 +1130,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement //Assert.assertNotEquals("", cardName); Permanent found = getPermanent(cardName); if (subType != null) { - Assert.assertTrue("(Battlefield) card sub-type equal (" + cardName + ':' + subType.getDescription() + ')', found.getSubtype(currentGame).contains(subType)); + Assert.assertTrue("(Battlefield) card sub-type 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 bfa2123cbb..088d3e1189 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -4,6 +4,7 @@ import com.google.common.base.CharMatcher; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.effects.keyword.ScryEffect; +import mage.abilities.keyword.ChangelingAbility; import mage.abilities.keyword.MenaceAbility; import mage.abilities.keyword.MultikickerAbility; import mage.cards.*; @@ -108,9 +109,6 @@ public class VerifyCardDataTest { // subtype skipListCreate(SKIP_LIST_SUBTYPE); skipListAddName(SKIP_LIST_SUBTYPE, "UGL", "Miss Demeanor"); - skipListAddName(SKIP_LIST_SUBTYPE, "ZNR", "Veteran Adventurer"); // TODO: additional types must be added by effect, not direct? - skipListAddName(SKIP_LIST_SUBTYPE, "ZNR", "Stonework Packbeast"); // TODO: additional types must be added by effect, not direct? - skipListAddName(SKIP_LIST_SUBTYPE, "ZNR", "Tajuru Paragon"); // TODO: additional types must be added by effect, not direct? // number skipListCreate(SKIP_LIST_NUMBER); @@ -1252,6 +1250,10 @@ 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 fd55bb3893..59c99106ab 100644 --- a/Mage/src/main/java/mage/MageObject.java +++ b/Mage/src/main/java/mage/MageObject.java @@ -1,25 +1,25 @@ package mage; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - import mage.abilities.Abilities; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; -import mage.abilities.keyword.ChangelingAbility; import mage.abilities.text.TextPart; import mage.cards.Card; import mage.cards.FrameStyle; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.SubTypeSet; import mage.constants.SuperType; import mage.game.Game; import mage.game.events.ZoneChangeEvent; import mage.util.SubTypeList; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + public interface MageObject extends MageItem, Serializable { String getName(); @@ -126,6 +126,10 @@ public interface MageObject extends MageItem, Serializable { return getCardType().contains(CardType.PLANESWALKER); } + default boolean isTribal() { + return getCardType().contains(CardType.TRIBAL); + } + default boolean isPermanent() { return isCreature() || isArtifact() || isPlaneswalker() || isEnchantment() || isLand(); } @@ -139,6 +143,9 @@ public interface MageObject extends MageItem, Serializable { } default void addSuperType(SuperType superType) { + if (getSuperType().contains(superType)) { + return; + } getSuperType().add(superType); } @@ -151,9 +158,31 @@ public interface MageObject extends MageItem, Serializable { } default void addCardType(CardType cardType) { + if (getCardType().contains(cardType)) { + return; + } getCardType().add(cardType); } + default void addSubType(Game game, SubType... subTypes) { + for (SubType subType : subTypes) { + if (subType.canGain(this) + && !hasSubtype(subType, game)) { + getSubtype(game).add(subType); + } + } + } + + default void removeAllSubTypes(Game game) { + getSubtype(game).clear(); + setIsAllCreatureTypes(false); + } + + default void removeAllCreatureTypes(Game game) { + getSubtype(game).removeAll(SubType.getCreatureTypes()); + setIsAllCreatureTypes(false); + } + /** * Checks whether two cards share card types. * @@ -180,27 +209,36 @@ public interface MageObject extends MageItem, Serializable { return false; } - default boolean shareSubtypes(Card otherCard, Game game) { - - if (otherCard == null) { - throw new IllegalArgumentException("Params can't be null"); + default boolean shareCreatureTypes(Card otherCard, Game game) { + if (!isCreature() && !isTribal()) { + return false; } - - if (this.isCreature() && otherCard.isCreature()) { - if (this.hasAbility(ChangelingAbility.getInstance(), game) - || this.isAllCreatureTypes() - || otherCard.hasAbility(ChangelingAbility.getInstance(), game) - || otherCard.isAllCreatureTypes()) { - return true; - } + if (!otherCard.isCreature() && !otherCard.isTribal()) { + return false; } - for (SubType subtype : this.getSubtype(game)) { - if (otherCard.hasSubtype(subtype, game)) { - return true; - } + boolean isAllA = this.isAllCreatureTypes(); + boolean isAnyA = isAllA || this.getSubtype(game) + .stream() + .map(SubType::getSubTypeSet) + .anyMatch(SubTypeSet.CreatureType::equals); + boolean isAllB = otherCard.isAllCreatureTypes(); + boolean isAnyB = isAllB || otherCard + .getSubtype(game) + .stream() + .map(SubType::getSubTypeSet) + .anyMatch(SubTypeSet.CreatureType::equals); + if (!isAnyA || !isAnyB) { + return false; } - - return false; + if (isAllA) { + return isAllB || isAnyB; + } + return isAnyA + && (isAllB || this + .getSubtype(game) + .stream() + .filter(subType -> subType.getSubTypeSet() == SubTypeSet.CreatureType) + .anyMatch(subType -> otherCard.hasSubtype(subType, game))); } boolean isAllCreatureTypes(); diff --git a/Mage/src/main/java/mage/MageObjectImpl.java b/Mage/src/main/java/mage/MageObjectImpl.java index aa3792e486..9c737da894 100644 --- a/Mage/src/main/java/mage/MageObjectImpl.java +++ b/Mage/src/main/java/mage/MageObjectImpl.java @@ -1,7 +1,5 @@ package mage; -import java.util.*; - import mage.abilities.Abilities; import mage.abilities.AbilitiesImpl; import mage.abilities.Ability; @@ -11,7 +9,6 @@ import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; -import mage.abilities.keyword.ChangelingAbility; import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.text.TextPart; import mage.abilities.text.TextPartSubType; @@ -20,10 +17,11 @@ import mage.cards.mock.MockCard; import mage.constants.*; import mage.game.Game; import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; import mage.util.GameLog; import mage.util.SubTypeList; +import java.util.*; + public abstract class MageObjectImpl implements MageObject { protected UUID objectId; @@ -230,25 +228,10 @@ public abstract class MageObjectImpl implements MageObject { if (value == null) { return false; } - SubTypeList subtypes = this.getSubtype(game); - if (subtypes.contains(value)) { + if (value.getSubTypeSet() == SubTypeSet.CreatureType && isAllCreatureTypes()) { return true; - } else { - // checking for Changeling - // first make sure input parameter is a creature subtype - // if not, then ChangelingAbility doesn't matter - if (value.getSubTypeSet() != SubTypeSet.CreatureType) { - return false; - } - // as it is a creature subtype, then check the existence of Changeling - Abilities checkList; - if (this instanceof Permanent) { - checkList = ((Permanent) this).getAbilities(game); - } else { - checkList = abilities; - } - return checkList.contains(ChangelingAbility.getInstance()) || isAllCreatureTypes(); } + return getSubtype(game).contains(value); } @Override @@ -289,7 +272,7 @@ public abstract class MageObjectImpl implements MageObject { @Override public void setIsAllCreatureTypes(boolean value) { - isAllCreatureTypes = value; + isAllCreatureTypes = 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 6c28ca572f..c1c7aa687b 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.shareSubtypes(card, game)) { + if (sourcePermanent.shareCreatureTypes(card, game)) { 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/common/AttachedToCreatureSourceTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AttachedToCreatureSourceTriggeredAbility.java index 1387a45d9c..b6d216230b 100644 --- a/Mage/src/main/java/mage/abilities/common/AttachedToCreatureSourceTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AttachedToCreatureSourceTriggeredAbility.java @@ -7,10 +7,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import static mage.constants.CardType.CREATURE; - /** - * * @author htrajan */ public class AttachedToCreatureSourceTriggeredAbility extends TriggeredAbilityImpl { @@ -33,7 +30,7 @@ public class AttachedToCreatureSourceTriggeredAbility extends TriggeredAbilityIm @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent attachedPermanent = game.getPermanent(event.getTargetId()); - return attachedPermanent != null && attachedPermanent.getCardType().contains(CREATURE); + return attachedPermanent != null && attachedPermanent.isCreature(); } @Override diff --git a/Mage/src/main/java/mage/abilities/common/LicidAbility.java b/Mage/src/main/java/mage/abilities/common/LicidAbility.java index e5aae7688f..96fd32d097 100644 --- a/Mage/src/main/java/mage/abilities/common/LicidAbility.java +++ b/Mage/src/main/java/mage/abilities/common/LicidAbility.java @@ -1,8 +1,5 @@ package mage.abilities.common; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.SpecialAction; @@ -15,22 +12,18 @@ import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.CreateSpecialActionEffect; import mage.abilities.effects.common.RemoveSpecialActionEffect; import mage.abilities.keyword.EnchantAbility; -import mage.constants.CardType; -import mage.constants.DependencyType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.SubType; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** - * * @author emerald000 */ public class LicidAbility extends ActivatedAbilityImpl { @@ -116,8 +109,8 @@ class LicidContinuousEffect extends ContinuousEffectImpl { case TypeChangingEffects_4: licid.getCardType().clear(); licid.addCardType(CardType.ENCHANTMENT); - licid.getSubtype(game).clear(); - licid.getSubtype(game).add(SubType.AURA); + licid.removeAllSubTypes(game); + licid.addSubType(game, SubType.AURA); break; case AbilityAddingRemovingEffects_6: List toRemove = new ArrayList<>(); 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 ae3f6c5e86..c857261bac 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java @@ -103,10 +103,11 @@ public class CopyEffect extends ContinuousEffectImpl { for (CardType type : copyFromObject.getCardType()) { permanent.addCardType(type); } - permanent.getSubtype(game).clear(); - for (SubType type : copyFromObject.getSubtype(game)) { - permanent.getSubtype(game).add(type); - } + + permanent.removeAllSubTypes(game); + permanent.getSubtype(game).addAll(copyFromObject.getSubtype(game)); + permanent.setIsAllCreatureTypes(copyFromObject.isAllCreatureTypes()); + permanent.getSuperType().clear(); for (SuperType type : copyFromObject.getSuperType()) { permanent.addSuperType(type); 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 d5de78070d..833f89e999 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java @@ -31,10 +31,11 @@ public class CopyTokenEffect extends ContinuousEffectImpl { for (CardType type : token.getCardType()) { permanent.addCardType(type); } - permanent.getSubtype(game).clear(); + permanent.removeAllSubTypes(game); for (SubType type : token.getSubtype(game)) { - permanent.getSubtype(game).add(type); + permanent.addSubType(game, type); } + permanent.setIsAllCreatureTypes(token.isAllCreatureTypes()); 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 3b01e3e4be..f6f1a2dd03 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java @@ -1,10 +1,5 @@ package mage.abilities.effects.common; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; - import mage.MageObject; import mage.ObjectColor; import mage.abilities.Ability; @@ -25,6 +20,11 @@ import mage.util.CardUtil; import mage.util.functions.ApplyToPermanent; import mage.util.functions.EmptyApplyToPermanent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + /** * @author LevelX2 */ @@ -179,10 +179,10 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { token.getSuperType().remove(SuperType.LEGENDARY); } - if (startingLoyalty!=-1){ + if (startingLoyalty != -1) { token.setStartingLoyalty(startingLoyalty); } - if (additionalCardType != null && !token.getCardType().contains(additionalCardType)) { + if (additionalCardType != null) { token.addCardType(additionalCardType); } if (hasHaste) { @@ -199,12 +199,12 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { token.removePTCDA(); token.getToughness().modifyBaseValue(tokenToughness); } - if (additionalSubType != null && !token.hasSubtype(additionalSubType, game)) { - token.getSubtype(game).add(additionalSubType); + if (onlySubType != null) { + token.removeAllCreatureTypes(game); + token.addSubType(game, onlySubType); } - if (onlySubType != null && !token.hasSubtype(onlySubType, game)) { - token.getSubtype(game).clear(); - token.getSubtype(game).add(onlySubType); + if (additionalSubType != null && !token.hasSubtype(additionalSubType, game)) { + token.addSubType(game, additionalSubType); } if (color != null) { token.getColor(game).setColor(color); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java index e013d1b60e..cd0835983d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java @@ -29,9 +29,7 @@ public class AddCardSubTypeTargetEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { Permanent target = game.getPermanent(targetPointer.getFirst(game, source)); if (target != null) { - if (!target.hasSubtype(addedSubType, game)) { - target.getSubtype(game).add(addedSubType); - } + target.addSubType(game, addedSubType); } else { if (duration == Duration.Custom) { discard(); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAllEffect.java index 66bfc9bf0a..a35c0a5af1 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAllEffect.java @@ -35,8 +35,8 @@ public class AddCardSubtypeAllEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - if (perm != null && !perm.hasSubtype(addedSubtype, game)) { - perm.getSubtype(game).add(addedSubtype); + if (perm != null) { + perm.addSubType(game, addedSubtype); } } return true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java index a98ade7d82..18bf9b5d70 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java @@ -33,8 +33,8 @@ public class AddCardSubtypeAttachedEffect extends ContinuousEffectImpl { Permanent equipment = game.getPermanent(source.getSourceId()); if (equipment != null && equipment.getAttachedTo() != null) { Permanent target = game.getPermanent(equipment.getAttachedTo()); - if (target != null && !target.hasSubtype(addedSubtype, game)) - target.getSubtype(game).add(addedSubtype); + if (target != null) + target.addSubType(game, addedSubtype); } return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeAttachedEffect.java index a09b001d53..edc0e7f5ef 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeAttachedEffect.java @@ -33,7 +33,7 @@ public class AddCardTypeAttachedEffect extends ContinuousEffectImpl { Permanent equipment = game.getPermanent(source.getSourceId()); if (equipment != null && equipment.getAttachedTo() != null) { Permanent target = game.getPermanent(equipment.getAttachedTo()); - if (target != null && !target.getCardType().contains(addedCardType)) { + if (target != null) { target.addCardType(addedCardType); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java index 00892f24aa..08ce421fea 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java @@ -1,8 +1,5 @@ - package mage.abilities.effects.common.continuous; -import java.util.ArrayList; -import java.util.Locale; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.Mode; @@ -11,6 +8,9 @@ import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.Locale; + /** * @author emerald000 */ @@ -46,9 +46,7 @@ public class AddCardTypeSourceEffect extends ContinuousEffectImpl { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null && affectedObjectList.contains(new MageObjectReference(permanent, game))) { for (CardType cardType : addedCardTypes) { - if (!permanent.getCardType().contains(cardType)) { - permanent.addCardType(cardType); - } + permanent.addCardType(cardType); } return true; } else if (this.getDuration() == Duration.Custom) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java index b8f0933039..f5fc9f611a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java @@ -1,20 +1,15 @@ - package mage.abilities.effects.common.continuous; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; + import java.util.ArrayList; import java.util.Locale; import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.Mode; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.constants.CardType; -import mage.constants.DependencyType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.game.Game; -import mage.game.permanent.Permanent; /** * @author nantuko @@ -48,9 +43,7 @@ public class AddCardTypeTargetEffect extends ContinuousEffectImpl { Permanent target = game.getPermanent(targetId); if (target != null) { for (CardType cardType : addedCardTypes) { - if (!target.getCardType().contains(cardType)) { - target.addCardType(cardType); - } + target.addCardType(cardType); } result = true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java index cf8c158d7b..1a6a44e2be 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java @@ -23,8 +23,8 @@ public class AddChosenSubtypeEffect extends ContinuousEffectImpl { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(permanent.getId(), game); - if (subType != null && !permanent.hasSubtype(subType, game)) { - permanent.getSubtype(game).add(subType); + if (subType != null) { + permanent.addSubType(game, subType); } } return true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java index 592f3cc64c..411c4045a6 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java @@ -14,7 +14,7 @@ import mage.game.permanent.Permanent; public class BecomesAllBasicsControlledEffect extends ContinuousEffectImpl { public BecomesAllBasicsControlledEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); this.staticText = "Lands you control are every basic land type in addition to their other types"; dependencyTypes.add(DependencyType.BecomeMountain); dependencyTypes.add(DependencyType.BecomeForest); @@ -27,65 +27,29 @@ public class BecomesAllBasicsControlledEffect extends ContinuousEffectImpl { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public BecomesAllBasicsControlledEffect copy() { return new BecomesAllBasicsControlledEffect(this); } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { for (Permanent permanent : game.getBattlefield().getActivePermanents( StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, source.getControllerId(), game)) { - switch (layer) { - case TypeChangingEffects_4: - if (!permanent.hasSubtype(SubType.SWAMP, game)) { - permanent.getSubtype(game).add(SubType.SWAMP); - } - if (!permanent.hasSubtype(SubType.MOUNTAIN, game)) { - permanent.getSubtype(game).add(SubType.MOUNTAIN); - } - if (!permanent.hasSubtype(SubType.FOREST, game)) { - permanent.getSubtype(game).add(SubType.FOREST); - } - if (!permanent.hasSubtype(SubType.ISLAND, game)) { - permanent.getSubtype(game).add(SubType.ISLAND); - } - if (!permanent.hasSubtype(SubType.PLAINS, game)) { - permanent.getSubtype(game).add(SubType.PLAINS); - } - if (permanent.hasSubtype(SubType.SWAMP, game) - && !permanent.getAbilities().containsRule(new BlackManaAbility())) { - permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game); - } - if (permanent.hasSubtype(SubType.MOUNTAIN, game) - && !permanent.getAbilities().containsRule(new RedManaAbility())) { - permanent.addAbility(new RedManaAbility(), source.getSourceId(), game); - } - if (permanent.hasSubtype(SubType.FOREST, game) - && !permanent.getAbilities().containsRule(new GreenManaAbility())) { - permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } - if (permanent.hasSubtype(SubType.ISLAND, game) - && !permanent.getAbilities().containsRule(new BlueManaAbility())) { - permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - if (permanent.hasSubtype(SubType.PLAINS, game) - && !permanent.getAbilities().containsRule(new WhiteManaAbility())) { - permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - } - break; - } + permanent.addSubType( + game, + SubType.PLAINS, + SubType.ISLAND, + SubType.SWAMP, + SubType.MOUNTAIN, + SubType.FOREST + ); + permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game); + permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game); + permanent.addAbility(new RedManaAbility(), source.getSourceId(), game); + permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); } return true; } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java index af5fdfba2a..49b8bd9021 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java @@ -5,18 +5,12 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.keyword.EnchantAbility; -import mage.constants.DependencyType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.SubType; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; /** - * * @author LevelX2 */ public class BecomesAuraSourceEffect extends ContinuousEffectImpl implements SourceEffect { @@ -58,9 +52,7 @@ public class BecomesAuraSourceEffect extends ContinuousEffectImpl implements Sou switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - if (!permanent.hasSubtype(SubType.AURA, game)) { - permanent.getSubtype(game).add(SubType.AURA); - } + permanent.addSubType(game, SubType.AURA); } break; case AbilityAddingRemovingEffects_6: 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 54b223b032..d7b789d6ca 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 @@ -16,7 +16,7 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl { protected List landTypes = new ArrayList<>(); public BecomesBasicLandEnchantedEffect(SubType... landNames) { - super(Duration.WhileOnBattlefield, Outcome.Detriment); + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); landTypes.addAll(Arrays.asList(landNames)); this.staticText = setText(); } @@ -26,68 +26,55 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl { this.landTypes.addAll(effect.landTypes); } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public BecomesBasicLandEnchantedEffect copy() { return new BecomesBasicLandEnchantedEffect(this); } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null && enchantment.getAttachedTo() != null) { - Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - // 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.removeAllAbilities(source.getSourceId(), game); - for (SubType landType : landTypes) { - switch (landType) { - case SWAMP: - if (permanent.hasSubtype(SubType.SWAMP, game)) { - permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game); - } - break; - case MOUNTAIN: - if (permanent.hasSubtype(SubType.MOUNTAIN, game)) { - permanent.addAbility(new RedManaAbility(), source.getSourceId(), game); - } - break; - case FOREST: - if (permanent.hasSubtype(SubType.FOREST, game)) { - permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } - break; - case ISLAND: - if (permanent.hasSubtype(SubType.ISLAND, game)) { - permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - break; - case PLAINS: - if (permanent.hasSubtype(SubType.PLAINS, game)) { - permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - } - break; - } - } - break; - } - return true; + if (enchantment == null || enchantment.getAttachedTo() == null) { + return false; + } + Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); + if (permanent == null) { + 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.removeAllAbilities(source.getSourceId(), game); + for (SubType landType : landTypes) { + switch (landType) { + case PLAINS: + if (permanent.hasSubtype(SubType.PLAINS, game)) { + permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + } + break; + case ISLAND: + if (permanent.hasSubtype(SubType.ISLAND, game)) { + permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game); + } + break; + case SWAMP: + if (permanent.hasSubtype(SubType.SWAMP, game)) { + permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game); + } + break; + case MOUNTAIN: + if (permanent.hasSubtype(SubType.MOUNTAIN, game)) { + permanent.addAbility(new RedManaAbility(), source.getSourceId(), game); + } + break; + case FOREST: + if (permanent.hasSubtype(SubType.FOREST, game)) { + permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); + } + break; } } - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; + return true; } private String setText() { 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 1dde326c6b..dd30acc1ff 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 @@ -123,7 +123,7 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl { landTypesToAdd.clear(); for (SubType subtype : landTypes) { if (!land.hasSubtype(subtype, game)) { - land.getSubtype(game).add(subtype); + land.addSubType(game, subtype); landTypesToAdd.add(subtype); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBlackZombieAdditionEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBlackZombieAdditionEffect.java index 6e448439b1..17ddab7d19 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBlackZombieAdditionEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBlackZombieAdditionEffect.java @@ -60,14 +60,10 @@ public class BecomesBlackZombieAdditionEffect extends ContinuousEffectImpl { if (creature != null) { switch (layer) { case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - if (!creature.hasSubtype(SubType.ZOMBIE, game)) { - creature.getSubtype(game).add(SubType.ZOMBIE); - } - } + creature.addSubType(game, SubType.ZOMBIE); break; case ColorChangingEffects_5: - if (sublayer == SubLayer.NA && this.giveBlackColor) { + if (this.giveBlackColor) { creature.getColor(game).setBlack(true); } break; 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 66d103472c..ba392ef745 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 @@ -25,18 +25,18 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl { private boolean loseTypes = false; protected boolean loseName = false; - public BecomesCreatureAllEffect(Token token, String theyAreStillType, - FilterPermanent filter, Duration duration, boolean loseColor) { + public BecomesCreatureAllEffect(Token token, String theyAreStillType, + FilterPermanent filter, Duration duration, boolean loseColor) { this(token, theyAreStillType, filter, duration, loseColor, false, false); } - public BecomesCreatureAllEffect(Token token, String theyAreStillType, - FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName) { + public BecomesCreatureAllEffect(Token token, String theyAreStillType, + FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName) { this(token, theyAreStillType, filter, duration, loseColor, loseName, false); } - public BecomesCreatureAllEffect(Token token, String theyAreStillType, - FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName, boolean loseTypes) { + public BecomesCreatureAllEffect(Token token, String theyAreStillType, + FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName, boolean loseTypes) { super(duration, Outcome.BecomeCreature); this.token = token; this.theyAreStillType = theyAreStillType; @@ -44,7 +44,7 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl { this.loseColor = loseColor; this.loseName = loseName; this.loseTypes = loseTypes; - + this.dependencyTypes.add(DependencyType.BecomeCreature); } @@ -87,83 +87,67 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl { } for (Permanent permanent : affectedPermanents) { - if (permanent != null) { - switch (layer) { - case TextChangingEffects_3: - if (sublayer == SubLayer.NA) { - if (loseName) { - permanent.setName(token.getName()); - } + if (permanent == null) { + continue; + } + switch (layer) { + case TextChangingEffects_3: + if (loseName) { + permanent.setName(token.getName()); + } + break; + + case TypeChangingEffects_4: + for (CardType t : token.getCardType()) { + permanent.addCardType(t); + } + if (theyAreStillType != null || loseTypes) { + permanent.removeAllCreatureTypes(game); + } + for (SubType t : token.getSubtype(game)) { + permanent.addSubType(game, t); + } + permanent.setIsAllCreatureTypes(token.isAllCreatureTypes()); + + for (SuperType t : token.getSuperType()) { + if (!permanent.getSuperType().contains(t)) { + permanent.addSuperType(t); } - break; + } - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - if (theyAreStillType != null) { - permanent.getSubtype(game).retainAll(SubType.getLandTypes()); - permanent.getSubtype(game).addAll(token.getSubtype(game)); - } else { - if (loseTypes) { - permanent.getSubtype(game).retainAll(SubType.getLandTypes()); - } + break; - for (SubType t : token.getSubtype(game)) { - if (!permanent.hasSubtype(t, game)) { - permanent.getSubtype(game).add(t); - } - } - } + case ColorChangingEffects_5: + if (this.loseColor) { + 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; - for (SuperType t : token.getSuperType()) { - if (!permanent.getSuperType().contains(t)) { - permanent.addSuperType(t); - } - } - - for (CardType t : token.getCardType()) { - if (!permanent.getCardType().contains(t)) { - permanent.addCardType(t); - } - } + case AbilityAddingRemovingEffects_6: + if (!token.getAbilities().isEmpty()) { + for (Ability ability : token.getAbilities()) { + permanent.addAbility(ability, source.getSourceId(), game); } - break; + } + break; - case ColorChangingEffects_5: - if (sublayer == SubLayer.NA) { - if (this.loseColor) { - permanent.getColor(game).setBlack(false); - permanent.getColor(game).setGreen(false); - permanent.getColor(game).setBlue(false); - permanent.getColor(game).setWhite(false); - permanent.getColor(game).setRed(false); - } - if (token.getColor(game).hasColor()) { - permanent.getColor(game).addColor(token.getColor(game)); - } + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + int power = token.getPower().getValue(); + int toughness = token.getToughness().getValue(); + if (power != 0 && toughness != 0) { + permanent.getPower().setValue(power); + permanent.getToughness().setValue(toughness); } - break; - - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - if (!token.getAbilities().isEmpty()) { - for (Ability ability : token.getAbilities()) { - permanent.addAbility(ability, source.getSourceId(), game); - } - } - } - break; - - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - int power = token.getPower().getValue(); - int toughness = token.getToughness().getValue(); - if (power != 0 && toughness != 0) { - permanent.getPower().setValue(power); - permanent.getToughness().setValue(toughness); - } - } - break; - } + } + break; } } return true; 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 cb9ec1db5b..5369d5465a 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 @@ -78,19 +78,14 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl { switch (loseType) { case ALL: case ALL_BUT_COLOR: + permanent.removeAllSubTypes(game); + break; case ABILITIES_SUBTYPE: - if (permanent.isLand()) { - permanent.getSubtype(game).retainAll(SubType.getLandTypes()); - } else { - permanent.getSubtype(game).clear(); - } - permanent.setIsAllCreatureTypes(false); + permanent.removeAllCreatureTypes(game); break; } for (SubType t : token.getSubtype(game)) { - if (!permanent.hasSubtype(t, game)) { - permanent.getSubtype(game).add(t); - } + permanent.addSubType(game, t); } } break; @@ -98,11 +93,11 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl { case ColorChangingEffects_5: if (sublayer == SubLayer.NA) { if (loseType == LoseType.ALL || loseType == LoseType.COLOR) { - permanent.getColor(game).setBlack(false); - permanent.getColor(game).setGreen(false); - permanent.getColor(game).setBlue(false); 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)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java index e7727fe2b6..af09a5bbfb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java @@ -1,42 +1,33 @@ package mage.abilities.effects.common.continuous; -import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.constants.*; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Duration; +import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.Token; +import mage.target.targetpointer.FixedTarget; /** * @author jeffwadsworth */ -public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends ContinuousEffectImpl { +public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends OneShotEffect { - public enum LoseType { - NONE, ALL, ALL_BUT_COLOR, ABILITIES, ABILITIES_SUBTYPE_AND_PT - } - - protected Token token; - protected String type; - protected LoseType loseType; // what attributes are lost + private final Token token; + private final Duration duration; public BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect(Token token, String text, Duration duration) { - this(token, text, duration, LoseType.NONE); - } - - public BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect(Token token, String text, Duration duration, LoseType loseType) { - super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature); - this.token = token; - this.loseType = loseType; + super(Outcome.BecomeCreature); staticText = text; + this.token = token; + this.duration = duration; } public BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect(final BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect effect) { super(effect); this.token = effect.token.copy(); - this.type = effect.type; - this.loseType = effect.loseType; + this.duration = effect.duration; } @Override @@ -44,122 +35,19 @@ public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends Co return new BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect(this); } - @Override - public void init(Ability source, Game game) { - super.init(source, game); - Permanent attachedPermanent = game.getPermanent(source.getSourceId()); - if (attachedPermanent != null) { - Permanent permanentAttachedTo = game.getPermanent(attachedPermanent.getAttachedTo()); - if (permanentAttachedTo != null) { - affectedObjectList.add(new MageObjectReference(permanentAttachedTo, game)); - } - } - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - boolean attachedExists = false; - Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null) { - for (MageObjectReference mageObjectReference : affectedObjectList) { - Permanent permanentAttachedTo = mageObjectReference.getPermanent(game); - if (permanentAttachedTo != null) { - attachedExists = true; - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - for (SuperType superType : token.getSuperType()) { - permanentAttachedTo.addSuperType(superType); - - } - // card type - switch (loseType) { - case ALL: - case ALL_BUT_COLOR: - permanentAttachedTo.getCardType().clear(); - break; - } - for (CardType cardType : token.getCardType()) { - permanentAttachedTo.addCardType(cardType); - } - - // sub type - switch (loseType) { - case ALL: - case ALL_BUT_COLOR: - case ABILITIES_SUBTYPE_AND_PT: - permanentAttachedTo.getSubtype(game).retainAll(SubType.getLandTypes()); - break; - } - for (SubType subType : token.getSubtype(game)) { - if (!permanentAttachedTo.hasSubtype(subType, game)) { - permanentAttachedTo.getSubtype(game).add(subType); - } - } - - } - break; - - case ColorChangingEffects_5: - if (sublayer == SubLayer.NA) { - if (loseType == LoseType.ALL) { - permanentAttachedTo.getColor(game).setBlack(false); - permanentAttachedTo.getColor(game).setGreen(false); - permanentAttachedTo.getColor(game).setBlue(false); - permanentAttachedTo.getColor(game).setWhite(false); - permanentAttachedTo.getColor(game).setRed(false); - } - if (token.getColor(game).hasColor()) { - permanentAttachedTo.getColor(game).setColor(token.getColor(game)); - } - } - break; - - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - switch (loseType) { - case ALL: - case ALL_BUT_COLOR: - case ABILITIES: - case ABILITIES_SUBTYPE_AND_PT: - permanentAttachedTo.removeAllAbilities(source.getSourceId(), game); - break; - } - for (Ability ability : token.getAbilities()) { - permanentAttachedTo.addAbility(ability, source.getSourceId(), game); - } - - } - break; - - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - permanentAttachedTo.getPower().setValue(token.getPower().getValue()); - permanentAttachedTo.getToughness().setValue(token.getToughness().getValue()); - } - break; - } - } - if (!attachedExists) { - discard(); - } - return true; - } - } - return false; - } - @Override public boolean apply(Game game, Ability source) { - return false; + Permanent permanent = source.getSourcePermanentOrLKI(game); + if (permanent == null) { + return false; + } + Permanent enchanted = game.getPermanent(permanent.getAttachedTo()); + if (enchanted == null) { + return false; + } + game.addEffect(new BecomesCreatureTargetEffect( + token, false, true, duration + ).setTargetPointer(new FixedTarget(enchanted, game)), source); + return true; } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.PTChangingEffects_7 - || layer == Layer.AbilityAddingRemovingEffects_6 - || layer == Layer.ColorChangingEffects_5 - || layer == Layer.TypeChangingEffects_4; - } - } 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 882d828e6a..ab88478ab1 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 @@ -82,78 +82,66 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements } else { permanent = game.getPermanent(source.getSourceId()); } - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - if (losePreviousTypes) { - permanent.getCardType().clear(); - } - for (CardType cardType : token.getCardType()) { - if (permanent.getCardType().contains(cardType)) { - continue; - } - permanent.addCardType(cardType); - } - - if (theyAreStillType != null && theyAreStillType.isEmpty() || theyAreStillType == null && permanent.isLand()) { - permanent.getSubtype(game).retainAll(SubType.getLandTypes()); - } - if (!token.getSubtype(game).isEmpty()) { - for (SubType subType : token.getSubtype(game)) { - if (permanent.hasSubtype(subType, game)) { - continue; - } - permanent.getSubtype(game).add(subType); - } - } - permanent.setIsAllCreatureTypes(token.isAllCreatureTypes()); - } - break; - - case ColorChangingEffects_5: - if (sublayer == SubLayer.NA) { - if (token.getColor(game).hasColor()) { - permanent.getColor(game).setColor(token.getColor(game)); - } - } - break; - - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - if (loseAbilities) { - permanent.removeAllAbilities(source.getSourceId(), game); - } - for (Ability ability : token.getAbilities()) { - permanent.addAbility(ability, source.getSourceId(), game); - } - } - break; - - case PTChangingEffects_7: - if ((sublayer == SubLayer.CharacteristicDefining_7a && isCharacterDefining()) - || (sublayer == SubLayer.SetPT_7b && !isCharacterDefining())) { - if (power != null) { - permanent.getPower().setValue(power.calculate(game, source, this)); // check all other becomes to use calculate? - } else if (token.getPower() != null) { - permanent.getPower().setValue(token.getPower().getValue()); - } - if (toughness != null) { - permanent.getToughness().setValue(toughness.calculate(game, source, this)); - } else if (token.getToughness() != null) { - permanent.getToughness().setValue(token.getToughness().getValue()); - } - } - break; + if (permanent == null) { + if (duration == Duration.Custom) { + this.discard(); } + return false; + } + switch (layer) { + case TypeChangingEffects_4: + if (losePreviousTypes) { + permanent.getCardType().clear(); + } + for (CardType cardType : token.getCardType()) { + permanent.addCardType(cardType); + } - return true; + if (theyAreStillType != null && theyAreStillType.isEmpty() + || 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()); + break; - } else if (duration == Duration.Custom) { - this.discard(); + case ColorChangingEffects_5: + if (token.getColor(game).hasColor()) { + permanent.getColor(game).setColor(token.getColor(game)); + } + break; + + case AbilityAddingRemovingEffects_6: + if (loseAbilities) { + permanent.removeAllAbilities(source.getSourceId(), game); + } + for (Ability ability : token.getAbilities()) { + permanent.addAbility(ability, source.getSourceId(), game); + } + break; + + case PTChangingEffects_7: + if ((sublayer == SubLayer.CharacteristicDefining_7a && isCharacterDefining()) + || (sublayer == SubLayer.SetPT_7b && !isCharacterDefining())) { + if (power != null) { + permanent.getPower().setValue(power.calculate(game, source, this)); // check all other becomes to use calculate? + } else if (token.getPower() != null) { + permanent.getPower().setValue(token.getPower().getValue()); + } + if (toughness != null) { + permanent.getToughness().setValue(toughness.calculate(game, source, this)); + } else if (token.getToughness() != null) { + permanent.getToughness().setValue(token.getToughness().getValue()); + } + } + break; } - return false; + return true; } @Override @@ -171,7 +159,10 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements @Override public boolean hasLayer(Layer layer) { - return layer == Layer.PTChangingEffects_7 || layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4; + return layer == Layer.PTChangingEffects_7 + || layer == Layer.AbilityAddingRemovingEffects_6 + || layer == Layer.ColorChangingEffects_5 + || layer == Layer.TypeChangingEffects_4; } } 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 dfcabb361b..630d301301 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 @@ -70,82 +70,68 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl { boolean result = false; for (UUID permanentId : targetPointer.getTargets(game, source)) { Permanent permanent = game.getPermanent(permanentId); - if (permanent != null) { - switch (layer) { - case TextChangingEffects_3: - if (sublayer == SubLayer.NA) { - if (loseName) { - permanent.setName(token.getName()); - } - } - break; - - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - if (loseAllAbilities) { - permanent.getSubtype(game).retainAll(SubType.getLandTypes()); - permanent.getCardType().clear(); // remove all CardTypes - permanent.getSubtype(game).addAll(token.getSubtype(game)); - } else { - if (removeSubtypes) { - permanent.getSubtype(game).clear(); - } - for (SubType t : token.getSubtype(game)) { - if (!permanent.hasSubtype(t, game)) { - permanent.getSubtype(game).add(t); - } - } - } - - for (SuperType t : token.getSuperType()) { - if (!permanent.getSuperType().contains(t)) { - permanent.addSuperType(t); - } - } - - for (CardType t : token.getCardType()) { - if (!permanent.getCardType().contains(t)) { - permanent.addCardType(t); - } - } - } - break; - - case ColorChangingEffects_5: - if (sublayer == SubLayer.NA) { - if (loseAllAbilities) { - permanent.getColor(game).setBlack(false); - permanent.getColor(game).setGreen(false); - permanent.getColor(game).setBlue(false); - permanent.getColor(game).setWhite(false); - permanent.getColor(game).setBlack(false); - } - if (token.getColor(game).hasColor()) { - permanent.getColor(game).setColor(token.getColor(game)); - } - } - break; - - case AbilityAddingRemovingEffects_6: - if (loseAllAbilities && !keepAbilities) { - permanent.removeAllAbilities(source.getSourceId(), game); - } - if (sublayer == SubLayer.NA) { - if (!token.getAbilities().isEmpty()) { - for (Ability ability : token.getAbilities()) { - permanent.addAbility(ability, source.getSourceId(), game); - } - } - } - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { // CDA can only define a characteristic of either the card or token it comes from. - permanent.getToughness().setValue(token.getToughness().getValue()); - permanent.getPower().setValue(token.getPower().getValue()); - } - } - result = true; + if (permanent == null) { + continue; } + switch (layer) { + case TextChangingEffects_3: + if (loseName) { + permanent.setName(token.getName()); + } + break; + + case TypeChangingEffects_4: + for (CardType t : token.getCardType()) { + permanent.addCardType(t); + } + if (loseAllAbilities || removeSubtypes) { + permanent.removeAllCreatureTypes(game); + } + for (SubType t : token.getSubtype(game)) { + permanent.addSubType(game, t); + } + + for (SuperType t : token.getSuperType()) { + if (!permanent.getSuperType().contains(t)) { + permanent.addSuperType(t); + } + } + + break; + + case ColorChangingEffects_5: + if (loseAllAbilities) { + 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).setColor(token.getColor(game)); + } + break; + + case AbilityAddingRemovingEffects_6: + if (loseAllAbilities && !keepAbilities) { + permanent.removeAllAbilities(source.getSourceId(), game); + } + if (sublayer == SubLayer.NA) { + if (!token.getAbilities().isEmpty()) { + for (Ability ability : token.getAbilities()) { + permanent.addAbility(ability, source.getSourceId(), game); + } + } + } + break; + + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { // CDA can only define a characteristic of either the card or token it comes from. + permanent.getToughness().setValue(token.getToughness().getValue()); + permanent.getPower().setValue(token.getPower().getValue()); + } + } + result = true; } if (!result && this.duration == Duration.Custom) { this.discard(); 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 44ddd08cd9..68a8b7deea 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 @@ -1,8 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package mage.abilities.effects.common.continuous; import mage.abilities.Ability; @@ -19,15 +14,15 @@ import java.util.UUID; */ public class BecomesCreatureTypeTargetEffect extends ContinuousEffectImpl { - protected SubTypeList subtypes = new SubTypeList(); - protected boolean loseOther; // loses other creature types + private final SubTypeList subtypes = new SubTypeList(); + private final boolean loseOther; // loses other creature types public BecomesCreatureTypeTargetEffect(Duration duration, SubType subtype) { - this(duration, createArrayList(subtype)); + this(duration, new SubTypeList(subtype)); } public BecomesCreatureTypeTargetEffect(Duration duration, SubType subtype, boolean loseOther) { - this(duration, createArrayList(subtype), loseOther); + this(duration, new SubTypeList(subtype), loseOther); } public BecomesCreatureTypeTargetEffect(Duration duration, SubTypeList subtypes) { @@ -35,67 +30,45 @@ public class BecomesCreatureTypeTargetEffect extends ContinuousEffectImpl { } public BecomesCreatureTypeTargetEffect(Duration duration, SubTypeList subtypes, boolean loseOther) { - super(duration, Outcome.Detriment); - this.subtypes = subtypes; + super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); + this.subtypes.addAll(subtypes); this.staticText = setText(); this.loseOther = loseOther; } - private static SubTypeList createArrayList(SubType subtype) { - SubTypeList subtypes = new SubTypeList(); - subtypes.add(subtype); - return subtypes; - } - public BecomesCreatureTypeTargetEffect(final BecomesCreatureTypeTargetEffect effect) { super(effect); this.subtypes.addAll(effect.subtypes); this.loseOther = effect.loseOther; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public BecomesCreatureTypeTargetEffect copy() { return new BecomesCreatureTypeTargetEffect(this); } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { + boolean flag = false; for (UUID targetPermanent : targetPointer.getTargets(game, source)) { Permanent permanent = game.getPermanent(targetPermanent); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (loseOther) { - permanent.getSubtype(game).retainAll(SubType.getLandTypes()); - permanent.getSubtype(game).addAll(subtypes); - } else { - for (SubType subtype : subtypes) { - if (!permanent.hasSubtype(subtype, game)) { - permanent.getSubtype(game).add(subtype); - } - } - } - break; - } - } else { - if (duration == Duration.Custom) { - discard(); - } + if (permanent == null) { + continue; + } + flag = true; + if (loseOther) { + permanent.removeAllCreatureTypes(game); + } + for (SubType subtype : subtypes) { + permanent.addSubType(game, subtype); } } + if (!flag && duration == Duration.Custom) { + discard(); + } return true; } - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } - private String setText() { StringBuilder sb = new StringBuilder(); sb.append("Target creature becomes that type"); 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 064e11c4a0..35d94fe5e9 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 @@ -1,33 +1,21 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package mage.abilities.effects.common.continuous; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; -import mage.constants.CardType; -import mage.constants.DependencyType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; /** - * * @author jeffwadsworth */ public class BecomesEnchantmentSourceEffect extends ContinuousEffectImpl implements SourceEffect { public BecomesEnchantmentSourceEffect() { - super(Duration.Custom, Outcome.AddAbility); + super(Duration.Custom, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.AddAbility); staticText = "{this} becomes an Enchantment"; dependencyTypes.add(DependencyType.EnchantmentAddingRemoving); - } public BecomesEnchantmentSourceEffect(final BecomesEnchantmentSourceEffect effect) { @@ -45,35 +33,17 @@ public class BecomesEnchantmentSourceEffect extends ContinuousEffectImpl impleme affectedObjectList.add(new MageObjectReference(source.getSourceId(), game)); } - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent = affectedObjectList.get(0).getPermanent(game); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.getCardType().clear(); - permanent.getSubtype(game).clear(); - if (!permanent.getCardType().contains(CardType.ENCHANTMENT)) { - permanent.getCardType().add(CardType.ENCHANTMENT); - } - } - break; - } - return true; - } - this.discard(); - return false; - } - @Override public boolean apply(Game game, Ability source) { - return false; + Permanent permanent = affectedObjectList.get(0).getPermanent(game); + if (permanent == null) { + this.discard(); + return false; + } + permanent.getCardType().clear(); + permanent.getCardType().add(CardType.ENCHANTMENT); + permanent.getSubtype(game).retainAll(SubType.getEnchantmentTypes()); + permanent.setIsAllCreatureTypes(false); + return true; } - - @Override - public boolean hasLayer(Layer layer) { - return Layer.TypeChangingEffects_4 == layer; - } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java index 202788360b..8b01f0fbc1 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java @@ -75,7 +75,7 @@ public class BecomesFaceDownCreatureAllEffect extends ContinuousEffectImpl imple permanent.getSuperType().clear(); permanent.getCardType().clear(); permanent.addCardType(CardType.CREATURE); - permanent.getSubtype(game).clear(); + permanent.removeAllSubTypes(game); permanent.getManaCost().clear(); break; case ColorChangingEffects_5: diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java index 06e5f1c012..3f5fd586d1 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java @@ -136,7 +136,7 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen permanent.getSuperType().clear(); permanent.getCardType().clear(); permanent.addCardType(CardType.CREATURE); - permanent.getSubtype(game).clear(); + permanent.removeAllSubTypes(game); break; case ColorChangingEffects_5: permanent.getColor(game).setColor(new ObjectColor()); 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 97f506cbf3..a11f9aeb37 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 @@ -8,6 +8,7 @@ package mage.abilities.effects.common.continuous; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -18,33 +19,26 @@ import mage.util.SubTypeList; */ public class BecomesSubtypeAllEffect extends ContinuousEffectImpl { - protected SubTypeList subtypes = new SubTypeList(); - protected boolean loseOther; // loses other subtypes - protected FilterCreaturePermanent filter; + private final SubTypeList subtypes = new SubTypeList(); + private final boolean loseOther; // loses other subtypes + private final FilterCreaturePermanent filter; public BecomesSubtypeAllEffect(Duration duration, SubType subtype) { - this(duration, createArrayList(subtype)); + this(duration, new SubTypeList(subtype)); } public BecomesSubtypeAllEffect(Duration duration, SubTypeList subtypes) { - this(duration, subtypes, new FilterCreaturePermanent("All creatures"), true); + this(duration, subtypes, StaticFilters.FILTER_PERMANENT_CREATURE, true); } - public BecomesSubtypeAllEffect(Duration duration, - SubTypeList subtypes, FilterCreaturePermanent filter, boolean loseOther) { - super(duration, Outcome.Detriment); - this.subtypes = subtypes; + public BecomesSubtypeAllEffect(Duration duration, SubTypeList subtypes, FilterCreaturePermanent filter, boolean loseOther) { + super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); + this.subtypes.addAll(subtypes); this.staticText = setText(); this.loseOther = loseOther; this.filter = filter; } - private static SubTypeList createArrayList(SubType subtype) { - SubTypeList subtypes = new SubTypeList(); - subtypes.add(subtype); - return subtypes; - } - public BecomesSubtypeAllEffect(final BecomesSubtypeAllEffect effect) { super(effect); this.subtypes.addAll(effect.subtypes); @@ -52,47 +46,32 @@ public class BecomesSubtypeAllEffect extends ContinuousEffectImpl { this.filter = effect.filter; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public BecomesSubtypeAllEffect copy() { return new BecomesSubtypeAllEffect(this); } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, - Game game) { + public boolean apply(Game game, Ability source) { + boolean flag = false; for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (loseOther) { - permanent.getSubtype(game).retainAll(SubType.getLandTypes()); - permanent.getSubtype(game).addAll(subtypes); - } else { - for (SubType subtype : subtypes) { - if (!permanent.hasSubtype(subtype, game)) { - permanent.getSubtype(game).add(subtype); - } - } - } - break; - } - } else if (duration == Duration.Custom) { - discard(); + if (permanent == null) { + continue; + } + flag = true; + if (loseOther) { + permanent.removeAllCreatureTypes(game); + } + for (SubType subtype : subtypes) { + permanent.addSubType(game, subtype); } } + if (!flag && duration == Duration.Custom) { + discard(); + } return true; } - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } - private String setText() { StringBuilder sb = new StringBuilder(); sb.append("Target creature becomes that type"); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesBecomeOtherTypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesBecomeOtherTypeEffect.java index e2513cac56..01cd5cafab 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesBecomeOtherTypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesBecomeOtherTypeEffect.java @@ -40,10 +40,8 @@ public class CreaturesBecomeOtherTypeEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { if (layer == Layer.TypeChangingEffects_4) { - for (Permanent object: game.getBattlefield().getActivePermanents(this.filter, source.getControllerId(), game)) { - if (!object.hasSubtype(this.subType, game)) { - object.getSubtype(game).add(this.subType); - } + for (Permanent object : game.getBattlefield().getActivePermanents(this.filter, source.getControllerId(), game)) { + object.addSubType(game, this.subType); } } 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 new file mode 100644 index 0000000000..a9473a5103 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAllCreatureTypesAttachedEffect.java @@ -0,0 +1,44 @@ +package mage.abilities.effects.common.continuous; + +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; +import mage.game.permanent.Permanent; + +/** + * @author TheElk801 + */ +public class GainAllCreatureTypesAttachedEffect extends ContinuousEffectImpl { + + public GainAllCreatureTypesAttachedEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); + staticText = "and is every creature type"; + } + + public GainAllCreatureTypesAttachedEffect(final GainAllCreatureTypesAttachedEffect effect) { + super(effect); + } + + @Override + public GainAllCreatureTypesAttachedEffect copy() { + return new GainAllCreatureTypesAttachedEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent equipment = game.getPermanent(source.getSourceId()); + if (equipment == null) { + return false; + } + Permanent permanent = game.getPermanent(equipment.getAttachedTo()); + if (permanent == null) { + return false; + } + permanent.setIsAllCreatureTypes(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 new file mode 100644 index 0000000000..da28687227 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAllCreatureTypesTargetEffect.java @@ -0,0 +1,53 @@ +package mage.abilities.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.Mode; +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; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public class GainAllCreatureTypesTargetEffect extends ContinuousEffectImpl { + + public GainAllCreatureTypesTargetEffect(Duration duration) { + super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); + } + + public GainAllCreatureTypesTargetEffect(final GainAllCreatureTypesTargetEffect effect) { + super(effect); + } + + @Override + public GainAllCreatureTypesTargetEffect copy() { + return new GainAllCreatureTypesTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int affectedTargets = 0; + for (UUID permanentId : targetPointer.getTargets(game, source)) { + Permanent target = game.getPermanent(permanentId); + if (target != null) { + target.setIsAllCreatureTypes(true); + affectedTargets++; + } + } + return affectedTargets > 0; + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + return "target " + mode.getTargets().get(0).getTargetName() + " gains all creature types " + duration.toString(); + } +} 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 new file mode 100644 index 0000000000..1b444035e2 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/HasSubtypesSourceEffect.java @@ -0,0 +1,71 @@ +package mage.abilities.effects.common.continuous; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.*; +import mage.game.Game; +import mage.util.SubTypeList; + +/** + * @author TheElk801 + */ +public class HasSubtypesSourceEffect extends ContinuousEffectImpl { + + private final SubTypeList subtypes = new SubTypeList(); + + public HasSubtypesSourceEffect(SubType... subTypes) { + super(Duration.EndOfGame, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); + subtypes.add(subTypes); + this.staticText = setText(); + } + + public HasSubtypesSourceEffect(final HasSubtypesSourceEffect effect) { + super(effect); + this.subtypes.addAll(effect.subtypes); + } + + @Override + public HasSubtypesSourceEffect copy() { + return new HasSubtypesSourceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + MageObject sourceObject = game.getObject(source.getSourceId()); + if (sourceObject == null) { + return false; + } + for (SubType subType : subtypes) { + sourceObject.addSubType(game, subType); + } + return true; + } + + private String setText() { + String s = "{this} is also "; + switch (subtypes.size()) { + case 0: + throw new UnsupportedOperationException("Can't have zero subtypes"); + case 1: + s += subtypes.get(0).getIndefiniteArticle() + " " + subtypes.get(0); + break; + case 2: + s += subtypes.get(0).getIndefiniteArticle() + " " + subtypes.get(0); + s += " and "; + s += subtypes.get(1).getIndefiniteArticle() + " " + subtypes.get(1); + break; + default: + for (int i = 0; i < subtypes.size(); i++) { + if (i == 0) { + s += subtypes.get(0).getIndefiniteArticle() + " " + subtypes.get(0) + ", "; + } else if (i == subtypes.size() - 1) { + s += "and " + subtypes.get(0); + } else { + s += subtypes.get(0) + ", "; + } + } + } + return s; + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAllCreatureTypesTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAllCreatureTypesTargetEffect.java index 7be4c3ef7b..0424ad4fb9 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAllCreatureTypesTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAllCreatureTypesTargetEffect.java @@ -3,7 +3,10 @@ package mage.abilities.effects.common.continuous; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.ContinuousEffectImpl; -import mage.constants.*; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; import mage.game.Game; import mage.game.permanent.Permanent; @@ -29,8 +32,8 @@ public class LoseAllCreatureTypesTargetEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent != null) { - permanent.setIsAllCreatureTypes(false); - return permanent.getSubtype(game).retainAll(SubType.getLandTypes()); + permanent.removeAllCreatureTypes(game); + return true; } return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseCreatureTypeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseCreatureTypeSourceEffect.java index 02405a9d04..27ce0e2b48 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseCreatureTypeSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseCreatureTypeSourceEffect.java @@ -24,7 +24,7 @@ public class LoseCreatureTypeSourceEffect extends ContinuousEffectImpl implement * @param lessThan */ public LoseCreatureTypeSourceEffect(DynamicValue dynamicValue, int lessThan) { - super(Duration.WhileOnBattlefield, Outcome.Detriment); + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); this.dynamicValue = dynamicValue; this.lessThan = lessThan; setText(); @@ -53,31 +53,22 @@ public class LoseCreatureTypeSourceEffect extends ContinuousEffectImpl implement } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean apply(Game game, Ability source) { if (dynamicValue.calculate(game, source, this) >= lessThan) { return false; } Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - switch (layer) { - case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.getCardType().remove(CardType.CREATURE); - permanent.getSubtype(game).retainAll(SubType.getLandTypes()); - if (permanent.isAttacking() || permanent.getBlocking() > 0) { - permanent.removeFromCombat(game); - } - } - break; - } - return true; + if (permanent == null) { + return false; } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; + permanent.getCardType().remove(CardType.CREATURE); + if (!permanent.isTribal()) { + permanent.removeAllCreatureTypes(game); + } + if (permanent.isAttacking() || permanent.getBlocking() > 0) { + permanent.removeFromCombat(game); + } + return true; } private void setText() { @@ -86,10 +77,4 @@ public class LoseCreatureTypeSourceEffect extends ContinuousEffectImpl implement sb.append(CardUtil.numberToText(lessThan)).append(", {this} isn't a creature"); staticText = sb.toString(); } - - @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 05da896fff..fe82e4e7b0 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 @@ -22,20 +22,6 @@ public class SetCardSubtypeAttachedEffect extends ContinuousEffectImpl { this.setText(); } - /*public SetCardSubtypeAttachedEffect(SubType setSubtype, Duration duration, AttachmentType attachmentType) { - super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); - this.setSubtypes.add(setSubtype); - this.attachmentType = attachmentType; - setText(); - } - - public SetCardSubtypeAttachedEffect(List setSubtypes, Duration duration, AttachmentType attachmentType) { - super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); - this.setSubtypes.addAll(setSubtypes); - this.attachmentType = attachmentType; - setText(); - }*/ - public SetCardSubtypeAttachedEffect(final SetCardSubtypeAttachedEffect effect) { super(effect); this.setSubtypes = effect.setSubtypes; @@ -45,13 +31,15 @@ public class SetCardSubtypeAttachedEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { Permanent equipment = game.getPermanent(source.getSourceId()); - if (equipment != null && equipment.getAttachedTo() != null) { - Permanent target = game.getPermanent(equipment.getAttachedTo()); - if (target != null) { - target.getSubtype(game).retainAll(SubType.getLandTypes()); - target.getSubtype(game).addAll(setSubtypes); - } + if (equipment == null || equipment.getAttachedTo() == null) { + return true; } + Permanent target = game.getPermanent(equipment.getAttachedTo()); + if (target == null) { + return true; + } + target.removeAllCreatureTypes(game); + target.getSubtype(game).addAll(setSubtypes); return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java index d2d2914682..84a0bc0751 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java @@ -9,9 +9,9 @@ import mage.game.Game; import mage.game.permanent.Permanent; /** - * * IMPORTANT: This only adds the chosen subtype while the source permanent is entering the battlefield. * You should also use @link{mage.abilities.effects.common.continuous.AddChosenSubtypeEffect} to make the subtype persist. + * * @author LevelX2 */ public class EnterAttributeAddChosenSubtypeEffect extends OneShotEffect { @@ -35,9 +35,7 @@ public class EnterAttributeAddChosenSubtypeEffect extends OneShotEffect { Permanent permanent = game.getPermanentEntering(source.getSourceId()); SubType subtype = (SubType) game.getState().getValue(source.getSourceId() + "_type"); if (permanent != null && subtype != null) { - if (!permanent.getSubtype(game).contains(subtype)) { - permanent.getSubtype(game).add(subtype); - } + permanent.addSubType(game, subtype); return true; } return false; diff --git a/Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java b/Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java index cd50dd7120..c96cd120db 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.keyword; import mage.ObjectColor; @@ -19,7 +18,6 @@ import mage.players.Player; import mage.util.CardUtil; /** - * * @author LevelX2 */ public class EmbalmAbility extends ActivatedAbilityImpl { @@ -89,9 +87,7 @@ class EmbalmEffect extends OneShotEffect { EmptyToken token = new EmptyToken(); CardUtil.copyTo(token).from(card); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer) token.getColor(game).setColor(ObjectColor.WHITE); - if (!token.hasSubtype(SubType.ZOMBIE, game)) { - token.getSubtype(game).add(0, SubType.ZOMBIE); - } + token.addSubType(game, SubType.ZOMBIE); token.getManaCost().clear(); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.EMBALMED_CREATURE, token.getId(), source.getSourceId(), controller.getId())); token.putOntoBattlefield(1, game, source.getSourceId(), 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 494b2cb2c2..61d185e263 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EternalizeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EternalizeAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.keyword; import mage.ObjectColor; @@ -19,7 +18,6 @@ import mage.players.Player; import mage.util.CardUtil; /** - * * @author igoudt */ public class EternalizeAbility extends ActivatedAbilityImpl { @@ -94,9 +92,7 @@ class EternalizeEffect extends OneShotEffect { EmptyToken token = new EmptyToken(); CardUtil.copyTo(token).from(card); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer) token.getColor(game).setColor(ObjectColor.BLACK); - if (!token.hasSubtype(SubType.ZOMBIE, game)) { - token.getSubtype(game).add(0, SubType.ZOMBIE); - } + token.addSubType(game, SubType.ZOMBIE); token.getManaCost().clear(); token.removePTCDA(); token.getPower().modifyBaseValue(4); diff --git a/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java b/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java index 6e45eccd8a..025c6cebcb 100644 --- a/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java @@ -52,9 +52,10 @@ public class TransformAbility extends SimpleStaticAbility { for (CardType type : sourceCard.getCardType()) { permanent.addCardType(type); } - permanent.getSubtype(game).clear(); + permanent.removeAllSubTypes(game); + permanent.setIsAllCreatureTypes(sourceCard.isAllCreatureTypes()); for (SubType type : sourceCard.getSubtype(game)) { - permanent.getSubtype(game).add(type); + permanent.addSubType(game, type); } permanent.getSuperType().clear(); for (SuperType type : sourceCard.getSuperType()) { diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 154fc8292a..48b90a1cf3 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -3,11 +3,8 @@ package mage.constants; import mage.MageObject; import mage.filter.predicate.Predicate; import mage.game.Game; -import mage.util.SubTypeList; -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; public enum SubType { @@ -468,6 +465,22 @@ public enum SubType { } } + private static final Set landTypes = new HashSet<>(); + private static final Map> subTypeSetMap = new HashMap<>(); + + static { + for (SubTypeSet subTypeSet : SubTypeSet.values()) { + subTypeSetMap.put( + subTypeSet, + Arrays.stream(values()) + .filter(subType -> subType.getSubTypeSet() == subTypeSet) + .collect(Collectors.toSet()) + ); + } + landTypes.addAll(subTypeSetMap.get(SubTypeSet.BasicLandType)); + landTypes.addAll(subTypeSetMap.get(SubTypeSet.NonBasicLandType)); + } + private final SubTypeSet subTypeSet; private final String description; private final boolean customSet; @@ -534,49 +547,46 @@ public enum SubType { return subTypeSet; } - public static Set getArtifactTypes() { - Set subTypes = EnumSet.noneOf(SubType.class); - for (SubType subType : values()) { - if (subType.getSubTypeSet() == SubTypeSet.ArtifactType) { - subTypes.add(subType); - } + public boolean canGain(MageObject mageObject) { + switch (subTypeSet) { + case CreatureType: + return mageObject.isCreature() || mageObject.isTribal(); + case BasicLandType: + case NonBasicLandType: + return mageObject.isLand(); + case EnchantmentType: + return mageObject.isEnchantment(); + case ArtifactType: + return mageObject.isArtifact(); + case PlaneswalkerType: + return mageObject.isPlaneswalker(); } - return subTypes; + return false; + } + + public static Set getArtifactTypes() { + return subTypeSetMap.get(SubTypeSet.ArtifactType); + } + + public static Set getEnchantmentTypes() { + return subTypeSetMap.get(SubTypeSet.EnchantmentType); } public static Set getPlaneswalkerTypes() { - Set subTypes = EnumSet.noneOf(SubType.class); - for (SubType subType : values()) { - if (subType.getSubTypeSet() == SubTypeSet.PlaneswalkerType) { - subTypes.add(subType); - } - } - return subTypes; + return subTypeSetMap.get(SubTypeSet.PlaneswalkerType); + } public static Set getCreatureTypes() { - Set subTypes = EnumSet.noneOf(SubType.class); - for (SubType subType : values()) { - if (subType.getSubTypeSet() == SubTypeSet.CreatureType) { - subTypes.add(subType); - } - } - return subTypes; + return subTypeSetMap.get(SubTypeSet.CreatureType); + } public static Set getBasicLands() { - return Arrays.stream(values()) - .filter(p -> p.getSubTypeSet() == SubTypeSet.BasicLandType) - .collect(Collectors.toSet()); + return subTypeSetMap.get(SubTypeSet.BasicLandType); } - public static SubTypeList getLandTypes() { - SubTypeList landTypes = new SubTypeList(); - for (SubType subType : values()) { - if (subType.getSubTypeSet() == SubTypeSet.BasicLandType || subType.getSubTypeSet() == SubTypeSet.NonBasicLandType) { - landTypes.add(subType); - } - } + public static Set getLandTypes() { return landTypes; } } 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 a5314fa346..5aa82f2742 100644 --- a/Mage/src/main/java/mage/game/permanent/token/CribSwapShapeshifterWhiteToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/CribSwapShapeshifterWhiteToken.java @@ -1,13 +1,11 @@ - - package mage.game.permanent.token; -import mage.constants.CardType; -import mage.constants.SubType; + import mage.MageInt; import mage.abilities.keyword.ChangelingAbility; +import mage.constants.CardType; +import mage.constants.SubType; /** - * * @author spjspj */ public final class CribSwapShapeshifterWhiteToken extends TokenImpl { @@ -19,6 +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()); } 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 7f5d05ce52..dc9edaa5f1 100644 --- a/Mage/src/main/java/mage/game/permanent/token/ShapeshifterToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/ShapeshifterToken.java @@ -27,6 +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()); } diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index d8342f952c..ac1ea12de4 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -247,7 +247,7 @@ public class Spell extends StackObjImpl implements Card { // Otherwise effects like evolve trigger from creature comes into play event card.getCardType().remove(CardType.CREATURE); if (!card.getSubtype(game).contains(SubType.AURA)) { - card.getSubtype(game).add(SubType.AURA); + card.addSubType(game, SubType.AURA); } } UUID permId = null; @@ -271,9 +271,7 @@ public class Spell extends StackObjImpl implements Card { Permanent permanent = game.getPermanent(permId); if (permanent instanceof PermanentCard) { permanent.setSpellAbility(ability); // otherwise spell ability without bestow will be set - if (!card.getCardType().contains(CardType.CREATURE)) { - card.addCardType(CardType.CREATURE); - } + card.addCardType(CardType.CREATURE); card.getSubtype(game).remove(SubType.AURA); } } diff --git a/Mage/src/main/java/mage/target/common/TargetCreaturePermanentWithDifferentTypes.java b/Mage/src/main/java/mage/target/common/TargetCreaturePermanentWithDifferentTypes.java index 7807cb601c..feedd0a4db 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.shareSubtypes(selectedCreature, game)) { + if (creature.shareCreatureTypes(selectedCreature, game)) { return false; } } diff --git a/Mage/src/main/java/mage/util/functions/AddSubtypeApplier.java b/Mage/src/main/java/mage/util/functions/AddSubtypeApplier.java index 6f5c35e93d..0d762ff865 100644 --- a/Mage/src/main/java/mage/util/functions/AddSubtypeApplier.java +++ b/Mage/src/main/java/mage/util/functions/AddSubtypeApplier.java @@ -28,7 +28,7 @@ public class AddSubtypeApplier extends ApplyToPermanent { @Override public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { if (!permanent.hasSubtype(subtype, game)) { - permanent.getSubtype(game).add(subtype); + permanent.addSubType(game, subtype); } return true; } @@ -36,7 +36,7 @@ public class AddSubtypeApplier extends ApplyToPermanent { @Override public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { if (!mageObject.hasSubtype(subtype, game)) { - mageObject.getSubtype(game).add(subtype); + mageObject.addSubType(game, subtype); } 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 d83b3ed0dc..0f89823500 100644 --- a/Mage/src/main/java/mage/watchers/common/ProwlWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/ProwlWatcher.java @@ -1,7 +1,5 @@ - package mage.watchers.common; -import mage.abilities.keyword.ChangelingAbility; import mage.constants.SubType; import mage.constants.WatcherScope; import mage.game.Game; @@ -30,22 +28,24 @@ public class ProwlWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { - if (event.getType() == EventType.DAMAGED_PLAYER) { - DamagedPlayerEvent dEvent = (DamagedPlayerEvent) event; - if (dEvent.isCombatDamage()) { - Permanent creature = game.getPermanent(dEvent.getSourceId()); - if (creature != null && !allSubtypes.contains(creature.getControllerId())) { - if (creature.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature.isAllCreatureTypes()) { - allSubtypes.add(creature.getControllerId()); - } else { - Set subtypes = damagingSubtypes.getOrDefault(creature.getControllerId(), new LinkedHashSet<>()); - - subtypes.addAll(creature.getSubtype(game)); - damagingSubtypes.put(creature.getControllerId(), subtypes); - } - } - } + if (event.getType() != EventType.DAMAGED_PLAYER) { + return; } + DamagedPlayerEvent dEvent = (DamagedPlayerEvent) event; + if (!dEvent.isCombatDamage()) { + return; + } + Permanent creature = game.getPermanent(dEvent.getSourceId()); + if (creature == null || allSubtypes.contains(creature.getControllerId())) { + return; + } + if (creature.isAllCreatureTypes()) { + allSubtypes.add(creature.getControllerId()); + return; + } + damagingSubtypes + .computeIfAbsent(creature.getControllerId(), m -> new LinkedHashSet<>()) + .addAll(creature.getSubtype(game)); } @Override