diff --git a/Mage.Sets/src/mage/cards/h/HavengulLaboratory.java b/Mage.Sets/src/mage/cards/h/HavengulLaboratory.java index 766da704cd2..de73f6a1d11 100644 --- a/Mage.Sets/src/mage/cards/h/HavengulLaboratory.java +++ b/Mage.Sets/src/mage/cards/h/HavengulLaboratory.java @@ -1,53 +1,80 @@ package mage.cards.h; +import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.TransformIntoSourceTriggeredAbility; import mage.abilities.condition.Condition; +import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.keyword.InvestigateEffect; -import mage.abilities.keyword.TransformAbility; +import mage.abilities.mana.BlackManaAbility; import mage.abilities.mana.ColorlessManaAbility; -import mage.cards.CardImpl; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.cards.Card; import mage.cards.CardSetInfo; +import mage.cards.TransformingDoubleFacedCard; import mage.constants.*; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; import mage.util.CardUtil; import mage.watchers.Watcher; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; /** * @author TheElk801 */ -public final class HavengulLaboratory extends CardImpl { +public final class HavengulLaboratory extends TransformingDoubleFacedCard { public HavengulLaboratory(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - this.supertype.add(SuperType.LEGENDARY); + super( + ownerId, setInfo, + new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.LAND}, new SubType[]{}, "", + "Havengul Mystery", + new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.LAND}, new SubType[]{}, "" + ); this.secondSideCardClazz = mage.cards.h.HavengulMystery.class; // {T}: Add {C}. - this.addAbility(new ColorlessManaAbility()); + this.getLeftHalfCard().addAbility(new ColorlessManaAbility()); // {4}, {T}: Investigate. Ability ability = new SimpleActivatedAbility(new InvestigateEffect(), new GenericManaCost(4)); ability.addCost(new TapSourceCost()); - this.addAbility(ability); + this.getLeftHalfCard().addAbility(ability); // At the beginning of your end step, if you sacrificed three or more Clues this turn, transform Havengul Laboratory. - this.addAbility(new TransformAbility()); - this.addAbility(new BeginningOfEndStepTriggeredAbility( + this.getLeftHalfCard().addAbility(new BeginningOfEndStepTriggeredAbility( TargetController.YOU, new TransformSourceEffect(), false, HavengulLaboratoryCondition.instance ), new HavengulLaboratoryWatcher()); + + // When this land transforms into Havengul Mystery, return target creature card from your graveyard to the battlefield. + ability = new TransformIntoSourceTriggeredAbility(new HavengulMysteryEffect()) + .setTriggerPhrase("When this land transforms into {this}, "); + ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); + this.getRightHalfCard().addAbility(ability); + + // When the creature put onto the battlefield with Havengul Mystery leaves the battlefield, transform Havengul Mystery. + this.getRightHalfCard().addAbility(new HavengulMysteryLeavesAbility()); + + // {T}, Pay 1 life: Add {B}. + ability = new BlackManaAbility(); + ability.addCost(new PayLifeCost(1)); + this.getRightHalfCard().addAbility(ability); + + this.finalizeDFC(); } private HavengulLaboratory(final HavengulLaboratory card) { @@ -58,6 +85,10 @@ public final class HavengulLaboratory extends CardImpl { public HavengulLaboratory copy() { return new HavengulLaboratory(this); } + + static String makeKey(Ability source, Game game) { + return "HavengulMystery_" + source.getSourceId() + '_' + CardUtil.getActualSourceObjectZoneChangeCounter(game, source); + } } enum HavengulLaboratoryCondition implements Condition { @@ -108,3 +139,85 @@ class HavengulLaboratoryWatcher extends Watcher { .getOrDefault(playerId, 0) >= 3; } } + +class HavengulMysteryEffect extends OneShotEffect { + + HavengulMysteryEffect() { + super(Outcome.Benefit); + staticText = "return target creature card from your graveyard to the battlefield"; + } + + private HavengulMysteryEffect(final HavengulMysteryEffect effect) { + super(effect); + } + + @Override + public HavengulMysteryEffect copy() { + return new HavengulMysteryEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Card card = game.getCard(getTargetPointer().getFirst(game, source)); + if (player == null || card == null) { + return false; + } + player.moveCards(card, Zone.BATTLEFIELD, source, game); + Permanent permanent = CardUtil.getPermanentFromCardPutToBattlefield(card, game); + if (permanent == null) { + return false; + } + String key = HavengulLaboratory.makeKey(source, game); + Set morSet; + if (game.getState().getValue(key) != null) { + morSet = (Set) game.getState().getValue(key); + } else { + morSet = new HashSet<>(); + game.getState().setValue(key, morSet); + } + morSet.add(new MageObjectReference(permanent, game)); + return true; + } +} + +class HavengulMysteryLeavesAbility extends TriggeredAbilityImpl { + + HavengulMysteryLeavesAbility() { + super(Zone.BATTLEFIELD, new TransformSourceEffect()); + setLeavesTheBattlefieldTrigger(true); + } + + private HavengulMysteryLeavesAbility(final HavengulMysteryLeavesAbility ability) { + super(ability); + } + + @Override + public HavengulMysteryLeavesAbility copy() { + return new HavengulMysteryLeavesAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getFromZone() != Zone.BATTLEFIELD) { + return false; + } + + String key = HavengulLaboratory.makeKey(this, game); + Set morSet = (Set) game.getState().getValue(key); + return morSet != null + && !morSet.isEmpty() + && morSet.stream().anyMatch(mor -> mor.refersTo(zEvent.getTarget(), game)); + } + + @Override + public String getRule() { + return "When the creature put onto the battlefield with {this} leaves the battlefield, transform {this}."; + } +} diff --git a/Mage.Sets/src/mage/cards/h/HavengulMystery.java b/Mage.Sets/src/mage/cards/h/HavengulMystery.java index 24cca60c3b1..353fa6831ab 100644 --- a/Mage.Sets/src/mage/cards/h/HavengulMystery.java +++ b/Mage.Sets/src/mage/cards/h/HavengulMystery.java @@ -1,31 +1,10 @@ package mage.cards.h; -import mage.MageObjectReference; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.common.TransformIntoSourceTriggeredAbility; -import mage.abilities.costs.common.PayLifeCost; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.TransformSourceEffect; -import mage.abilities.mana.BlackManaAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.TransformingDoubleFacedCard; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.SuperType; -import mage.constants.Zone; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetCardInYourGraveyard; -import mage.util.CardUtil; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; /** @@ -34,23 +13,9 @@ import java.util.UUID; public final class HavengulMystery extends CardImpl { public HavengulMystery(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - this.supertype.add(SuperType.LEGENDARY); + super(ownerId, setInfo, new CardType[]{}, ""); this.nightCard = true; - - // When this land transforms into Havengul Mystery, return target creature card from your graveyard to the battlefield. - Ability ability = new TransformIntoSourceTriggeredAbility(new HavengulMysteryEffect()) - .setTriggerPhrase("When this land transforms into {this}, "); - ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); - this.addAbility(ability); - - // When the creature put onto the battlefield with Havengul Mystery leaves the battlefield, transform Havengul Mystery. - this.addAbility(new HavengulMysteryLeavesAbility()); - - // {T}, Pay 1 life: Add {B}. - Ability ability2 = new BlackManaAbility(); - ability2.addCost(new PayLifeCost(1)); - this.addAbility(ability2); + TransformingDoubleFacedCard.copyToBackFace(new HavengulLaboratory(ownerId, setInfo), this); } private HavengulMystery(final HavengulMystery card) { @@ -61,90 +26,4 @@ public final class HavengulMystery extends CardImpl { public HavengulMystery copy() { return new HavengulMystery(this); } - - static String makeKey(Ability source, Game game) { - return "HavengulMystery_" + source.getSourceId() + '_' + CardUtil.getActualSourceObjectZoneChangeCounter(game, source); - } -} - -class HavengulMysteryEffect extends OneShotEffect { - - HavengulMysteryEffect() { - super(Outcome.Benefit); - staticText = "return target creature card from your graveyard to the battlefield"; - } - - private HavengulMysteryEffect(final HavengulMysteryEffect effect) { - super(effect); - } - - @Override - public HavengulMysteryEffect copy() { - return new HavengulMysteryEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Card card = game.getCard(getTargetPointer().getFirst(game, source)); - if (player == null || card == null) { - return false; - } - player.moveCards(card, Zone.BATTLEFIELD, source, game); - Permanent permanent = CardUtil.getPermanentFromCardPutToBattlefield(card, game); - if (permanent == null) { - return false; - } - String key = HavengulMystery.makeKey(source, game); - Set morSet; - if (game.getState().getValue(key) != null) { - morSet = (Set) game.getState().getValue(key); - } else { - morSet = new HashSet<>(); - game.getState().setValue(key, morSet); - } - morSet.add(new MageObjectReference(permanent, game)); - return true; - } -} - -class HavengulMysteryLeavesAbility extends TriggeredAbilityImpl { - - HavengulMysteryLeavesAbility() { - super(Zone.BATTLEFIELD, new TransformSourceEffect()); - setLeavesTheBattlefieldTrigger(true); - } - - private HavengulMysteryLeavesAbility(final HavengulMysteryLeavesAbility ability) { - super(ability); - } - - @Override - public HavengulMysteryLeavesAbility copy() { - return new HavengulMysteryLeavesAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ZONE_CHANGE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() != Zone.BATTLEFIELD) { - return false; - } - - String key = HavengulMystery.makeKey(this, game); - Set morSet = (Set) game.getState().getValue(key); - return morSet != null - && !morSet.isEmpty() - && morSet.stream().anyMatch(mor -> mor.refersTo(zEvent.getTarget(), game)); - } - - @Override - public String getRule() { - return "When the creature put onto the battlefield with {this} leaves the battlefield, transform {this}."; - } } diff --git a/Mage.Sets/src/mage/cards/i/InvasionOfKylem.java b/Mage.Sets/src/mage/cards/i/InvasionOfKylem.java index 9fe9458f3a3..3b41b0ed289 100644 --- a/Mage.Sets/src/mage/cards/i/InvasionOfKylem.java +++ b/Mage.Sets/src/mage/cards/i/InvasionOfKylem.java @@ -3,14 +3,16 @@ package mage.cards.i; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SiegeAbility; +import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.VigilanceAbility; -import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.TransformingDoubleFacedCard; import mage.constants.CardType; import mage.constants.SubType; +import mage.game.permanent.token.ValorsReachTagTeamToken; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -18,17 +20,21 @@ import java.util.UUID; /** * @author TheElk801 */ -public final class InvasionOfKylem extends CardImpl { +public final class InvasionOfKylem extends TransformingDoubleFacedCard { public InvasionOfKylem(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.BATTLE}, "{2}{R}{W}"); + super( + ownerId, setInfo, + new CardType[]{CardType.BATTLE}, new SubType[]{SubType.SIEGE}, "{2}{R}{W}", + "Valor's Reach Tag Team", + new CardType[]{CardType.SORCERY}, new SubType[]{}, "RW" + ); + this.getLeftHalfCard().setStartingDefense(5); - this.subtype.add(SubType.SIEGE); - this.setStartingDefense(5); this.secondSideCardClazz = mage.cards.v.ValorsReachTagTeam.class; // (As a Siege enters, choose an opponent to protect it. You and others can attack it. When it's defeated, exile it, then cast it transformed.) - this.addAbility(new SiegeAbility()); + this.getLeftHalfCard().addAbility(new SiegeAbility()); // When Invasion of Kylem enters the battlefield, up to two target creatures each get +2/+0 and gain vigilance and haste until end of turn. Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(2, 0) @@ -38,7 +44,13 @@ public final class InvasionOfKylem extends CardImpl { ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance()) .setText("and haste until end of turn")); ability.addTarget(new TargetCreaturePermanent(0, 2)); - this.addAbility(ability); + this.getLeftHalfCard().addAbility(ability); + + // Valor's Reach Tag Team + // Create two 3/2 red and white Warrior creature tokens with "Whenever this creature and at least one other creature token attack, put a +1/+1 counter on this creature." + this.getRightHalfCard().getSpellAbility().addEffect(new CreateTokenEffect(new ValorsReachTagTeamToken(), 2)); + + this.finalizeDFC(); } private InvasionOfKylem(final InvasionOfKylem card) { diff --git a/Mage.Sets/src/mage/cards/o/OrmendahlProfanePrince.java b/Mage.Sets/src/mage/cards/o/OrmendahlProfanePrince.java index 1df4cf81eeb..eabe68b210f 100644 --- a/Mage.Sets/src/mage/cards/o/OrmendahlProfanePrince.java +++ b/Mage.Sets/src/mage/cards/o/OrmendahlProfanePrince.java @@ -1,43 +1,22 @@ - package mage.cards.o; -import java.util.UUID; -import mage.MageInt; -import mage.abilities.keyword.FlyingAbility; -import mage.abilities.keyword.HasteAbility; -import mage.abilities.keyword.IndestructibleAbility; -import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.TransformingDoubleFacedCard; +import mage.cards.w.WestvaleAbbey; import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.SuperType; + +import java.util.UUID; /** - * * @author fireshoes */ public final class OrmendahlProfanePrince extends CardImpl { public OrmendahlProfanePrince(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},""); - this.supertype.add(SuperType.LEGENDARY); - this.subtype.add(SubType.DEMON); - this.power = new MageInt(9); - this.toughness = new MageInt(7); - this.color.setBlack(true); - - // this card is the second face of double-faced card + super(ownerId, setInfo, new CardType[]{}, ""); this.nightCard = true; - - // Flying - this.addAbility(FlyingAbility.getInstance()); - // Lifelink - this.addAbility(LifelinkAbility.getInstance()); - // Indestructible - this.addAbility(IndestructibleAbility.getInstance()); - // Haste - this.addAbility(HasteAbility.getInstance()); + TransformingDoubleFacedCard.copyToBackFace(new WestvaleAbbey(ownerId, setInfo), this); } private OrmendahlProfanePrince(final OrmendahlProfanePrince card) { diff --git a/Mage.Sets/src/mage/cards/v/ValorsReachTagTeam.java b/Mage.Sets/src/mage/cards/v/ValorsReachTagTeam.java index b01d199a7c8..f57bf9fa092 100644 --- a/Mage.Sets/src/mage/cards/v/ValorsReachTagTeam.java +++ b/Mage.Sets/src/mage/cards/v/ValorsReachTagTeam.java @@ -1,10 +1,10 @@ package mage.cards.v; -import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.TransformingDoubleFacedCard; +import mage.cards.i.InvasionOfKylem; import mage.constants.CardType; -import mage.game.permanent.token.ValorsReachTagTeamToken; import java.util.UUID; @@ -14,14 +14,9 @@ import java.util.UUID; public final class ValorsReachTagTeam extends CardImpl { public ValorsReachTagTeam(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, ""); - - this.color.setWhite(true); - this.color.setRed(true); + super(ownerId, setInfo, new CardType[]{}, ""); this.nightCard = true; - - // Create two 3/2 red and white Warrior creature tokens with "Whenever this creature and at least one other creature token attack, put a +1/+1 counter on this creature." - this.getSpellAbility().addEffect(new CreateTokenEffect(new ValorsReachTagTeamToken(), 2)); + TransformingDoubleFacedCard.copyToBackFace(new InvasionOfKylem(ownerId, setInfo), this); } private ValorsReachTagTeam(final ValorsReachTagTeam card) { diff --git a/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java b/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java index f618bb62b61..c5bfb06c439 100644 --- a/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java +++ b/Mage.Sets/src/mage/cards/w/WestvaleAbbey.java @@ -1,8 +1,5 @@ - package mage.cards.w; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.PayLifeCost; @@ -12,43 +9,67 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.UntapSourceEffect; -import mage.abilities.keyword.TransformAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.IndestructibleAbility; +import mage.abilities.keyword.LifelinkAbility; import mage.abilities.mana.ColorlessManaAbility; -import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.TransformingDoubleFacedCard; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.permanent.token.HumanClericToken; -import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** * @author fireshoes */ -public final class WestvaleAbbey extends CardImpl { +public final class WestvaleAbbey extends TransformingDoubleFacedCard { public WestvaleAbbey(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + super( + ownerId, setInfo, + new SuperType[]{}, new CardType[]{CardType.LAND}, new SubType[]{}, "", + "Ormendahl, Profane Prince", + new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.DEMON}, "B" + ); + this.getRightHalfCard().setPT(9, 7); this.secondSideCardClazz = mage.cards.o.OrmendahlProfanePrince.class; // {T}: Add {C}. - this.addAbility(new ColorlessManaAbility()); + this.getLeftHalfCard().addAbility(new ColorlessManaAbility()); // {5}, {T}, Pay 1 life: Create a 1/1 white and black Human Cleric creature token. Ability ability = new SimpleActivatedAbility(new CreateTokenEffect(new HumanClericToken()), new GenericManaCost(5)); ability.addCost(new TapSourceCost()); ability.addCost(new PayLifeCost(1)); - this.addAbility(ability); + this.getLeftHalfCard().addAbility(ability); // {5}, {T}, Sacrifice five creatures: Transform Westvale Abbey and untap it. - this.addAbility(new TransformAbility()); ability = new SimpleActivatedAbility(new TransformSourceEffect(), new GenericManaCost(5)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeTargetCost(5, StaticFilters.FILTER_PERMANENT_CREATURES)); ability.addEffect(new UntapSourceEffect().setText("untap it").concatBy(", then")); - this.addAbility(ability); + this.getLeftHalfCard().addAbility(ability); + + // Ormendahl, Profane Prince + // Flying + this.getRightHalfCard().addAbility(FlyingAbility.getInstance()); + + // Lifelink + this.getRightHalfCard().addAbility(LifelinkAbility.getInstance()); + + // Indestructible + this.getRightHalfCard().addAbility(IndestructibleAbility.getInstance()); + + // Haste + this.getRightHalfCard().addAbility(HasteAbility.getInstance()); + + this.finalizeDFC(); } private WestvaleAbbey(final WestvaleAbbey card) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/battle/BattleBaseTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/battle/BattleBaseTest.java index 9b078cee3ed..b7de713b2b2 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/battle/BattleBaseTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/battle/BattleBaseTest.java @@ -19,6 +19,7 @@ public class BattleBaseTest extends CardTestPlayerBaseWithAIHelps { protected static final String impact = "Explosive Impact"; protected static final String stifle = "Stifle"; protected static final String fayden = "Dack Fayden"; + protected static final String kylem = "Invasion of Kylem"; protected void assertBattle(Player controller, Player protector, String name) { assertPermanentCount(controller, name, 1); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/battle/BattleDuelTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/battle/BattleDuelTest.java index 0655ccc4a0a..2f50e4e6993 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/battle/BattleDuelTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/battle/BattleDuelTest.java @@ -4,6 +4,7 @@ import mage.constants.PhaseStep; import mage.constants.Zone; import mage.counters.CounterType; import org.junit.Test; +import org.mage.test.player.TestPlayer; /** * @author TheElk801, JayDi85 @@ -264,4 +265,24 @@ public class BattleDuelTest extends BattleBaseTest { assertCounterCount(belenon, CounterType.DEFENSE, 5); assertCounterCount(fayden, CounterType.LOYALTY, 3 - 2); } + + @Test + public void testInvasionOfKylem() { + addCard(Zone.BATTLEFIELD, playerA, "Plateau", 4 + 6); + addCard(Zone.HAND, playerA, kylem); + addCard(Zone.HAND, playerA, impact); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, kylem); + addTarget(playerA, TestPlayer.TARGET_SKIP); // don't choose any targets for etb trigger + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, impact, kylem); + setChoice(playerA, true); // yes to cast it transformed + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, kylem, 0); + assertPermanentCount(playerA, "Warrior Token", 2); + } } diff --git a/Mage/src/main/java/mage/cards/Card.java b/Mage/src/main/java/mage/cards/Card.java index 9f842f74ae2..c645b504fea 100644 --- a/Mage/src/main/java/mage/cards/Card.java +++ b/Mage/src/main/java/mage/cards/Card.java @@ -18,6 +18,7 @@ import mage.game.GameState; import mage.game.Ownerable; import mage.game.permanent.Permanent; import mage.util.ManaUtil; +import mage.watchers.Watcher; import mage.watchers.common.CommanderPlaysCountWatcher; import java.util.List; @@ -155,6 +156,11 @@ public interface Card extends MageObject, Ownerable { Counters getCounters(GameState state); + default void addAbility(Ability ability, Watcher watcher) { + addAbility(ability); + ability.addWatcher(watcher); + } + void addAbility(Ability ability); void looseAllAbilities(Game game); diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index b65430bd221..78b3e1580ca 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -26,7 +26,6 @@ import mage.game.stack.StackObject; import mage.util.CardUtil; import mage.util.GameLog; import mage.util.ManaUtil; -import mage.watchers.Watcher; import org.apache.log4j.Logger; import java.lang.reflect.Constructor; @@ -357,11 +356,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card { } } - protected void addAbility(Ability ability, Watcher watcher) { - addAbility(ability); - ability.addWatcher(watcher); - } - public void replaceSpellAbility(SpellAbility newAbility) { SpellAbility oldAbility = this.getSpellAbility(); while (oldAbility != null) { diff --git a/Mage/src/main/java/mage/cards/TransformingDoubleFacedCard.java b/Mage/src/main/java/mage/cards/TransformingDoubleFacedCard.java index 2767d41214c..ed8f29831bd 100644 --- a/Mage/src/main/java/mage/cards/TransformingDoubleFacedCard.java +++ b/Mage/src/main/java/mage/cards/TransformingDoubleFacedCard.java @@ -41,8 +41,8 @@ public abstract class TransformingDoubleFacedCard extends CardImpl { SuperType[] superTypesRight, CardType[] typesRight, SubType[] subTypesRight, String colorRight ) { super(ownerId, setInfo, typesLeft, costsLeft); - this.leftHalfCard = new TransformingDoubleFacedCardHalfImpl(ownerId, setInfo, costsLeft); - this.rightHalfCard = new TransformingDoubleFacedCardHalfImpl(ownerId, setInfo, ""); + this.leftHalfCard = new TransformingDoubleFacedCardHalfImpl(ownerId, setInfo, typesLeft, costsLeft); + this.rightHalfCard = new TransformingDoubleFacedCardHalfImpl(ownerId, setInfo, typesRight, ""); for (SuperType superType : superTypesLeft) { this.getLeftHalfCard().getSuperType().add(superType); } @@ -50,7 +50,6 @@ public abstract class TransformingDoubleFacedCard extends CardImpl { for (SuperType superType : superTypesRight) { this.getRightHalfCard().getSuperType().add(superType); } - this.getRightHalfCard().addCardType(typesRight); this.getRightHalfCard().setName(secondSideName); this.getRightHalfCard().addSubType(subTypesRight); this.getRightHalfCard().getColor().addColor(new ObjectColor(colorRight)); @@ -86,11 +85,14 @@ public abstract class TransformingDoubleFacedCard extends CardImpl { if (!this.getAbilities().containsClass(TransformAbility.class)) { this.addAbility(new TransformAbility()); } - for (Effect effect : this.getLeftHalfCard().getSpellAbility().getEffects()) { - this.getSpellAbility().addEffect(effect); - } - for (Target target : this.getLeftHalfCard().getSpellAbility().getTargets()) { - this.getSpellAbility().addTarget(target); + if (this.getLeftHalfCard().getSpellAbility() != null) { + for (Effect effect : this.getLeftHalfCard().getSpellAbility().getEffects()) { + this.getSpellAbility().addEffect(effect); + } + for (Target target : this.getLeftHalfCard().getSpellAbility().getTargets()) { + this.getSpellAbility().addTarget(target); + } + this.getSpellAbility().setTargetAdjuster(this.getLeftHalfCard().getSpellAbility().getTargetAdjuster()); } this.power = this.getLeftHalfCard().getPower().copy(); this.toughness = this.getLeftHalfCard().getToughness().copy(); @@ -109,11 +111,14 @@ public abstract class TransformingDoubleFacedCard extends CardImpl { card.addAbility(ability); } } - for (Effect effect : tdfc.getRightHalfCard().getSpellAbility().getEffects()) { - card.getSpellAbility().addEffect(effect); - } - for (Target target : tdfc.getRightHalfCard().getSpellAbility().getTargets()) { - card.getSpellAbility().addTarget(target); + if (tdfc.getRightHalfCard().getSpellAbility() != null) { + for (Effect effect : tdfc.getRightHalfCard().getSpellAbility().getEffects()) { + card.getSpellAbility().addEffect(effect); + } + for (Target target : tdfc.getRightHalfCard().getSpellAbility().getTargets()) { + card.getSpellAbility().addTarget(target); + } + card.getSpellAbility().setTargetAdjuster(tdfc.getRightHalfCard().getSpellAbility().getTargetAdjuster()); } card.setPT(tdfc.getRightHalfCard().getPower().copy(), tdfc.getRightHalfCard().getToughness().copy()); card.setStartingLoyalty(tdfc.getRightHalfCard().getStartingLoyalty()); diff --git a/Mage/src/main/java/mage/cards/TransformingDoubleFacedCardHalfImpl.java b/Mage/src/main/java/mage/cards/TransformingDoubleFacedCardHalfImpl.java index a50afecb033..0f44ad512be 100644 --- a/Mage/src/main/java/mage/cards/TransformingDoubleFacedCardHalfImpl.java +++ b/Mage/src/main/java/mage/cards/TransformingDoubleFacedCardHalfImpl.java @@ -9,8 +9,8 @@ import java.util.UUID; */ public class TransformingDoubleFacedCardHalfImpl extends CardImpl { - TransformingDoubleFacedCardHalfImpl(UUID ownerId, CardSetInfo setInfo, String costs) { - super(ownerId, setInfo, new CardType[]{}, costs); + TransformingDoubleFacedCardHalfImpl(UUID ownerId, CardSetInfo setInfo, CardType[] cardTypes, String costs) { + super(ownerId, setInfo, cardTypes, costs); } private TransformingDoubleFacedCardHalfImpl(final TransformingDoubleFacedCardHalfImpl card) {