diff --git a/Mage.Sets/src/mage/cards/a/AberrantResearcher.java b/Mage.Sets/src/mage/cards/a/AberrantResearcher.java index 04fb9353392..154fbf79013 100644 --- a/Mage.Sets/src/mage/cards/a/AberrantResearcher.java +++ b/Mage.Sets/src/mage/cards/a/AberrantResearcher.java @@ -28,7 +28,6 @@ public final class AberrantResearcher extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.p.PerfectedForm.class; // Flying @@ -71,7 +70,7 @@ class AberrantResearcherEffect extends OneShotEffect { .noneMatch(card -> card.isInstantOrSorcery(game))) { return false; } - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); return true; } diff --git a/Mage.Sets/src/mage/cards/a/AccursedWitch.java b/Mage.Sets/src/mage/cards/a/AccursedWitch.java index d157b752a25..bf88d81b5e9 100644 --- a/Mage.Sets/src/mage/cards/a/AccursedWitch.java +++ b/Mage.Sets/src/mage/cards/a/AccursedWitch.java @@ -30,7 +30,6 @@ public final class AccursedWitch extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.InfectiousCurse.class; // Spells your opponents cast that target Accursed Witch cost {1} less to cast. diff --git a/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java b/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java index d340c1ace39..b5dc48b063c 100644 --- a/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java +++ b/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java @@ -20,7 +20,6 @@ public final class AfflictedDeserter extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WerewolfRansacker.class; this.power = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java b/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java index b292ac13b41..63256a34839 100644 --- a/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java +++ b/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java @@ -36,7 +36,6 @@ public final class AmbitiousFarmhand extends CardImpl { this.subtype.add(SubType.PEASANT); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SeasonedCathar.class; // When Ambitious Farmhand enters the battlefield, you may search your library for a basic Plains card, reveal it, put it into your hand, then shuffle. @@ -47,7 +46,7 @@ public final class AmbitiousFarmhand extends CardImpl { // Coven—{1}{W}{W}: Transform Ambitious Farmhand. Activate only if you control three or more creatures with different powers. this.addAbility(new TransformAbility()); this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new TransformSourceEffect(true), + Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl<>("{1}{W}{W}"), CovenCondition.instance ).setAbilityWord(AbilityWord.COVEN).addHint(CovenHint.instance)); } diff --git a/Mage.Sets/src/mage/cards/a/AnakinSkywalker.java b/Mage.Sets/src/mage/cards/a/AnakinSkywalker.java index e8a3e9c205f..ad03a0f3c92 100644 --- a/Mage.Sets/src/mage/cards/a/AnakinSkywalker.java +++ b/Mage.Sets/src/mage/cards/a/AnakinSkywalker.java @@ -38,7 +38,6 @@ public final class AnakinSkywalker extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DarthVader.class; // Whenever another creature dies, put a +1/+1 counter on Anakin Skywalker. @@ -82,7 +81,7 @@ class AnakinSkywalkerEffect extends ReplacementEffectImpl { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { permanent.regenerate(source, game); - return new TransformSourceEffect(true).apply(game, source); + return new TransformSourceEffect().apply(game, source); } return false; } diff --git a/Mage.Sets/src/mage/cards/a/AngelicEnforcer.java b/Mage.Sets/src/mage/cards/a/AngelicEnforcer.java new file mode 100644 index 00000000000..a1b545ee4c6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AngelicEnforcer.java @@ -0,0 +1,60 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.ControllerLifeCount; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; +import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AngelicEnforcer extends CardImpl { + + public AngelicEnforcer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + this.color.setWhite(true); + this.nightCard = true; + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // You have hexproof. + this.addAbility(new SimpleStaticAbility(new GainAbilityControllerEffect(HexproofAbility.getInstance()))); + + // Angelic Enforcer's power and toughness are each equal to your life total. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect( + ControllerLifeCount.instance, Duration.EndOfGame + ).setText("{this}'s power and toughness are each equal to your life total"))); + + // Whenever Angelic Enforcer attacks, double your life total. + this.addAbility(new AttacksTriggeredAbility(new GainLifeEffect( + ControllerLifeCount.instance + ).setText("double your life total"))); + } + + private AngelicEnforcer(final AngelicEnforcer card) { + super(card); + } + + @Override + public AngelicEnforcer copy() { + return new AngelicEnforcer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArchangelAvacyn.java b/Mage.Sets/src/mage/cards/a/ArchangelAvacyn.java index 3156f5621e0..605363d4870 100644 --- a/Mage.Sets/src/mage/cards/a/ArchangelAvacyn.java +++ b/Mage.Sets/src/mage/cards/a/ArchangelAvacyn.java @@ -1,30 +1,23 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.TransformTargetEffect; -import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; /** - * * @author fireshoes */ public final class ArchangelAvacyn extends CardImpl { @@ -37,14 +30,13 @@ public final class ArchangelAvacyn extends CardImpl { } public ArchangelAvacyn(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.ANGEL); this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = AvacynThePurifier.class; // Flash @@ -57,15 +49,18 @@ public final class ArchangelAvacyn extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // When Archangel Avacyn enters the battlefield, creatures you control gain indestructible until end of turn. - Ability ability = new EntersBattlefieldTriggeredAbility( - new GainAbilityAllEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn, - new FilterControlledCreaturePermanent("creatures you control")), false); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainAbilityControlledEffect( + IndestructibleAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURES + ), false)); // When a non-Angel creature you control dies, transform Archangel Avacyn at the beginning of the next upkeep. this.addAbility(new TransformAbility()); - this.addAbility(new DiesCreatureTriggeredAbility(new ArchangelAvacynEffect(), false, filter)); - + this.addAbility(new DiesCreatureTriggeredAbility( + new CreateDelayedTriggeredAbilityEffect( + new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new TransformSourceEffect()) + ).setText("transform {this} at the beginning of the next upkeep"), false, filter + ).setTriggerPhrase("When a non-Angel creature you control dies, ")); } private ArchangelAvacyn(final ArchangelAvacyn card) { @@ -77,36 +72,3 @@ public final class ArchangelAvacyn extends CardImpl { return new ArchangelAvacyn(this); } } - -class ArchangelAvacynEffect extends OneShotEffect { - - private static final String effectText = "transform {this} at the beginning of the next upkeep"; - - ArchangelAvacynEffect() { - super(Outcome.Benefit); - staticText = effectText; - } - - ArchangelAvacynEffect(ArchangelAvacynEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - MageObject sourceObject = source.getSourceObjectIfItStillExists(game); - if (sourceObject instanceof Permanent) { - //create delayed triggered ability - Effect effect = new TransformTargetEffect(false); - effect.setTargetPointer(new FixedTarget((Permanent) sourceObject, game)); - AtTheBeginOfNextUpkeepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(effect); - game.addDelayedTriggeredAbility(delayedAbility, source); - } - return true; - - } - - @Override - public ArchangelAvacynEffect copy() { - return new ArchangelAvacynEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java b/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java index 24536e649aa..b8127b27631 100644 --- a/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java +++ b/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java @@ -39,7 +39,6 @@ public final class ArchdemonOfGreed extends CardImpl { this.color.setBlack(true); this.nightCard = true; - this.transformable = true; this.power = new MageInt(9); this.toughness = new MageInt(9); diff --git a/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java b/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java index c026815658a..7516cde5dc8 100644 --- a/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java +++ b/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java @@ -26,7 +26,6 @@ public final class ArchiveHaunt extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java b/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java index a590432997f..7e6f55b301b 100644 --- a/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java +++ b/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java @@ -29,7 +29,6 @@ public final class ArguelsBloodFast extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TempleOfAclazotz.class; // {1}{B}, Pay 2 life: Draw a card. @@ -40,7 +39,7 @@ public final class ArguelsBloodFast extends CardImpl { // At the beginning of your upkeep, if you have 5 or less life, you may transform Arguel's Blood Fast. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, true), + new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, true), FatefulHourCondition.instance, "At the beginning of your upkeep, if you have 5 or less life, you may transform {this}" )); diff --git a/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java b/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java index 1a2d5b1ae44..786926b4687 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java @@ -35,7 +35,6 @@ public final class ArlinnEmbracedByTheMoon extends CardImpl { this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // +1: Creatures you control get +1/+1 and gain trample until end of turn. Effect effect = new BoostControlledEffect(1, 1, Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE); @@ -50,7 +49,7 @@ public final class ArlinnEmbracedByTheMoon extends CardImpl { this.addAbility(new TransformAbility()); ability = new LoyaltyAbility(new DamageTargetEffect(3), -1); ability.addTarget(new TargetAnyTarget()); - ability.addEffect(new TransformSourceEffect(false)); + ability.addEffect(new TransformSourceEffect()); this.addAbility(ability); // -6: You get an emblem with "Creatures you control have haste and '{T}: This creature deals damage equal to its power to any target.'" diff --git a/Mage.Sets/src/mage/cards/a/ArlinnKord.java b/Mage.Sets/src/mage/cards/a/ArlinnKord.java index 80b3c240fb6..96f3e33cc21 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnKord.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnKord.java @@ -32,7 +32,6 @@ public final class ArlinnKord extends CardImpl { this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.ARLINN); - this.transformable = true; this.secondSideCardClazz = ArlinnEmbracedByTheMoon.class; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); @@ -53,7 +52,7 @@ public final class ArlinnKord extends CardImpl { // 0: Create a 2/2 green Wolf creature token. Transform Arlinn Kord. this.addAbility(new TransformAbility()); ability = new LoyaltyAbility(new CreateTokenEffect(new WolfToken()), 0); - ability.addEffect(new TransformSourceEffect(true)); + ability.addEffect(new TransformSourceEffect()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java b/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java index 98e064a041b..f6ce1f507a5 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java @@ -31,7 +31,6 @@ public final class ArlinnTheMoonsFury extends CardImpl { this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4)); this.color.setRed(true); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Nightbound diff --git a/Mage.Sets/src/mage/cards/a/ArlinnThePacksHope.java b/Mage.Sets/src/mage/cards/a/ArlinnThePacksHope.java index ee4f826916a..36d2f2f4726 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnThePacksHope.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnThePacksHope.java @@ -35,7 +35,6 @@ public final class ArlinnThePacksHope extends CardImpl { this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.ARLINN); this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4)); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.ArlinnTheMoonsFury.class; // Daybound diff --git a/Mage.Sets/src/mage/cards/a/AshmouthDragon.java b/Mage.Sets/src/mage/cards/a/AshmouthDragon.java index aa7fae2f965..f4c11eb6b55 100644 --- a/Mage.Sets/src/mage/cards/a/AshmouthDragon.java +++ b/Mage.Sets/src/mage/cards/a/AshmouthDragon.java @@ -26,7 +26,6 @@ public final class AshmouthDragon extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/a/AutumnalGloom.java b/Mage.Sets/src/mage/cards/a/AutumnalGloom.java index 41d6cb6a286..fbf7ac43200 100644 --- a/Mage.Sets/src/mage/cards/a/AutumnalGloom.java +++ b/Mage.Sets/src/mage/cards/a/AutumnalGloom.java @@ -25,7 +25,6 @@ public final class AutumnalGloom extends CardImpl { public AutumnalGloom(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); - this.transformable = true; this.secondSideCardClazz = AncientOfTheEquinox.class; // {B}: Put the top card of your library into your graveyard. @@ -33,7 +32,7 @@ public final class AutumnalGloom extends CardImpl { // Delirium — At the beginning of your end step, if there are four or more card types among cards in your graveyard, transform Autumnal Gloom. this.addAbility(new TransformAbility()); - Ability ability = new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), TargetController.YOU, DeliriumCondition.instance, false); + Ability ability = new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), TargetController.YOU, DeliriumCondition.instance, false); ability.setAbilityWord(AbilityWord.DELIRIUM); ability.addHint(CardTypesInGraveyardHint.YOU); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AvacynianMissionaries.java b/Mage.Sets/src/mage/cards/a/AvacynianMissionaries.java index 44308396600..a9469350d33 100644 --- a/Mage.Sets/src/mage/cards/a/AvacynianMissionaries.java +++ b/Mage.Sets/src/mage/cards/a/AvacynianMissionaries.java @@ -27,12 +27,11 @@ public final class AvacynianMissionaries extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LunarchInquisitors.class; // At the beginning of your end step, if Avacynian Missionaries is equipped, transform it. this.addAbility(new TransformAbility()); - this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), TargetController.YOU, EquippedSourceCondition.instance, false)); + this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), TargetController.YOU, EquippedSourceCondition.instance, false)); } diff --git a/Mage.Sets/src/mage/cards/a/AwokenDemon.java b/Mage.Sets/src/mage/cards/a/AwokenDemon.java index d7b9e1c6edc..dabf328e6ce 100644 --- a/Mage.Sets/src/mage/cards/a/AwokenDemon.java +++ b/Mage.Sets/src/mage/cards/a/AwokenDemon.java @@ -20,7 +20,6 @@ public final class AwokenDemon extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; } diff --git a/Mage.Sets/src/mage/cards/a/AzcantaTheSunkenRuin.java b/Mage.Sets/src/mage/cards/a/AzcantaTheSunkenRuin.java index 32fa65cc5ff..4352f6c7813 100644 --- a/Mage.Sets/src/mage/cards/a/AzcantaTheSunkenRuin.java +++ b/Mage.Sets/src/mage/cards/a/AzcantaTheSunkenRuin.java @@ -37,7 +37,6 @@ public final class AzcantaTheSunkenRuin extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // (Transforms from Search for Azcanta)/ // {T} : Add {U}. diff --git a/Mage.Sets/src/mage/cards/a/AzorsGateway.java b/Mage.Sets/src/mage/cards/a/AzorsGateway.java index a8d4649e8b2..9e97185af0c 100644 --- a/Mage.Sets/src/mage/cards/a/AzorsGateway.java +++ b/Mage.Sets/src/mage/cards/a/AzorsGateway.java @@ -36,7 +36,6 @@ public final class AzorsGateway extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SanctumOfTheSun.class; // {1}, {T}: Draw a card, then exile a card from your hand. If cards with five or more different converted mana costs are exiled with Azor's Gateway, you gain 5 life, untap Azor's Gateway, and transform it. @@ -94,7 +93,7 @@ class AzorsGatewayEffect extends OneShotEffect { if (usedCMC.size() > 4) { controller.gainLife(4, game, source); new UntapSourceEffect().apply(game, source); - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); } } return true; diff --git a/Mage.Sets/src/mage/cards/b/BaithookAngler.java b/Mage.Sets/src/mage/cards/b/BaithookAngler.java index 200ccb38c7a..123f91a1395 100644 --- a/Mage.Sets/src/mage/cards/b/BaithookAngler.java +++ b/Mage.Sets/src/mage/cards/b/BaithookAngler.java @@ -23,7 +23,6 @@ public final class BaithookAngler extends CardImpl { this.subtype.add(SubType.PEASANT); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HookHauntDrifter.class; // Disturb {1}{U} diff --git a/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java b/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java index a787fbe86ec..db8f96ac32a 100644 --- a/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java +++ b/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java @@ -22,7 +22,6 @@ public final class BaneOfHanweir extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(5); diff --git a/Mage.Sets/src/mage/cards/b/BanebladeScoundrel.java b/Mage.Sets/src/mage/cards/b/BanebladeScoundrel.java new file mode 100644 index 00000000000..fa410c3874e --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BanebladeScoundrel.java @@ -0,0 +1,57 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.common.BecomesBlockedSourceTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.keyword.DayboundAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.BlockingOrBlockedBySourcePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BanebladeScoundrel extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(BlockingOrBlockedBySourcePredicate.BLOCKING); + } + + public BanebladeScoundrel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.subtype.add(SubType.WEREWOLF); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.b.BaneclawMarauder.class; + + // Whenever Baneblade Scoundrel becomes blocked, each creature blocking it gets -1/-1 until end of turn. + this.addAbility(new BecomesBlockedSourceTriggeredAbility(new BoostAllEffect( + -1, -1, Duration.EndOfTurn, filter, false + ).setText("each creature blocking it gets -1/-1 until end of turn"), false)); + + // Daybound + this.addAbility(new TransformAbility()); + this.addAbility(new DayboundAbility()); + } + + private BanebladeScoundrel(final BanebladeScoundrel card) { + super(card); + } + + @Override + public BanebladeScoundrel copy() { + return new BanebladeScoundrel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BaneclawMarauder.java b/Mage.Sets/src/mage/cards/b/BaneclawMarauder.java new file mode 100644 index 00000000000..2a2394c962e --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BaneclawMarauder.java @@ -0,0 +1,126 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.common.BecomesBlockedSourceTriggeredAbility; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.common.LoseLifeTargetControllerEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.keyword.NightboundAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.WatcherScope; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.predicate.permanent.BlockingOrBlockedBySourcePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.watchers.Watcher; + +import java.util.*; + +/** + * @author TheElk801 + */ +public final class BaneclawMarauder extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterPermanent filter2 = new FilterCreaturePermanent("a creature blocking {this}"); + + static { + filter.add(BlockingOrBlockedBySourcePredicate.BLOCKING); + filter2.add(BaneclawMarauderPredicate.instance); + } + + public BaneclawMarauder(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.subtype.add(SubType.WEREWOLF); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + this.color.setBlack(true); + this.nightCard = true; + + // Whenever Baneclaw Marauder becomes blocked, each creature blocking it gets -1/-1 until end of turn. + this.addAbility(new BecomesBlockedSourceTriggeredAbility(new BoostAllEffect( + -1, -1, Duration.EndOfTurn, filter, false + ).setText("each creature blocking it gets -1/-1 until end of turn"), false)); + + // Whenever a creature blocking Baneclaw Marauder dies, its controller loses 1 life. + this.addAbility(new DiesCreatureTriggeredAbility( + new LoseLifeTargetControllerEffect(1) + .setText("that creature's controller loses 1 life"), + false, filter2, true + ), new BaneclawMarauderWatcher()); + + // Nightbound + this.addAbility(new NightboundAbility()); + } + + private BaneclawMarauder(final BaneclawMarauder card) { + super(card); + } + + @Override + public BaneclawMarauder copy() { + return new BaneclawMarauder(this); + } +} + +enum BaneclawMarauderPredicate implements ObjectSourcePlayerPredicate { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return BaneclawMarauderWatcher.check(input.getSourceId(), input.getObject(), game); + } +} + +class BaneclawMarauderWatcher extends Watcher { + + private final Map> blockerMap = new HashMap<>(); + + BaneclawMarauderWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + switch (event.getType()) { + case BLOCKER_DECLARED: + blockerMap + .computeIfAbsent(new MageObjectReference(event.getTargetId(), game), x -> new HashSet<>()) + .add(new MageObjectReference(event.getSourceId(), game)); + return; + case END_COMBAT_STEP_POST: + blockerMap.clear(); + return; + case REMOVED_FROM_COMBAT: + blockerMap + .values() + .stream() + .forEach(set -> set.removeIf(mor -> mor.refersTo(event.getTargetId(), game))); + } + } + + @Override + public void reset() { + super.reset(); + blockerMap.clear(); + } + + static boolean check(UUID sourceId, Permanent blocker, Game game) { + return game.getState() + .getWatcher(BaneclawMarauderWatcher.class) + .blockerMap + .getOrDefault(new MageObjectReference(sourceId, game), Collections.emptySet()) + .stream() + .anyMatch(mor -> mor.refersTo(blocker, game)); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BenevolentGeist.java b/Mage.Sets/src/mage/cards/b/BenevolentGeist.java index f54295208ea..814302e5078 100644 --- a/Mage.Sets/src/mage/cards/b/BenevolentGeist.java +++ b/Mage.Sets/src/mage/cards/b/BenevolentGeist.java @@ -28,7 +28,6 @@ public final class BenevolentGeist extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/b/BereavedSurvivor.java b/Mage.Sets/src/mage/cards/b/BereavedSurvivor.java index 69b57d3edae..463b0716483 100644 --- a/Mage.Sets/src/mage/cards/b/BereavedSurvivor.java +++ b/Mage.Sets/src/mage/cards/b/BereavedSurvivor.java @@ -24,13 +24,12 @@ public final class BereavedSurvivor extends CardImpl { this.subtype.add(SubType.PEASANT); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DauntlessAvenger.class; // When another creature you control dies, transform Bereaved Survivor. this.addAbility(new TransformAbility()); this.addAbility(new DiesCreatureTriggeredAbility( - new TransformSourceEffect(true), false, + new TransformSourceEffect(), false, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE ).setTriggerPhrase("When another creature you control dies, ")); } diff --git a/Mage.Sets/src/mage/cards/b/BirdAdmirer.java b/Mage.Sets/src/mage/cards/b/BirdAdmirer.java index 3ee4bc0bd70..c6e18af59bf 100644 --- a/Mage.Sets/src/mage/cards/b/BirdAdmirer.java +++ b/Mage.Sets/src/mage/cards/b/BirdAdmirer.java @@ -24,7 +24,6 @@ public final class BirdAdmirer extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(1); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WingShredder.class; // Reach diff --git a/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java b/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java index 90918844994..f651d1a1ec9 100644 --- a/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java +++ b/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java @@ -41,7 +41,6 @@ public final class BloodlineKeeper extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LordOfLineage.class; this.addAbility(FlyingAbility.getInstance()); @@ -50,7 +49,7 @@ public final class BloodlineKeeper extends CardImpl { // {B}: Transform Bloodline Keeper. Activate this ability only if you control five or more Vampires. this.addAbility(new TransformAbility()); Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new TransformSourceEffect(true), + new TransformSourceEffect(), new ManaCostsImpl("{B}"), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 4)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/b/BloodswornSquire.java b/Mage.Sets/src/mage/cards/b/BloodswornSquire.java index baf0f7716b3..a13ac16a0a7 100644 --- a/Mage.Sets/src/mage/cards/b/BloodswornSquire.java +++ b/Mage.Sets/src/mage/cards/b/BloodswornSquire.java @@ -33,8 +33,6 @@ public final class BloodswornSquire extends CardImpl { this.subtype.add(SubType.SOLDIER); this.power = new MageInt(3); this.toughness = new MageInt(3); - - this.transformable = true; this.secondSideCardClazz = mage.cards.b.BloodswornKnight.class; this.addAbility(new TransformAbility()); @@ -47,7 +45,7 @@ public final class BloodswornSquire extends CardImpl { ability.addCost(new DiscardCardCost()); ability.addEffect(new TapSourceEffect().setText("tap it")); ability.addEffect(new ConditionalOneShotEffect( - new TransformSourceEffect(true, true), + new TransformSourceEffect(), new CardsInControllerGraveyardCondition(4, StaticFilters.FILTER_CARD_CREATURES), "Then if there are four or more creature cards in your graveyard, transform {this}" )); diff --git a/Mage.Sets/src/mage/cards/b/BrandedHowler.java b/Mage.Sets/src/mage/cards/b/BrandedHowler.java index 3b5fb571a4a..4aac4619373 100644 --- a/Mage.Sets/src/mage/cards/b/BrandedHowler.java +++ b/Mage.Sets/src/mage/cards/b/BrandedHowler.java @@ -2,18 +2,11 @@ package mage.cards.b; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.WerewolfBackTriggeredAbility; -import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.TransformSourceEffect; -import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; /** * @@ -30,7 +23,6 @@ public final class BrandedHowler extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Branded Howler. this.addAbility(new WerewolfBackTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/b/BreakneckRider.java b/Mage.Sets/src/mage/cards/b/BreakneckRider.java index f0936aedf8c..fbc0c3322e3 100644 --- a/Mage.Sets/src/mage/cards/b/BreakneckRider.java +++ b/Mage.Sets/src/mage/cards/b/BreakneckRider.java @@ -21,7 +21,6 @@ public final class BreakneckRider extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.n.NeckBreaker.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Breakneck Rider. diff --git a/Mage.Sets/src/mage/cards/b/BrutalCathar.java b/Mage.Sets/src/mage/cards/b/BrutalCathar.java index 902e0277d02..4b5037da2f3 100644 --- a/Mage.Sets/src/mage/cards/b/BrutalCathar.java +++ b/Mage.Sets/src/mage/cards/b/BrutalCathar.java @@ -32,7 +32,6 @@ public final class BrutalCathar extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MoonrageBrute.class; // When this creature enters the battlefield or transforms into Brutal Cathar, exile target creature an opponent controls until this creature leaves the battlefield. diff --git a/Mage.Sets/src/mage/cards/b/BurlyBreaker.java b/Mage.Sets/src/mage/cards/b/BurlyBreaker.java index 4f327728240..36fd55168c3 100644 --- a/Mage.Sets/src/mage/cards/b/BurlyBreaker.java +++ b/Mage.Sets/src/mage/cards/b/BurlyBreaker.java @@ -24,7 +24,6 @@ public final class BurlyBreaker extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(6); this.toughness = new MageInt(5); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DireStrainDemolisher.class; // Ward {1} diff --git a/Mage.Sets/src/mage/cards/c/CatapultFodder.java b/Mage.Sets/src/mage/cards/c/CatapultFodder.java index 6c227759f65..3e5a9c90a68 100644 --- a/Mage.Sets/src/mage/cards/c/CatapultFodder.java +++ b/Mage.Sets/src/mage/cards/c/CatapultFodder.java @@ -28,14 +28,12 @@ public final class CatapultFodder extends CardImpl { this.subtype.add(SubType.ZOMBIE); this.power = new MageInt(1); this.toughness = new MageInt(5); - - this.transformable = true; this.secondSideCardClazz = mage.cards.c.CatapultCaptain.class; // At the beginning of combat on your turn, if you control three or more creatures that each have toughness greater than their power, transform Catapult Fodder. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility(new TransformSourceEffect(true, true), TargetController.YOU, false), + new BeginningOfCombatTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), CatapultFodderCondition.instance, "At the beginning of combat on your turn, if you control three or more creatures that each have toughness greater than their power, transform {this}" )); diff --git a/Mage.Sets/src/mage/cards/c/ChaliceOfLife.java b/Mage.Sets/src/mage/cards/c/ChaliceOfLife.java index 50e16626431..b9a4a4768a8 100644 --- a/Mage.Sets/src/mage/cards/c/ChaliceOfLife.java +++ b/Mage.Sets/src/mage/cards/c/ChaliceOfLife.java @@ -25,7 +25,6 @@ public final class ChaliceOfLife extends CardImpl { public ChaliceOfLife(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); - this.transformable = true; this.secondSideCardClazz = ChaliceOfDeath.class; this.addAbility(new TransformAbility()); @@ -66,8 +65,7 @@ class ChaliceOfLifeEffect extends OneShotEffect { // if you have at least 10 life more than your starting life total, transform Chalice of Life. if (player.getLife() >= game.getStartingLife() + 10) { - permanent.transform(game); - game.informPlayers(permanent.getName() + " transforms into " + permanent.getSecondCardFace().getName()); + permanent.transform(source, game); } } } diff --git a/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java b/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java index 217cd782ff0..4a13c2dcbcc 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java +++ b/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java @@ -45,7 +45,6 @@ public final class ChandraFireOfKaladesh extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = ChandraRoaringFlame.class; // Whenever you cast a red spell, untap Chandra, Fire of Kaladesh. diff --git a/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java b/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java index 09ebc62e4d4..0308ad1de7d 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java +++ b/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java @@ -33,7 +33,6 @@ public final class ChandraRoaringFlame extends CardImpl { this.color.setRed(true); this.nightCard = true; - this.transformable = true; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4)); diff --git a/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java b/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java index 397c975f90c..d5ac684e100 100644 --- a/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java +++ b/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java @@ -31,7 +31,6 @@ public final class ChapelShieldgeist extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); this.color.setWhite(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/c/ChaplainOfAlms.java b/Mage.Sets/src/mage/cards/c/ChaplainOfAlms.java index 73105c7bf2f..68e2524ff5d 100644 --- a/Mage.Sets/src/mage/cards/c/ChaplainOfAlms.java +++ b/Mage.Sets/src/mage/cards/c/ChaplainOfAlms.java @@ -25,7 +25,6 @@ public final class ChaplainOfAlms extends CardImpl { this.subtype.add(SubType.CLERIC); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.c.ChapelShieldgeist.class; // First strike diff --git a/Mage.Sets/src/mage/cards/c/ChillingChronicle.java b/Mage.Sets/src/mage/cards/c/ChillingChronicle.java index 27b55de43e1..12036ef2743 100644 --- a/Mage.Sets/src/mage/cards/c/ChillingChronicle.java +++ b/Mage.Sets/src/mage/cards/c/ChillingChronicle.java @@ -22,13 +22,12 @@ public final class ChillingChronicle extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, ""); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // {1}, {T}: Tap target nonland permanent. Transform Chilling Chronicle. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); - ability.addEffect(new TransformSourceEffect(false)); + ability.addEffect(new TransformSourceEffect()); ability.addTarget(new TargetNonlandPermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java b/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java index 43a0143df8b..b52ded12bbe 100644 --- a/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java +++ b/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java @@ -37,12 +37,11 @@ public final class ChosenOfMarkov extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MarkovsServant.class; // {tap}, Tap an untapped Vampire you control: Transform Chosen of Markov. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new TapSourceCost()); ability.addCost(new TapTargetCost(new TargetControlledPermanent(filter))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CivilizedScholar.java b/Mage.Sets/src/mage/cards/c/CivilizedScholar.java index 2810cb556df..be6d388e56a 100644 --- a/Mage.Sets/src/mage/cards/c/CivilizedScholar.java +++ b/Mage.Sets/src/mage/cards/c/CivilizedScholar.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.UUID; @@ -12,7 +11,6 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.h.HomicidalBruteWatcher; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Outcome; @@ -31,7 +29,6 @@ public final class CivilizedScholar extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.ADVISOR); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HomicidalBrute.class; this.power = new MageInt(0); @@ -39,7 +36,7 @@ public final class CivilizedScholar extends CardImpl { // {tap}: Draw a card, then discard a card. If a creature card is discarded this way, untap Civilized Scholar, then transform it. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CivilizedScholarEffect(), new TapSourceCost())); - this.addAbility(new TransformAbility(), new HomicidalBruteWatcher()); + this.addAbility(new TransformAbility()); } private CivilizedScholar(final CivilizedScholar card) { @@ -80,7 +77,7 @@ class CivilizedScholarEffect extends OneShotEffect { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { permanent.untap(game); - permanent.transform(game); + permanent.transform(source, game); } } return true; diff --git a/Mage.Sets/src/mage/cards/c/CloisteredYouth.java b/Mage.Sets/src/mage/cards/c/CloisteredYouth.java index 09cecfb9115..d98ba02068c 100644 --- a/Mage.Sets/src/mage/cards/c/CloisteredYouth.java +++ b/Mage.Sets/src/mage/cards/c/CloisteredYouth.java @@ -25,12 +25,11 @@ public final class CloisteredYouth extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.u.UnholyFiend.class; // At the beginning of your upkeep, you may transform Cloistered Youth. this.addAbility(new TransformAbility()); - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, true)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, true)); } private CloisteredYouth(final CloisteredYouth card) { diff --git a/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java b/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java index 80233f34d53..caa54922039 100644 --- a/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java +++ b/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java @@ -33,7 +33,6 @@ public final class ConduitOfStorms extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = ConduitOfEmrakul.class; // Whenever Conduit of Storms attacks, add {R} at the beginning of your next main phase this turn. @@ -44,7 +43,7 @@ public final class ConduitOfStorms extends CardImpl { this.addAbility(new AttacksTriggeredAbility(effect, false)); // {3}{R}{R}: Transform Conduit of Storms. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{3}{R}{R}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{3}{R}{R}"))); } private ConduitOfStorms(final ConduitOfStorms card) { diff --git a/Mage.Sets/src/mage/cards/c/ConquerorsGalleon.java b/Mage.Sets/src/mage/cards/c/ConquerorsGalleon.java index bc45f90e584..854a195f392 100644 --- a/Mage.Sets/src/mage/cards/c/ConquerorsGalleon.java +++ b/Mage.Sets/src/mage/cards/c/ConquerorsGalleon.java @@ -27,7 +27,6 @@ public final class ConquerorsGalleon extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(10); - this.transformable = true; this.secondSideCardClazz = ConquerorsFoothold.class; // When Conqueror's Galleon attacks, exile it at the end of combat, then return it to the battlefield transformed under your control. diff --git a/Mage.Sets/src/mage/cards/c/ConvictedKiller.java b/Mage.Sets/src/mage/cards/c/ConvictedKiller.java index b81f22ce7e1..ed0602e0025 100644 --- a/Mage.Sets/src/mage/cards/c/ConvictedKiller.java +++ b/Mage.Sets/src/mage/cards/c/ConvictedKiller.java @@ -3,18 +3,12 @@ package mage.cards.c; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.WerewolfFrontTriggeredAbility; -import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; /** * @author fireshoes @@ -28,7 +22,6 @@ public final class ConvictedKiller extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.b.BrandedHowler.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Convicted Killer. diff --git a/Mage.Sets/src/mage/cards/c/CovertCutpurse.java b/Mage.Sets/src/mage/cards/c/CovertCutpurse.java index 4659de478d1..2065b9ee04b 100644 --- a/Mage.Sets/src/mage/cards/c/CovertCutpurse.java +++ b/Mage.Sets/src/mage/cards/c/CovertCutpurse.java @@ -39,7 +39,6 @@ public final class CovertCutpurse extends CardImpl { this.subtype.add(SubType.ROGUE); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.c.CovetousGeist.class; // When Covert Cutpurse enters the battlefield, destroy target creature you don't control that was dealt damage this turn. diff --git a/Mage.Sets/src/mage/cards/c/CovetousCastaway.java b/Mage.Sets/src/mage/cards/c/CovetousCastaway.java index 9f1a2180606..a92f0b9f97e 100644 --- a/Mage.Sets/src/mage/cards/c/CovetousCastaway.java +++ b/Mage.Sets/src/mage/cards/c/CovetousCastaway.java @@ -24,7 +24,6 @@ public final class CovetousCastaway extends CardImpl { this.subtype.add(SubType.HUMAN); this.power = new MageInt(1); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.g.GhostlyCastigator.class; // When Covetous Castaway dies, mill three cards. diff --git a/Mage.Sets/src/mage/cards/c/CovetousGeist.java b/Mage.Sets/src/mage/cards/c/CovetousGeist.java index 7f1be068826..fbc4f1faec1 100644 --- a/Mage.Sets/src/mage/cards/c/CovetousGeist.java +++ b/Mage.Sets/src/mage/cards/c/CovetousGeist.java @@ -25,7 +25,6 @@ public final class CovetousGeist extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/c/CreepingInn.java b/Mage.Sets/src/mage/cards/c/CreepingInn.java index 791bfedba22..5ba7b0aa98c 100644 --- a/Mage.Sets/src/mage/cards/c/CreepingInn.java +++ b/Mage.Sets/src/mage/cards/c/CreepingInn.java @@ -37,7 +37,6 @@ public final class CreepingInn extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(7); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Whenever Creeping Inn attacks, you may exile a creature card from your graveyard. @@ -46,7 +45,7 @@ public final class CreepingInn extends CardImpl { this.addAbility(new AttacksTriggeredAbility(new CreepingInnEffect())); // {4}: Creeping Inn phases out. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PhaseOutSourceEffect(), new ManaCostsImpl("{4}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PhaseOutSourceEffect(), new ManaCostsImpl<>("{4}"))); } private CreepingInn(final CreepingInn card) { diff --git a/Mage.Sets/src/mage/cards/c/CryptolithFragment.java b/Mage.Sets/src/mage/cards/c/CryptolithFragment.java index 8730d91c2e3..8d7683d41b9 100644 --- a/Mage.Sets/src/mage/cards/c/CryptolithFragment.java +++ b/Mage.Sets/src/mage/cards/c/CryptolithFragment.java @@ -25,7 +25,6 @@ public final class CryptolithFragment extends CardImpl { public CryptolithFragment(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AuroraOfEmrakul.class; // Cryptolith Fragment enters the battlefield tapped. @@ -39,7 +38,7 @@ public final class CryptolithFragment extends CardImpl { // At the beginning of your upkeep, if each player has 10 or less life, transform Cryptolith Fragment. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), new XorLessLifeCondition(XorLessLifeCondition.CheckType.EACH_PLAYER, 10), "At the beginning of your upkeep, if each player has 10 or less life, transform Cryptolith Fragment.")); } diff --git a/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java b/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java index ad14b25935a..3c67f2eb171 100644 --- a/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java +++ b/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java @@ -33,7 +33,6 @@ public final class CuriousHomunculus extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.v.VoraciousReader.class; // {T}: Add {C}. Spend this mana only to cast an instant or sorcery spell. @@ -42,7 +41,7 @@ public final class CuriousHomunculus extends CardImpl { // At the beginning of your upkeep, if there are three or more instant and/or sorcery cards in your graveyard, transform Curious Homunculus. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), new InstantOrSorceryCardsInControllerGraveyardCondition(3), "At the beginning of your upkeep, if there are three or more instant and/or sorcery cards in your graveyard, transform {this}")); } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfLeeches.java b/Mage.Sets/src/mage/cards/c/CurseOfLeeches.java new file mode 100644 index 00000000000..75555e0aaa6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CurseOfLeeches.java @@ -0,0 +1,111 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.keyword.DayboundAbility; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPlayer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CurseOfLeeches extends CardImpl { + + public CurseOfLeeches(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); + + this.subtype.add(SubType.AURA); + this.subtype.add(SubType.CURSE); + this.secondSideCardClazz = mage.cards.l.LeechingLurker.class; + + // Enchant player + TargetPlayer auraTarget = new TargetPlayer(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // As this permanent transforms into Curse of Leeches, attach it to a player. + this.addAbility(new SimpleStaticAbility(new CurseOfLeechesEffect())); + + // At the beginning of enchanted player's upkeep, they lose 1 life and you gain 1 life. + ability = new BeginningOfUpkeepTriggeredAbility( + Zone.BATTLEFIELD, new LoseLifeTargetEffect(1).setText("they lose 1 life"), + TargetController.ENCHANTED, false, true + ); + ability.addEffect(new GainLifeEffect(1).concatBy("and")); + this.addAbility(ability); + + // Daybound + this.addAbility(new TransformAbility()); + this.addAbility(new DayboundAbility()); + } + + private CurseOfLeeches(final CurseOfLeeches card) { + super(card); + } + + @Override + public CurseOfLeeches copy() { + return new CurseOfLeeches(this); + } +} + +class CurseOfLeechesEffect extends ReplacementEffectImpl { + + CurseOfLeechesEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "as this permanent transforms into {this}, attach it to a player"; + } + + private CurseOfLeechesEffect(final CurseOfLeechesEffect effect) { + super(effect); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + TargetPlayer target = new TargetPlayer(); + target.withChooseHint("Player to attach to").setNotTarget(true); + controller.choose(Outcome.Detriment, target, source.getSourceId(), game); + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null) { + return false; + } + permanent.addAttachment(target.getFirstTarget(), source, game); + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRANSFORMING; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return source.getSourceId().equals(event.getTargetId()); + } + + @Override + public CurseOfLeechesEffect copy() { + return new CurseOfLeechesEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DaringSleuth.java b/Mage.Sets/src/mage/cards/d/DaringSleuth.java index de0ba14e6c2..01499f1e4ce 100644 --- a/Mage.Sets/src/mage/cards/d/DaringSleuth.java +++ b/Mage.Sets/src/mage/cards/d/DaringSleuth.java @@ -12,7 +12,6 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import java.util.UUID; @@ -28,7 +27,6 @@ public final class DaringSleuth extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.b.BearerOfOverwhelmingTruths.class; // When you sacrifice a Clue, transform Daring Sleuth. @@ -49,7 +47,7 @@ public final class DaringSleuth extends CardImpl { class DaringSleuthTriggeredAbility extends TriggeredAbilityImpl { public DaringSleuthTriggeredAbility() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true)); + super(Zone.BATTLEFIELD, new TransformSourceEffect()); } public DaringSleuthTriggeredAbility(final DaringSleuthTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/d/DauntlessAvenger.java b/Mage.Sets/src/mage/cards/d/DauntlessAvenger.java index d7004ce3498..8659565dace 100644 --- a/Mage.Sets/src/mage/cards/d/DauntlessAvenger.java +++ b/Mage.Sets/src/mage/cards/d/DauntlessAvenger.java @@ -36,7 +36,6 @@ public final class DauntlessAvenger extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); this.color.setWhite(true); - this.transformable = true; this.nightCard = true; // Whenever Dauntless Avenger attacks, return target creature card with mana value 2 or less from your graveyard to the battlefield tapped and attacking. diff --git a/Mage.Sets/src/mage/cards/d/DaybreakRanger.java b/Mage.Sets/src/mage/cards/d/DaybreakRanger.java index a5bf78e375a..6048aa33965 100644 --- a/Mage.Sets/src/mage/cards/d/DaybreakRanger.java +++ b/Mage.Sets/src/mage/cards/d/DaybreakRanger.java @@ -37,7 +37,6 @@ public final class DaybreakRanger extends CardImpl { this.subtype.add(SubType.RANGER); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.n.NightfallPredator.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java b/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java index 99b151931c9..7d39869b0f5 100644 --- a/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java +++ b/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java @@ -30,7 +30,6 @@ public final class DeathbonnetHulk extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // At the beginning of your upkeep, you may exile a card from a graveyard. If a creature card was exiled this way, put a +1/+1 counter on Deathbonnet Hulk. diff --git a/Mage.Sets/src/mage/cards/d/DeathbonnetSprout.java b/Mage.Sets/src/mage/cards/d/DeathbonnetSprout.java index 051e7980c91..9089004165e 100644 --- a/Mage.Sets/src/mage/cards/d/DeathbonnetSprout.java +++ b/Mage.Sets/src/mage/cards/d/DeathbonnetSprout.java @@ -39,7 +39,6 @@ public final class DeathbonnetSprout extends CardImpl { this.subtype.add(SubType.FUNGUS); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DeathbonnetHulk.class; // At the beginning of your upkeep, mill a card. Then if there are three or more creature cards in your graveyard, transform Deathbonnet Sprout. @@ -48,7 +47,7 @@ public final class DeathbonnetSprout extends CardImpl { new MillCardsControllerEffect(1), TargetController.YOU, false ); ability.addEffect(new ConditionalOneShotEffect( - new TransformSourceEffect(true), condition, + new TransformSourceEffect(), condition, "Then if there are three or more creature cards in your graveyard, transform {this}" )); this.addAbility(ability.addHint(hint)); diff --git a/Mage.Sets/src/mage/cards/d/DelverOfSecrets.java b/Mage.Sets/src/mage/cards/d/DelverOfSecrets.java index b0c282c70dc..a02bc453eaf 100644 --- a/Mage.Sets/src/mage/cards/d/DelverOfSecrets.java +++ b/Mage.Sets/src/mage/cards/d/DelverOfSecrets.java @@ -33,7 +33,6 @@ public final class DelverOfSecrets extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.InsectileAberration.class; // At the beginning of your upkeep, look at the top card of your library. You may reveal that card. If an instant or sorcery card is revealed this way, transform Delver of Secrets. @@ -73,25 +72,25 @@ class DelverOfSecretsEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (player != null && sourcePermanent != null) { - if (player.getLibrary().hasCards()) { - Card card = player.getLibrary().getFromTop(game); - if(card == null){ - return false; - } - Cards cards = new CardsImpl(); - cards.add(card); - player.lookAtCards(sourcePermanent.getName(), cards, game); - if (player.chooseUse(Outcome.DrawCard, "Reveal the top card of your library?", source, game)) { - player.revealCards(sourcePermanent.getName(), cards, game); - if (filter.match(card, game)) { - return new TransformSourceEffect(true, true).apply(game, source); - } - } - - } - return true; + if (player == null || sourcePermanent == null) { + return false; } - return false; + if (player.getLibrary().hasCards()) { + Card card = player.getLibrary().getFromTop(game); + if(card == null){ + return false; + } + Cards cards = new CardsImpl(); + cards.add(card); + player.lookAtCards(sourcePermanent.getName(), cards, game); + if (player.chooseUse(Outcome.DrawCard, "Reveal the top card of your library?", source, game)) { + player.revealCards(sourcePermanent.getName(), cards, game); + if (filter.match(card, game)) { + return new TransformSourceEffect().apply(game, source); + } + } + + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/d/Demilich.java b/Mage.Sets/src/mage/cards/d/Demilich.java index da6ff4323ec..1a0aa25a236 100644 --- a/Mage.Sets/src/mage/cards/d/Demilich.java +++ b/Mage.Sets/src/mage/cards/d/Demilich.java @@ -76,7 +76,7 @@ enum DemilichValue implements DynamicValue { SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { for (Spell spell : watcher.getSpellsCastThisTurn(sourceAbility.getControllerId())) { - if (spell.isInstantOrSorcery()) { + if (spell.isInstantOrSorcery(game)) { spells++; } } diff --git a/Mage.Sets/src/mage/cards/d/DennickPiousApprentice.java b/Mage.Sets/src/mage/cards/d/DennickPiousApprentice.java index 20107974ca3..862393b75a3 100644 --- a/Mage.Sets/src/mage/cards/d/DennickPiousApprentice.java +++ b/Mage.Sets/src/mage/cards/d/DennickPiousApprentice.java @@ -29,7 +29,6 @@ public final class DennickPiousApprentice extends CardImpl { this.subtype.add(SubType.SOLDIER); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DennickPiousApparition.class; // Lifelink diff --git a/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java b/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java index 91e19c92f0f..c937f9d2991 100644 --- a/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java +++ b/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java @@ -25,7 +25,6 @@ public final class DepartedSoulkeeper extends CardImpl { this.toughness = new MageInt(1); this.color.setWhite(true); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java b/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java index 667d86340c4..83b9adc4a0b 100644 --- a/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java +++ b/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java @@ -32,7 +32,6 @@ public final class DevotedGrafkeeper extends CardImpl { this.subtype.add(SubType.PEASANT); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DepartedSoulkeeper.class; // When Devoted Grafkeeper enters the battlefield, mill two cards. diff --git a/Mage.Sets/src/mage/cards/d/DireStrainBrawler.java b/Mage.Sets/src/mage/cards/d/DireStrainBrawler.java index c7116d20e7f..b1ee9f52960 100644 --- a/Mage.Sets/src/mage/cards/d/DireStrainBrawler.java +++ b/Mage.Sets/src/mage/cards/d/DireStrainBrawler.java @@ -22,7 +22,6 @@ public final class DireStrainBrawler extends CardImpl { this.power = new MageInt(6); this.toughness = new MageInt(6); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Vigilance diff --git a/Mage.Sets/src/mage/cards/d/DireStrainDemolisher.java b/Mage.Sets/src/mage/cards/d/DireStrainDemolisher.java index 51fcdcc7077..abb57f23514 100644 --- a/Mage.Sets/src/mage/cards/d/DireStrainDemolisher.java +++ b/Mage.Sets/src/mage/cards/d/DireStrainDemolisher.java @@ -23,7 +23,6 @@ public final class DireStrainDemolisher extends CardImpl { this.power = new MageInt(8); this.toughness = new MageInt(7); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Ward {3} diff --git a/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java b/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java index 1848042ea01..eff5ca4030d 100644 --- a/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java +++ b/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java @@ -45,7 +45,6 @@ public final class DocentOfPerfection extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.f.FinalIteration.class; // Flying @@ -98,7 +97,7 @@ class DocentOfPerfectionEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { if (game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) >= 3) { - return new TransformSourceEffect(true).apply(game, source); + return new TransformSourceEffect().apply(game, source); } } return false; diff --git a/Mage.Sets/src/mage/cards/d/DormantGrove.java b/Mage.Sets/src/mage/cards/d/DormantGrove.java index 1bb4d62b255..e2cf7d115e2 100644 --- a/Mage.Sets/src/mage/cards/d/DormantGrove.java +++ b/Mage.Sets/src/mage/cards/d/DormantGrove.java @@ -27,7 +27,6 @@ public final class DormantGrove extends CardImpl { public DormantGrove(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.g.GnarledGrovestrider.class; // At the beginning of combat on your turn, put a +1/+1 counter on target creature you control. @@ -39,7 +38,7 @@ public final class DormantGrove extends CardImpl { TargetController.YOU, false ); ability.addEffect(new ConditionalOneShotEffect( - new TransformSourceEffect(true, true), + new TransformSourceEffect(), DormatGroveCondition.instance, "Then if that creature has toughness 6 or greater, transform {this}" )); diff --git a/Mage.Sets/src/mage/cards/d/DowsingDagger.java b/Mage.Sets/src/mage/cards/d/DowsingDagger.java index bbd5575d4db..eb4887c3495 100644 --- a/Mage.Sets/src/mage/cards/d/DowsingDagger.java +++ b/Mage.Sets/src/mage/cards/d/DowsingDagger.java @@ -33,7 +33,6 @@ public final class DowsingDagger extends CardImpl { this.subtype.add(SubType.EQUIPMENT); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LostVale.class; // When Dowsing Dagger enters the battlefield, target opponent creates two 0/2 green Plant creature tokens with defender. @@ -47,7 +46,7 @@ public final class DowsingDagger extends CardImpl { // Whenever equipped creature deals combat damage to a player, you may transform Dowsing Dagger. this.addAbility(new TransformAbility()); - this.addAbility(new DealsDamageToAPlayerAttachedTriggeredAbility(new TransformSourceEffect(true), "equipped", true)); + this.addAbility(new DealsDamageToAPlayerAttachedTriggeredAbility(new TransformSourceEffect(), "equipped", true)); // Equip 2 this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); diff --git a/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java b/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java index ec4aa4d065a..b7ea9403b6a 100644 --- a/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java +++ b/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java @@ -3,21 +3,15 @@ package mage.cards.d; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.WerewolfFrontTriggeredAbility; -import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; -import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.common.FilterCreatureCard; @@ -34,7 +28,6 @@ public final class DuskwatchRecruiter extends CardImpl { this.subtype.add(SubType.WARRIOR); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.k.KrallenhordeHowler.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/e/EcstaticAwakener.java b/Mage.Sets/src/mage/cards/e/EcstaticAwakener.java index 50f4541680b..200f79689a2 100644 --- a/Mage.Sets/src/mage/cards/e/EcstaticAwakener.java +++ b/Mage.Sets/src/mage/cards/e/EcstaticAwakener.java @@ -30,7 +30,6 @@ public final class EcstaticAwakener extends CardImpl { this.subtype.add(SubType.WIZARD); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AwokenDemon.class; // {2}{B}, Sacrifice another creature: Draw a card, then transform Ecstatic Awakener. Activate only once each turn. @@ -38,7 +37,7 @@ public final class EcstaticAwakener extends CardImpl { Ability ability = new LimitedTimesPerTurnActivatedAbility( Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{2}{B}") ); - ability.addEffect(new TransformSourceEffect(true).concatBy(", then")); + ability.addEffect(new TransformSourceEffect().concatBy(", then")); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ElbrusTheBindingBlade.java b/Mage.Sets/src/mage/cards/e/ElbrusTheBindingBlade.java index 591d5dddfe4..ee01415f79f 100644 --- a/Mage.Sets/src/mage/cards/e/ElbrusTheBindingBlade.java +++ b/Mage.Sets/src/mage/cards/e/ElbrusTheBindingBlade.java @@ -1,4 +1,3 @@ - package mage.cards.e; import java.util.UUID; @@ -31,7 +30,6 @@ public final class ElbrusTheBindingBlade extends CardImpl { addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.EQUIPMENT); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WithengarUnbound.class; this.addAbility(new TransformAbility()); @@ -70,9 +68,7 @@ class ElbrusTheBindingBladeEffect extends OneShotEffect { Permanent attachedTo = game.getPermanent(equipment.getAttachedTo()); if (attachedTo != null) { attachedTo.removeAttachment(equipment.getId(), source, game); - equipment.transform(game); - game.informPlayers(equipment.getName() + " transforms into " + equipment.getSecondCardFace().getName()); - + equipment.transform(source, game); } } return false; diff --git a/Mage.Sets/src/mage/cards/e/ElusiveTormentor.java b/Mage.Sets/src/mage/cards/e/ElusiveTormentor.java index 592a56393b0..8e60ab80195 100644 --- a/Mage.Sets/src/mage/cards/e/ElusiveTormentor.java +++ b/Mage.Sets/src/mage/cards/e/ElusiveTormentor.java @@ -28,12 +28,11 @@ public final class ElusiveTormentor extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.InsidiousMist.class; // {1}, Discard a card: Transform Elusive Tormentor. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new GenericManaCost(1)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new GenericManaCost(1)); ability.addCost(new DiscardCardCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EmbodimentOfFlame.java b/Mage.Sets/src/mage/cards/e/EmbodimentOfFlame.java index f6159aff10a..7b06303bf68 100644 --- a/Mage.Sets/src/mage/cards/e/EmbodimentOfFlame.java +++ b/Mage.Sets/src/mage/cards/e/EmbodimentOfFlame.java @@ -34,7 +34,6 @@ public final class EmbodimentOfFlame extends CardImpl { this.toughness = new MageInt(3); this.color.setRed(true); this.nightCard = true; - this.transformable = true; // Whenever a spell you control deals damage, put a flame counter on Embodiment of Flame. this.addAbility(new EmbodimentOfFlameTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/e/EnduringAngel.java b/Mage.Sets/src/mage/cards/e/EnduringAngel.java new file mode 100644 index 00000000000..cb4b85471a4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EnduringAngel.java @@ -0,0 +1,110 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HexproofAbility; +import mage.abilities.keyword.TransformAbility; +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.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EnduringAngel extends CardImpl { + + public EnduringAngel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}{W}"); + + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.a.AngelicEnforcer.class; + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Double strike + this.addAbility(DoubleStrikeAbility.getInstance()); + + // You have hexproof. + this.addAbility(new SimpleStaticAbility(new GainAbilityControllerEffect(HexproofAbility.getInstance()))); + + // If your life total would be reduced to 0 or less, instead transform Enduring Angel and your life total becomes 3. Then if Enduring Angel didn't transform this way, you lose the game. + this.addAbility(new TransformAbility()); + this.addAbility(new SimpleStaticAbility(new EnduringAngelEffect())); + } + + private EnduringAngel(final EnduringAngel card) { + super(card); + } + + @Override + public EnduringAngel copy() { + return new EnduringAngel(this); + } +} + +class EnduringAngelEffect extends ReplacementEffectImpl { + + EnduringAngelEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "if your life total would be reduced to 0 or less, instead transform {this} " + + "and your life total becomes 3. Then if {this} didn't transform this way, you lose the game"; + } + + private EnduringAngelEffect(final EnduringAngelEffect effect) { + super(effect); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (player == null || permanent == null || player.getLife() - event.getAmount() > 0) { + return false; + } + boolean transformed = permanent.transform(source, game); + if (player.getLife() > 3) { + event.setAmount(player.getLife() - 3); + } else if (player.getLife() < 3) { + event.setAmount(0); + player.setLife(3, game, source); + } else { + event.setAmount(0); + } + if (!transformed) { + player.lost(game); + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.LOSE_LIFE; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return source.isControlledBy(event.getPlayerId()); + } + + @Override + public EnduringAngelEffect copy() { + return new EnduringAngelEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java b/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java index 37699775eb2..191b698e828 100644 --- a/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java +++ b/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java @@ -42,7 +42,6 @@ public final class ExtricatorOfSin extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = ExtricatorOfFlesh.class; // When Extricator of Sin enters the battlefield, you may sacrifice another permanent. If you do, create a 3/2 colorless Eldrazi Horror creature token. @@ -52,7 +51,7 @@ public final class ExtricatorOfSin extends CardImpl { // Delirium — At the beginning of your upkeep, if there are four or more card types among cards in your graveyard, transform Extricator of Sin. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), TargetController.YOU, false), DeliriumCondition.instance, "Delirium — At the beginning of your upkeep, if there are four or more card types among cards in your graveyard, " + " transform {this}.") diff --git a/Mage.Sets/src/mage/cards/f/FangbladeBrigand.java b/Mage.Sets/src/mage/cards/f/FangbladeBrigand.java index c8bab4a3313..ab8610811c5 100644 --- a/Mage.Sets/src/mage/cards/f/FangbladeBrigand.java +++ b/Mage.Sets/src/mage/cards/f/FangbladeBrigand.java @@ -29,7 +29,6 @@ public final class FangbladeBrigand extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(3); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.f.FangbladeEviscerator.class; // {1}{R}: Fangblade Brigand gets +1/+0 and gains first strike until end of turn. diff --git a/Mage.Sets/src/mage/cards/f/FangbladeEviscerator.java b/Mage.Sets/src/mage/cards/f/FangbladeEviscerator.java index f3a9ba0926a..b9c7a4dabec 100644 --- a/Mage.Sets/src/mage/cards/f/FangbladeEviscerator.java +++ b/Mage.Sets/src/mage/cards/f/FangbladeEviscerator.java @@ -29,7 +29,6 @@ public final class FangbladeEviscerator extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(5); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // {1}{R}: Fangblade Eviscerator gets +1/+0 and gains first strike until end of turn. diff --git a/Mage.Sets/src/mage/cards/f/FlameChanneler.java b/Mage.Sets/src/mage/cards/f/FlameChanneler.java index ee029cffe2f..8bce9da31b1 100644 --- a/Mage.Sets/src/mage/cards/f/FlameChanneler.java +++ b/Mage.Sets/src/mage/cards/f/FlameChanneler.java @@ -27,7 +27,7 @@ public final class FlameChanneler extends CardImpl { this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable=true;this.secondSideCardClazz=mage.cards.e.EmbodimentOfFlame.class; + this.secondSideCardClazz = mage.cards.e.EmbodimentOfFlame.class; // When a spell you control deals damage, transform Flame Channeler. this.addAbility(new TransformAbility()); @@ -47,7 +47,7 @@ public final class FlameChanneler extends CardImpl { class FlameChannelerTriggeredAbility extends TriggeredAbilityImpl { FlameChannelerTriggeredAbility() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true)); + super(Zone.BATTLEFIELD, new TransformSourceEffect()); } private FlameChannelerTriggeredAbility(final FlameChannelerTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java b/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java index 84bf2aba136..b73d8bc11e7 100644 --- a/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java +++ b/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java @@ -26,7 +26,6 @@ public final class FlameheartWerewolf extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Whenever Flameheart Werewolf blocks or becomes blocked by a creature, Flameheart Werewolf deals 2 damage to that creature. this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new DamageTargetEffect(2, true, "that creature"), diff --git a/Mage.Sets/src/mage/cards/f/FrenziedTrapbreaker.java b/Mage.Sets/src/mage/cards/f/FrenziedTrapbreaker.java index 40af95b9dff..771d12a6289 100644 --- a/Mage.Sets/src/mage/cards/f/FrenziedTrapbreaker.java +++ b/Mage.Sets/src/mage/cards/f/FrenziedTrapbreaker.java @@ -39,7 +39,6 @@ public final class FrenziedTrapbreaker extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // {1}, Sacrifice Frenzied Trapbreaker: Destroy target artifact or enchantment. diff --git a/Mage.Sets/src/mage/cards/g/Galedrifter.java b/Mage.Sets/src/mage/cards/g/Galedrifter.java index 1ef6a7f13da..aff87e6ee3a 100644 --- a/Mage.Sets/src/mage/cards/g/Galedrifter.java +++ b/Mage.Sets/src/mage/cards/g/Galedrifter.java @@ -23,7 +23,6 @@ public final class Galedrifter extends CardImpl { this.subtype.add(SubType.HIPPOGRIFF); this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.Waildrifter.class; // Flying diff --git a/Mage.Sets/src/mage/cards/g/GarrukRelentless.java b/Mage.Sets/src/mage/cards/g/GarrukRelentless.java index a6a35b52442..1ac3ece0df2 100644 --- a/Mage.Sets/src/mage/cards/g/GarrukRelentless.java +++ b/Mage.Sets/src/mage/cards/g/GarrukRelentless.java @@ -31,7 +31,6 @@ public final class GarrukRelentless extends CardImpl { this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.GARRUK); - this.transformable = true; this.secondSideCardClazz = GarrukTheVeilCursed.class; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); @@ -63,7 +62,7 @@ public final class GarrukRelentless extends CardImpl { class GarrukRelentlessStateTrigger extends StateTriggeredAbility { public GarrukRelentlessStateTrigger() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true)); + super(Zone.BATTLEFIELD, new TransformSourceEffect()); } public GarrukRelentlessStateTrigger(final GarrukRelentlessStateTrigger ability) { diff --git a/Mage.Sets/src/mage/cards/g/GarrukTheVeilCursed.java b/Mage.Sets/src/mage/cards/g/GarrukTheVeilCursed.java index 65231c23e64..065638a1a87 100644 --- a/Mage.Sets/src/mage/cards/g/GarrukTheVeilCursed.java +++ b/Mage.Sets/src/mage/cards/g/GarrukTheVeilCursed.java @@ -38,7 +38,6 @@ public final class GarrukTheVeilCursed extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.color.setGreen(true); this.color.setBlack(true); diff --git a/Mage.Sets/src/mage/cards/g/GatstafArsonists.java b/Mage.Sets/src/mage/cards/g/GatstafArsonists.java index d71ff6bac96..198d47e1d7b 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafArsonists.java +++ b/Mage.Sets/src/mage/cards/g/GatstafArsonists.java @@ -2,18 +2,12 @@ package mage.cards.g; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.WerewolfFrontTriggeredAbility; -import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; /** * @@ -28,7 +22,6 @@ public final class GatstafArsonists extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = GatstafRavagers.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Gatstaf Arsonists. diff --git a/Mage.Sets/src/mage/cards/g/GatstafHowler.java b/Mage.Sets/src/mage/cards/g/GatstafHowler.java index df0faacf87c..3d98791e211 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafHowler.java +++ b/Mage.Sets/src/mage/cards/g/GatstafHowler.java @@ -22,7 +22,6 @@ public final class GatstafHowler extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(3); this.toughness = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/g/GatstafRavagers.java b/Mage.Sets/src/mage/cards/g/GatstafRavagers.java index ce353bf6473..fd2463f180d 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafRavagers.java +++ b/Mage.Sets/src/mage/cards/g/GatstafRavagers.java @@ -23,7 +23,6 @@ public final class GatstafRavagers extends CardImpl { this.color.setRed(true); - this.transformable = true; this.nightCard = true; // Menace diff --git a/Mage.Sets/src/mage/cards/g/GatstafShepherd.java b/Mage.Sets/src/mage/cards/g/GatstafShepherd.java index 1e49e181c0f..47d1bb9d281 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafShepherd.java +++ b/Mage.Sets/src/mage/cards/g/GatstafShepherd.java @@ -20,7 +20,6 @@ public final class GatstafShepherd extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = GatstafHowler.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/g/GeierReachBandit.java b/Mage.Sets/src/mage/cards/g/GeierReachBandit.java index 9fde0db14a4..004e24bd542 100644 --- a/Mage.Sets/src/mage/cards/g/GeierReachBandit.java +++ b/Mage.Sets/src/mage/cards/g/GeierReachBandit.java @@ -24,7 +24,6 @@ public final class GeierReachBandit extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.v.VildinPackAlpha.class; // Haste diff --git a/Mage.Sets/src/mage/cards/g/GhastlyHaunting.java b/Mage.Sets/src/mage/cards/g/GhastlyHaunting.java index 1dd17b39100..b388bb76547 100644 --- a/Mage.Sets/src/mage/cards/g/GhastlyHaunting.java +++ b/Mage.Sets/src/mage/cards/g/GhastlyHaunting.java @@ -25,7 +25,6 @@ public final class GhastlyHaunting extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); diff --git a/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java b/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java index 35833d52144..f18d5299621 100644 --- a/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java +++ b/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java @@ -27,7 +27,6 @@ public final class GhostlyCastigator extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(4); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/g/GideonBattleForged.java b/Mage.Sets/src/mage/cards/g/GideonBattleForged.java index 740e82a5b4f..740ad27a0b8 100644 --- a/Mage.Sets/src/mage/cards/g/GideonBattleForged.java +++ b/Mage.Sets/src/mage/cards/g/GideonBattleForged.java @@ -42,7 +42,6 @@ public final class GideonBattleForged extends CardImpl { this.color.setWhite(true); this.nightCard = true; - this.transformable = true; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); diff --git a/Mage.Sets/src/mage/cards/g/GoldenGuardian.java b/Mage.Sets/src/mage/cards/g/GoldenGuardian.java index 1cfe74e73d6..6e575c7c147 100644 --- a/Mage.Sets/src/mage/cards/g/GoldenGuardian.java +++ b/Mage.Sets/src/mage/cards/g/GoldenGuardian.java @@ -47,7 +47,6 @@ public final class GoldenGuardian extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = GoldForgeGarrison.class; // Defender diff --git a/Mage.Sets/src/mage/cards/g/GraveyardGlutton.java b/Mage.Sets/src/mage/cards/g/GraveyardGlutton.java index 8cd92dd191b..2fd570828e3 100644 --- a/Mage.Sets/src/mage/cards/g/GraveyardGlutton.java +++ b/Mage.Sets/src/mage/cards/g/GraveyardGlutton.java @@ -35,7 +35,6 @@ public final class GraveyardGlutton extends CardImpl { this.toughness = new MageInt(4); this.color.setBlack(true); this.nightCard = true; - this.transformable = true; // Ward—Discard a card. this.addAbility(new WardAbility(new DiscardCardCost())); diff --git a/Mage.Sets/src/mage/cards/g/GraveyardTrespasser.java b/Mage.Sets/src/mage/cards/g/GraveyardTrespasser.java index 4b505e9d417..100d764de41 100644 --- a/Mage.Sets/src/mage/cards/g/GraveyardTrespasser.java +++ b/Mage.Sets/src/mage/cards/g/GraveyardTrespasser.java @@ -35,7 +35,6 @@ public final class GraveyardTrespasser extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.g.GraveyardGlutton.class; // Ward—Discard a card. diff --git a/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java b/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java index d569fee265c..94c472489d7 100644 --- a/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java +++ b/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java @@ -46,8 +46,7 @@ public final class GrimlockDinobotLeader extends CardImpl{ this.subtype.add(SubType.AUTOBOT); this.power = new MageInt(4); this.toughness = new MageInt(4); - - this.transformable = true; + this.secondSideCardClazz = GrimlockFerociousKing.class; // Dinosaurs, Vehicles and other Transformers creatures you control get +2/+0. @@ -56,7 +55,7 @@ public final class GrimlockDinobotLeader extends CardImpl{ // {2}: Grimlock, Dinobot Leader becomes Grimlock, Ferocious King. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{2}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{2}"))); } private GrimlockDinobotLeader(final GrimlockDinobotLeader card) { diff --git a/Mage.Sets/src/mage/cards/g/GrimlockFerociousKing.java b/Mage.Sets/src/mage/cards/g/GrimlockFerociousKing.java index ca8ba185e9a..5b16978b087 100644 --- a/Mage.Sets/src/mage/cards/g/GrimlockFerociousKing.java +++ b/Mage.Sets/src/mage/cards/g/GrimlockFerociousKing.java @@ -31,15 +31,14 @@ public final class GrimlockFerociousKing extends CardImpl{ this.color.setGreen(true); this.color.setWhite(true); - this.transformable = true; - this.nightCard = true; + this.nightCard = true; // Trample this.addAbility(TrampleAbility.getInstance()); // {2}: Grimlock, Ferocious King becomes Grimlock, Dinobot Leader. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(false), new ManaCostsImpl("{2}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{2}"))); } private GrimlockFerociousKing(final GrimlockFerociousKing card) { diff --git a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java index 20b7016afb2..3726aae9f96 100644 --- a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java +++ b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java @@ -32,7 +32,6 @@ public final class GrizzledAngler extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = GrislyAnglerfish.class; // {T}: Put the top two cards of your library into your graveyard. Then if there is a colorless creature card in your graveyard, transform Grizzled Angler. @@ -78,7 +77,7 @@ class GrizzledAnglerEffect extends OneShotEffect { if (controller != null) { controller.millCards(2, source, game); if (controller.getGraveyard().count(filter, source.getSourceId(), source.getControllerId(), game) >= 1) { - return new TransformSourceEffect(true).apply(game, source); + return new TransformSourceEffect().apply(game, source); } } return false; diff --git a/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java b/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java index 947f486a369..ab0bcf6566e 100644 --- a/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java +++ b/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java @@ -20,7 +20,6 @@ public final class GrizzledOutcasts extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.k.KrallenhordeWantons.class; this.power = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java b/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java index 6f32b3a86f5..a4216f7cb5b 100644 --- a/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java +++ b/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java @@ -36,7 +36,6 @@ public final class GrowingRitesOfItlimoc extends CardImpl { this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.ItlimocCradleOfTheSun.class; // When Growing Rites of Itlimoc enters the battlefield, look at the top four cards of your library. @@ -47,7 +46,7 @@ public final class GrowingRitesOfItlimoc extends CardImpl { // At the beginning of your end step, if you control four or more creatures, transform Growing Rites of Itlimoc. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_A_CREATURE, ComparisonType.MORE_THAN, 3), "At the beginning of your end step, if you control four or more creatures, transform {this}")); } diff --git a/Mage.Sets/src/mage/cards/h/HadanasClimb.java b/Mage.Sets/src/mage/cards/h/HadanasClimb.java index 633a238a48c..223b770c7c3 100644 --- a/Mage.Sets/src/mage/cards/h/HadanasClimb.java +++ b/Mage.Sets/src/mage/cards/h/HadanasClimb.java @@ -27,14 +27,13 @@ public final class HadanasClimb extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}{U}"); this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WingedTempleOfOrazca.class; // At the beginning of combat on your turn, put a +1/+1 counter on target creature you control. Then if that creature has three or more +1/+1 counters on it, transform Hadana's Climb. this.addAbility(new TransformAbility()); Ability ability = new BeginningOfCombatTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), TargetController.YOU, false); - ability.addEffect(new ConditionalOneShotEffect(new TransformSourceEffect(true), new TargetHasCounterCondition(CounterType.P1P1, 3, Integer.MAX_VALUE), + ability.addEffect(new ConditionalOneShotEffect(new TransformSourceEffect(), new TargetHasCounterCondition(CounterType.P1P1, 3, Integer.MAX_VALUE), "Then if that creature has three or more +1/+1 counters on it, transform {this}")); ability.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java b/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java index dceb0b20ec4..2e1a11f1925 100644 --- a/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java +++ b/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java @@ -31,13 +31,12 @@ public final class HanweirMilitiaCaptain extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WestvaleCultLeader.class; // At the beginning of your upkeep, if you control four or more creatures, transform Hanweir Militia Captain. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 3), "At the beginning of your upkeep, if you control four or more creatures, transform {this}")); } diff --git a/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java b/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java index cd550520cca..85997f17d36 100644 --- a/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java +++ b/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java @@ -22,7 +22,6 @@ public final class HanweirWatchkeep extends CardImpl { this.subtype.add(SubType.WARRIOR); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.b.BaneOfHanweir.class; this.power = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/h/HarvestHand.java b/Mage.Sets/src/mage/cards/h/HarvestHand.java index a5af36de700..29fb77f3e5b 100644 --- a/Mage.Sets/src/mage/cards/h/HarvestHand.java +++ b/Mage.Sets/src/mage/cards/h/HarvestHand.java @@ -29,7 +29,6 @@ public final class HarvestHand extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.ScroungedScythe.class; // When Harvest Hand dies, return it to the battlefield transformed under your control. diff --git a/Mage.Sets/src/mage/cards/h/HarvesttideAssailant.java b/Mage.Sets/src/mage/cards/h/HarvesttideAssailant.java index 55c37c19d41..c1d10320d80 100644 --- a/Mage.Sets/src/mage/cards/h/HarvesttideAssailant.java +++ b/Mage.Sets/src/mage/cards/h/HarvesttideAssailant.java @@ -22,7 +22,6 @@ public final class HarvesttideAssailant extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // Trample diff --git a/Mage.Sets/src/mage/cards/h/HarvesttideInfiltrator.java b/Mage.Sets/src/mage/cards/h/HarvesttideInfiltrator.java index 66e8715dc57..4695e36a651 100644 --- a/Mage.Sets/src/mage/cards/h/HarvesttideInfiltrator.java +++ b/Mage.Sets/src/mage/cards/h/HarvesttideInfiltrator.java @@ -23,7 +23,6 @@ public final class HarvesttideInfiltrator extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HarvesttideAssailant.class; // Trample diff --git a/Mage.Sets/src/mage/cards/h/HawkinsNationalLaboratory.java b/Mage.Sets/src/mage/cards/h/HawkinsNationalLaboratory.java index 236fed263c2..614a9b2263b 100644 --- a/Mage.Sets/src/mage/cards/h/HawkinsNationalLaboratory.java +++ b/Mage.Sets/src/mage/cards/h/HawkinsNationalLaboratory.java @@ -29,9 +29,8 @@ public final class HawkinsNationalLaboratory extends CardImpl { public HawkinsNationalLaboratory(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; + this.secondSideCardClazz = mage.cards.t.TheUpsideDown.class; // {T}: Add {C}. @@ -45,7 +44,7 @@ public final class HawkinsNationalLaboratory extends CardImpl { // At the beginning of your end step, if you sacrificed three or more Clues this turn, transform Hawkins National Laboratory. this.addAbility(new TransformAbility()); this.addAbility(new BeginningOfEndStepTriggeredAbility( - Zone.BATTLEFIELD, new TransformSourceEffect(true), + Zone.BATTLEFIELD, new TransformSourceEffect(), TargetController.YOU, HawkinsNationalLaboratoryCondition.instance, false ), new HawkinsNationalLaboratoryWatcher()); } diff --git a/Mage.Sets/src/mage/cards/h/HeirOfFalkenrath.java b/Mage.Sets/src/mage/cards/h/HeirOfFalkenrath.java index e3a8262c096..f86c9772c4c 100644 --- a/Mage.Sets/src/mage/cards/h/HeirOfFalkenrath.java +++ b/Mage.Sets/src/mage/cards/h/HeirOfFalkenrath.java @@ -25,12 +25,11 @@ public final class HeirOfFalkenrath extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = HeirToTheNight.class; // Discard a card: Transform Heir of Falkenrath. Activate this ability only once each turn. this.addAbility(new TransformAbility()); - this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new DiscardCardCost())); + this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new DiscardCardCost())); } private HeirOfFalkenrath(final HeirOfFalkenrath card) { diff --git a/Mage.Sets/src/mage/cards/h/HeirloomMirror.java b/Mage.Sets/src/mage/cards/h/HeirloomMirror.java index 43f576e01c1..4d71dcec837 100644 --- a/Mage.Sets/src/mage/cards/h/HeirloomMirror.java +++ b/Mage.Sets/src/mage/cards/h/HeirloomMirror.java @@ -28,7 +28,6 @@ public final class HeirloomMirror extends CardImpl { public HeirloomMirror(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{B}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.InheritedFiend.class; // {1}, {T}, Pay 1 life, Discard a card: Draw a card, mill a card, then put a ritual counter on Heirloom Mirror. Then if it has 3 or more ritual counters on it, remove them and transform it. Activate only as a sorcery. @@ -82,7 +81,7 @@ class HeirloomMirrorEffect extends OneShotEffect { return true; } permanent.removeCounters(CounterType.RITUAL.createInstance(counters), source, game); - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); return true; } } diff --git a/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java b/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java index 5b2becc29b4..e14800c3298 100644 --- a/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java +++ b/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java @@ -12,7 +12,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterSpell; import mage.filter.StaticFilters; import java.util.UUID; @@ -29,7 +28,6 @@ public final class HermitOfTheNatterknolls extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LoneWolfOfTheNatterknolls.class; // Whenever an opponent casts a spell during your turn, draw a card. diff --git a/Mage.Sets/src/mage/cards/h/HinterlandHermit.java b/Mage.Sets/src/mage/cards/h/HinterlandHermit.java index f1d42887767..549ec1ed1bd 100644 --- a/Mage.Sets/src/mage/cards/h/HinterlandHermit.java +++ b/Mage.Sets/src/mage/cards/h/HinterlandHermit.java @@ -20,7 +20,6 @@ public final class HinterlandHermit extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = HinterlandScourge.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/h/HinterlandLogger.java b/Mage.Sets/src/mage/cards/h/HinterlandLogger.java index a8e62953227..51df4a09630 100644 --- a/Mage.Sets/src/mage/cards/h/HinterlandLogger.java +++ b/Mage.Sets/src/mage/cards/h/HinterlandLogger.java @@ -22,7 +22,6 @@ public final class HinterlandLogger extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TimberShredder.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Hinterland Logger. diff --git a/Mage.Sets/src/mage/cards/h/HinterlandScourge.java b/Mage.Sets/src/mage/cards/h/HinterlandScourge.java index 155deff8108..942dfb7e1ef 100644 --- a/Mage.Sets/src/mage/cards/h/HinterlandScourge.java +++ b/Mage.Sets/src/mage/cards/h/HinterlandScourge.java @@ -25,7 +25,6 @@ public final class HinterlandScourge extends CardImpl { // this card is the second face of double-faced card of Hinterland Hermit this.nightCard = true; - this.transformable = true; this.power = new MageInt(3); this.toughness = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/h/HomicidalBrute.java b/Mage.Sets/src/mage/cards/h/HomicidalBrute.java index b4ec7d0412a..7e0ebe1baf0 100644 --- a/Mage.Sets/src/mage/cards/h/HomicidalBrute.java +++ b/Mage.Sets/src/mage/cards/h/HomicidalBrute.java @@ -10,10 +10,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.WatcherScope; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.watchers.Watcher; /** @@ -28,14 +28,13 @@ public final class HomicidalBrute extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.color.setRed(true); this.power = new MageInt(5); this.toughness = new MageInt(1); // At the beginning of your end step, if Homicidal Brute didn't attack this turn, tap Homicidal Brute, then transform it. - this.addAbility(new HomicidalBruteTriggeredAbility()); + this.addAbility(new HomicidalBruteTriggeredAbility(), new HomicidalBruteWatcher()); } private HomicidalBrute(final HomicidalBrute card) { @@ -53,7 +52,7 @@ class HomicidalBruteTriggeredAbility extends TriggeredAbilityImpl { public HomicidalBruteTriggeredAbility() { super(Zone.BATTLEFIELD, new TapSourceEffect(), false); - addEffect(new TransformSourceEffect(false)); + addEffect(new TransformSourceEffect()); } public HomicidalBruteTriggeredAbility(HomicidalBruteTriggeredAbility ability) { @@ -87,5 +86,19 @@ class HomicidalBruteTriggeredAbility extends TriggeredAbilityImpl { } } +class HomicidalBruteWatcher extends Watcher { + public HomicidalBruteWatcher() { + super(WatcherScope.CARD); + } + @Override + public void watch(GameEvent event, Game game) { + if (condition) { + return; + } + if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(sourceId)) { + condition = true; + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/h/HomicidalBruteWatcher.java b/Mage.Sets/src/mage/cards/h/HomicidalBruteWatcher.java deleted file mode 100644 index 4425e8cba38..00000000000 --- a/Mage.Sets/src/mage/cards/h/HomicidalBruteWatcher.java +++ /dev/null @@ -1,23 +0,0 @@ -package mage.cards.h; - -import mage.constants.WatcherScope; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.watchers.Watcher; - -public class HomicidalBruteWatcher extends Watcher { - - public HomicidalBruteWatcher() { - super(WatcherScope.CARD); - } - - @Override - public void watch(GameEvent event, Game game) { - if (condition) { - return; - } - if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(sourceId)) { - condition = true; - } - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java b/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java index bd3eaf73dd4..20484b801dd 100644 --- a/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java +++ b/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java @@ -23,7 +23,6 @@ public final class HookHauntDrifter extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/h/HostileHostel.java b/Mage.Sets/src/mage/cards/h/HostileHostel.java index 9156b6faebf..b0ceff1be5a 100644 --- a/Mage.Sets/src/mage/cards/h/HostileHostel.java +++ b/Mage.Sets/src/mage/cards/h/HostileHostel.java @@ -6,7 +6,6 @@ import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; @@ -31,7 +30,6 @@ public final class HostileHostel extends CardImpl { public HostileHostel(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - this.transformable = true; this.secondSideCardClazz = mage.cards.c.CreepingInn.class; // {T}: Add {C}. @@ -39,11 +37,10 @@ public final class HostileHostel extends CardImpl { // {1}, {T}, Sacrifice a creature: Put a soul counter on Hostile Hostel. Then if there are three or more soul counters on it, remove those counters, transform it, then untap it. Activate only as a sorcery. this.addAbility(new TransformAbility()); - Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new HostileHostelEffect(), new ManaCostsImpl("{1}")); + Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new HostileHostelEffect(), new ManaCostsImpl<>("{1}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); this.addAbility(ability); - } private HostileHostel(final HostileHostel card) { @@ -82,7 +79,7 @@ class HostileHostelEffect extends OneShotEffect { int counters = permanent.getCounters(game).getCount(CounterType.SOUL); if (counters > 2) { permanent.removeCounters(CounterType.SOUL.getName(), counters, source, game); - new TransformSourceEffect(true).apply(game, source); + permanent.transform(source, game); permanent.untap(game); } return true; diff --git a/Mage.Sets/src/mage/cards/h/HoundTamer.java b/Mage.Sets/src/mage/cards/h/HoundTamer.java index d45833ecbd5..f7cd37cdef8 100644 --- a/Mage.Sets/src/mage/cards/h/HoundTamer.java +++ b/Mage.Sets/src/mage/cards/h/HoundTamer.java @@ -29,7 +29,6 @@ public final class HoundTamer extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.u.UntamedPup.class; // Trample diff --git a/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java b/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java index b877500f252..8ac3ceb528c 100644 --- a/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java +++ b/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java @@ -40,7 +40,6 @@ public final class HowlpackAlpha extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.color.setGreen(true); this.power = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java b/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java index ded182d3163..42f61342450 100644 --- a/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java +++ b/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java @@ -21,7 +21,6 @@ public final class HowlpackOfEstwald extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(4); this.toughness = new MageInt(6); diff --git a/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java b/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java index a79558e8ae4..b2ab1b638ea 100644 --- a/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java +++ b/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java @@ -28,7 +28,6 @@ public final class HuntmasterOfTheFells extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.r.RavagerOfTheFells.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/i/InfectiousCurse.java b/Mage.Sets/src/mage/cards/i/InfectiousCurse.java index 4d5aec75422..1ed1ff50d5e 100644 --- a/Mage.Sets/src/mage/cards/i/InfectiousCurse.java +++ b/Mage.Sets/src/mage/cards/i/InfectiousCurse.java @@ -33,7 +33,6 @@ public final class InfectiousCurse extends CardImpl { this.color.setBlack(true); this.nightCard = true; - this.transformable = true; // Enchant player TargetPlayer auraTarget = new TargetPlayer(); diff --git a/Mage.Sets/src/mage/cards/i/InheritedFiend.java b/Mage.Sets/src/mage/cards/i/InheritedFiend.java index e76ba9ef80c..52f35e6004c 100644 --- a/Mage.Sets/src/mage/cards/i/InheritedFiend.java +++ b/Mage.Sets/src/mage/cards/i/InheritedFiend.java @@ -32,7 +32,6 @@ public final class InheritedFiend extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/i/InsidiousMist.java b/Mage.Sets/src/mage/cards/i/InsidiousMist.java index d429fc40bee..f5598c337da 100644 --- a/Mage.Sets/src/mage/cards/i/InsidiousMist.java +++ b/Mage.Sets/src/mage/cards/i/InsidiousMist.java @@ -36,7 +36,6 @@ public final class InsidiousMist extends CardImpl { this.color.setBlue(true); this.nightCard = true; - this.transformable = true; // Hexproof this.addAbility(HexproofAbility.getInstance()); @@ -53,7 +52,7 @@ public final class InsidiousMist extends CardImpl { // Whenever Insideous Mist attacks and isn't blocked, you may pay {2}{B}. If you do, transform it. this.addAbility(new TransformAbility()); - this.addAbility(new AttacksAndIsNotBlockedTriggeredAbility(new DoIfCostPaid(new TransformSourceEffect(false), new ManaCostsImpl("{2}{B}"), "Pay {2}{B} to transform?"))); + this.addAbility(new AttacksAndIsNotBlockedTriggeredAbility(new DoIfCostPaid(new TransformSourceEffect(), new ManaCostsImpl("{2}{B}"), "Pay {2}{B} to transform?"))); } private InsidiousMist(final InsidiousMist card) { diff --git a/Mage.Sets/src/mage/cards/i/InstigatorGang.java b/Mage.Sets/src/mage/cards/i/InstigatorGang.java index adbbb4ac482..a88e96462f2 100644 --- a/Mage.Sets/src/mage/cards/i/InstigatorGang.java +++ b/Mage.Sets/src/mage/cards/i/InstigatorGang.java @@ -24,7 +24,6 @@ public final class InstigatorGang extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WildbloodPack.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/i/Ironfang.java b/Mage.Sets/src/mage/cards/i/Ironfang.java index 2e287c13515..500ad43411f 100644 --- a/Mage.Sets/src/mage/cards/i/Ironfang.java +++ b/Mage.Sets/src/mage/cards/i/Ironfang.java @@ -22,7 +22,6 @@ public final class Ironfang extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(3); this.toughness = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java b/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java index 16aa5f01c56..2ae3ad22e52 100644 --- a/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java +++ b/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java @@ -31,7 +31,6 @@ public final class JaceTelepathUnbound extends CardImpl { this.color.setBlue(true); this.nightCard = true; - this.transformable = true; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5)); diff --git a/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java b/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java index e2af5275a3b..ec26a8ab46b 100644 --- a/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java +++ b/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java @@ -34,7 +34,6 @@ public final class JaceVrynsProdigy extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = JaceTelepathUnbound.class; // {T}: Draw a card, then discard a card. If there are five or more cards in your graveyard, exile Jace, Vryn's Prodigy, then return him to the battefield transformed under his owner's control. diff --git a/Mage.Sets/src/mage/cards/j/JerrenCorruptedBishop.java b/Mage.Sets/src/mage/cards/j/JerrenCorruptedBishop.java index aafbae17164..36eb28f00ad 100644 --- a/Mage.Sets/src/mage/cards/j/JerrenCorruptedBishop.java +++ b/Mage.Sets/src/mage/cards/j/JerrenCorruptedBishop.java @@ -45,7 +45,6 @@ public final class JerrenCorruptedBishop extends CardImpl { this.subtype.add(SubType.CLERIC); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.o.OrmendahlTheCorrupter.class; // Whenever Jerren, Corrupted Bishop enters the battlefield or another nontoken Human you control dies, you lose 1 life and create a 1/1 white Human creature token. @@ -61,7 +60,7 @@ public final class JerrenCorruptedBishop extends CardImpl { // At the beginning of your end step, if you have exactly 13 life, you may pay {4}{B}{B}. If you do, transform Jerren. this.addAbility(new TransformAbility()); this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new DoIfCostPaid( - new TransformSourceEffect(true), new ManaCostsImpl<>("{4}{B}{B}") + new TransformSourceEffect(), new ManaCostsImpl<>("{4}{B}{B}") ), TargetController.YOU, JerrenCorruptedBishopCondition.instance, false)); } diff --git a/Mage.Sets/src/mage/cards/j/JourneyToEternity.java b/Mage.Sets/src/mage/cards/j/JourneyToEternity.java index 71595f95f74..cb54bb7b777 100644 --- a/Mage.Sets/src/mage/cards/j/JourneyToEternity.java +++ b/Mage.Sets/src/mage/cards/j/JourneyToEternity.java @@ -34,7 +34,6 @@ public final class JourneyToEternity extends CardImpl { this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.AURA); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AtzalCaveOfEternity.class; // Enchant creature you control diff --git a/Mage.Sets/src/mage/cards/k/KessigForgemaster.java b/Mage.Sets/src/mage/cards/k/KessigForgemaster.java index 110c958e848..1b2339634d8 100644 --- a/Mage.Sets/src/mage/cards/k/KessigForgemaster.java +++ b/Mage.Sets/src/mage/cards/k/KessigForgemaster.java @@ -26,7 +26,6 @@ public final class KessigForgemaster extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.f.FlameheartWerewolf.class; // Whenever Kessig Forgemaster blocks or becomes blocked by a creature, Kessig Forgemaster deals 1 damage to that creature. diff --git a/Mage.Sets/src/mage/cards/k/KessigNaturalist.java b/Mage.Sets/src/mage/cards/k/KessigNaturalist.java index bc9096b8f54..bd4771b75f6 100644 --- a/Mage.Sets/src/mage/cards/k/KessigNaturalist.java +++ b/Mage.Sets/src/mage/cards/k/KessigNaturalist.java @@ -30,7 +30,6 @@ public final class KessigNaturalist extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LordOfTheUlvenwald.class; // Whenever Kessig Naturalist attacks, add {R} or {G}. Until end of turn, you don't lose this mana as steps and phases end. diff --git a/Mage.Sets/src/mage/cards/k/KessigProwler.java b/Mage.Sets/src/mage/cards/k/KessigProwler.java index 358e2cd7467..93a7767ae4d 100644 --- a/Mage.Sets/src/mage/cards/k/KessigProwler.java +++ b/Mage.Sets/src/mage/cards/k/KessigProwler.java @@ -26,12 +26,11 @@ public final class KessigProwler extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SinuousPredator.class; // {4}{G}: Transform Kessig Prowler. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{4}{G}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{4}{G}"))); } private KessigProwler(final KessigProwler card) { diff --git a/Mage.Sets/src/mage/cards/k/KindlyStranger.java b/Mage.Sets/src/mage/cards/k/KindlyStranger.java index 93e43fbd9e0..d6edfa74ece 100644 --- a/Mage.Sets/src/mage/cards/k/KindlyStranger.java +++ b/Mage.Sets/src/mage/cards/k/KindlyStranger.java @@ -26,13 +26,12 @@ public final class KindlyStranger extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DemonPossessedWitch.class; // Delirium — {2}{B}: Transform Kindly Stranger. Activate this ability only if there are four or more card types among cards in your graveyard. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl<>("{2}{B}"), + Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl<>("{2}{B}"), DeliriumCondition.instance, "Delirium — {2}{B}: Transform {this}. " + "Activate only if there are four or more card types among cards in your graveyard." ).addHint(CardTypesInGraveyardHint.YOU)); diff --git a/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java b/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java index 6d7fcccf936..c57d2e864bb 100644 --- a/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java +++ b/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java @@ -29,7 +29,6 @@ public final class KrallenhordeHowler extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Creature spells you cast cost {1} less to cast. this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(FILTER, 1))); diff --git a/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java b/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java index 71088f54106..6e7e4c4c8dd 100644 --- a/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java +++ b/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java @@ -28,7 +28,6 @@ public final class KrallenhordeKiller extends CardImpl { this.toughness = new MageInt(2); this.nightCard = true; - this.transformable = true; // {3}{G}: Krallenhorde Killer gets +4/+4 until end of turn. Activate this ability only once each turn. this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(4, 4, Duration.EndOfTurn), new ManaCostsImpl("{3}{G}"))); diff --git a/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java b/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java index abd6712e7e5..dc8e2624601 100644 --- a/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java +++ b/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java @@ -21,7 +21,6 @@ public final class KrallenhordeWantons extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(7); this.toughness = new MageInt(7); diff --git a/Mage.Sets/src/mage/cards/k/KruinOutlaw.java b/Mage.Sets/src/mage/cards/k/KruinOutlaw.java index 63c8a27ebc3..71b48621976 100644 --- a/Mage.Sets/src/mage/cards/k/KruinOutlaw.java +++ b/Mage.Sets/src/mage/cards/k/KruinOutlaw.java @@ -22,7 +22,6 @@ public final class KruinOutlaw extends CardImpl { this.subtype.add(SubType.ROGUE); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TerrorOfKruinPass.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java index 0cb6d0ab75d..768d3aaa976 100644 --- a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java +++ b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java @@ -40,7 +40,6 @@ public final class KytheonHeroOfAkros extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.g.GideonBattleForged.class; // At end of combat, if Kytheon, Hero of Akros and at least two other creatures attacked this combat, exile Kytheon, diff --git a/Mage.Sets/src/mage/cards/l/LambholtButcher.java b/Mage.Sets/src/mage/cards/l/LambholtButcher.java index b44499d9a5f..7e168fbffb3 100644 --- a/Mage.Sets/src/mage/cards/l/LambholtButcher.java +++ b/Mage.Sets/src/mage/cards/l/LambholtButcher.java @@ -2,18 +2,11 @@ package mage.cards.l; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.WerewolfBackTriggeredAbility; -import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.TransformSourceEffect; -import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; /** * @@ -30,7 +23,6 @@ public final class LambholtButcher extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Lambholt Butcher. this.addAbility(new WerewolfBackTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/l/LambholtElder.java b/Mage.Sets/src/mage/cards/l/LambholtElder.java index 6ef1223ee39..9706367e69e 100644 --- a/Mage.Sets/src/mage/cards/l/LambholtElder.java +++ b/Mage.Sets/src/mage/cards/l/LambholtElder.java @@ -23,7 +23,6 @@ public final class LambholtElder extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SilverpeltWerewolf.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Lambholt Elder. diff --git a/Mage.Sets/src/mage/cards/l/LambholtPacifist.java b/Mage.Sets/src/mage/cards/l/LambholtPacifist.java index 023c468e6c2..3c19a77b79b 100644 --- a/Mage.Sets/src/mage/cards/l/LambholtPacifist.java +++ b/Mage.Sets/src/mage/cards/l/LambholtPacifist.java @@ -29,7 +29,6 @@ public final class LambholtPacifist extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = LambholtButcher.class; // Lambholt Pacifist can't attack unless you control a creature with power 4 or greater. diff --git a/Mage.Sets/src/mage/cards/l/LeechingLurker.java b/Mage.Sets/src/mage/cards/l/LeechingLurker.java new file mode 100644 index 00000000000..1fc7474793a --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LeechingLurker.java @@ -0,0 +1,43 @@ +package mage.cards.l; + +import mage.MageInt; +import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.keyword.NightboundAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class LeechingLurker extends CardImpl { + + public LeechingLurker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.subtype.add(SubType.LEECH); + this.subtype.add(SubType.HORROR); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + this.color.setBlack(true); + this.nightCard = true; + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // Nightbound + this.addAbility(new NightboundAbility()); + } + + private LeechingLurker(final LeechingLurker card) { + super(card); + } + + @Override + public LeechingLurker copy() { + return new LeechingLurker(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LegionsLanding.java b/Mage.Sets/src/mage/cards/l/LegionsLanding.java index 62dc9fed1ce..baed5ab2413 100644 --- a/Mage.Sets/src/mage/cards/l/LegionsLanding.java +++ b/Mage.Sets/src/mage/cards/l/LegionsLanding.java @@ -28,7 +28,6 @@ public final class LegionsLanding extends CardImpl { this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AdantoTheFirstFort.class; // When Legion's Landing enters the battlefield, create a 1/1 white Vampire creature token with lifelink. @@ -36,7 +35,7 @@ public final class LegionsLanding extends CardImpl { // When you attack with three or more creatures, transform Legion's Landing. this.addAbility(new TransformAbility()); - this.addAbility(new LegionsLandingTriggeredAbility(new TransformSourceEffect(true))); + this.addAbility(new LegionsLandingTriggeredAbility(new TransformSourceEffect())); } private LegionsLanding(final LegionsLanding card) { diff --git a/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java b/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java index fd5b07b1b8b..740f2f21863 100644 --- a/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java +++ b/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java @@ -42,7 +42,6 @@ public final class LilianaHereticalHealer extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = LilianaDefiantNecromancer.class; this.addAbility(new TransformAbility()); diff --git a/Mage.Sets/src/mage/cards/l/LoneRider.java b/Mage.Sets/src/mage/cards/l/LoneRider.java index 8dc9205f81a..b87c872bc69 100644 --- a/Mage.Sets/src/mage/cards/l/LoneRider.java +++ b/Mage.Sets/src/mage/cards/l/LoneRider.java @@ -37,7 +37,6 @@ public final class LoneRider extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.ItThatRidesAsOne.class; // First strike @@ -50,7 +49,7 @@ public final class LoneRider extends CardImpl { this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility( - new TransformSourceEffect(true), TargetController.NEXT, false + new TransformSourceEffect(), TargetController.NEXT, false ), condition, ruleText ).addHint(hint), new PlayerGainedLifeWatcher()); } diff --git a/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java b/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java index 1f6020f6f6e..7dd9ba8be11 100644 --- a/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java +++ b/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java @@ -11,7 +11,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterSpell; import mage.filter.StaticFilters; import java.util.UUID; @@ -29,7 +28,6 @@ public final class LoneWolfOfTheNatterknolls extends CardImpl { this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // Whenever an opponent cast a spell during your turn, draw two cards. this.addAbility(new ConditionalTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/l/LordOfLineage.java b/Mage.Sets/src/mage/cards/l/LordOfLineage.java index b20e7d61509..1c8d6079993 100644 --- a/Mage.Sets/src/mage/cards/l/LordOfLineage.java +++ b/Mage.Sets/src/mage/cards/l/LordOfLineage.java @@ -40,7 +40,6 @@ public final class LordOfLineage extends CardImpl { // this card is the second face of double-faced card Bloodline Keeper this.nightCard = true; - this.transformable = true; this.addAbility(FlyingAbility.getInstance()); // Other Vampire creatures you control get +2/+2. diff --git a/Mage.Sets/src/mage/cards/l/LordOfTheUlvenwald.java b/Mage.Sets/src/mage/cards/l/LordOfTheUlvenwald.java index 05f56567b31..7fed8fc3c0f 100644 --- a/Mage.Sets/src/mage/cards/l/LordOfTheUlvenwald.java +++ b/Mage.Sets/src/mage/cards/l/LordOfTheUlvenwald.java @@ -45,7 +45,6 @@ public final class LordOfTheUlvenwald extends CardImpl { this.color.setRed(true); this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // Other Wolves and Werewolves you control get +1/+1. this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( diff --git a/Mage.Sets/src/mage/cards/l/LoyalCathar.java b/Mage.Sets/src/mage/cards/l/LoyalCathar.java index 656073481fb..eaa59129349 100644 --- a/Mage.Sets/src/mage/cards/l/LoyalCathar.java +++ b/Mage.Sets/src/mage/cards/l/LoyalCathar.java @@ -32,7 +32,6 @@ public final class LoyalCathar extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); - this.transformable = true; this.secondSideCardClazz = mage.cards.u.UnhallowedCathar.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/l/LudevicNecrogenius.java b/Mage.Sets/src/mage/cards/l/LudevicNecrogenius.java new file mode 100644 index 00000000000..d7dab640a37 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LudevicNecrogenius.java @@ -0,0 +1,61 @@ +package mage.cards.l; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; +import mage.abilities.costs.common.ExileXFromYourGraveCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.costs.mana.VariableManaCost; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.MillCardsControllerEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class LudevicNecrogenius extends CardImpl { + + public LudevicNecrogenius(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.o.OlagLudevicsHubris.class; + + // Whenever Ludevic, Necrogenius enters the battlefield or attacks, mill a card. + this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new MillCardsControllerEffect(1))); + + // {X}{U}{U}{B}{B}, Exile X creature cards from your graveyard: Transform Ludevic, Necrogenius. X can't be zero. Activate only as a sorcery. + this.addAbility(new TransformAbility()); + Ability ability = new ActivateAsSorceryActivatedAbility( + new TransformSourceEffect(), new ManaCostsImpl<>("{X}{U}{U}{B}{B}") + ); + ability.addEffect(new InfoEffect("X can't be 0")); + ability.addCost(new ExileXFromYourGraveCost(StaticFilters.FILTER_CARD_CREATURES_YOUR_GRAVEYARD)); + CardUtil.castStream(ability.getCosts().stream(), VariableManaCost.class).forEach(cost -> cost.setMinX(1)); + this.addAbility(ability); + } + + private LudevicNecrogenius(final LudevicNecrogenius card) { + super(card); + } + + @Override + public LudevicNecrogenius copy() { + return new LudevicNecrogenius(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LudevicsAbomination.java b/Mage.Sets/src/mage/cards/l/LudevicsAbomination.java index 4d9f5c33702..dcfe9517ef7 100644 --- a/Mage.Sets/src/mage/cards/l/LudevicsAbomination.java +++ b/Mage.Sets/src/mage/cards/l/LudevicsAbomination.java @@ -23,7 +23,6 @@ public final class LudevicsAbomination extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(13); this.toughness = new MageInt(13); diff --git a/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java b/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java index 6733f34f0a1..509e225b80a 100644 --- a/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java +++ b/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java @@ -34,7 +34,6 @@ public final class LudevicsTestSubject extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = LudevicsAbomination.class; this.addAbility(DefenderAbility.getInstance()); @@ -72,7 +71,7 @@ class LudevicsTestSubjectEffect extends OneShotEffect { if (p != null) { if (p.getCounters(game).getCount(CounterType.HATCHLING) >= 5) { p.removeCounters(CounterType.HATCHLING.getName(), p.getCounters(game).getCount(CounterType.HATCHLING), source, game); - TransformSourceEffect effect = new TransformSourceEffect(true); + TransformSourceEffect effect = new TransformSourceEffect(); return effect.apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/l/LuminousPhantom.java b/Mage.Sets/src/mage/cards/l/LuminousPhantom.java index 577fd9493f3..052b41b86de 100644 --- a/Mage.Sets/src/mage/cards/l/LuminousPhantom.java +++ b/Mage.Sets/src/mage/cards/l/LuminousPhantom.java @@ -36,7 +36,6 @@ public final class LuminousPhantom extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); this.color.setWhite(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/l/LunarchVeteran.java b/Mage.Sets/src/mage/cards/l/LunarchVeteran.java index 61596d263f3..a446183f230 100644 --- a/Mage.Sets/src/mage/cards/l/LunarchVeteran.java +++ b/Mage.Sets/src/mage/cards/l/LunarchVeteran.java @@ -26,7 +26,6 @@ public final class LunarchVeteran extends CardImpl { this.subtype.add(SubType.CLERIC); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.l.LuminousPhantom.class; // Whenever another creature enters the battlefield under your control, you gain 1 life. diff --git a/Mage.Sets/src/mage/cards/m/MalevolentHermit.java b/Mage.Sets/src/mage/cards/m/MalevolentHermit.java index 743e168f114..83cd130ef3f 100644 --- a/Mage.Sets/src/mage/cards/m/MalevolentHermit.java +++ b/Mage.Sets/src/mage/cards/m/MalevolentHermit.java @@ -30,7 +30,6 @@ public final class MalevolentHermit extends CardImpl { this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.b.BenevolentGeist.class; // {U}, Sacrifice Malevolent Hermit: Counter target noncreature spell unless its controller pays {3}. diff --git a/Mage.Sets/src/mage/cards/m/MarkovsServant.java b/Mage.Sets/src/mage/cards/m/MarkovsServant.java index 5b73ca58c87..81a62c53563 100644 --- a/Mage.Sets/src/mage/cards/m/MarkovsServant.java +++ b/Mage.Sets/src/mage/cards/m/MarkovsServant.java @@ -22,7 +22,6 @@ public final class MarkovsServant extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.nightCard = true; } diff --git a/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java b/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java index d3a85d1084b..f9f11c93350 100644 --- a/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java +++ b/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java @@ -31,7 +31,6 @@ public final class MayorOfAvabruck extends CardImpl { this.subtype.add(SubType.ADVISOR); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HowlpackAlpha.class; this.power = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/m/MercilessPredator.java b/Mage.Sets/src/mage/cards/m/MercilessPredator.java index 579f9b79f7b..9ea43ac8cd2 100644 --- a/Mage.Sets/src/mage/cards/m/MercilessPredator.java +++ b/Mage.Sets/src/mage/cards/m/MercilessPredator.java @@ -21,7 +21,6 @@ public final class MercilessPredator extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(3); this.toughness = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/m/MondronenShaman.java b/Mage.Sets/src/mage/cards/m/MondronenShaman.java index 2bedb848b58..8683524fe7d 100644 --- a/Mage.Sets/src/mage/cards/m/MondronenShaman.java +++ b/Mage.Sets/src/mage/cards/m/MondronenShaman.java @@ -24,7 +24,6 @@ public final class MondronenShaman extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TovolarsMagehunter.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Mondronen Shaman. diff --git a/Mage.Sets/src/mage/cards/m/Moonmist.java b/Mage.Sets/src/mage/cards/m/Moonmist.java index e039f421f2d..a952836ca18 100644 --- a/Mage.Sets/src/mage/cards/m/Moonmist.java +++ b/Mage.Sets/src/mage/cards/m/Moonmist.java @@ -1,7 +1,5 @@ - package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.PreventAllDamageByAllPermanentsEffect; @@ -16,13 +14,15 @@ import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author BetaSteward */ public final class Moonmist extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures other than Werewolves and Wolves"); + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("creatures other than Werewolves and Wolves"); static { filter.add(Predicates.not(SubType.WEREWOLF.getPredicate())); @@ -30,8 +30,7 @@ public final class Moonmist extends CardImpl { } public Moonmist(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); // Transform all Humans. Prevent all combat damage that would be dealt this turn by creatures other than Werewolves and Wolves. this.getSpellAbility().addEffect(new MoonmistEffect()); @@ -67,11 +66,8 @@ class MoonmistEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { - if (permanent.isTransformable()) { - permanent.transform(game); - game.informPlayers(permanent.getName() + " transforms into " + permanent.getSecondCardFace().getName()); - } + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { + permanent.transform(source, game); } return true; } @@ -80,5 +76,4 @@ class MoonmistEffect extends OneShotEffect { public MoonmistEffect copy() { return new MoonmistEffect(this); } - } diff --git a/Mage.Sets/src/mage/cards/m/MoonrageBrute.java b/Mage.Sets/src/mage/cards/m/MoonrageBrute.java index bbd90c57b43..eb754cd791e 100644 --- a/Mage.Sets/src/mage/cards/m/MoonrageBrute.java +++ b/Mage.Sets/src/mage/cards/m/MoonrageBrute.java @@ -24,7 +24,6 @@ public final class MoonrageBrute extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // First strike diff --git a/Mage.Sets/src/mage/cards/m/MoonragersSlash.java b/Mage.Sets/src/mage/cards/m/MoonragersSlash.java index f76db81ef33..a9167956ced 100644 --- a/Mage.Sets/src/mage/cards/m/MoonragersSlash.java +++ b/Mage.Sets/src/mage/cards/m/MoonragersSlash.java @@ -4,7 +4,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.NightCondition; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; -import mage.abilities.hint.common.NightHint; +import mage.abilities.hint.common.DayNightHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -24,7 +24,7 @@ public final class MoonragersSlash extends CardImpl { // This spell costs {2} less to cast if it's night. this.addAbility(new SimpleStaticAbility( Zone.ALL, new SpellCostReductionSourceEffect(2, NightCondition.instance) - ).addHint(NightHint.instance).setRuleAtTheTop(true)); + ).addHint(DayNightHint.instance).setRuleAtTheTop(true)); // Moonrager's Slash deals 3 damage to any target. this.getSpellAbility().addEffect(new DamageTargetEffect(3)); diff --git a/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java b/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java index b765b98d6af..0d53062f18e 100644 --- a/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java +++ b/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java @@ -24,7 +24,6 @@ public final class MoonriseIntruder extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Menace this.addAbility(new MenaceAbility()); diff --git a/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java b/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java index c5ee197498b..7bc6a02be36 100644 --- a/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java +++ b/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java @@ -29,7 +29,6 @@ public final class MoonscarredWerewolf extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.addAbility(VigilanceAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/m/MorningApparition.java b/Mage.Sets/src/mage/cards/m/MorningApparition.java index 2ab7a6c2582..3b04cf354d8 100644 --- a/Mage.Sets/src/mage/cards/m/MorningApparition.java +++ b/Mage.Sets/src/mage/cards/m/MorningApparition.java @@ -25,7 +25,6 @@ public final class MorningApparition extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); this.color.setWhite(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/m/MourningPatrol.java b/Mage.Sets/src/mage/cards/m/MourningPatrol.java index 8065c06f1f8..cf0aad468d3 100644 --- a/Mage.Sets/src/mage/cards/m/MourningPatrol.java +++ b/Mage.Sets/src/mage/cards/m/MourningPatrol.java @@ -24,7 +24,6 @@ public final class MourningPatrol extends CardImpl { this.subtype.add(SubType.SOLDIER); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MorningApparition.class; // Vigilance diff --git a/Mage.Sets/src/mage/cards/m/MysteriousTome.java b/Mage.Sets/src/mage/cards/m/MysteriousTome.java index 3458823bb07..100d607c828 100644 --- a/Mage.Sets/src/mage/cards/m/MysteriousTome.java +++ b/Mage.Sets/src/mage/cards/m/MysteriousTome.java @@ -21,7 +21,6 @@ public final class MysteriousTome extends CardImpl { public MysteriousTome(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{U}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.c.ChillingChronicle.class; // {2}, {T}: Draw a card. Transform Mysterious Tome. @@ -30,7 +29,7 @@ public final class MysteriousTome extends CardImpl { new DrawCardSourceControllerEffect(1), new GenericManaCost(2) ); ability.addCost(new TapSourceCost()); - ability.addEffect(new TransformSourceEffect(true)); + ability.addEffect(new TransformSourceEffect()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MysticMonstrosity.java b/Mage.Sets/src/mage/cards/m/MysticMonstrosity.java index 931d03eba21..3ba9014ef37 100644 --- a/Mage.Sets/src/mage/cards/m/MysticMonstrosity.java +++ b/Mage.Sets/src/mage/cards/m/MysticMonstrosity.java @@ -24,7 +24,6 @@ public final class MysticMonstrosity extends CardImpl { this.subtype.add(SubType.CONSTRUCT); this.power = new MageInt(5); this.toughness = new MageInt(6); - this.transformable = true; this.nightCard = true; // Lands you control have "{T}: Add one mana of any color." diff --git a/Mage.Sets/src/mage/cards/m/MysticSkull.java b/Mage.Sets/src/mage/cards/m/MysticSkull.java index 5c655efc6de..e9a14a86354 100644 --- a/Mage.Sets/src/mage/cards/m/MysticSkull.java +++ b/Mage.Sets/src/mage/cards/m/MysticSkull.java @@ -21,7 +21,6 @@ public final class MysticSkull extends CardImpl { public MysticSkull(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MysticMonstrosity.class; // {1}, {T}: Add one mana of any color. @@ -31,7 +30,7 @@ public final class MysticSkull extends CardImpl { // {5}, {T}: Transform Mystic Skull. this.addAbility(new TransformAbility()); - ability = new SimpleActivatedAbility(new TransformSourceEffect(true), new GenericManaCost(5)); + ability = new SimpleActivatedAbility(new TransformSourceEffect(), new GenericManaCost(5)); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NeckBreaker.java b/Mage.Sets/src/mage/cards/n/NeckBreaker.java index 4f9b4f0b7fb..96ced371e3f 100644 --- a/Mage.Sets/src/mage/cards/n/NeckBreaker.java +++ b/Mage.Sets/src/mage/cards/n/NeckBreaker.java @@ -30,7 +30,6 @@ public final class NeckBreaker extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Attacking creatures you control get +1/+0 and have trample. Ability ability = new SimpleStaticAbility(new BoostControlledEffect( diff --git a/Mage.Sets/src/mage/cards/n/NeglectedHeirloom.java b/Mage.Sets/src/mage/cards/n/NeglectedHeirloom.java index f2506666e47..810e1cb6d35 100644 --- a/Mage.Sets/src/mage/cards/n/NeglectedHeirloom.java +++ b/Mage.Sets/src/mage/cards/n/NeglectedHeirloom.java @@ -28,7 +28,6 @@ public final class NeglectedHeirloom extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); this.subtype.add(SubType.EQUIPMENT); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AshmouthBlade.class; // Equipped creature gets +1/+1. @@ -56,7 +55,7 @@ public final class NeglectedHeirloom extends CardImpl { class NeglectedHeirloomTriggeredAbility extends TriggeredAbilityImpl { public NeglectedHeirloomTriggeredAbility() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true), false); + super(Zone.BATTLEFIELD, new TransformSourceEffect(), false); } public NeglectedHeirloomTriggeredAbility(final NeglectedHeirloomTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/n/NicolBolasTheArisen.java b/Mage.Sets/src/mage/cards/n/NicolBolasTheArisen.java index 1b28ff7329e..de5f1adbe81 100644 --- a/Mage.Sets/src/mage/cards/n/NicolBolasTheArisen.java +++ b/Mage.Sets/src/mage/cards/n/NicolBolasTheArisen.java @@ -48,7 +48,6 @@ public final class NicolBolasTheArisen extends CardImpl { this.color.setBlack(true); this.color.setRed(true); this.nightCard = true; - this.transformable = true; this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(7)); diff --git a/Mage.Sets/src/mage/cards/n/NicolBolasTheRavager.java b/Mage.Sets/src/mage/cards/n/NicolBolasTheRavager.java index 30a8d6b8266..2ffc04c2ac5 100644 --- a/Mage.Sets/src/mage/cards/n/NicolBolasTheRavager.java +++ b/Mage.Sets/src/mage/cards/n/NicolBolasTheRavager.java @@ -34,7 +34,6 @@ public final class NicolBolasTheRavager extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = NicolBolasTheArisen.class; // Flying diff --git a/Mage.Sets/src/mage/cards/n/NightfallPredator.java b/Mage.Sets/src/mage/cards/n/NightfallPredator.java index 7b3d840e22c..bc354ed5429 100644 --- a/Mage.Sets/src/mage/cards/n/NightfallPredator.java +++ b/Mage.Sets/src/mage/cards/n/NightfallPredator.java @@ -30,7 +30,6 @@ public final class NightfallPredator extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // {R}, {tap}: Nightfall Predator fights target creature. Ability activatedAbility = new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java b/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java index 0323490ff24..63dbfb18982 100644 --- a/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java +++ b/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java @@ -40,8 +40,7 @@ public final class NissaVastwoodSeer extends CardImpl { this.subtype.add(SubType.SCOUT); this.power = new MageInt(2); this.toughness = new MageInt(2); - - this.transformable = true; + this.secondSideCardClazz = NissaSageAnimist.class; // When Nissa, Vastwood Seer enters the battlefield, you may search your library for a basic Forest card, reveal it, put it into your hand, then shuffle your library. diff --git a/Mage.Sets/src/mage/cards/o/OlagLudevicsHubris.java b/Mage.Sets/src/mage/cards/o/OlagLudevicsHubris.java new file mode 100644 index 00000000000..b3cf3cd498a --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OlagLudevicsHubris.java @@ -0,0 +1,135 @@ +package mage.cards.o; + +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.CopyEffect; +import mage.cards.*; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.PermanentCard; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInExile; +import mage.util.CardUtil; +import mage.util.functions.CopyApplier; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class OlagLudevicsHubris extends CardImpl { + + public OlagLudevicsHubris(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ZOMBIE); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + this.color.setBlue(true); + this.color.setBlack(true); + this.nightCard = true; + + // As this creature transforms in Olag, Ludevic's Hubris, it becomes a copy of a creature card exiled with it, except its name is Olag, Ludevic's Hubris, it's 4/4, and it's a legendary blue and black Zombie in addition to its other colors and types. Put a number of +1/+1 counters on Olag equal to the number of creature cards exiled with it. + this.addAbility(new SimpleStaticAbility(new OlagLudevicsHubrisEffect())); + } + + private OlagLudevicsHubris(final OlagLudevicsHubris card) { + super(card); + } + + @Override + public OlagLudevicsHubris copy() { + return new OlagLudevicsHubris(this); + } +} + +class OlagLudevicsHubrisEffect extends ReplacementEffectImpl { + + OlagLudevicsHubrisEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "as this creature transforms into {this}, it becomes a copy of a creature card exiled with it, " + + "except its name is Olag, Ludevic's Hubris, it's 4/4, and it's a legendary blue and black " + + "Zombie in addition to its other colors and types. Put a number of +1/+1 counters on {this} " + + "equal to the number of creature cards exiled with it"; + } + + private OlagLudevicsHubrisEffect(final OlagLudevicsHubrisEffect effect) { + super(effect); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Cards cards = new CardsImpl(game.getExile().getExileZone(CardUtil.getExileZoneId(game, source))); + cards.removeIf(uuid -> !game.getCard(uuid).isCreature(game)); + if (cards.isEmpty()) { + return false; + } + Card copyFromCard = getCard(cards, source, game); + if (copyFromCard == null) { + return false; + } + Permanent newBluePrint = new PermanentCard(copyFromCard, source.getControllerId(), game); + newBluePrint.assignNewId(); + CopyApplier applier = new OlagLudevicsHubrisCopyApplier(); + applier.apply(game, newBluePrint, source, source.getSourceId()); + CopyEffect copyEffect = new CopyEffect(Duration.Custom, newBluePrint, source.getSourceId()); + copyEffect.newId(); + copyEffect.setApplier(applier); + Ability newAbility = source.copy(); + copyEffect.init(newAbility, game); + game.addEffect(copyEffect, newAbility); + return false; + } + + private Card getCard(Cards cards, Ability source, Game game) { + if (cards.size() == 1) { + return cards.getRandom(game); + } + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return cards.getRandom(game); + } + TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD); + player.choose(outcome, target, source.getSourceId(), game); + return cards.get(target.getFirstTarget(), game); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRANSFORMING; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return source.getSourceId().equals(event.getTargetId()) + && source.getSourcePermanentIfItStillExists(game) != null; + } + + @Override + public OlagLudevicsHubrisEffect copy() { + return new OlagLudevicsHubrisEffect(this); + } +} + +class OlagLudevicsHubrisCopyApplier extends CopyApplier { + + @Override + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.setName("Olag, Ludevic's Hubris"); + blueprint.addSuperType(SuperType.LEGENDARY); + blueprint.addSubType(SubType.ZOMBIE); + blueprint.getColor().setBlue(true); + blueprint.getColor().setBlack(true); + blueprint.getPower().modifyBaseValue(4); + blueprint.getToughness().modifyBaseValue(4); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/o/OliviasMidnightAmbush.java b/Mage.Sets/src/mage/cards/o/OliviasMidnightAmbush.java index 872ea104fa6..ca02f9b7920 100644 --- a/Mage.Sets/src/mage/cards/o/OliviasMidnightAmbush.java +++ b/Mage.Sets/src/mage/cards/o/OliviasMidnightAmbush.java @@ -4,7 +4,7 @@ import mage.abilities.Ability; import mage.abilities.condition.common.NightCondition; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; -import mage.abilities.hint.common.NightHint; +import mage.abilities.hint.common.DayNightHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -25,7 +25,7 @@ public final class OliviasMidnightAmbush extends CardImpl { // Target creature gets -2/-2 until end of turn. If it's night, that creature gets -13/-13 until end of turn instead. this.getSpellAbility().addEffect(new OliviasMidnightAmbushEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addHint(NightHint.instance); + this.getSpellAbility().addHint(DayNightHint.instance); } private OliviasMidnightAmbush(final OliviasMidnightAmbush card) { diff --git a/Mage.Sets/src/mage/cards/o/OneOfThePack.java b/Mage.Sets/src/mage/cards/o/OneOfThePack.java index 9a47b281d50..40ce2562a2d 100644 --- a/Mage.Sets/src/mage/cards/o/OneOfThePack.java +++ b/Mage.Sets/src/mage/cards/o/OneOfThePack.java @@ -22,7 +22,6 @@ public final class OneOfThePack extends CardImpl { this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // At the beginning of each upkeep, if a player cast two or more spells last turn, transform One of the Pack. this.addAbility(new WerewolfBackTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/o/OrmendahlTheCorrupter.java b/Mage.Sets/src/mage/cards/o/OrmendahlTheCorrupter.java index 59c786aa5df..5fd1f827fc5 100644 --- a/Mage.Sets/src/mage/cards/o/OrmendahlTheCorrupter.java +++ b/Mage.Sets/src/mage/cards/o/OrmendahlTheCorrupter.java @@ -30,7 +30,6 @@ public final class OrmendahlTheCorrupter extends CardImpl { this.power = new MageInt(6); this.toughness = new MageInt(6); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/o/OutlandLiberator.java b/Mage.Sets/src/mage/cards/o/OutlandLiberator.java index 3e27af77112..d384f06dc53 100644 --- a/Mage.Sets/src/mage/cards/o/OutlandLiberator.java +++ b/Mage.Sets/src/mage/cards/o/OutlandLiberator.java @@ -12,6 +12,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import java.util.UUID; @@ -27,12 +29,12 @@ public final class OutlandLiberator extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.f.FrenziedTrapbreaker.class; // {1}, Sacrifice Outland Liberator: Destroy target artifact or enchantment. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new GenericManaCost(1)); ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); this.addAbility(ability); // Daybound diff --git a/Mage.Sets/src/mage/cards/o/OverwhelmedArchivist.java b/Mage.Sets/src/mage/cards/o/OverwhelmedArchivist.java index 724a434b1f5..52313b4b837 100644 --- a/Mage.Sets/src/mage/cards/o/OverwhelmedArchivist.java +++ b/Mage.Sets/src/mage/cards/o/OverwhelmedArchivist.java @@ -25,7 +25,6 @@ public final class OverwhelmedArchivist extends CardImpl { this.subtype.add(SubType.WIZARD); this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.ArchiveHaunt.class; // When Overwhelmed Archivist enters the battlefield, draw a card, then discard a card. diff --git a/Mage.Sets/src/mage/cards/p/PathOfMettle.java b/Mage.Sets/src/mage/cards/p/PathOfMettle.java index 78af4037d56..70584579e9c 100644 --- a/Mage.Sets/src/mage/cards/p/PathOfMettle.java +++ b/Mage.Sets/src/mage/cards/p/PathOfMettle.java @@ -45,7 +45,6 @@ public final class PathOfMettle extends CardImpl { this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MetzaliTowerOfTriumph.class; // When Path of Mettle enters the battlefield, it deals 1 damage to each creature that doesn't have first strike, double strike, vigilance, or haste. @@ -80,7 +79,7 @@ class PathOfMettleTriggeredAbility extends TriggeredAbilityImpl { } public PathOfMettleTriggeredAbility() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true)); + super(Zone.BATTLEFIELD, new TransformSourceEffect()); } public PathOfMettleTriggeredAbility(final PathOfMettleTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/p/PersistentNightmare.java b/Mage.Sets/src/mage/cards/p/PersistentNightmare.java index 13511fdea1a..d1825f3f44b 100644 --- a/Mage.Sets/src/mage/cards/p/PersistentNightmare.java +++ b/Mage.Sets/src/mage/cards/p/PersistentNightmare.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.effects.common.ReturnToHandSourceEffect; @@ -11,14 +9,15 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class PersistentNightmare extends CardImpl { public PersistentNightmare(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},""); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); this.subtype.add(SubType.NIGHTMARE); this.power = new MageInt(1); this.toughness = new MageInt(1); @@ -31,7 +30,9 @@ public final class PersistentNightmare extends CardImpl { this.addAbility(new SkulkAbility()); // When Persistent Nightmare deals combat damage to a player, return it to its owner's hand. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ReturnToHandSourceEffect(), false)); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new ReturnToHandSourceEffect(), false + ).setTriggerPhrase("When {this} deals combat damage to a player, ")); } private PersistentNightmare(final PersistentNightmare card) { diff --git a/Mage.Sets/src/mage/cards/p/PiousEvangel.java b/Mage.Sets/src/mage/cards/p/PiousEvangel.java index e4dd6ae851d..c7ac5cb8e30 100644 --- a/Mage.Sets/src/mage/cards/p/PiousEvangel.java +++ b/Mage.Sets/src/mage/cards/p/PiousEvangel.java @@ -43,7 +43,6 @@ public final class PiousEvangel extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WaywardDisciple.class; // Whenever Pious Evangel or another creature enters the battlefield under your control, you gain 1 life. @@ -51,7 +50,7 @@ public final class PiousEvangel extends CardImpl { // {2}, {T}, Sacrifice another permanent: Transform Pious Evangel. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new GenericManaCost(2)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new GenericManaCost(2)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter2))); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/p/PoppetFactory.java b/Mage.Sets/src/mage/cards/p/PoppetFactory.java index b4a7985bb24..0dd45685704 100644 --- a/Mage.Sets/src/mage/cards/p/PoppetFactory.java +++ b/Mage.Sets/src/mage/cards/p/PoppetFactory.java @@ -26,14 +26,13 @@ public final class PoppetFactory extends CardImpl { this.color.setBlue(true); this.nightCard = true; - this.transformable = true; // Creature tokens you control lose all abilities and have base power and toughness 3/3. this.addAbility(new SimpleStaticAbility(new PoppetFactoryEffect())); // At the beginning of your upkeep, you may transform Poppet Factory. this.addAbility(new BeginningOfUpkeepTriggeredAbility( - new TransformSourceEffect(false), TargetController.YOU, true + new TransformSourceEffect(), TargetController.YOU, true )); } diff --git a/Mage.Sets/src/mage/cards/p/PoppetStitcher.java b/Mage.Sets/src/mage/cards/p/PoppetStitcher.java index 7cd11c4d79d..07e4dab0ae6 100644 --- a/Mage.Sets/src/mage/cards/p/PoppetStitcher.java +++ b/Mage.Sets/src/mage/cards/p/PoppetStitcher.java @@ -43,7 +43,6 @@ public final class PoppetStitcher extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.p.PoppetFactory.class; // Whenever you cast an instant or sorcery spell, create a 2/2 black Zombie creature token with decayed. @@ -56,7 +55,7 @@ public final class PoppetStitcher extends CardImpl { this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility( - new TransformSourceEffect(true), + new TransformSourceEffect(), TargetController.YOU, true ), condition, "At the beginning of your upkeep, " + "if you control three or more creature tokens, you may transform {this}." diff --git a/Mage.Sets/src/mage/cards/p/PrimalAmulet.java b/Mage.Sets/src/mage/cards/p/PrimalAmulet.java index d8e17789c65..b15a482046b 100644 --- a/Mage.Sets/src/mage/cards/p/PrimalAmulet.java +++ b/Mage.Sets/src/mage/cards/p/PrimalAmulet.java @@ -39,7 +39,6 @@ public final class PrimalAmulet extends CardImpl { public PrimalAmulet(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); - this.transformable = true; this.secondSideCardClazz = PrimalWellspring.class; // Instant and sorcery spells you cast cost {1} less to cast. @@ -87,7 +86,7 @@ class PrimalAmuletEffect extends OneShotEffect { int counters = permanent.getCounters(game).getCount(CounterType.CHARGE); if (counters > 3 && player.chooseUse(Outcome.Benefit, "Transform this?", source, game)) { permanent.removeCounters("charge", counters, source, game); - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); } return true; } diff --git a/Mage.Sets/src/mage/cards/p/ProfaneProcession.java b/Mage.Sets/src/mage/cards/p/ProfaneProcession.java index 3c0baffc3eb..cdf06c4a1aa 100644 --- a/Mage.Sets/src/mage/cards/p/ProfaneProcession.java +++ b/Mage.Sets/src/mage/cards/p/ProfaneProcession.java @@ -33,7 +33,6 @@ public final class ProfaneProcession extends CardImpl { this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TombOfTheDuskRose.class; // {3}{W}{B}: Exile target creature. Then if there are three or more cards exiled with Profane Procession, transform it. @@ -79,7 +78,7 @@ class ProfaneProcessionEffect extends OneShotEffect { game.getState().processAction(game); ExileZone exileZone = game.getExile().getExileZone(exileId); if (exileZone != null && exileZone.size() > 2) { - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); } return true; } diff --git a/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java b/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java index 93cbf1d62ad..b31735e695b 100644 --- a/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java +++ b/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java @@ -21,7 +21,6 @@ public final class RampagingWerewolf extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(6); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java b/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java index 8b4c020a10f..788c49c74fb 100644 --- a/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java +++ b/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java @@ -40,7 +40,6 @@ public final class RavagerOfTheFells extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(4); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/r/RavenousDemon.java b/Mage.Sets/src/mage/cards/r/RavenousDemon.java index 59e53fbb941..d4f60829f80 100644 --- a/Mage.Sets/src/mage/cards/r/RavenousDemon.java +++ b/Mage.Sets/src/mage/cards/r/RavenousDemon.java @@ -30,7 +30,6 @@ public final class RavenousDemon extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.subtype.add(SubType.DEMON); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.ArchdemonOfGreed.class; this.power = new MageInt(4); @@ -38,7 +37,7 @@ public final class RavenousDemon extends CardImpl { // Sacrifice a Human: Transform Ravenous Demon. Activate this ability only any time you could cast a sorcery. this.addAbility(new TransformAbility()); - this.addAbility(new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new SacrificeTargetCost(new TargetControlledPermanent(filter)))); + this.addAbility(new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new SacrificeTargetCost(new TargetControlledPermanent(filter)))); } private RavenousDemon(final RavenousDemon card) { diff --git a/Mage.Sets/src/mage/cards/r/RecklessStormseeker.java b/Mage.Sets/src/mage/cards/r/RecklessStormseeker.java index 8b78f15c067..c6f1bce00ce 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessStormseeker.java +++ b/Mage.Sets/src/mage/cards/r/RecklessStormseeker.java @@ -30,7 +30,6 @@ public final class RecklessStormseeker extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.StormChargedSlasher.class; // At the beginning of combat on your turn, target creature you control gets +1/+0 and gains haste until end of turn. diff --git a/Mage.Sets/src/mage/cards/r/RecklessWaif.java b/Mage.Sets/src/mage/cards/r/RecklessWaif.java index 848d23ac623..dae8b27df78 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessWaif.java +++ b/Mage.Sets/src/mage/cards/r/RecklessWaif.java @@ -21,7 +21,6 @@ public final class RecklessWaif extends CardImpl { this.subtype.add(SubType.ROGUE); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MercilessPredator.class; this.power = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java b/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java index 1dd23df3725..0d28e9a5cf6 100644 --- a/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java +++ b/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java @@ -33,7 +33,6 @@ public final class SageOfAncientLore extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(0); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WerewolfOfAncientHunger.class; // Sage of Ancient Lore's power and toughness are each equal to the number of cards in your hand. diff --git a/Mage.Sets/src/mage/cards/s/ScornedVillager.java b/Mage.Sets/src/mage/cards/s/ScornedVillager.java index 69cce60517a..2092c0575b1 100644 --- a/Mage.Sets/src/mage/cards/s/ScornedVillager.java +++ b/Mage.Sets/src/mage/cards/s/ScornedVillager.java @@ -24,7 +24,6 @@ public final class ScornedVillager extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MoonscarredWerewolf.class; // {tap}: Add {G}. diff --git a/Mage.Sets/src/mage/cards/s/ScreechingBat.java b/Mage.Sets/src/mage/cards/s/ScreechingBat.java index 8c1c31fd8b7..ddfabda8560 100644 --- a/Mage.Sets/src/mage/cards/s/ScreechingBat.java +++ b/Mage.Sets/src/mage/cards/s/ScreechingBat.java @@ -1,12 +1,9 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.costs.Cost; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TransformAbility; @@ -14,11 +11,9 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; +import mage.constants.TargetController; + +import java.util.UUID; /** * @author nantuko @@ -29,7 +24,6 @@ public final class ScreechingBat extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); this.subtype.add(SubType.BAT); - this.transformable = true; this.secondSideCardClazz = StalkingVampire.class; this.power = new MageInt(2); @@ -39,7 +33,10 @@ public final class ScreechingBat extends CardImpl { // At the beginning of your upkeep, you may pay {2}{B}{B}. If you do, transform Screeching Bat. this.addAbility(new TransformAbility()); - this.addAbility(new ScreechingBatBeginningOfUpkeepTriggeredAbility()); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid( + new TransformSourceEffect(), + new ManaCostsImpl<>("{2}{B}{B}") + ), TargetController.YOU, false)); } private ScreechingBat(final ScreechingBat card) { @@ -51,65 +48,3 @@ public final class ScreechingBat extends CardImpl { return new ScreechingBat(this); } } - -class ScreechingBatBeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl { - - public ScreechingBatBeginningOfUpkeepTriggeredAbility() { - super(Zone.BATTLEFIELD, new ScreechingBatTransformSourceEffect(), true); - } - - public ScreechingBatBeginningOfUpkeepTriggeredAbility(final ScreechingBatBeginningOfUpkeepTriggeredAbility ability) { - super(ability); - } - - @Override - public ScreechingBatBeginningOfUpkeepTriggeredAbility copy() { - return new ScreechingBatBeginningOfUpkeepTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals(this.controllerId); - } - - @Override - public String getRule() { - return "At the beginning of your upkeep, you may pay {2}{B}{B}. If you do, transform {this}."; - } -} - -class ScreechingBatTransformSourceEffect extends OneShotEffect { - - public ScreechingBatTransformSourceEffect() { - super(Outcome.Transform); - staticText = "transform {this}"; - } - - public ScreechingBatTransformSourceEffect(final ScreechingBatTransformSourceEffect effect) { - super(effect); - } - - @Override - public ScreechingBatTransformSourceEffect copy() { - return new ScreechingBatTransformSourceEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - Cost cost = new ManaCostsImpl("{2}{B}{B}"); - if (cost.pay(source, game, source, permanent.getControllerId(), false, null)) { - new TransformSourceEffect(true).apply(game, source); - } - return true; - } - return false; - } - -} diff --git a/Mage.Sets/src/mage/cards/s/SeafaringWerewolf.java b/Mage.Sets/src/mage/cards/s/SeafaringWerewolf.java index c075a58ed96..56b3b8c7054 100644 --- a/Mage.Sets/src/mage/cards/s/SeafaringWerewolf.java +++ b/Mage.Sets/src/mage/cards/s/SeafaringWerewolf.java @@ -24,7 +24,6 @@ public final class SeafaringWerewolf extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Seafaring Werewolf can't be blocked. diff --git a/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java b/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java index 32cb3ac1446..6973145726a 100644 --- a/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java +++ b/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java @@ -29,7 +29,6 @@ public final class SearchForAzcanta extends CardImpl { public SearchForAzcanta(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AzcantaTheSunkenRuin.class; this.addSuperType(SuperType.LEGENDARY); @@ -80,7 +79,7 @@ class SearchForAzcantaLookLibraryEffect extends OneShotEffect { controller.moveCards(card, Zone.GRAVEYARD, source, game); } if (controller.getGraveyard().size() > 6 && controller.chooseUse(Outcome.Neutral, "Transform " + sourceObject.getLogName() + "?", source, game)) { - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); } } } diff --git a/Mage.Sets/src/mage/cards/s/SeasonedCathar.java b/Mage.Sets/src/mage/cards/s/SeasonedCathar.java index 85d9b7e5876..57397897f3d 100644 --- a/Mage.Sets/src/mage/cards/s/SeasonedCathar.java +++ b/Mage.Sets/src/mage/cards/s/SeasonedCathar.java @@ -22,7 +22,6 @@ public final class SeasonedCathar extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); this.color.setWhite(true); - this.transformable = true; this.nightCard = true; // Lifelink diff --git a/Mage.Sets/src/mage/cards/s/ShadyTraveler.java b/Mage.Sets/src/mage/cards/s/ShadyTraveler.java index f2424f30024..97840bed8d0 100644 --- a/Mage.Sets/src/mage/cards/s/ShadyTraveler.java +++ b/Mage.Sets/src/mage/cards/s/ShadyTraveler.java @@ -23,7 +23,6 @@ public final class ShadyTraveler extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.StalkingPredator.class; // Menace diff --git a/Mage.Sets/src/mage/cards/s/ShrillHowler.java b/Mage.Sets/src/mage/cards/s/ShrillHowler.java index bfd0b23bd22..b08fa88df95 100644 --- a/Mage.Sets/src/mage/cards/s/ShrillHowler.java +++ b/Mage.Sets/src/mage/cards/s/ShrillHowler.java @@ -28,7 +28,6 @@ public final class ShrillHowler extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HowlingChorus.class; // Creatures with power less than Shrill Howler's power can't block it. @@ -36,7 +35,7 @@ public final class ShrillHowler extends CardImpl { // {5}{G}: Transform Shrill Howler. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl<>("{5}{G}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl<>("{5}{G}"))); } diff --git a/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java b/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java index e98bee109b9..8bf1157c998 100644 --- a/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java +++ b/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java @@ -24,7 +24,6 @@ public final class SilverpeltWerewolf extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(5); - this.transformable = true; this.nightCard = true; // Whenever Silverpelt Werewolf deals combat damage to a player, draw a card. diff --git a/Mage.Sets/src/mage/cards/s/SkinInvasion.java b/Mage.Sets/src/mage/cards/s/SkinInvasion.java index 570fc75c936..d41fd9d2657 100644 --- a/Mage.Sets/src/mage/cards/s/SkinInvasion.java +++ b/Mage.Sets/src/mage/cards/s/SkinInvasion.java @@ -34,7 +34,6 @@ public final class SkinInvasion extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{R}"); this.subtype.add(SubType.AURA); - this.transformable = true; this.secondSideCardClazz = SkinShedder.class; // Enchant creature diff --git a/Mage.Sets/src/mage/cards/s/SmolderingEgg.java b/Mage.Sets/src/mage/cards/s/SmolderingEgg.java index b64c045305d..cf07316e41b 100644 --- a/Mage.Sets/src/mage/cards/s/SmolderingEgg.java +++ b/Mage.Sets/src/mage/cards/s/SmolderingEgg.java @@ -33,7 +33,6 @@ public final class SmolderingEgg extends CardImpl { this.subtype.add(SubType.EGG); this.power = new MageInt(0); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AshmouthDragon.class; // Defender @@ -92,7 +91,7 @@ class SmolderingEggEffect extends OneShotEffect { return true; } permanent.removeCounters(CounterType.EMBER.createInstance(counters), source, game); - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SmolderingWerewolf.java b/Mage.Sets/src/mage/cards/s/SmolderingWerewolf.java index 755b9fa4600..42825ddfeed 100644 --- a/Mage.Sets/src/mage/cards/s/SmolderingWerewolf.java +++ b/Mage.Sets/src/mage/cards/s/SmolderingWerewolf.java @@ -31,7 +31,6 @@ public final class SmolderingWerewolf extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.e.EruptingDreadwolf.class; // When Smoldering Werewolf enters the battlefield, it deals 1 damage to each of up to two target creatures. @@ -43,7 +42,7 @@ public final class SmolderingWerewolf extends CardImpl { // {4}{R}{R}: Transform Smoldering Werewolf. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{4}{R}{R}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{4}{R}{R}"))); } private SmolderingWerewolf(final SmolderingWerewolf card) { diff --git a/Mage.Sets/src/mage/cards/s/SolitaryHunter.java b/Mage.Sets/src/mage/cards/s/SolitaryHunter.java index 12a6694d70f..29ca759d8e4 100644 --- a/Mage.Sets/src/mage/cards/s/SolitaryHunter.java +++ b/Mage.Sets/src/mage/cards/s/SolitaryHunter.java @@ -24,7 +24,6 @@ public final class SolitaryHunter extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.o.OneOfThePack.class; // At the beginning of each upkeep, if no spells were cast last turn, transform Solitary Hunter. diff --git a/Mage.Sets/src/mage/cards/s/SoulSeizer.java b/Mage.Sets/src/mage/cards/s/SoulSeizer.java index f3b909ec3f6..0902e44ae2e 100644 --- a/Mage.Sets/src/mage/cards/s/SoulSeizer.java +++ b/Mage.Sets/src/mage/cards/s/SoulSeizer.java @@ -1,8 +1,5 @@ - package mage.cards.s; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; @@ -12,19 +9,20 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * @author BetaSteward */ @@ -34,7 +32,6 @@ public final class SoulSeizer extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); this.subtype.add(SubType.SPIRIT); - this.transformable = true; this.secondSideCardClazz = mage.cards.g.GhastlyHaunting.class; this.power = new MageInt(1); @@ -113,16 +110,11 @@ class SoulSeizerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null && permanent.isTransformable()) { - if (permanent.transform(game)) { - game.informPlayers(permanent.getName() + " transforms into " + permanent.getSecondCardFace().getName()); - Permanent attachTo = game.getPermanent(targetPointer.getFirst(game, source)); - if (attachTo != null) { - return attachTo.addAttachment(source.getSourceId(), source, game); - } - } + if (permanent == null || !permanent.transform(source, game)) { + return false; } - return false; + Permanent attachTo = game.getPermanent(targetPointer.getFirst(game, source)); + return attachTo != null && attachTo.addAttachment(source.getSourceId(), source, game); } @Override diff --git a/Mage.Sets/src/mage/cards/s/SpellruneHowler.java b/Mage.Sets/src/mage/cards/s/SpellruneHowler.java index a7419fbe12c..e8c5b16fdcf 100644 --- a/Mage.Sets/src/mage/cards/s/SpellruneHowler.java +++ b/Mage.Sets/src/mage/cards/s/SpellruneHowler.java @@ -26,7 +26,6 @@ public final class SpellruneHowler extends CardImpl { this.toughness = new MageInt(4); this.color.setRed(true); this.nightCard = true; - this.transformable = true; // Whenever you cast an instant or sorcery spell, Spellrune Howler gets +2/+2 until end of turn. this.addAbility(new SpellCastControllerTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/s/SpellrunePainter.java b/Mage.Sets/src/mage/cards/s/SpellrunePainter.java index 8a7b20c3458..572b4cf414b 100644 --- a/Mage.Sets/src/mage/cards/s/SpellrunePainter.java +++ b/Mage.Sets/src/mage/cards/s/SpellrunePainter.java @@ -27,7 +27,6 @@ public final class SpellrunePainter extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SpellruneHowler.class; // Whenever you cast an instant or sorcery spell, Spellrune Painter gets +1/+1 until end of turn. diff --git a/Mage.Sets/src/mage/cards/s/StalkingPredator.java b/Mage.Sets/src/mage/cards/s/StalkingPredator.java index 98ce16017b5..41a12f42f97 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingPredator.java +++ b/Mage.Sets/src/mage/cards/s/StalkingPredator.java @@ -22,7 +22,6 @@ public final class StalkingPredator extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Menace diff --git a/Mage.Sets/src/mage/cards/s/StalkingVampire.java b/Mage.Sets/src/mage/cards/s/StalkingVampire.java index 66065d0fbac..c126b2078ec 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingVampire.java +++ b/Mage.Sets/src/mage/cards/s/StalkingVampire.java @@ -1,23 +1,17 @@ package mage.cards.s; import mage.MageInt; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.TransformSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.TargetController; import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.costs.Cost; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.TransformSourceEffect; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; /** * @author nantuko @@ -30,13 +24,15 @@ public final class StalkingVampire extends CardImpl { this.color.setBlack(true); this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(5); // At the beginning of your upkeep, you may pay {2}{B}{B}. If you do, transform Stalking Vampire. - this.addAbility(new StalkingVampireBeginningOfUpkeepTriggeredAbility()); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid( + new TransformSourceEffect(), + new ManaCostsImpl<>("{2}{B}{B}") + ), TargetController.YOU, false)); } private StalkingVampire(final StalkingVampire card) { @@ -48,65 +44,3 @@ public final class StalkingVampire extends CardImpl { return new StalkingVampire(this); } } - -class StalkingVampireBeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl { - - public StalkingVampireBeginningOfUpkeepTriggeredAbility() { - super(Zone.BATTLEFIELD, new StalkingVampireTransformSourceEffect(), true); - } - - public StalkingVampireBeginningOfUpkeepTriggeredAbility(final StalkingVampireBeginningOfUpkeepTriggeredAbility ability) { - super(ability); - } - - @Override - public StalkingVampireBeginningOfUpkeepTriggeredAbility copy() { - return new StalkingVampireBeginningOfUpkeepTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals(this.controllerId); - } - - @Override - public String getRule() { - return "At the beginning of your upkeep, you may pay {2}{B}{B}. If you do, transform {this}."; - } -} - -class StalkingVampireTransformSourceEffect extends OneShotEffect { - - public StalkingVampireTransformSourceEffect() { - super(Outcome.Transform); - staticText = "transform {this}"; - } - - public StalkingVampireTransformSourceEffect(final StalkingVampireTransformSourceEffect effect) { - super(effect); - } - - @Override - public StalkingVampireTransformSourceEffect copy() { - return new StalkingVampireTransformSourceEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - Cost cost = new ManaCostsImpl("{2}{B}{B}"); - if (cost.pay(source, game, source, permanent.getControllerId(), false, null)) { - new TransformSourceEffect(false).apply(game, source); - } - return true; - } - return false; - } - -} diff --git a/Mage.Sets/src/mage/cards/s/StartledAwake.java b/Mage.Sets/src/mage/cards/s/StartledAwake.java index ee34baf9f96..d2709bba456 100644 --- a/Mage.Sets/src/mage/cards/s/StartledAwake.java +++ b/Mage.Sets/src/mage/cards/s/StartledAwake.java @@ -1,8 +1,6 @@ - package mage.cards.s; -import java.util.UUID; - +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -19,6 +17,8 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** * @author LevelX2 */ @@ -27,7 +27,6 @@ public final class StartledAwake extends CardImpl { public StartledAwake(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}{U}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.p.PersistentNightmare.class; // Target opponent puts the top thirteen cards of their library into their graveyard. @@ -36,9 +35,9 @@ public final class StartledAwake extends CardImpl { // {3}{U}{U}: Put Startled Awake from your graveyard onto the battlefield transformed. Activate this ability only any time you could cast a sorcery. this.addAbility(new TransformAbility()); - Ability ability = new ActivateAsSorceryActivatedAbility(Zone.GRAVEYARD, new StartledAwakeReturnTransformedEffect(), new ManaCostsImpl("{3}{U}{U}")); - this.addAbility(ability); - + this.addAbility(new ActivateAsSorceryActivatedAbility( + Zone.GRAVEYARD, new StartledAwakeReturnTransformedEffect(), new ManaCostsImpl<>("{3}{U}{U}") + )); } private StartledAwake(final StartledAwake card) { @@ -70,16 +69,16 @@ class StartledAwakeReturnTransformedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - if (game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { - game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE); - Card card = game.getCard(source.getSourceId()); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } + MageObject sourceObject = source.getSourceObjectIfItStillExists(game); + if (controller == null || !(sourceObject instanceof Card)) { + return false; + } + if (game.getState().getZone(source.getSourceId()) != Zone.GRAVEYARD) { return true; } - return false; + Card card = (Card) sourceObject; + game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), true); + controller.moveCards(card, Zone.BATTLEFIELD, source, game); + return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/StormChargedSlasher.java b/Mage.Sets/src/mage/cards/s/StormChargedSlasher.java index 93ba611b364..7557903736a 100644 --- a/Mage.Sets/src/mage/cards/s/StormChargedSlasher.java +++ b/Mage.Sets/src/mage/cards/s/StormChargedSlasher.java @@ -30,7 +30,6 @@ public final class StormChargedSlasher extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(4); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // At the beginning of combat on your turn, target creature you control gets +2/+0 and gains trample and haste until end of turn. diff --git a/Mage.Sets/src/mage/cards/s/StormTheVault.java b/Mage.Sets/src/mage/cards/s/StormTheVault.java index 5dd55b22a31..7e40fbc0493 100644 --- a/Mage.Sets/src/mage/cards/s/StormTheVault.java +++ b/Mage.Sets/src/mage/cards/s/StormTheVault.java @@ -29,7 +29,6 @@ public final class StormTheVault extends CardImpl { this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.v.VaultOfCatlacan.class; // Whenever one or more creatures you control deal combat damage to a player, create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color." @@ -38,7 +37,7 @@ public final class StormTheVault extends CardImpl { // At the beginning of your end step, if you control five or more artifacts, transform Storm the Vault. this.addAbility(new TransformAbility()); this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), + new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, ComparisonType.MORE_THAN, 4), "At the beginning of your end step, if you control five or more artifacts, transform {this}")); diff --git a/Mage.Sets/src/mage/cards/s/StranglingGrasp.java b/Mage.Sets/src/mage/cards/s/StranglingGrasp.java index c3665cff1ae..2c78cb5ff18 100644 --- a/Mage.Sets/src/mage/cards/s/StranglingGrasp.java +++ b/Mage.Sets/src/mage/cards/s/StranglingGrasp.java @@ -38,7 +38,6 @@ public final class StranglingGrasp extends CardImpl { this.subtype.add(SubType.AURA); this.color.setBlack(true); - this.transformable = true; this.nightCard = true; // Enchant creature or planeswalker an opponent controls diff --git a/Mage.Sets/src/mage/cards/s/SuspiciousStowaway.java b/Mage.Sets/src/mage/cards/s/SuspiciousStowaway.java index 83c217f6fc6..f12bb5ecd9a 100644 --- a/Mage.Sets/src/mage/cards/s/SuspiciousStowaway.java +++ b/Mage.Sets/src/mage/cards/s/SuspiciousStowaway.java @@ -26,7 +26,6 @@ public final class SuspiciousStowaway extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SeafaringWerewolf.class; // Suspicious Stowaway can't be blocked. diff --git a/Mage.Sets/src/mage/cards/t/TangleclawWerewolf.java b/Mage.Sets/src/mage/cards/t/TangleclawWerewolf.java index a7133e5cb15..5ddfe0c12bc 100644 --- a/Mage.Sets/src/mage/cards/t/TangleclawWerewolf.java +++ b/Mage.Sets/src/mage/cards/t/TangleclawWerewolf.java @@ -29,7 +29,6 @@ public final class TangleclawWerewolf extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.f.FibrousEntangler.class; // Tangleclaw Werewolf can block an additional creature each combat. @@ -37,7 +36,7 @@ public final class TangleclawWerewolf extends CardImpl { // {6}{G}: Transform Tangleclaw Werewolf. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl<>("{6}{G}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl<>("{6}{G}"))); } private TangleclawWerewolf(final TangleclawWerewolf card) { diff --git a/Mage.Sets/src/mage/cards/t/TavernRuffian.java b/Mage.Sets/src/mage/cards/t/TavernRuffian.java index b06f875bd57..dc0e39395e6 100644 --- a/Mage.Sets/src/mage/cards/t/TavernRuffian.java +++ b/Mage.Sets/src/mage/cards/t/TavernRuffian.java @@ -24,7 +24,6 @@ public final class TavernRuffian extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(5); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TavernSmasher.class; // Daybound diff --git a/Mage.Sets/src/mage/cards/t/TavernSmasher.java b/Mage.Sets/src/mage/cards/t/TavernSmasher.java index 8a3b1258e57..23e61cd013e 100644 --- a/Mage.Sets/src/mage/cards/t/TavernSmasher.java +++ b/Mage.Sets/src/mage/cards/t/TavernSmasher.java @@ -22,7 +22,6 @@ public final class TavernSmasher extends CardImpl { this.color.setRed(true); this.nightCard = true; - this.transformable = true; this.power = new MageInt(6); this.toughness = new MageInt(5); diff --git a/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java b/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java index 7e3cb3b8a88..7811cf8be57 100644 --- a/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java +++ b/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java @@ -28,7 +28,6 @@ public final class TerrorOfKruinPass extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.color.setRed(true); this.power = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java b/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java index a3d446cfae2..f8ca94370ef 100644 --- a/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java +++ b/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java @@ -31,7 +31,6 @@ public final class ThaumaticCompass extends CardImpl { public ThaumaticCompass(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SpiresOfOrazca.class; // {3}, {T}: Search your library for a basic land card, reveal it, put it into your hand, then shuffle your library. @@ -43,7 +42,7 @@ public final class ThaumaticCompass extends CardImpl { // At the beginning of your end step, if you control seven or more lands, transform Thaumatic Compass. this.addAbility(new TransformAbility()); - TriggeredAbility ability2 = new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false); + TriggeredAbility ability2 = new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(), TargetController.YOU, false); this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability2, new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), ComparisonType.MORE_THAN, 6, true), diff --git a/Mage.Sets/src/mage/cards/t/TheCelestus.java b/Mage.Sets/src/mage/cards/t/TheCelestus.java new file mode 100644 index 00000000000..24bc5c1f851 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheCelestus.java @@ -0,0 +1,114 @@ +package mage.cards.t; + +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.BecomeDayAsEntersAbility; +import mage.abilities.common.BecomesDayOrNightTriggeredAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.mana.AnyColorManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheCelestus extends CardImpl { + + public TheCelestus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + this.addSuperType(SuperType.LEGENDARY); + + // If it's neither day nor night, it becomes day as The Celestus enters the battlefield. + this.addAbility(new BecomeDayAsEntersAbility()); + + // {T}: Add one mana of any color. + this.addAbility(new AnyColorManaAbility()); + + // {3}, {T}: If it's night, it becomes day. Otherwise, it becomes night. Activate only as a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility( + new TheCelestusDayNightEffect(), new GenericManaCost(3) + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + + // Whenever day becomes night or night becomes day, you gain 1 life. You may draw a card. If you do, discard a card. + this.addAbility(new BecomesDayOrNightTriggeredAbility(new TheCelestusLootEffect())); + } + + private TheCelestus(final TheCelestus card) { + super(card); + } + + @Override + public TheCelestus copy() { + return new TheCelestus(this); + } +} + +class TheCelestusDayNightEffect extends OneShotEffect { + + TheCelestusDayNightEffect() { + super(Outcome.Benefit); + staticText = "if it's night, it becomes day. Otherwise, it becomes night"; + } + + private TheCelestusDayNightEffect(final TheCelestusDayNightEffect effect) { + super(effect); + } + + @Override + public TheCelestusDayNightEffect copy() { + return new TheCelestusDayNightEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (game.checkDayNight(false)) { + game.setDaytime(true); + } else { + game.setDaytime(false); + } + return true; + } +} + +class TheCelestusLootEffect extends OneShotEffect { + + TheCelestusLootEffect() { + super(Outcome.DrawCard); + staticText = "you gain 1 life. You may draw a card. If you do, discard a card"; + } + + private TheCelestusLootEffect(final TheCelestusLootEffect effect) { + super(effect); + } + + @Override + public TheCelestusLootEffect copy() { + return new TheCelestusLootEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + player.gainLife(1, game, source); + if (player.chooseUse(outcome, "Draw a card?", source, game)) { + player.drawCards(1, source, game); + player.discard(1, false, false, source, game); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TheUpsideDown.java b/Mage.Sets/src/mage/cards/t/TheUpsideDown.java index a0098686064..cdaed4dd00d 100644 --- a/Mage.Sets/src/mage/cards/t/TheUpsideDown.java +++ b/Mage.Sets/src/mage/cards/t/TheUpsideDown.java @@ -33,9 +33,8 @@ public final class TheUpsideDown extends CardImpl { public TheUpsideDown(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; + this.nightCard = true; // When this land transforms into The Upside Down, return target creature card from your graveyard to the battlefield. @@ -144,7 +143,7 @@ class TheUpsideDownEffect extends OneShotEffect { class TheUpsideDownLeavesAbility extends TriggeredAbilityImpl { TheUpsideDownLeavesAbility() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(false)); + super(Zone.BATTLEFIELD, new TransformSourceEffect()); } private TheUpsideDownLeavesAbility(final TheUpsideDownLeavesAbility ability) { diff --git a/Mage.Sets/src/mage/cards/t/ThingInTheIce.java b/Mage.Sets/src/mage/cards/t/ThingInTheIce.java index 5274ac890ea..20a03323497 100644 --- a/Mage.Sets/src/mage/cards/t/ThingInTheIce.java +++ b/Mage.Sets/src/mage/cards/t/ThingInTheIce.java @@ -42,7 +42,6 @@ public final class ThingInTheIce extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AwokenHorror.class; // Defender @@ -58,7 +57,7 @@ public final class ThingInTheIce extends CardImpl { effect = new RemoveCounterSourceEffect(CounterType.ICE.createInstance(1)); effect.setText("remove an ice counter from {this}"); Ability ability = new SpellCastControllerTriggeredAbility(effect, filter, false); - effect = new ConditionalOneShotEffect(new TransformSourceEffect(true), new SourceHasCounterCondition(CounterType.ICE, 0, 0), + effect = new ConditionalOneShotEffect(new TransformSourceEffect(), new SourceHasCounterCondition(CounterType.ICE, 0, 0), "if there are no ice counters on it, transform it"); ability.addEffect(effect); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/t/ThrabenGargoyle.java b/Mage.Sets/src/mage/cards/t/ThrabenGargoyle.java index 0aa7323da1e..d2861c441bc 100644 --- a/Mage.Sets/src/mage/cards/t/ThrabenGargoyle.java +++ b/Mage.Sets/src/mage/cards/t/ThrabenGargoyle.java @@ -26,7 +26,6 @@ public final class ThrabenGargoyle extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.StonewingAntagonizer.class; // Defender @@ -34,7 +33,7 @@ public final class ThrabenGargoyle extends CardImpl { // {6}: Transform Thraben Gargoyle. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new GenericManaCost(6))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new GenericManaCost(6))); } private ThrabenGargoyle(final ThrabenGargoyle card) { diff --git a/Mage.Sets/src/mage/cards/t/ThrabenMilitia.java b/Mage.Sets/src/mage/cards/t/ThrabenMilitia.java index 65bad5e707e..d9998dc5920 100644 --- a/Mage.Sets/src/mage/cards/t/ThrabenMilitia.java +++ b/Mage.Sets/src/mage/cards/t/ThrabenMilitia.java @@ -22,7 +22,6 @@ public final class ThrabenMilitia extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/t/ThrabenSentry.java b/Mage.Sets/src/mage/cards/t/ThrabenSentry.java index 5b6ceba84f0..1269ff1b844 100644 --- a/Mage.Sets/src/mage/cards/t/ThrabenSentry.java +++ b/Mage.Sets/src/mage/cards/t/ThrabenSentry.java @@ -23,7 +23,6 @@ public final class ThrabenSentry extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); - this.transformable = true; this.secondSideCardClazz = ThrabenMilitia.class; this.power = new MageInt(2); @@ -33,7 +32,7 @@ public final class ThrabenSentry extends CardImpl { // Whenever another creature you control dies, you may transform Thraben Sentry. this.addAbility(new TransformAbility()); - this.addAbility(new DiesCreatureTriggeredAbility(new TransformSourceEffect(true), true, new FilterControlledCreaturePermanent())); + this.addAbility(new DiesCreatureTriggeredAbility(new TransformSourceEffect(), true, new FilterControlledCreaturePermanent())); } private ThrabenSentry(final ThrabenSentry card) { diff --git a/Mage.Sets/src/mage/cards/t/TimberShredder.java b/Mage.Sets/src/mage/cards/t/TimberShredder.java index 186ba31618f..6fe22125f0b 100644 --- a/Mage.Sets/src/mage/cards/t/TimberShredder.java +++ b/Mage.Sets/src/mage/cards/t/TimberShredder.java @@ -24,7 +24,6 @@ public final class TimberShredder extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Trample this.addAbility(TrampleAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/t/TirelessHauler.java b/Mage.Sets/src/mage/cards/t/TirelessHauler.java index c50d0ac4ca8..5c643892b1c 100644 --- a/Mage.Sets/src/mage/cards/t/TirelessHauler.java +++ b/Mage.Sets/src/mage/cards/t/TirelessHauler.java @@ -23,7 +23,6 @@ public final class TirelessHauler extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(4); this.toughness = new MageInt(5); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DireStrainBrawler.class; // Vigilance diff --git a/Mage.Sets/src/mage/cards/t/TormentedPariah.java b/Mage.Sets/src/mage/cards/t/TormentedPariah.java index 36a88c23c02..7d5997a1c5c 100644 --- a/Mage.Sets/src/mage/cards/t/TormentedPariah.java +++ b/Mage.Sets/src/mage/cards/t/TormentedPariah.java @@ -21,7 +21,6 @@ public final class TormentedPariah extends CardImpl { this.subtype.add(SubType.WARRIOR); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.r.RampagingWerewolf.class; this.power = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/t/TovolarDireOverlord.java b/Mage.Sets/src/mage/cards/t/TovolarDireOverlord.java new file mode 100644 index 00000000000..4a50e155299 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TovolarDireOverlord.java @@ -0,0 +1,125 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.abilities.keyword.DayboundAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TovolarDireOverlord extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent("a Wolf or Werewolf you control"); + + static { + filter.add(Predicates.or( + SubType.WOLF.getPredicate(), + SubType.WEREWOLF.getPredicate() + )); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 2); + private static final Hint hint = new ValueHint("Wolves and Werewolves you control", new PermanentsOnBattlefieldCount(filter)); + + public TovolarDireOverlord(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WEREWOLF); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.t.TovolarTheMidnightScourge.class; + + // Whenever a Wolf or Werewolf you control deals combat damage to a player, draw a card. + this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility( + new DrawCardSourceControllerEffect(1), filter, + false, SetTargetPointer.NONE, true + )); + + // At the beginning of your upkeep, if you control three or more Wolves and/or Werewolves, it becomes night. Then transform any number of Human Werewolves you control. + this.addAbility(new ConditionalInterveningIfTriggeredAbility( + new BeginningOfUpkeepTriggeredAbility( + new TovolarDireOverlordEffect(), TargetController.YOU, false + ), condition, "At the beginning of your upkeep, if you control three or more Wolves " + + "and/or Werewolves, it becomes night. Then transform any number of Human Werewolves you control." + )); + + // Daybound + this.addAbility(new TransformAbility()); + this.addAbility(new DayboundAbility()); + } + + private TovolarDireOverlord(final TovolarDireOverlord card) { + super(card); + } + + @Override + public TovolarDireOverlord copy() { + return new TovolarDireOverlord(this); + } +} + +class TovolarDireOverlordEffect extends OneShotEffect { + + private static final FilterPermanent filter = new FilterControlledPermanent("Human Werewolves you control"); + + static { + filter.add(SubType.HUMAN.getPredicate()); + filter.add(SubType.WEREWOLF.getPredicate()); + } + + TovolarDireOverlordEffect() { + super(Outcome.Benefit); + } + + private TovolarDireOverlordEffect(final TovolarDireOverlordEffect effect) { + super(effect); + } + + @Override + public TovolarDireOverlordEffect copy() { + return new TovolarDireOverlordEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + game.setDaytime(false); + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return true; + } + TargetPermanent target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); + player.choose(outcome, target, source.getControllerId(), game); + for (UUID permanentId : target.getTargets()) { + Permanent permanent = game.getPermanent(permanentId); + if (permanent != null) { + permanent.transform(source, game); + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TovolarTheMidnightScourge.java b/Mage.Sets/src/mage/cards/t/TovolarTheMidnightScourge.java new file mode 100644 index 00000000000..667ce360431 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TovolarTheMidnightScourge.java @@ -0,0 +1,78 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.NightboundAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TovolarTheMidnightScourge extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent("a Wolf or Werewolf you control"); + + static { + filter.add(Predicates.or( + SubType.WOLF.getPredicate(), + SubType.WEREWOLF.getPredicate() + )); + } + + public TovolarTheMidnightScourge(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.WEREWOLF); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + this.color.setRed(true); + this.color.setGreen(true); + this.nightCard = true; + + // Whenever a Wolf or Werewolf you control deals combat damage to a player, draw a card. + this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility( + new DrawCardSourceControllerEffect(1), filter, + false, SetTargetPointer.NONE, true + )); + + // {X}{R}{G}: Target Wolf or Werewolf you control gets +X/+0 and gains trample until end of turn. + Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn + ).setText("Target Wolf or Werewolf you control gets +X/+0"), new ManaCostsImpl<>("{X}{R}{G}")); + ability.addEffect(new BoostTargetEffect( + ManacostVariableValue.REGULAR, StaticValue.get(0), Duration.EndOfTurn + ).setText("and gains trample until end of turn")); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + + // Nightbound + this.addAbility(new NightboundAbility()); + } + + private TovolarTheMidnightScourge(final TovolarTheMidnightScourge card) { + super(card); + } + + @Override + public TovolarTheMidnightScourge copy() { + return new TovolarTheMidnightScourge(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TovolarsHuntmaster.java b/Mage.Sets/src/mage/cards/t/TovolarsHuntmaster.java index 728ea25305f..1c3af8d996b 100644 --- a/Mage.Sets/src/mage/cards/t/TovolarsHuntmaster.java +++ b/Mage.Sets/src/mage/cards/t/TovolarsHuntmaster.java @@ -25,7 +25,6 @@ public final class TovolarsHuntmaster extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(6); this.toughness = new MageInt(6); - this.transformable = true; this.secondSideCardClazz = mage.cards.t.TovolarsPackleader.class; // Whenever Tovolar's Huntmaster enters the battlefield, create two 2/2 green Wolf creature tokens. diff --git a/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java b/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java index 046a6da18ad..0fcba4dc888 100644 --- a/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java +++ b/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java @@ -30,7 +30,6 @@ public final class TovolarsMagehunter extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Whenever an opponent casts a spell, Tovolar's Magehunter deals 2 damage to that player. this.addAbility(new TovolarsMagehunterTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/t/TovolarsPackleader.java b/Mage.Sets/src/mage/cards/t/TovolarsPackleader.java index ce1a3bff2a2..83475a7ea2d 100644 --- a/Mage.Sets/src/mage/cards/t/TovolarsPackleader.java +++ b/Mage.Sets/src/mage/cards/t/TovolarsPackleader.java @@ -45,7 +45,6 @@ public final class TovolarsPackleader extends CardImpl { this.power = new MageInt(7); this.toughness = new MageInt(7); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Whenever Tovolar's Packleader enters the battlefield or attacks, create two 2/2 green Wolf creature tokens. diff --git a/Mage.Sets/src/mage/cards/t/TownGossipmonger.java b/Mage.Sets/src/mage/cards/t/TownGossipmonger.java index 672fac061f8..1d032506c25 100644 --- a/Mage.Sets/src/mage/cards/t/TownGossipmonger.java +++ b/Mage.Sets/src/mage/cards/t/TownGossipmonger.java @@ -36,12 +36,11 @@ public final class TownGossipmonger extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.IncitedRabble.class; // {T}, Tap an untapped creature you control: Transform Town Gossipmonger. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new TapSourceCost()); ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TreasureMap.java b/Mage.Sets/src/mage/cards/t/TreasureMap.java index 5a36dbcd0fe..f641c5d6b1a 100644 --- a/Mage.Sets/src/mage/cards/t/TreasureMap.java +++ b/Mage.Sets/src/mage/cards/t/TreasureMap.java @@ -29,7 +29,6 @@ public final class TreasureMap extends CardImpl { public TreasureMap(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); - this.transformable = true; this.secondSideCardClazz = TreasureCove.class; // {1}, {T}: Scry 1. Put a landmark counter on Treasure Map. Then if there are three or more landmark counters on it, remove those counters, transform Treasure Map, and create three colorless Treasure artifact tokens with "{T}, Sacrifice this artifact: Add one mana of any color." @@ -79,7 +78,7 @@ class TreasureMapEffect extends OneShotEffect { int counters = permanent.getCounters(game).getCount(CounterType.LANDMARK); if (counters > 2) { permanent.removeCounters("landmark", counters, source, game); - new TransformSourceEffect(true).apply(game, source); + new TransformSourceEffect().apply(game, source); new CreateTokenEffect(new TreasureToken(), 3).apply(game, source); } return true; diff --git a/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java b/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java index 276c819511e..5d575350b44 100644 --- a/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java +++ b/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java @@ -29,7 +29,6 @@ public final class UlrichOfTheKrallenhorde extends CardImpl { this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = UlrichUncontestedAlpha.class; // Whenever this creature enters the battlefield or transforms into Ulrich of the Krallenhorde, target creature gets +4/+4 until end of turn. diff --git a/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java b/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java index 5da9d4f8c41..912555a2670 100644 --- a/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java +++ b/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java @@ -33,7 +33,6 @@ public final class UlrichUncontestedAlpha extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; // Whenever this creature transforms into Ulrich, Uncontested Alpha, you may have it fight target non-Werewolf creature you don't control. this.addAbility(new UlrichUncontestedAlphaAbility()); diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldCaptive.java b/Mage.Sets/src/mage/cards/u/UlvenwaldCaptive.java index c6a47b7eefe..bc813d5ac1a 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldCaptive.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldCaptive.java @@ -28,7 +28,6 @@ public final class UlvenwaldCaptive extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = UlvenwaldAbomination.class; // Defender @@ -39,7 +38,7 @@ public final class UlvenwaldCaptive extends CardImpl { // {5}{G}{G}: Transform Ulvenwald Captive. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{5}{G}{G}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{5}{G}{G}"))); } private UlvenwaldCaptive(final UlvenwaldCaptive card) { diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java b/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java index 3703f8792ae..f4c838a6c34 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java @@ -21,7 +21,6 @@ public final class UlvenwaldMystics extends CardImpl { this.subtype.add(SubType.SHAMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = UlvenwaldPrimordials.class; this.power = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldOddity.java b/Mage.Sets/src/mage/cards/u/UlvenwaldOddity.java index b46afa7a5c0..ae8c3820b74 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldOddity.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldOddity.java @@ -25,7 +25,6 @@ public final class UlvenwaldOddity extends CardImpl { this.subtype.add(SubType.BEAST); this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.u.UlvenwaldBehemoth.class; // Trample @@ -37,7 +36,7 @@ public final class UlvenwaldOddity extends CardImpl { // {5}{G}{G}: Transform Ulvenwald Oddity. this.addAbility(new TransformAbility()); this.addAbility(new SimpleActivatedAbility( - new TransformSourceEffect(true), new ManaCostsImpl<>("{5}{G}{G}") + new TransformSourceEffect(), new ManaCostsImpl<>("{5}{G}{G}") )); } diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java b/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java index b76a5fe24ac..d963de0208c 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java @@ -24,7 +24,6 @@ public final class UlvenwaldPrimordials extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(5); diff --git a/Mage.Sets/src/mage/cards/u/UnhallowedCathar.java b/Mage.Sets/src/mage/cards/u/UnhallowedCathar.java index b765c55e0d1..9f61fbec892 100644 --- a/Mage.Sets/src/mage/cards/u/UnhallowedCathar.java +++ b/Mage.Sets/src/mage/cards/u/UnhallowedCathar.java @@ -23,7 +23,6 @@ public final class UnhallowedCathar extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(2); this.toughness = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/u/UninvitedGeist.java b/Mage.Sets/src/mage/cards/u/UninvitedGeist.java index f83b9c384b6..1a635c3c0d9 100644 --- a/Mage.Sets/src/mage/cards/u/UninvitedGeist.java +++ b/Mage.Sets/src/mage/cards/u/UninvitedGeist.java @@ -24,7 +24,6 @@ public final class UninvitedGeist extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - this.transformable = true; this.secondSideCardClazz = UnimpededTrespasser.class; // Skulk (This creature can't be blocked by creatures with greater power.) @@ -32,7 +31,7 @@ public final class UninvitedGeist extends CardImpl { // When Uninvited Geist deals combat damage to a player, transform it. this.addAbility(new TransformAbility()); - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new TransformSourceEffect(true), false)); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new TransformSourceEffect(), false)); } diff --git a/Mage.Sets/src/mage/cards/u/UnnaturalMoonrise.java b/Mage.Sets/src/mage/cards/u/UnnaturalMoonrise.java new file mode 100644 index 00000000000..45824e42ec8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UnnaturalMoonrise.java @@ -0,0 +1,81 @@ +package mage.cards.u; + +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.hint.common.DayNightHint; +import mage.abilities.keyword.FlashbackAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class UnnaturalMoonrise extends CardImpl { + + public UnnaturalMoonrise(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}{G}"); + + // It becomes night. Until end of turn, target creature gets +1/+0 and gains trample and has "Whenever this creature deals combat damage to a player, draw a card." + this.getSpellAbility().addEffect(new UnnaturalMoonriseEffect()); + this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0) + .setText("Until end of turn, target creature gets +1/+0")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains trample")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + new DealsCombatDamageToAPlayerTriggeredAbility( + new DrawCardSourceControllerEffect(1), false + ).setTriggerPhrase("Whenever this creature deals combat damage to a player, "), Duration.EndOfTurn + ).setText("and \"Whenever this creature deals combat damage to a player, draw a card.\"")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addHint(DayNightHint.instance); + + // Flashback {2}{R}{G} + this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{2}{R}{G}"))); + } + + private UnnaturalMoonrise(final UnnaturalMoonrise card) { + super(card); + } + + @Override + public UnnaturalMoonrise copy() { + return new UnnaturalMoonrise(this); + } +} + +class UnnaturalMoonriseEffect extends OneShotEffect { + + UnnaturalMoonriseEffect() { + super(Outcome.Benefit); + staticText = "It becomes night."; + } + + private UnnaturalMoonriseEffect(final UnnaturalMoonriseEffect effect) { + super(effect); + } + + @Override + public UnnaturalMoonriseEffect copy() { + return new UnnaturalMoonriseEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + game.setDaytime(false); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/u/UntamedPup.java b/Mage.Sets/src/mage/cards/u/UntamedPup.java index 519b2ef3353..4dbcd4007c9 100644 --- a/Mage.Sets/src/mage/cards/u/UntamedPup.java +++ b/Mage.Sets/src/mage/cards/u/UntamedPup.java @@ -42,7 +42,6 @@ public final class UntamedPup extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); this.color.setGreen(true); - this.transformable = true; this.nightCard = true; // Trample @@ -50,7 +49,7 @@ public final class UntamedPup extends CardImpl { // Other Wolves and Werewolves you control have trample. this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( - TrampleAbility.getInstance(), Duration.WhileOnBattlefield, filter + TrampleAbility.getInstance(), Duration.WhileOnBattlefield, filter, true ))); // {3}{G}: Put a +1/+1 counter on target creature. diff --git a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java index 2c8eac60fff..225ad68753b 100644 --- a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java +++ b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java @@ -37,7 +37,6 @@ public final class VancesBlastingCannons extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); this.addSuperType(SuperType.LEGENDARY); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.SpitfireBastion.class; // At the beginning of your upkeep, exile the top card of your library. If it's a nonland card, you may cast that card this turn. @@ -132,7 +131,7 @@ class CastFromNonHandZoneTargetEffect extends AsThoughEffectImpl { class VancesBlastingCannonsFlipTrigger extends TriggeredAbilityImpl { public VancesBlastingCannonsFlipTrigger() { - super(Zone.BATTLEFIELD, new TransformSourceEffect(true), true); + super(Zone.BATTLEFIELD, new TransformSourceEffect(), true); } public VancesBlastingCannonsFlipTrigger(final VancesBlastingCannonsFlipTrigger ability) { diff --git a/Mage.Sets/src/mage/cards/v/VengefulStrangler.java b/Mage.Sets/src/mage/cards/v/VengefulStrangler.java index f1ca4ac0437..1b1de179298 100644 --- a/Mage.Sets/src/mage/cards/v/VengefulStrangler.java +++ b/Mage.Sets/src/mage/cards/v/VengefulStrangler.java @@ -38,7 +38,6 @@ public final class VengefulStrangler extends CardImpl { this.subtype.add(SubType.ROGUE); this.power = new MageInt(2); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.s.StranglingGrasp.class; // Vengeful Strangler can't block. diff --git a/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java b/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java index a567911d8a4..37bbb7367be 100644 --- a/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java +++ b/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java @@ -8,6 +8,7 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -20,6 +21,8 @@ import java.util.UUID; */ public final class VildinPackAlpha extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent(SubType.WEREWOLF, "a Werewolf"); + public VildinPackAlpha(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); this.subtype.add(SubType.WEREWOLF); @@ -27,11 +30,13 @@ public final class VildinPackAlpha extends CardImpl { this.toughness = new MageInt(3); this.color.setRed(true); - this.transformable = true; this.nightCard = true; // Whenever a Werewolf enters the battlefield under your control, you may transform it. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new VildinPackAlphaEffect(), new FilterCreaturePermanent(SubType.WEREWOLF, "a Werewolf"), true, SetTargetPointer.PERMANENT, null)); + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, new VildinPackAlphaEffect(), filter, + true, SetTargetPointer.PERMANENT, null + )); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Vildin-Pack Alpha. this.addAbility(new WerewolfBackTriggeredAbility()); @@ -66,13 +71,13 @@ class VildinPackAlphaEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Permanent werewolf = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (werewolf != null && werewolf.isTransformable()) { - werewolf.transform(game); - } - return true; + if (controller == null) { + return false; } - return false; + Permanent werewolf = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (werewolf != null) { + werewolf.transform(source, game); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/v/VildinPackOutcast.java b/Mage.Sets/src/mage/cards/v/VildinPackOutcast.java index 67e4cdb4377..60678b9ff21 100644 --- a/Mage.Sets/src/mage/cards/v/VildinPackOutcast.java +++ b/Mage.Sets/src/mage/cards/v/VildinPackOutcast.java @@ -29,7 +29,6 @@ public final class VildinPackOutcast extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.transformable = true; this.secondSideCardClazz = mage.cards.d.DronepackKindred.class; // Trample @@ -40,7 +39,7 @@ public final class VildinPackOutcast extends CardImpl { // {5}{R}{R}: Transform Vildin-Pack Outcast. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new ManaCostsImpl("{5}{R}{R}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl("{5}{R}{R}"))); } private VildinPackOutcast(final VildinPackOutcast card) { diff --git a/Mage.Sets/src/mage/cards/v/VillageIronsmith.java b/Mage.Sets/src/mage/cards/v/VillageIronsmith.java index 7bbf0b9366f..408f637c9d1 100644 --- a/Mage.Sets/src/mage/cards/v/VillageIronsmith.java +++ b/Mage.Sets/src/mage/cards/v/VillageIronsmith.java @@ -21,7 +21,6 @@ public final class VillageIronsmith extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.i.Ironfang.class; this.power = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/v/VillageMessenger.java b/Mage.Sets/src/mage/cards/v/VillageMessenger.java index 72d6bc10310..c1f2f7b5aa5 100644 --- a/Mage.Sets/src/mage/cards/v/VillageMessenger.java +++ b/Mage.Sets/src/mage/cards/v/VillageMessenger.java @@ -23,7 +23,6 @@ public final class VillageMessenger extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.m.MoonriseIntruder.class; // Haste diff --git a/Mage.Sets/src/mage/cards/v/VillageReavers.java b/Mage.Sets/src/mage/cards/v/VillageReavers.java index efa4fe5e3ff..ccdf2918732 100644 --- a/Mage.Sets/src/mage/cards/v/VillageReavers.java +++ b/Mage.Sets/src/mage/cards/v/VillageReavers.java @@ -38,7 +38,6 @@ public final class VillageReavers extends CardImpl { this.color.setRed(true); this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/v/VillageWatch.java b/Mage.Sets/src/mage/cards/v/VillageWatch.java index c620c73046f..67a7484622d 100644 --- a/Mage.Sets/src/mage/cards/v/VillageWatch.java +++ b/Mage.Sets/src/mage/cards/v/VillageWatch.java @@ -24,7 +24,6 @@ public final class VillageWatch extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.v.VillageReavers.class; // Haste diff --git a/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java b/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java index ed3cdb7f6aa..ce821011a2f 100644 --- a/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java +++ b/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java @@ -20,7 +20,6 @@ public final class VillagersOfEstwald extends CardImpl { this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); - this.transformable = true; this.secondSideCardClazz = mage.cards.h.HowlpackOfEstwald.class; this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java b/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java index f178d60313a..ff4b32081b8 100644 --- a/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java +++ b/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java @@ -1,11 +1,6 @@ package mage.cards.v; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; @@ -19,25 +14,20 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect; 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.constants.WatcherScope; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.game.stack.StackAbility; import mage.target.common.TargetControlledCreaturePermanent; import mage.watchers.Watcher; +import java.util.*; + /** - * * @author L_J */ public final class VodalianWarMachine extends CardImpl { @@ -66,7 +56,7 @@ public final class VodalianWarMachine extends CardImpl { this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(2, 1, Duration.EndOfTurn), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true)))); // When Vodalian War Machine dies, destroy all Merfolk tapped this turn to pay for its abilities. - this.addAbility(new VodalianWarMachineTriggeredAbility(), new VodalianWarMachineWatcher()); + this.addAbility(new DiesSourceTriggeredAbility(new VodalianWarMachineEffect()), new VodalianWarMachineWatcher()); } private VodalianWarMachine(final VodalianWarMachine card) { @@ -79,41 +69,6 @@ public final class VodalianWarMachine extends CardImpl { } } -class VodalianWarMachineTriggeredAbility extends DiesSourceTriggeredAbility { - - public VodalianWarMachineTriggeredAbility() { - super(new VodalianWarMachineEffect(), false); - } - - public VodalianWarMachineTriggeredAbility(VodalianWarMachineTriggeredAbility ability) { - super(ability); - } - - @Override - public VodalianWarMachineTriggeredAbility copy() { - return new VodalianWarMachineTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent before = ((ZoneChangeEvent) event).getTarget(); - if (before == null) { - return false; - } - if (super.checkTrigger(event, game)) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getTarget().isTransformable()) { - if (!zEvent.getTarget().getAbilities().contains(this)) { - return false; - } - } - return true; - } - return false; - } - -} - class VodalianWarMachineEffect extends OneShotEffect { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Merfolk tapped this turn to pay for its abilities"); diff --git a/Mage.Sets/src/mage/cards/v/VoldarenPariah.java b/Mage.Sets/src/mage/cards/v/VoldarenPariah.java index 09dbf6d09aa..d5ead032805 100644 --- a/Mage.Sets/src/mage/cards/v/VoldarenPariah.java +++ b/Mage.Sets/src/mage/cards/v/VoldarenPariah.java @@ -38,7 +38,6 @@ public final class VoldarenPariah extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - this.transformable = true; this.secondSideCardClazz = mage.cards.a.AbolisherOfBloodlines.class; // Flying @@ -46,7 +45,7 @@ public final class VoldarenPariah extends CardImpl { // Sacrifice three other creatures: Transform Voldaren Pariah. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new SacrificeTargetCost(new TargetControlledPermanent(3, 3, filter, false)))); // Madness {B}{B}{B} diff --git a/Mage.Sets/src/mage/cards/w/Waildrifter.java b/Mage.Sets/src/mage/cards/w/Waildrifter.java index 14dde19604a..dec610a203d 100644 --- a/Mage.Sets/src/mage/cards/w/Waildrifter.java +++ b/Mage.Sets/src/mage/cards/w/Waildrifter.java @@ -24,7 +24,6 @@ public final class Waildrifter extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); this.color.setBlue(true); - this.transformable = true; this.nightCard = true; // Flying diff --git a/Mage.Sets/src/mage/cards/w/WaxingMoon.java b/Mage.Sets/src/mage/cards/w/WaxingMoon.java index 2d6a8a3e8f6..d3b293fb03f 100644 --- a/Mage.Sets/src/mage/cards/w/WaxingMoon.java +++ b/Mage.Sets/src/mage/cards/w/WaxingMoon.java @@ -1,45 +1,43 @@ - package mage.cards.w; -import java.util.UUID; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.TransformTargetEffect; -import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.TrampleAbility; 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.constants.TargetController; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class WaxingMoon extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Werewolf you control"); - - static { - filter.add(SubType.WEREWOLF.getPredicate()); - filter.add(TargetController.YOU.getControllerPredicate()); - } + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.WEREWOLF); public WaxingMoon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); // Transform up to one target Werewolf you control. - Effect effect = new TransformTargetEffect(false); - effect.setText("Transform up to one target Werewolf you control"); - this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + this.getSpellAbility().addEffect(new WaxingMoonEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter)); // Creatures you control gain trample until end of turn. - this.getSpellAbility().addEffect(new GainAbilityAllEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, new FilterControlledCreaturePermanent(), "Creatures you control gain trample until end of turn")); + this.getSpellAbility().addEffect(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURES + )); } private WaxingMoon(final WaxingMoon card) { @@ -51,3 +49,26 @@ public final class WaxingMoon extends CardImpl { return new WaxingMoon(this); } } + +class WaxingMoonEffect extends OneShotEffect { + + WaxingMoonEffect() { + super(Outcome.Benefit); + staticText = "transform up to one target Werewolf you control"; + } + + private WaxingMoonEffect(final WaxingMoonEffect effect) { + super(effect); + } + + @Override + public WaxingMoonEffect copy() { + return new WaxingMoonEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + return permanent != null && permanent.transform(source, game); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WearyPrisoner.java b/Mage.Sets/src/mage/cards/w/WearyPrisoner.java index ccfdb51a9a3..4feabe40411 100644 --- a/Mage.Sets/src/mage/cards/w/WearyPrisoner.java +++ b/Mage.Sets/src/mage/cards/w/WearyPrisoner.java @@ -23,6 +23,7 @@ public final class WearyPrisoner extends CardImpl { this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(2); this.toughness = new MageInt(6); + this.secondSideCardClazz = mage.cards.w.WrathfulJailbreaker.class; // Defender diff --git a/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java b/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java index 1c256f09d30..a690a4dc8bf 100644 --- a/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java +++ b/Mage.Sets/src/mage/cards/w/WeddingAnnouncement.java @@ -29,7 +29,6 @@ public final class WeddingAnnouncement extends CardImpl { public WeddingAnnouncement(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); - this.transformable = true; this.secondSideCardClazz = mage.cards.w.WeddingFestivity.class; // At the beginning of your end step, put an invitation counter on Wedding Announcement. @@ -45,7 +44,7 @@ public final class WeddingAnnouncement extends CardImpl { "If you attacked with two or more creatures this turn, draw card. Otherwise, create a 1/1 white Human creature token" )); ability.addEffect(new ConditionalOneShotEffect( - new TransformSourceEffect(true, true), + new TransformSourceEffect(), new SourceHasCounterCondition(CounterType.INVITATION, 3), "Then if {this} has three or more invitation counters on it, transform it" )); diff --git a/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java b/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java index 511f969c939..9a834b909b7 100644 --- a/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java +++ b/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java @@ -31,7 +31,6 @@ public final class WerewolfOfAncientHunger extends CardImpl { this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // Vigilance this.addAbility(VigilanceAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java b/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java index bc1614ded9f..c29592c747a 100644 --- a/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java +++ b/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java @@ -31,7 +31,6 @@ public final class WerewolfRansacker extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java b/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java index d3b45ed59f7..9e52eaf3d88 100644 --- a/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java +++ b/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java @@ -30,7 +30,6 @@ public final class WestvaleAbbey extends CardImpl { public WestvaleAbbey(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - this.transformable = true; this.secondSideCardClazz = mage.cards.o.OrmendahlProfanePrince.class; // {T}: Add {C}. @@ -44,7 +43,7 @@ public final class WestvaleAbbey extends CardImpl { // {5}, {T}, Sacrifice five creatures: Transform Westvale Abbey and untap it. this.addAbility(new TransformAbility()); - ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), new GenericManaCost(5)); + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new GenericManaCost(5)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(5, 5, new FilterControlledCreaturePermanent("creatures"), true))); ability.addEffect(new UntapSourceEffect()); diff --git a/Mage.Sets/src/mage/cards/w/WildbloodPack.java b/Mage.Sets/src/mage/cards/w/WildbloodPack.java index 07981c1cdd0..6dd0d6f908a 100644 --- a/Mage.Sets/src/mage/cards/w/WildbloodPack.java +++ b/Mage.Sets/src/mage/cards/w/WildbloodPack.java @@ -26,7 +26,6 @@ public final class WildbloodPack extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(5); this.toughness = new MageInt(5); diff --git a/Mage.Sets/src/mage/cards/w/WingShredder.java b/Mage.Sets/src/mage/cards/w/WingShredder.java index e1946dd6e5b..daf016f1dd5 100644 --- a/Mage.Sets/src/mage/cards/w/WingShredder.java +++ b/Mage.Sets/src/mage/cards/w/WingShredder.java @@ -18,13 +18,11 @@ public final class WingShredder extends CardImpl { public WingShredder(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); - this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(3); this.toughness = new MageInt(5); this.color.setGreen(true); this.nightCard = true; - this.transformable = true; // Reach this.addAbility(ReachAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/w/WithengarUnbound.java b/Mage.Sets/src/mage/cards/w/WithengarUnbound.java index e06bd24c180..523c7e10c9d 100644 --- a/Mage.Sets/src/mage/cards/w/WithengarUnbound.java +++ b/Mage.Sets/src/mage/cards/w/WithengarUnbound.java @@ -17,7 +17,6 @@ import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; /** * @@ -33,7 +32,6 @@ public final class WithengarUnbound extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - this.transformable = true; this.power = new MageInt(13); this.toughness = new MageInt(13); diff --git a/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java b/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java index 692ca2c899b..947f1e86a90 100644 --- a/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java +++ b/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java @@ -28,7 +28,6 @@ public final class WolfbittenCaptive extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - this.transformable = true; this.secondSideCardClazz = mage.cards.k.KrallenhordeKiller.class; // {1}{G}: Wolfbitten Captive gets +2/+2 until end of turn. Activate this ability only once each turn. diff --git a/Mage.Sets/src/mage/cards/w/WrathfulJailbreaker.java b/Mage.Sets/src/mage/cards/w/WrathfulJailbreaker.java index b3befd7c8c2..3e0bf2c9f1b 100644 --- a/Mage.Sets/src/mage/cards/w/WrathfulJailbreaker.java +++ b/Mage.Sets/src/mage/cards/w/WrathfulJailbreaker.java @@ -22,6 +22,7 @@ public final class WrathfulJailbreaker extends CardImpl { this.power = new MageInt(6); this.toughness = new MageInt(6); this.color.setRed(true); + this.nightCard = true; // Wrathful Jailbreaker attacks each combat if able. diff --git a/Mage.Sets/src/mage/sets/InnistradMidnightHunt.java b/Mage.Sets/src/mage/sets/InnistradMidnightHunt.java index a4201ba0e33..bbc78f743d5 100644 --- a/Mage.Sets/src/mage/sets/InnistradMidnightHunt.java +++ b/Mage.Sets/src/mage/sets/InnistradMidnightHunt.java @@ -17,7 +17,7 @@ import java.util.List; */ public final class InnistradMidnightHunt extends ExpansionSet { - private static final List unfinished = Arrays.asList("Arlinn, the Pack's Hope", "Arlinn, the Moon's Fury", "Baithook Angler", "Hook-Haunt Drifter", "Baneblade Scoundrel", "Baneclaw Marauder", "Beloved Beggar", "Generous Soul", "Bird Admirer", "Wing Shredder", "Brimstone Vandal", "Brutal Cathar", "Moonrage Brute", "Burly Breaker", "Dire-Strain Demolisher", "Celestus Sanctifier", "Chaplain of Alms", "Chapel Shieldgeist", "Component Collector", "Covert Cutpurse", "Covetous Geist", "Covetous Castaway", "Ghostly Castigator", "Curse of Leeches", "Leeching Lurker", "Dennick, Pious Apprentice", "Dennick, Pious Apparition", "Devoted Grafkeeper", "Departed Soulkeeper", "Fangblade Brigand", "Fangblade Eviscerator", "Firmament Sage", "Galedrifter", "Waildrifter", "Gavony Dawnguard", "Graveyard Trespasser", "Graveyard Glutton", "Harvesttide Infiltrator", "Harvesttide Assailant", "Hound Tamer", "Untamed Pup", "Kessig Naturalist", "Lord of the Ulvenwald", "Lunarch Veteran", "Luminous Phantom", "Malevolent Hermit", "Benevolent Geist", "Mourning Patrol", "Morning Apparition", "Obsessive Astronomer", "Outland Liberator", "Frenzied Trapbreaker", "Overwhelmed Archivist", "Archive Haunt", "Phantom Carriage", "Reckless Stormseeker", "Storm-Charged Slasher", "Shady Traveler", "Stalking Predator", "Shipwreck Sifters", "Spellrune Painter", "Spellrune Howler", "Sunrise Cavalier", "Sunstreak Phoenix", "Suspicious Stowaway", "Seafaring Werewolf", "Tavern Ruffian", "Tavern Smasher", "The Celestus", "Thraben Exorcism", "Tireless Hauler", "Dire-Strain Brawler", "Tovolar, Dire Overlord", "Tovolar, the Midnight Scourge", "Tovolar's Huntmaster", "Tovolar's Packleader", "Unblinking Observer", "Vadrik, Astral Archmage", "Village Watch", "Village Reavers"); + private static final List unfinished = Arrays.asList("Baithook Angler", "Hook-Haunt Drifter", "Beloved Beggar", "Generous Soul", "Chaplain of Alms", "Chapel Shieldgeist", "Covert Cutpurse", "Covetous Geist", "Covetous Castaway", "Ghostly Castigator", "Dennick, Pious Apprentice", "Dennick, Pious Apparition", "Devoted Grafkeeper", "Departed Soulkeeper", "Galedrifter", "Waildrifter", "Lunarch Veteran", "Luminous Phantom", "Malevolent Hermit", "Benevolent Geist", "Mourning Patrol", "Morning Apparition", "Overwhelmed Archivist", "Archive Haunt", "Phantom Carriage", "Shipwreck Sifters", "Thraben Exorcism", "Unblinking Observer"); private static final InnistradMidnightHunt instance = new InnistradMidnightHunt(); public static InnistradMidnightHunt getInstance() { @@ -40,6 +40,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Adeline, Resplendent Cathar", 1, Rarity.RARE, mage.cards.a.AdelineResplendentCathar.class)); cards.add(new SetCardInfo("Ambitious Farmhand", 2, Rarity.UNCOMMON, mage.cards.a.AmbitiousFarmhand.class)); cards.add(new SetCardInfo("Angelfire Ignition", 209, Rarity.RARE, mage.cards.a.AngelfireIgnition.class)); + cards.add(new SetCardInfo("Angelic Enforcer", 17, Rarity.MYTHIC, mage.cards.a.AngelicEnforcer.class)); cards.add(new SetCardInfo("Arcane Infusion", 210, Rarity.UNCOMMON, mage.cards.a.ArcaneInfusion.class)); cards.add(new SetCardInfo("Archive Haunt", 68, Rarity.UNCOMMON, mage.cards.a.ArchiveHaunt.class)); cards.add(new SetCardInfo("Ardent Elementalist", 128, Rarity.COMMON, mage.cards.a.ArdentElementalist.class)); @@ -50,6 +51,8 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Augur of Autumn", 168, Rarity.RARE, mage.cards.a.AugurOfAutumn.class)); cards.add(new SetCardInfo("Awoken Demon", 100, Rarity.COMMON, mage.cards.a.AwokenDemon.class)); cards.add(new SetCardInfo("Baithook Angler", 42, Rarity.COMMON, mage.cards.b.BaithookAngler.class)); + cards.add(new SetCardInfo("Baneblade Scoundrel", 85, Rarity.UNCOMMON, mage.cards.b.BanebladeScoundrel.class)); + cards.add(new SetCardInfo("Baneclaw Marauder", 85, Rarity.UNCOMMON, mage.cards.b.BaneclawMarauder.class)); cards.add(new SetCardInfo("Bat Whisperer", 86, Rarity.COMMON, mage.cards.b.BatWhisperer.class)); cards.add(new SetCardInfo("Benevolent Geist", 61, Rarity.RARE, mage.cards.b.BenevolentGeist.class)); cards.add(new SetCardInfo("Bereaved Survivor", 4, Rarity.UNCOMMON, mage.cards.b.BereavedSurvivor.class)); @@ -97,6 +100,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Creeping Inn", 264, Rarity.MYTHIC, mage.cards.c.CreepingInn.class)); cards.add(new SetCardInfo("Croaking Counterpart", 215, Rarity.RARE, mage.cards.c.CroakingCounterpart.class)); cards.add(new SetCardInfo("Crossroads Candleguide", 253, Rarity.COMMON, mage.cards.c.CrossroadsCandleguide.class)); + cards.add(new SetCardInfo("Curse of Leeches", 94, Rarity.RARE, mage.cards.c.CurseOfLeeches.class)); cards.add(new SetCardInfo("Curse of Shaken Faith", 134, Rarity.RARE, mage.cards.c.CurseOfShakenFaith.class)); cards.add(new SetCardInfo("Curse of Silence", 15, Rarity.RARE, mage.cards.c.CurseOfSilence.class)); cards.add(new SetCardInfo("Curse of Surveillance", 46, Rarity.RARE, mage.cards.c.CurseOfSurveillance.class)); @@ -132,6 +136,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Ecstatic Awakener", 100, Rarity.COMMON, mage.cards.e.EcstaticAwakener.class)); cards.add(new SetCardInfo("Electric Revelation", 135, Rarity.COMMON, mage.cards.e.ElectricRevelation.class)); cards.add(new SetCardInfo("Embodiment of Flame", 141, Rarity.UNCOMMON, mage.cards.e.EmbodimentOfFlame.class)); + cards.add(new SetCardInfo("Enduring Angel", 17, Rarity.MYTHIC, mage.cards.e.EnduringAngel.class)); cards.add(new SetCardInfo("Evolving Wilds", 261, Rarity.COMMON, mage.cards.e.EvolvingWilds.class)); cards.add(new SetCardInfo("Fading Hope", 51, Rarity.UNCOMMON, mage.cards.f.FadingHope.class)); cards.add(new SetCardInfo("Faithful Mending", 221, Rarity.UNCOMMON, mage.cards.f.FaithfulMending.class)); @@ -196,6 +201,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Kessig Naturalist", 231, Rarity.UNCOMMON, mage.cards.k.KessigNaturalist.class)); cards.add(new SetCardInfo("Lambholt Harrier", 145, Rarity.COMMON, mage.cards.l.LambholtHarrier.class)); cards.add(new SetCardInfo("Larder Zombie", 58, Rarity.COMMON, mage.cards.l.LarderZombie.class)); + cards.add(new SetCardInfo("Leeching Lurker", 94, Rarity.RARE, mage.cards.l.LeechingLurker.class)); cards.add(new SetCardInfo("Lier, Disciple of the Drowned", 59, Rarity.MYTHIC, mage.cards.l.LierDiscipleOfTheDrowned.class)); cards.add(new SetCardInfo("Liesa, Forgotten Archangel", 232, Rarity.RARE, mage.cards.l.LiesaForgottenArchangel.class)); cards.add(new SetCardInfo("Light Up the Night", 146, Rarity.RARE, mage.cards.l.LightUpTheNight.class)); @@ -203,6 +209,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Lord of the Forsaken", 110, Rarity.MYTHIC, mage.cards.l.LordOfTheForsaken.class)); cards.add(new SetCardInfo("Lord of the Ulvenwald", 231, Rarity.UNCOMMON, mage.cards.l.LordOfTheUlvenwald.class)); cards.add(new SetCardInfo("Loyal Gryff", 26, Rarity.UNCOMMON, mage.cards.l.LoyalGryff.class)); + cards.add(new SetCardInfo("Ludevic, Necrogenius", 233, Rarity.RARE, mage.cards.l.LudevicNecrogenius.class)); cards.add(new SetCardInfo("Luminous Phantom", 27, Rarity.COMMON, mage.cards.l.LuminousPhantom.class)); cards.add(new SetCardInfo("Lunar Frenzy", 147, Rarity.UNCOMMON, mage.cards.l.LunarFrenzy.class)); cards.add(new SetCardInfo("Lunarch Veteran", 27, Rarity.COMMON, mage.cards.l.LunarchVeteran.class)); @@ -230,6 +237,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Novice Occultist", 117, Rarity.COMMON, mage.cards.n.NoviceOccultist.class)); cards.add(new SetCardInfo("Obsessive Astronomer", 152, Rarity.UNCOMMON, mage.cards.o.ObsessiveAstronomer.class)); cards.add(new SetCardInfo("Odric's Outrider", 29, Rarity.UNCOMMON, mage.cards.o.OdricsOutrider.class)); + cards.add(new SetCardInfo("Olag, Ludevic's Hubris", 233, Rarity.RARE, mage.cards.o.OlagLudevicsHubris.class)); cards.add(new SetCardInfo("Old Stickfingers", 234, Rarity.RARE, mage.cards.o.OldStickfingers.class)); cards.add(new SetCardInfo("Olivia's Midnight Ambush", 118, Rarity.COMMON, mage.cards.o.OliviasMidnightAmbush.class)); cards.add(new SetCardInfo("Ominous Roost", 65, Rarity.UNCOMMON, mage.cards.o.OminousRoost.class)); @@ -314,6 +322,7 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Tavern Ruffian", 163, Rarity.COMMON, mage.cards.t.TavernRuffian.class)); cards.add(new SetCardInfo("Tavern Smasher", 163, Rarity.COMMON, mage.cards.t.TavernSmasher.class)); cards.add(new SetCardInfo("Teferi, Who Slows the Sunset", 245, Rarity.MYTHIC, mage.cards.t.TeferiWhoSlowsTheSunset.class)); + cards.add(new SetCardInfo("The Celestus", 252, Rarity.RARE, mage.cards.t.TheCelestus.class)); cards.add(new SetCardInfo("The Meathook Massacre", 112, Rarity.MYTHIC, mage.cards.t.TheMeathookMassacre.class)); cards.add(new SetCardInfo("Thermo-Alchemist", 164, Rarity.UNCOMMON, mage.cards.t.ThermoAlchemist.class)); cards.add(new SetCardInfo("Thraben Exorcism", 39, Rarity.COMMON, mage.cards.t.ThrabenExorcism.class)); @@ -321,10 +330,13 @@ public final class InnistradMidnightHunt extends ExpansionSet { cards.add(new SetCardInfo("Tireless Hauler", 203, Rarity.COMMON, mage.cards.t.TirelessHauler.class)); cards.add(new SetCardInfo("Tovolar's Huntmaster", 204, Rarity.RARE, mage.cards.t.TovolarsHuntmaster.class)); cards.add(new SetCardInfo("Tovolar's Packleader", 204, Rarity.RARE, mage.cards.t.TovolarsPackleader.class)); + cards.add(new SetCardInfo("Tovolar, Dire Overlord", 246, Rarity.RARE, mage.cards.t.TovolarDireOverlord.class)); + cards.add(new SetCardInfo("Tovolar, the Midnight Scourge", 246, Rarity.RARE, mage.cards.t.TovolarTheMidnightScourge.class)); cards.add(new SetCardInfo("Triskaidekaphile", 81, Rarity.RARE, mage.cards.t.Triskaidekaphile.class)); cards.add(new SetCardInfo("Turn the Earth", 205, Rarity.UNCOMMON, mage.cards.t.TurnTheEarth.class)); cards.add(new SetCardInfo("Unblinking Observer", 82, Rarity.COMMON, mage.cards.u.UnblinkingObserver.class)); cards.add(new SetCardInfo("Unnatural Growth", 206, Rarity.RARE, mage.cards.u.UnnaturalGrowth.class)); + cards.add(new SetCardInfo("Unnatural Moonrise", 247, Rarity.UNCOMMON, mage.cards.u.UnnaturalMoonrise.class)); cards.add(new SetCardInfo("Unruly Mob", 40, Rarity.COMMON, mage.cards.u.UnrulyMob.class)); cards.add(new SetCardInfo("Untamed Pup", 187, Rarity.UNCOMMON, mage.cards.u.UntamedPup.class)); cards.add(new SetCardInfo("Vadrik, Astral Archmage", 248, Rarity.RARE, mage.cards.v.VadrikAstralArchmage.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DayNightTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DayNightTest.java new file mode 100644 index 00000000000..6525e7c0005 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DayNightTest.java @@ -0,0 +1,349 @@ +package org.mage.test.cards.abilities.keywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.game.permanent.Permanent; +import org.junit.Assert; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author TheElk801 + */ +public class DayNightTest extends CardTestPlayerBase { + + private static final String ruffian = "Tavern Ruffian"; + private static final String smasher = "Tavern Smasher"; + private static final String moonmist = "Moonmist"; + private static final String outcasts = "Grizzled Outcasts"; + private static final String wantons = "Krallenhorde Wantons"; + private static final String immerwolf = "Immerwolf"; + private static final String bolt = "Lightning Bolt"; + private static final String curse = "Curse of Leeches"; + private static final String lurker = "Leeching Lurker"; + private static final String vandal = "Brimstone Vandal"; + + private void assertDayNight(boolean daytime) { + Assert.assertTrue("It should not be neither day nor night", currentGame.hasDayNight()); + Assert.assertTrue("It should be " + (daytime ? "day" : "night"), currentGame.checkDayNight(daytime)); + Assert.assertFalse("It should not be " + (daytime ? "night" : "day"), currentGame.checkDayNight(!daytime)); + } + + private void assertRuffianSmasher(boolean daytime) { + assertDayNight(daytime); + if (daytime) { + assertPowerToughness(playerA, ruffian, 2, 5); + assertPermanentCount(playerA, smasher, 0); + } else { + assertPermanentCount(playerA, ruffian, 0); + assertPowerToughness(playerA, smasher, 6, 5); + } + } + + private void setDayNight(int turn, PhaseStep phaseStep, boolean daytime) { + runCode("set game to " + (daytime ? "day" : "night"), turn, phaseStep, playerA, (i, p, game) -> game.setDaytime(daytime)); + } + + @Test + public void testRegularDay() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(true); + } + + @Test + public void testNightbound() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(false); + } + + @Test + public void testDayToNightTransform() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + setDayNight(1, PhaseStep.POSTCOMBAT_MAIN, false); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(false); + } + + @Test + public void testNightToDayTransform() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + setDayNight(1, PhaseStep.POSTCOMBAT_MAIN, true); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(true); + } + + @Test + public void testMoonmistFails() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + addCard(Zone.BATTLEFIELD, playerA, ruffian); + addCard(Zone.BATTLEFIELD, playerA, outcasts); + addCard(Zone.HAND, playerA, moonmist); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, moonmist); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(true); + assertPermanentCount(playerA, outcasts, 0); + assertPowerToughness(playerA, wantons, 7, 7); + } + + @Test + public void testImmerwolfPreventsTransformation() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.BATTLEFIELD, playerA, immerwolf); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + setDayNight(1, PhaseStep.POSTCOMBAT_MAIN, true); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(true); + assertPowerToughness(playerA, smasher, 6 + 1, 5 + 1); + assertPermanentCount(playerA, ruffian, 0); + } + + @Test + public void testImmerwolfRemoved() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + addCard(Zone.BATTLEFIELD, playerA, immerwolf); + addCard(Zone.HAND, playerA, bolt); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + setDayNight(1, PhaseStep.BEGIN_COMBAT, true); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertDayNight(true); + assertPowerToughness(playerA, smasher, 6 + 1, 5 + 1); + assertPermanentCount(playerA, ruffian, 0); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bolt, immerwolf); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(true); + } + + @Test + public void testNoSpellsBecomesNight() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, ruffian); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertRuffianSmasher(true); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertRuffianSmasher(true); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(false); + } + + @Test + public void testTwoSpellsBecomesDay() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + addCard(Zone.HAND, playerA, ruffian); + addCard(Zone.HAND, playerA, bolt); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ruffian); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerB, 20 - 3); + assertGraveyardCount(playerA, bolt, 1); + assertRuffianSmasher(false); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertRuffianSmasher(true); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertRuffianSmasher(false); + } + + @Test + public void testCurseOfLeechesRegular() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.HAND, playerA, curse); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, curse, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(true); + Permanent permanent = getPermanent(curse); + Assert.assertTrue("Curse is attached to playerB", permanent.isAttachedTo(playerB.getId())); + assertPermanentCount(playerA, lurker, 0); + } + + @Test + public void testCurseOfLeechesNightbound() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.HAND, playerA, curse); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, curse, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(false); + assertPermanentCount(playerA, curse, 0); + assertPermanentCount(playerA, lurker, 1); + } + + @Test + public void testCurseOfLeechesDayToNight() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.HAND, playerA, curse); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, curse, playerB); + setDayNight(1, PhaseStep.POSTCOMBAT_MAIN, false); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(false); + assertPermanentCount(playerA, curse, 0); + assertPermanentCount(playerA, lurker, 1); + } + + @Test + public void testCurseOfLeechesNightToDay() { + currentGame.setDaytime(false); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.HAND, playerA, curse); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, curse, playerB); + setChoice(playerA, playerB.getName()); + setDayNight(1, PhaseStep.POSTCOMBAT_MAIN, true); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(true); + Permanent permanent = getPermanent(curse); + Assert.assertTrue("Curse is attached to playerB", permanent.isAttachedTo(playerB.getId())); + assertPermanentCount(playerA, lurker, 0); + } + + @Test + public void testBrimstoneVandalBecomeDay() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + addCard(Zone.HAND, playerA, vandal); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, vandal); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertDayNight(true); + assertLife(playerB, 20); + } + + @Test + public void testBrimstoneVandalTrigger() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + addCard(Zone.HAND, playerA, bolt, 2); + addCard(Zone.HAND, playerA, vandal); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, vandal); + + setStrictChooseMode(true); + setStopAt(3, PhaseStep.UPKEEP); + execute(); + + assertDayNight(false); + assertLife(playerB, 20 - 1); + + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, playerB); + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, playerB); + + setStopAt(4, PhaseStep.UPKEEP); + execute(); + assertAllCommandsUsed(); + + assertDayNight(true); + assertLife(playerB, 20 - 1 - 3 - 3 - 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java index 5329f99df1a..9ef18543e73 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java @@ -1,15 +1,13 @@ package org.mage.test.cards.abilities.keywords; +import mage.constants.CardType; import mage.constants.PhaseStep; import mage.constants.Zone; import mage.counters.CounterType; -import mage.game.permanent.Permanent; -import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * * @author LevelX2 */ public class TransformTest extends CardTestPlayerBase { @@ -133,7 +131,7 @@ public class TransformTest extends CardTestPlayerBase { * 4G Creature - Human Shaman Whenever a permanent you control transforms * into a non-Human creature, put a 2/2 green Wolf creature token onto the * battlefield. - * + *

* Reported bug: "It appears to trigger either when a non-human creature * transforms OR when a creature transforms from a non-human into a human * (as in when a werewolf flips back to the sun side), rather than when a @@ -171,24 +169,51 @@ public class TransformTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Startled Awake"); // SORCERY {2}{U}{U}" addCard(Zone.BATTLEFIELD, playerA, "Island", 9); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Startled Awake"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Startled Awake", playerB); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}{U}{U}"); + + setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); + assertAllCommandsUsed(); assertGraveyardCount(playerB, 13); assertGraveyardCount(playerA, "Startled Awake", 0); assertPermanentCount(playerA, "Persistent Nightmare", 1); // Night-side card of Startled Awake - Permanent nightmare = getPermanent("Persistent Nightmare", playerA); - Assert.assertTrue("Has to have creature card type", nightmare.isCreature(currentGame)); - Assert.assertFalse("Has not to have sorcery card type", nightmare.isSorcery(currentGame)); + assertType("Persistent Nightmare", CardType.CREATURE, true); + assertType("Persistent Nightmare", CardType.SORCERY, false); + } + + @Test + public void testStartledAwakeMoonmist() { + addCard(Zone.HAND, playerA, "Startled Awake"); + addCard(Zone.HAND, playerA, "Moonmist"); + addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 11); + addCard(Zone.BATTLEFIELD, playerA, "Maskwood Nexus"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Startled Awake", playerB); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}{U}{U}"); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Moonmist"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertGraveyardCount(playerB, 13); + assertGraveyardCount(playerA, "Startled Awake", 0); + assertPermanentCount(playerA, "Persistent Nightmare", 1); // Night-side card of Startled Awake + assertType("Persistent Nightmare", CardType.CREATURE, true); + assertType("Persistent Nightmare", CardType.SORCERY, false); } /** * When copy token of Lambholt Pacifist transforms with "its transform * ability", I see below error. Then rollback. - * + *

* 701.25a Only permanents represented by double-faced cards can transform. * (See rule 711, “Double-Faced Cards.”) If a spell or ability instructs a * player to transform any permanent that isn‘t represented by a @@ -221,7 +246,7 @@ public class TransformTest extends CardTestPlayerBase { /** * Mirror Mockery copies the front face of a Transformed card rather than * the current face. - * + *

* It's worth pointing out that my opponent cast Mirror Mockery the previous * turn - after it had transformed. I should have included the part of the * log that showed that Mirror Mockery was applied to the Unimpeded @@ -280,11 +305,13 @@ public class TransformTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Wastes", 3); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, true); - activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{2}{C}", "Archangel Avacyn", "Whenever a non-Angel creature you control dies"); + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{2}{C}", "Archangel Avacyn"); setStopAt(3, PhaseStep.PRECOMBAT_MAIN); execute(); + assertAllCommandsUsed(); assertGraveyardCount(playerA, "Lightning Bolt", 1); assertGraveyardCount(playerA, "Silvercoat Lion", 1); @@ -317,9 +344,9 @@ public class TransformTest extends CardTestPlayerBase { * was on stack, my opponent used Displacer's ability targeting Huntmaster. * That ability resolved and Huntmaster still transformed like it never left * the battlefield. - * + *

* http://www.slightlymagic.net/forum/viewtopic.php?f=70&t=20014&p=210533#p210513 - * + *

* The transform effect on the stack should fizzle. The card brought back * from Exile should be a new object unless I am interpreting the rules * incorrectly. The returned permanent uses the same GUID. @@ -356,12 +383,13 @@ public class TransformTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Ravager of the Fells", 0); assertPermanentCount(playerA, "Huntmaster of the Fells", 1); - assertPowerToughness(playerA, "Huntmaster of the Fells", 2, 2); + assertPowerToughness(playerA, "Huntmaster of the Fells", 2, 2); assertTappedCount("Plains", true, 2); assertTappedCount("Wastes", true, 1); } - @Test + + @Test public void testHuntmasterTransformed() { // Whenever this creature enters the battlefield or transforms into Huntmaster of the Fells, create a 2/2 green Wolf creature token and you gain 2 life. // At the beginning of each upkeep, if no spells were cast last turn, transform Huntmaster of the Fells. @@ -387,15 +415,16 @@ public class TransformTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Ravager of the Fells", 0); assertPermanentCount(playerA, "Huntmaster of the Fells", 1); assertPowerToughness(playerA, "Huntmaster of the Fells", 2, 2); - + } + /** * Having cast Phantasmal Image copying my opponent's flipped Thing in the * Ice, I was left with a 0/4 Awoken Horror. - * + *

* https://github.com/magefree/mage/issues/5893 - * + *

* The transform effect on the stack should fizzle. The card brought back * from Exile should be a new object unless I am interpreting the rules * incorrectly. The returned permanent uses the same GUID. @@ -440,4 +469,32 @@ public class TransformTest extends CardTestPlayerBase { } + @Test + public void testMoonmistDelver() { + addCard(Zone.BATTLEFIELD, playerA, "Island"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); + addCard(Zone.HAND, playerA, "Delver of Secrets"); + addCard(Zone.HAND, playerA, "Moonmist", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Delver of Secrets"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Moonmist"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Delver of Secrets", 0); + assertPermanentCount(playerA, "Insectile Aberration", 1); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Moonmist"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, "Delver of Secrets", 1); + assertPermanentCount(playerA, "Insectile Aberration", 0); + } } diff --git a/Mage/src/main/java/mage/abilities/Ability.java b/Mage/src/main/java/mage/abilities/Ability.java index 63cb477b0c7..725c671925a 100644 --- a/Mage/src/main/java/mage/abilities/Ability.java +++ b/Mage/src/main/java/mage/abilities/Ability.java @@ -531,6 +531,10 @@ public interface Ability extends Controllable, Serializable { */ Permanent getSourcePermanentOrLKI(Game game); + void setSourcePermanentTransformCount(Game game); + + boolean checkTransformCount(Permanent permanent, Game game); + String getTargetDescription(Targets targets, Game game); void setCanFizzle(boolean canFizzle); diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 44306218224..e9cdf569912 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -80,6 +80,7 @@ public abstract class AbilityImpl implements Ability { protected Outcome customOutcome = null; // uses for AI decisions instead effects protected MageIdentifier identifier; // used to identify specific ability (e.g. to match with corresponding watcher) protected String appendToRule = null; + protected int sourcePermanentTransformCount = 0; public AbilityImpl(AbilityType abilityType, Zone zone) { this.id = UUID.randomUUID(); @@ -135,6 +136,7 @@ public abstract class AbilityImpl implements Ability { this.identifier = ability.identifier; this.activated = ability.activated; this.appendToRule = ability.appendToRule; + this.sourcePermanentTransformCount = ability.sourcePermanentTransformCount; } @Override @@ -246,6 +248,7 @@ public abstract class AbilityImpl implements Ability { if (getSourceObjectZoneChangeCounter() == 0) { setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(getSourceId())); } + setSourcePermanentTransformCount(game); /* 20130201 - 601.2b * If the player wishes to splice any cards onto the spell (see rule 702.45), he @@ -1292,6 +1295,24 @@ public abstract class AbilityImpl implements Ability { return sourceObjectZoneChangeCounter; } + @Override + public void setSourcePermanentTransformCount(Game game) { + Permanent permanent = getSourcePermanentOrLKI(game); + if (permanent != null) { + this.sourcePermanentTransformCount = permanent.getTransformCount(); + } + } + + @Override + public boolean checkTransformCount(Permanent permanent, Game game) { + if (permanent == null + || !permanent.getId().equals(sourceId) + || permanent.getZoneChangeCounter(game) != sourceObjectZoneChangeCounter) { + return true; + } + return permanent.getTransformCount() == sourcePermanentTransformCount; + } + @Override public boolean canFizzle() { return canFizzle; diff --git a/Mage/src/main/java/mage/abilities/common/BecomeDayAsEntersAbility.java b/Mage/src/main/java/mage/abilities/common/BecomeDayAsEntersAbility.java index ac555d784e7..80ec12f0dca 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomeDayAsEntersAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BecomeDayAsEntersAbility.java @@ -2,17 +2,18 @@ package mage.abilities.common; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; +import mage.abilities.hint.common.DayNightHint; import mage.constants.Outcome; import mage.game.Game; /** * @author TheElk801 - * TODO: this is just a placeholder for the actual ability */ public class BecomeDayAsEntersAbility extends EntersBattlefieldAbility { public BecomeDayAsEntersAbility() { super(new BecomeDayEffect()); + this.addHint(DayNightHint.instance); } private BecomeDayAsEntersAbility(final BecomeDayAsEntersAbility ability) { @@ -33,7 +34,7 @@ public class BecomeDayAsEntersAbility extends EntersBattlefieldAbility { class BecomeDayEffect extends OneShotEffect { BecomeDayEffect() { - super(Outcome.Benefit); + super(Outcome.Neutral); } private BecomeDayEffect(final BecomeDayEffect effect) { @@ -47,6 +48,10 @@ class BecomeDayEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - return true; + if (!game.hasDayNight()) { + game.setDaytime(true); + return true; + } + return false; } } diff --git a/Mage/src/main/java/mage/abilities/common/BecomesDayOrNightTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BecomesDayOrNightTriggeredAbility.java index e955649af17..237805acbb7 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomesDayOrNightTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BecomesDayOrNightTriggeredAbility.java @@ -8,7 +8,6 @@ import mage.game.events.GameEvent; /** * @author TheElk801 - * TODO: this is just a placeholder for the actual ability */ public class BecomesDayOrNightTriggeredAbility extends TriggeredAbilityImpl { @@ -26,7 +25,7 @@ public class BecomesDayOrNightTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkEventType(GameEvent event, Game game) { - return false; + return event.getType() == GameEvent.EventType.BECOMES_DAY_NIGHT; } @Override diff --git a/Mage/src/main/java/mage/abilities/common/WerewolfBackTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/WerewolfBackTriggeredAbility.java index 536d4c10a05..1915abb7ec7 100644 --- a/Mage/src/main/java/mage/abilities/common/WerewolfBackTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/WerewolfBackTriggeredAbility.java @@ -11,7 +11,7 @@ import mage.game.Game; public class WerewolfBackTriggeredAbility extends BeginningOfUpkeepTriggeredAbility { public WerewolfBackTriggeredAbility() { - super(new TransformSourceEffect(false), TargetController.ANY, false); + super(new TransformSourceEffect(), TargetController.ANY, false); } private WerewolfBackTriggeredAbility(final WerewolfBackTriggeredAbility ability) { diff --git a/Mage/src/main/java/mage/abilities/common/WerewolfFrontTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/WerewolfFrontTriggeredAbility.java index 70d91b1a37c..033cb066818 100644 --- a/Mage/src/main/java/mage/abilities/common/WerewolfFrontTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/WerewolfFrontTriggeredAbility.java @@ -11,7 +11,7 @@ import mage.game.Game; public class WerewolfFrontTriggeredAbility extends BeginningOfUpkeepTriggeredAbility { public WerewolfFrontTriggeredAbility() { - super(new TransformSourceEffect(true), TargetController.ANY, false); + super(new TransformSourceEffect(), TargetController.ANY, false); } private WerewolfFrontTriggeredAbility(final WerewolfFrontTriggeredAbility ability) { diff --git a/Mage/src/main/java/mage/abilities/condition/common/NightCondition.java b/Mage/src/main/java/mage/abilities/condition/common/NightCondition.java index 29e5c709d64..11a6cd4bb58 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/NightCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/NightCondition.java @@ -6,14 +6,13 @@ import mage.game.Game; /** * @author TheElk801 - * TODO: Implement this */ public enum NightCondition implements Condition { instance; @Override public boolean apply(Game game, Ability source) { - return false; + return game.checkDayNight(false); } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/TransformSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/TransformSourceEffect.java index 13e8b95d1f3..329cab439e9 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/TransformSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/TransformSourceEffect.java @@ -1,43 +1,23 @@ - package mage.abilities.effects.common; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentCard; /** - * * @author nantuko */ public class TransformSourceEffect extends OneShotEffect { - private boolean withoutTrigger; - private boolean fromDayToNight; - - /** - * @param fromDayToNight Defines whether we transform from "day" side to - * "night" or vice versa. - */ - public TransformSourceEffect(boolean fromDayToNight) { - this(fromDayToNight, false); - } - - public TransformSourceEffect(boolean fromDayToNight, boolean withoutTrigger) { + public TransformSourceEffect() { super(Outcome.Transform); - this.withoutTrigger = withoutTrigger; - this.fromDayToNight = fromDayToNight; staticText = "transform {this}"; } public TransformSourceEffect(final TransformSourceEffect effect) { super(effect); - this.withoutTrigger = effect.withoutTrigger; - this.fromDayToNight = effect.fromDayToNight; } @Override @@ -47,37 +27,8 @@ public class TransformSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - MageObject sourceObject = source.getSourceObjectIfItStillExists(game); // Transform only if it's the same object as the effect was put on the stack - if (sourceObject instanceof Permanent) { - Permanent sourcePermanent = (Permanent) sourceObject; - if (sourcePermanent.canTransform(source, game)) { - // check not to transform twice the same side - if (sourcePermanent.isTransformed() != fromDayToNight) { - if (withoutTrigger) { - sourcePermanent.setTransformed(fromDayToNight); - } else { - if (sourcePermanent.isTransformed()) { - Card orgCard = game.getCard(source.getSourceId()); - sourcePermanent.getPower().modifyBaseValue(orgCard.getPower().getValue()); - sourcePermanent.getToughness().modifyBaseValue(orgCard.getToughness().getValue()); - } - sourcePermanent.transform(game); - } - if (!game.isSimulation()) { - if (fromDayToNight) { - if (sourcePermanent.getSecondCardFace() != null) { - if (sourcePermanent instanceof PermanentCard) { - game.informPlayers(((PermanentCard) sourcePermanent).getCard().getLogName() + " transforms into " + sourcePermanent.getSecondCardFace().getLogName()); - } - } - } else { - game.informPlayers(sourcePermanent.getSecondCardFace().getLogName() + " transforms into " + sourcePermanent.getLogName()); - } - } - } - } - } - return true; + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + // check not to transform twice the same side + return permanent != null && permanent.transform(source, game); } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/TransformTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/TransformTargetEffect.java deleted file mode 100644 index b128ae01081..00000000000 --- a/Mage/src/main/java/mage/abilities/effects/common/TransformTargetEffect.java +++ /dev/null @@ -1,88 +0,0 @@ -package mage.abilities.effects.common; - -import mage.abilities.Ability; -import mage.abilities.Mode; -import mage.abilities.effects.OneShotEffect; -import mage.constants.Outcome; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentCard; -import mage.target.Target; -import mage.util.CardUtil; - -/** - * - * @author LevelX2 - */ -public class TransformTargetEffect extends OneShotEffect { - - private boolean withoutTrigger; - - public TransformTargetEffect() { - this(true); - } - - public TransformTargetEffect(boolean withoutTrigger) { - super(Outcome.Transform); - this.withoutTrigger = withoutTrigger; - } - - public TransformTargetEffect(final TransformTargetEffect effect) { - super(effect); - this.withoutTrigger = effect.withoutTrigger; - } - - @Override - public TransformTargetEffect copy() { - return new TransformTargetEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent != null) { - if (permanent.canTransform(source, game)) { - // check not to transform twice the same side - if (withoutTrigger) { - permanent.setTransformed(!permanent.isTransformed()); - } else { - permanent.transform(game); - } - if (!game.isSimulation()) { - if (permanent.isTransformed()) { - if (permanent.getSecondCardFace() != null) { - if (permanent instanceof PermanentCard) { - game.informPlayers(((PermanentCard) permanent).getCard().getLogName() + " transforms into " + permanent.getSecondCardFace().getLogName()); - } - } - } else { - game.informPlayers(permanent.getSecondCardFace().getLogName() + " transforms into " + permanent.getLogName()); - } - } - } - - return true; - } - return false; - } - - @Override - public String getText(Mode mode) { - if (staticText != null && !staticText.isEmpty()) { - return staticText; - } - if (mode.getTargets().isEmpty()) { - return "transform target"; - } - Target target = mode.getTargets().get(0); - if (target.getMaxNumberOfTargets() > 1) { - if (target.getMaxNumberOfTargets() == target.getNumberOfTargets()) { - return "transform " + CardUtil.numberToText(target.getNumberOfTargets()) + " target " + target.getTargetName(); - } else { - return "transform up to " + CardUtil.numberToText(target.getMaxNumberOfTargets()) + " target " + target.getTargetName(); - } - } else { - return "transform target " + mode.getTargets().get(0).getTargetName(); - } - } -} diff --git a/Mage/src/main/java/mage/abilities/hint/common/DayNightHint.java b/Mage/src/main/java/mage/abilities/hint/common/DayNightHint.java new file mode 100644 index 00000000000..a4b56be021d --- /dev/null +++ b/Mage/src/main/java/mage/abilities/hint/common/DayNightHint.java @@ -0,0 +1,40 @@ +package mage.abilities.hint.common; + +import mage.abilities.Ability; +import mage.abilities.hint.Hint; +import mage.game.Game; +import mage.watchers.common.CastSpellLastTurnWatcher; + +/** + * @author TheElk801 + */ +public enum DayNightHint implements Hint { + instance; + + @Override + public String getText(Game game, Ability ability) { + if (!game.hasDayNight()) { + return "It's neither day nor night."; + } + boolean isDay = game.checkDayNight(true); + int spellsThisTurn = game + .getState() + .getWatcher(CastSpellLastTurnWatcher.class) + .getActivePlayerThisTurnCount(); + StringBuilder sb = new StringBuilder("It's currently "); + sb.append(isDay ? "day" : "night"); + sb.append(", active player has cast "); + sb.append(spellsThisTurn); + sb.append(" spells this turn. It will "); + sb.append((isDay ? spellsThisTurn == 0 : spellsThisTurn >= 2) ? "" : "not"); + sb.append(" become "); + sb.append(isDay ? "night" : "day"); + sb.append(" next turn."); + return sb.toString(); + } + + @Override + public DayNightHint copy() { + return this; + } +} diff --git a/Mage/src/main/java/mage/abilities/hint/common/NightHint.java b/Mage/src/main/java/mage/abilities/hint/common/NightHint.java deleted file mode 100644 index afc7f2631dd..00000000000 --- a/Mage/src/main/java/mage/abilities/hint/common/NightHint.java +++ /dev/null @@ -1,27 +0,0 @@ -package mage.abilities.hint.common; - -import mage.abilities.Ability; -import mage.abilities.condition.common.NightCondition; -import mage.abilities.hint.ConditionHint; -import mage.abilities.hint.Hint; -import mage.game.Game; - -/** - * @author TheElk801 - */ -public enum NightHint implements Hint { - instance; - private static final Hint hint = new ConditionHint( - NightCondition.instance, "It's currently night" - ); - - @Override - public String getText(Game game, Ability ability) { - return hint.getText(game, ability); - } - - @Override - public Hint copy() { - return this; - } -} diff --git a/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java b/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java index 1e8761d6b4c..619210a997f 100644 --- a/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java @@ -1,16 +1,20 @@ package mage.abilities.keyword; +import mage.abilities.Ability; import mage.abilities.StaticAbility; -import mage.constants.Zone; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.hint.common.DayNightHint; +import mage.constants.*; +import mage.game.Game; /** * @author TheElk801 - * TODO: Implement this */ public class DayboundAbility extends StaticAbility { public DayboundAbility() { - super(Zone.BATTLEFIELD, null); + super(Zone.BATTLEFIELD, new DayboundEffect()); + this.addHint(DayNightHint.instance); } private DayboundAbility(final DayboundAbility ability) { @@ -27,3 +31,27 @@ public class DayboundAbility extends StaticAbility { return new DayboundAbility(this); } } + +class DayboundEffect extends ContinuousEffectImpl { + + DayboundEffect() { + super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit); + } + + private DayboundEffect(final DayboundEffect effect) { + super(effect); + } + + @Override + public DayboundEffect copy() { + return new DayboundEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (!game.hasDayNight()) { + game.setDaytime(true); + } + return true; + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/NightboundAbility.java b/Mage/src/main/java/mage/abilities/keyword/NightboundAbility.java index 804b63c83cc..5269cd301bb 100644 --- a/Mage/src/main/java/mage/abilities/keyword/NightboundAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/NightboundAbility.java @@ -1,16 +1,21 @@ package mage.abilities.keyword; +import mage.abilities.Ability; import mage.abilities.StaticAbility; -import mage.constants.Zone; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.hint.common.DayNightHint; +import mage.cards.Card; +import mage.constants.*; +import mage.game.Game; /** * @author TheElk801 - * TODO: Implement this */ public class NightboundAbility extends StaticAbility { public NightboundAbility() { - super(Zone.BATTLEFIELD, null); + super(Zone.BATTLEFIELD, new NightboundEffect()); + this.addHint(DayNightHint.instance); } private NightboundAbility(final NightboundAbility ability) { @@ -26,4 +31,34 @@ public class NightboundAbility extends StaticAbility { public NightboundAbility copy() { return new NightboundAbility(this); } + + public static boolean checkCard(Card card, Game game) { + return game.checkDayNight(false) + && card.getSecondCardFace() != null + && card.getSecondCardFace().getAbilities().containsClass(NightboundAbility.class); + } +} + +class NightboundEffect extends ContinuousEffectImpl { + + NightboundEffect() { + super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit); + } + + private NightboundEffect(final NightboundEffect effect) { + super(effect); + } + + @Override + public NightboundEffect copy() { + return new NightboundEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (!game.hasDayNight()) { + game.setDaytime(false); + } + return true; + } } diff --git a/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java b/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java index 7017d0cd068..37223ad6141 100644 --- a/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java @@ -64,7 +64,6 @@ public class TransformAbility extends SimpleStaticAbility { } permanent.getPower().modifyBaseValue(sourceCard.getPower().getValue()); permanent.getToughness().modifyBaseValue(sourceCard.getToughness().getValue()); - permanent.setTransformable(sourceCard.isTransformable()); } } diff --git a/Mage/src/main/java/mage/cards/Card.java b/Mage/src/main/java/mage/cards/Card.java index c00bffaf700..5db0ca7208d 100644 --- a/Mage/src/main/java/mage/cards/Card.java +++ b/Mage/src/main/java/mage/cards/Card.java @@ -70,8 +70,6 @@ public interface Card extends MageObject { boolean isTransformable(); - void setTransformable(boolean transformable); - Card getSecondCardFace(); boolean isNightCard(); diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index e20db016323..a06431ed075 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -43,7 +43,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card { protected String tokenSetCode; protected String tokenDescriptor; protected Rarity rarity; - protected boolean transformable; protected Class secondSideCardClazz; protected Card secondSideCard; protected boolean nightCard; @@ -121,7 +120,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card { tokenDescriptor = card.tokenDescriptor; rarity = card.rarity; - transformable = card.transformable; secondSideCardClazz = card.secondSideCardClazz; secondSideCard = null; // will be set on first getSecondCardFace call if card has one nightCard = card.nightCard; @@ -618,12 +616,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { @Override public boolean isTransformable() { - return this.transformable; - } - - @Override - public void setTransformable(boolean transformable) { - this.transformable = transformable; + return this.secondSideCardClazz != null || this.nightCard; } @Override diff --git a/Mage/src/main/java/mage/cards/mock/MockCard.java b/Mage/src/main/java/mage/cards/mock/MockCard.java index 0a6b411344c..1e94fe8d553 100644 --- a/Mage/src/main/java/mage/cards/mock/MockCard.java +++ b/Mage/src/main/java/mage/cards/mock/MockCard.java @@ -63,7 +63,6 @@ public class MockCard extends CardImpl { this.flipCard = card.isFlipCard(); - this.transformable = card.isDoubleFaced(); this.nightCard = card.isNightCard(); if (card.getSecondSideName() != null && !card.getSecondSideName().isEmpty()) { this.secondSideCard = new MockCard(CardRepository.instance.findCardWPreferredSet(card.getSecondSideName(), card.getSetCode(), false)); diff --git a/Mage/src/main/java/mage/cards/mock/MockSplitCard.java b/Mage/src/main/java/mage/cards/mock/MockSplitCard.java index d0b3b861131..de5e116b608 100644 --- a/Mage/src/main/java/mage/cards/mock/MockSplitCard.java +++ b/Mage/src/main/java/mage/cards/mock/MockSplitCard.java @@ -37,7 +37,6 @@ public class MockSplitCard extends SplitCard { this.color = card.getColor(); this.flipCard = card.isFlipCard(); - this.transformable = card.isDoubleFaced(); this.nightCard = card.isNightCard(); if (card.getSecondSideName() != null && !card.getSecondSideName().isEmpty()) { this.secondSideCard = new MockCard(CardRepository.instance.findCardWPreferredSet(card.getSecondSideName(), card.getSetCode(), false)); diff --git a/Mage/src/main/java/mage/game/Game.java b/Mage/src/main/java/mage/game/Game.java index 9cbdbf01d50..1ec9f2439fa 100644 --- a/Mage/src/main/java/mage/game/Game.java +++ b/Mage/src/main/java/mage/game/Game.java @@ -386,6 +386,26 @@ public interface Game extends MageItem, Serializable, Copyable { void ventureIntoDungeon(UUID playerId); + /** + * Tells whether the current game has day or night, defaults to false + */ + boolean hasDayNight(); + + /** + * Sets game to day or night, sets hasDayNight to true + * + * @param daytime day is true, night is false + */ + void setDaytime(boolean daytime); + + /** + * Returns true if hasDayNight is true and parameter matches current day/night value + * Returns false if hasDayNight is false + * + * @param daytime day is true, night is false + */ + boolean checkDayNight(boolean daytime); + /** * Adds a permanent to the battlefield * diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 71cb83352f3..d21094e5452 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -14,10 +14,7 @@ import mage.abilities.effects.Effect; import mage.abilities.effects.PreventionEffectData; import mage.abilities.effects.common.CopyEffect; import mage.abilities.effects.common.InfoEffect; -import mage.abilities.keyword.BestowAbility; -import mage.abilities.keyword.CompanionAbility; -import mage.abilities.keyword.MorphAbility; -import mage.abilities.keyword.TransformAbility; +import mage.abilities.keyword.*; import mage.abilities.mana.DelayedTriggeredManaAbility; import mage.abilities.mana.TriggeredManaAbility; import mage.actions.impl.MageAction; @@ -552,6 +549,35 @@ public abstract class GameImpl implements Game { fireEvent(GameEvent.getEvent(GameEvent.EventType.VENTURED, playerId, null, playerId)); } + @Override + public boolean hasDayNight() { + return state.isHasDayNight(); + } + + @Override + public void setDaytime(boolean daytime) { + if (!state.isHasDayNight()) { + informPlayers("It has become " + (daytime ? "day" : "night")); + } + if (!state.setDaytime(daytime)) { + return; + } + // TODO: add day/night sound effect + informPlayers("It has become " + (daytime ? "day" : "night")); + fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_DAY_NIGHT, null, null, null)); + for (Permanent permanent : state.getBattlefield().getAllPermanents()) { + if ((daytime && permanent.getAbilities(this).containsClass(NightboundAbility.class)) + || (!daytime && permanent.getAbilities(this).containsClass(DayboundAbility.class))) { + permanent.transform(null, this, true); + } + } + } + + @Override + public boolean checkDayNight(boolean daytime) { + return state.isHasDayNight() && state.isDaytime() == daytime; + } + @Override public UUID getOwnerId(UUID objectId) { return getOwnerId(getObject(objectId)); @@ -1933,6 +1959,9 @@ public abstract class GameImpl implements Game { if (newAbility.getSourceObjectZoneChangeCounter() == 0) { newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(ability.getSourceId())); } + if (!(newAbility instanceof DelayedTriggeredAbility)) { + newAbility.setSourcePermanentTransformCount(this); + } newAbility.setTriggerEvent(triggeringEvent); state.addTriggeredAbility(newAbility); } @@ -1949,6 +1978,7 @@ public abstract class GameImpl implements Game { newAbility.newId(); if (source != null) { newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(source.getSourceId())); + newAbility.setSourcePermanentTransformCount(this); } newAbility.initOnAdding(this); // ability.init is called as the ability triggeres not now. @@ -2585,6 +2615,17 @@ public abstract class GameImpl implements Game { } } + // Daybound/Nightbound permanents should be transformed according to day/night + // This is not a state-based action but it's unclear where else to put it + if (hasDayNight()) { + for (Permanent permanent : getBattlefield().getAllActivePermanents()) { + if ((permanent.getAbilities(this).containsClass(DayboundAbility.class) && !state.isDaytime()) + || (permanent.getAbilities(this).containsClass(NightboundAbility.class) && state.isDaytime())) { + somethingHappened = permanent.transform(null, this, true) || somethingHappened; + } + } + } + //TODO: implement the rest return somethingHappened; } @@ -2757,6 +2798,8 @@ public abstract class GameImpl implements Game { @Override public void informPlayers(String message) { + // Uncomment to print game messages + // System.out.println(message.replaceAll("\\<.*?\\>", "")); if (simulation) { return; } diff --git a/Mage/src/main/java/mage/game/GameState.java b/Mage/src/main/java/mage/game/GameState.java index 491c26b5876..1bb704405fa 100644 --- a/Mage/src/main/java/mage/game/GameState.java +++ b/Mage/src/main/java/mage/game/GameState.java @@ -105,6 +105,8 @@ public class GameState implements Serializable, Copyable { private final Map usePowerInsteadOfToughnessForDamageLethalityFilters = new HashMap<>(); private Set commandersToStay = new HashSet<>(); // commanders that do not go back to command zone private boolean manaBurn = false; + private boolean hasDayNight = false; + private boolean isDaytime = true; private int applyEffectsCounter; // Upcounting number of each applyEffects execution @@ -193,6 +195,8 @@ public class GameState implements Serializable, Copyable { state.usePowerInsteadOfToughnessForDamageLethalityFilters.forEach((uuid, filter) -> this.usePowerInsteadOfToughnessForDamageLethalityFilters.put(uuid, filter.copy())); this.commandersToStay.addAll(state.commandersToStay); + this.hasDayNight = state.hasDayNight; + this.isDaytime = state.isDaytime; } public void clearOnGameRestart() { @@ -280,6 +284,8 @@ public class GameState implements Serializable, Copyable { state.usePowerInsteadOfToughnessForDamageLethalityFilters.forEach((uuid, filter) -> this.usePowerInsteadOfToughnessForDamageLethalityFilters.put(uuid, filter.copy())); this.commandersToStay = state.commandersToStay; + this.hasDayNight = state.hasDayNight; + this.isDaytime = state.isDaytime; } @Override @@ -872,7 +878,7 @@ public class GameState implements Serializable, Copyable { for (Map.Entry> entry : eventsByKey.entrySet()) { Set movedCards = new LinkedHashSet<>(); Set movedTokens = new LinkedHashSet<>(); - for (Iterator it = entry.getValue().iterator(); it.hasNext();) { + for (Iterator it = entry.getValue().iterator(); it.hasNext(); ) { GameEvent event = it.next(); ZoneChangeEvent castEvent = (ZoneChangeEvent) event; UUID targetId = castEvent.getTargetId(); @@ -946,8 +952,8 @@ public class GameState implements Serializable, Copyable { * span * * @param ability - * @param sourceId - if source object can be moved between zones then you - * must set it here (each game cycle clear all source related triggers) + * @param sourceId - if source object can be moved between zones then you + * must set it here (each game cycle clear all source related triggers) * @param attachedTo */ public void addAbility(Ability ability, UUID sourceId, MageObject attachedTo) { @@ -1153,8 +1159,8 @@ public class GameState implements Serializable, Copyable { * @param attachedTo * @param ability * @param copyAbility copies non MageSingleton abilities before adding to - * state (allows to have multiple instances in one object, e.g. false param - * will simulate keyword/singleton) + * state (allows to have multiple instances in one object, e.g. false param + * will simulate keyword/singleton) */ public void addOtherAbility(Card attachedTo, Ability ability, boolean copyAbility) { checkWrongDynamicAbilityUsage(attachedTo, ability); @@ -1413,6 +1419,21 @@ public class GameState implements Serializable, Copyable { return manaBurn; } + boolean isHasDayNight() { + return hasDayNight; + } + + boolean setDaytime(boolean daytime) { + boolean flag = this.hasDayNight && this.isDaytime != daytime; + this.hasDayNight = true; + this.isDaytime = daytime; + return flag; + } + + boolean isDaytime() { + return isDaytime; + } + @Override public String toString() { return CardUtil.getTurnInfo(this); diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java index 69c54154821..8a5f93b38f7 100644 --- a/Mage/src/main/java/mage/game/events/GameEvent.java +++ b/Mage/src/main/java/mage/game/events/GameEvent.java @@ -334,7 +334,7 @@ public class GameEvent implements Serializable { UNTAP, UNTAPPED, FLIP, FLIPPED, UNFLIP, UNFLIPPED, - TRANSFORM, TRANSFORMED, + TRANSFORM, TRANSFORMING, TRANSFORMED, ADAPT, BECOMES_MONSTROUS, /* BECOMES_EXERTED @@ -356,6 +356,7 @@ public class GameEvent implements Serializable { */ BECOME_MONARCH, BECOMES_MONARCH, + BECOMES_DAY_NIGHT, MEDITATED, PHASE_OUT, PHASED_OUT, PHASE_IN, PHASED_IN, diff --git a/Mage/src/main/java/mage/game/permanent/Permanent.java b/Mage/src/main/java/mage/game/permanent/Permanent.java index 65b47042538..b91b9f740ae 100644 --- a/Mage/src/main/java/mage/game/permanent/Permanent.java +++ b/Mage/src/main/java/mage/game/permanent/Permanent.java @@ -47,12 +47,16 @@ public interface Permanent extends Card, Controllable { boolean flip(Game game); - boolean transform(Game game); + boolean transform(Ability source, Game game); + + boolean transform(Ability source, Game game, boolean ignoreDayNight); boolean isTransformed(); void setTransformed(boolean value); + int getTransformCount(); + boolean isPhasedIn(); boolean isPhasedOutIndirectly(); @@ -289,15 +293,6 @@ public interface Permanent extends Card, Controllable { */ boolean canUseActivatedAbilities(Game game); - /** - * Checks by restriction effects if the permanent can transform - * - * @param ability the ability that causes the transform - * @param game - * @return true - permanent can transform - */ - boolean canTransform(Ability ability, Game game); - boolean removeFromCombat(Game game); boolean removeFromCombat(Game game, boolean withInfo); @@ -413,5 +408,4 @@ public interface Permanent extends Card, Controllable { } return getAttachedTo().equals(otherId); } - } diff --git a/Mage/src/main/java/mage/game/permanent/PermanentCard.java b/Mage/src/main/java/mage/game/permanent/PermanentCard.java index 8b813625aaf..13c4dc60f5b 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentCard.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentCard.java @@ -5,6 +5,7 @@ import mage.abilities.Abilities; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.keyword.NightboundAbility; import mage.abilities.keyword.TransformAbility; import mage.cards.Card; import mage.cards.LevelerCard; @@ -70,7 +71,8 @@ public class PermanentCard extends PermanentImpl { maxLevelCounters = ((LevelerCard) card).getMaxLevelCounters(); } if (isTransformable()) { - if (game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + getId()) != null) { + if (game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + getId()) != null + || NightboundAbility.checkCard(this, game)) { game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + getId(), null); setTransformed(true); TransformAbility.transform(this, getSecondCardFace(), game, null); @@ -132,14 +134,10 @@ public class PermanentCard extends PermanentImpl { this.cardNumber = card.getCardNumber(); this.usesVariousArt = card.getUsesVariousArt(); - this.transformable = card.isTransformable(); - if (this.transformable) { - this.nightCard = card.isNightCard(); - if (!this.nightCard) { - this.secondSideCard = card.getSecondCardFace(); - this.secondSideCardClazz = this.secondSideCard.getClass(); - } + if (card.getSecondCardFace() != null) { + this.secondSideCardClazz = card.getSecondCardFace().getClass(); } + this.nightCard = card.isNightCard(); this.flipCard = card.isFlipCard(); this.flipCardName = card.getFlipCardName(); } diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index 26b10e2d089..f27244bd087 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -103,6 +103,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { protected List markedDamage; protected int markedLifelink; protected int timesLoyaltyUsed = 0; + protected int transformCount = 0; protected Map info; protected int createOrder; @@ -168,6 +169,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { this.pairedPermanent = permanent.pairedPermanent; this.bandedCards.addAll(permanent.bandedCards); this.timesLoyaltyUsed = permanent.timesLoyaltyUsed; + this.transformCount = permanent.transformCount; this.morphed = permanent.morphed; this.manifested = permanent.manifested; @@ -562,16 +564,46 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { } @Override - public boolean transform(Game game) { - if (transformable) { - if (!replaceEvent(EventType.TRANSFORM, game)) { - setTransformed(!transformed); - game.applyEffects(); - game.addSimultaneousEvent(GameEvent.getEvent(GameEvent.EventType.TRANSFORMED, getId(), getControllerId())); - return true; - } + public boolean transform(Ability source, Game game) { + return this.transform(source, game, false); + } + + private boolean checkDayNightBound() { + return this.getAbilities().containsClass(DayboundAbility.class) + || this.getAbilities().containsClass(NightboundAbility.class); + } + + private Card getOtherFace() { + return transformed ? this.getMainCard() : this.getMainCard().getSecondCardFace(); + } + + @Override + public boolean transform(Ability source, Game game, boolean ignoreDayNight) { + if (!this.isTransformable() + || (!ignoreDayNight && this.checkDayNightBound()) + || this.getOtherFace().isInstantOrSorcery() + || (source != null && !source.checkTransformCount(this, game)) + || this.replaceEvent(EventType.TRANSFORM, game)) { + return false; } - return false; + if (this.transformed) { + Card orgCard = this.getMainCard(); + this.getPower().modifyBaseValue(orgCard.getPower().getValue()); + this.getToughness().modifyBaseValue(orgCard.getToughness().getValue()); + } + game.informPlayers(this.getLogName() + " transforms into " + this.getOtherFace().getLogName() + + CardUtil.getSourceLogName(game, source, this.getId())); + this.setTransformed(!this.transformed); + this.transformCount++; + game.applyEffects(); + this.replaceEvent(EventType.TRANSFORMING, game); + game.addSimultaneousEvent(GameEvent.getEvent(EventType.TRANSFORMED, this.getId(), this.getControllerId())); + return true; + } + + @Override + public int getTransformCount() { + return transformCount; } @Override @@ -1406,21 +1438,6 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { return true; } - @Override - public boolean canTransform(Ability source, Game game) { - if (transformable) { - for (Map.Entry> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) { - RestrictionEffect effect = entry.getKey(); - for (Ability ability : entry.getValue()) { - if (!effect.canTransform(this, ability, game, true)) { - return false; - } - } - } - } - return transformable; - } - @Override public void setAttacking(boolean attacking) { this.attacking = attacking; @@ -1750,5 +1767,4 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { detachAllAttachments(game); return successfullyMoved; } - } diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index 6738fd8f1a3..cec91473746 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -907,11 +907,6 @@ public class Spell extends StackObjectImpl implements Card { throw new UnsupportedOperationException("Unsupported operation"); } - @Override - public void setTransformable(boolean value) { - throw new UnsupportedOperationException("Unsupported operation"); - } - @Override public int getZoneChangeCounter(Game game) { // spell's zcc can't be changed after put to stack diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index e9493bcb317..bfddba81ce0 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -576,6 +576,16 @@ public class StackAbility extends StackObjectImpl implements Ability { return ability.getSourcePermanentOrLKI(game); } + @Override + public void setSourcePermanentTransformCount(Game game) { + ability.setSourcePermanentTransformCount(game); + } + + @Override + public boolean checkTransformCount(Permanent permanent, Game game) { + return ability.checkTransformCount(permanent, game); + } + @Override public int getZoneChangeCounter(Game game) { return game.getState().getZoneChangeCounter(getSourceId()); diff --git a/Mage/src/main/java/mage/game/turn/Turn.java b/Mage/src/main/java/mage/game/turn/Turn.java index 80410f1dba2..577eb988245 100644 --- a/Mage/src/main/java/mage/game/turn/Turn.java +++ b/Mage/src/main/java/mage/game/turn/Turn.java @@ -1,10 +1,5 @@ package mage.game.turn; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.constants.PhaseStep; import mage.constants.TurnPhase; @@ -17,6 +12,12 @@ import mage.game.stack.StackObject; import mage.players.Player; import mage.util.ThreadLocalStringBuilder; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.UUID; + /** * @author BetaSteward_at_googlemail.com */ @@ -95,7 +96,7 @@ public class Turn implements Serializable { * @param activePlayer * @return true if turn is skipped */ - public boolean play(Game game, Player activePlayer) { + public boolean play(Game game, Player activePlayer) { // uncomment this to trace triggered abilities and/or continous effects // TraceUtil.traceTriggeredAbilities(game); // game.getState().getContinuousEffects().traceContinuousEffects(game); @@ -121,24 +122,25 @@ public class Turn implements Serializable { if (game.isPaused() || game.checkIfGameIsOver()) { return false; } - if (!isEndTurnRequested() || phase.getType() == TurnPhase.END) { - currentPhase = phase; - game.fireEvent(new PhaseChangedEvent(activePlayer.getId(), null)); - if (!game.getState().getTurnMods().skipPhase(activePlayer.getId(), currentPhase.getType())) { - if (phase.play(game, activePlayer.getId())) { - if (game.executingRollback()) { - return false; - } - //20091005 - 500.4/703.4n - game.emptyManaPools(null); - game.saveState(false); - - //20091005 - 500.8 - while (playExtraPhases(game, phase.getType())) { - } - } - } + if (isEndTurnRequested() && phase.getType() != TurnPhase.END) { + continue; } + currentPhase = phase; + game.fireEvent(new PhaseChangedEvent(activePlayer.getId(), null)); + if (game.getState().getTurnMods().skipPhase( + activePlayer.getId(), currentPhase.getType() + ) || !phase.play(game, activePlayer.getId())) { + continue; + } + if (game.executingRollback()) { + return false; + } + //20091005 - 500.4/703.4n + game.emptyManaPools(null); + game.saveState(false); + + //20091005 - 500.8 + while (playExtraPhases(game, phase.getType())) ; } return false; } diff --git a/Mage/src/main/java/mage/game/turn/UntapStep.java b/Mage/src/main/java/mage/game/turn/UntapStep.java index d9c0c28f38d..658fba2190b 100644 --- a/Mage/src/main/java/mage/game/turn/UntapStep.java +++ b/Mage/src/main/java/mage/game/turn/UntapStep.java @@ -2,14 +2,15 @@ package mage.game.turn; -import java.util.UUID; import mage.constants.PhaseStep; import mage.game.Game; import mage.game.events.GameEvent.EventType; import mage.players.Player; +import mage.watchers.common.CastSpellLastTurnWatcher; + +import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ public class UntapStep extends Step { @@ -28,6 +29,7 @@ public class UntapStep extends Step { @Override public void beginStep(Game game, UUID activePlayerId) { super.beginStep(game, activePlayerId); + handleDayNight(game); Player activePlayer = game.getPlayer(activePlayerId); //20091005 - 502.1/703.4a activePlayer.phasing(game); @@ -41,4 +43,18 @@ public class UntapStep extends Step { return new UntapStep(this); } + private void handleDayNight(Game game) { + if (!game.hasDayNight() || game.getTurnNum() <= 1) { + return; + } + int previousSpells = game + .getState() + .getWatcher(CastSpellLastTurnWatcher.class) + .getActivePlayerPrevTurnCount(); + if (game.checkDayNight(true) && previousSpells == 0) { + game.setDaytime(false); + } else if (game.checkDayNight(false) && previousSpells >= 2) { + game.setDaytime(true); + } + } } diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 4b626d74dbd..1d4cbe15605 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -2063,11 +2063,11 @@ public abstract class PlayerImpl implements Player, Serializable { game.informPlayers(this.getLogName() + " loses " + event.getAmount() + " life" + (atCombat ? " at combat" : "") + CardUtil.getSourceLogName(game, " from ", needId, "", "")); } - if (amount > 0) { + if (event.getAmount() > 0) { game.fireEvent(new GameEvent(GameEvent.EventType.LOST_LIFE, - playerId, source, playerId, amount, atCombat)); + playerId, source, playerId, event.getAmount(), atCombat)); } - return amount; + return event.getAmount(); } return 0; } diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 402ecd44191..02c273d532e 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -1408,5 +1408,4 @@ public final class CardUtil { effect.apply(game, source); return true; } - } diff --git a/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java index c2fe4644a87..5a6ec9fbecb 100644 --- a/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/CastSpellLastTurnWatcher.java @@ -16,6 +16,8 @@ public class CastSpellLastTurnWatcher extends Watcher { private final Map amountOfSpellsCastOnPrevTurn = new HashMap<>(); private final Map amountOfSpellsCastOnCurrentTurn = new HashMap<>(); private final List spellsCastThisTurnInOrder = new ArrayList<>(); + private int activePlayerPrevTurnCount = 0; + private int activePlayerThisTurnCount = 0; public CastSpellLastTurnWatcher() { super(WatcherScope.GAME); @@ -29,7 +31,9 @@ public class CastSpellLastTurnWatcher extends Watcher { if (playerId != null) { amountOfSpellsCastOnCurrentTurn.putIfAbsent(playerId, 0); amountOfSpellsCastOnCurrentTurn.compute(playerId, (k, a) -> a + 1); - + } + if (game.isActivePlayer(playerId)) { + activePlayerThisTurnCount++; } } } @@ -41,6 +45,8 @@ public class CastSpellLastTurnWatcher extends Watcher { amountOfSpellsCastOnPrevTurn.putAll(amountOfSpellsCastOnCurrentTurn); amountOfSpellsCastOnCurrentTurn.clear(); spellsCastThisTurnInOrder.clear(); + activePlayerPrevTurnCount = activePlayerThisTurnCount; + activePlayerThisTurnCount = 0; } public Map getAmountOfSpellsCastOnPrevTurn() { @@ -69,4 +75,12 @@ public class CastSpellLastTurnWatcher extends Watcher { } return 0; } + + public int getActivePlayerPrevTurnCount() { + return activePlayerPrevTurnCount; + } + + public int getActivePlayerThisTurnCount() { + return activePlayerThisTurnCount; + } }