From ae932f9dd7ef886c2ee365dc3f40e36ecd6640fe Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 6 Apr 2016 00:37:29 +0200 Subject: [PATCH] Fixed some transformed triggered abilities after the recent change of transform handling. --- .../sets/darkascension/AfflictedDeserter.java | 13 +- .../darkascension/HuntmasterOfTheFells.java | 162 +----------------- .../sets/darkascension/RavagerOfTheFells.java | 157 ++++++++++++++++- .../sets/darkascension/WerewolfRansacker.java | 11 +- .../AvacynianMissionaries.java | 95 ---------- .../shadowsoverinnistrad/AwokenHorror.java | 66 ++++++- .../LunarchInquisitors.java | 96 ++++++++++- .../shadowsoverinnistrad/ThingInTheIce.java | 66 ------- .../cards/single/WerewolfRansackerTest.java | 6 +- .../cards/single/soi/ThingInTheIceTest.java | 39 +++-- .../main/java/mage/abilities/AbilityImpl.java | 3 + ...tlefieldUnderOwnerControlTargetEffect.java | 23 ++- 12 files changed, 363 insertions(+), 374 deletions(-) diff --git a/Mage.Sets/src/mage/sets/darkascension/AfflictedDeserter.java b/Mage.Sets/src/mage/sets/darkascension/AfflictedDeserter.java index 25f8113f256..a427b792729 100644 --- a/Mage.Sets/src/mage/sets/darkascension/AfflictedDeserter.java +++ b/Mage.Sets/src/mage/sets/darkascension/AfflictedDeserter.java @@ -28,11 +28,7 @@ package mage.sets.darkascension; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; @@ -40,6 +36,8 @@ import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.constants.TargetController; /** @@ -60,11 +58,6 @@ public class AfflictedDeserter extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); - // Whenever this creature transforms into Werewolf Ransacker, you may destroy target artifact. If that artifact is put into a graveyard this way, Werewolf Ransacker deals 3 damage to that artifact's controller. - Ability ability1 = new WerewolfRansackerAbility(); - ability1.setRuleVisible(false); // rule will be shown only on the other face of the card but triggers only on this side - this.addAbility(ability1); - // At the beginning of each upkeep, if no spells were cast last turn, transform Afflicted Deserter. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); @@ -80,5 +73,3 @@ public class AfflictedDeserter extends CardImpl { return new AfflictedDeserter(this); } } - - diff --git a/Mage.Sets/src/mage/sets/darkascension/HuntmasterOfTheFells.java b/Mage.Sets/src/mage/sets/darkascension/HuntmasterOfTheFells.java index 22098f98e2f..715c63ce32a 100644 --- a/Mage.Sets/src/mage/sets/darkascension/HuntmasterOfTheFells.java +++ b/Mage.Sets/src/mage/sets/darkascension/HuntmasterOfTheFells.java @@ -27,36 +27,24 @@ */ package mage.sets.darkascension; -import mage.constants.*; +import java.util.UUID; import mage.MageInt; import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; -import mage.filter.common.FilterCreaturePermanent; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.game.permanent.token.Token; import mage.game.permanent.token.WolfToken; -import mage.game.stack.StackObject; -import mage.players.Player; -import mage.target.Target; -import mage.target.TargetPermanent; -import mage.target.common.TargetOpponent; - -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; /** * @@ -79,9 +67,6 @@ public class HuntmasterOfTheFells extends CardImpl { // Whenever this creature enters the battlefield or transforms into Huntmaster of the Fells, put a 2/2 green Wolf creature token onto the battlefield and you gain 2 life. this.addAbility(new HuntmasterOfTheFellsAbility()); - // Whenever this creature transforms into Ravager of the Fells, it deals 2 damage to target opponent and 2 damage to up to one target creature that player controls. - this.addAbility(new RavagerOfTheFellsAbility()); - // At the beginning of each upkeep, if no spells were cast last turn, transform Huntmaster of the Fells. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); @@ -113,8 +98,6 @@ class HuntmasterOfTheFellsAbility extends TriggeredAbilityImpl { public HuntmasterOfTheFellsAbility copy() { return new HuntmasterOfTheFellsAbility(this); } - - @Override public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { @@ -126,12 +109,12 @@ class HuntmasterOfTheFellsAbility extends TriggeredAbilityImpl { } return super.isInUseableZone(game, source, event); } - + @Override public boolean checkEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.TRANSFORMED || event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; } - + @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.TRANSFORMED && event.getTargetId().equals(this.getSourceId())) { @@ -150,141 +133,4 @@ class HuntmasterOfTheFellsAbility extends TriggeredAbilityImpl { public String getRule() { return "Whenever this creature enters the battlefield or transforms into {this}, put a 2/2 green Wolf creature token onto the battlefield and you gain 2 life."; } - -} - -class RavagerOfTheFellsAbility extends TriggeredAbilityImpl { - - public RavagerOfTheFellsAbility() { - super(Zone.BATTLEFIELD, new RavagerOfTheFellsEffect(), false); - Target target1 = new TargetOpponent(); - this.addTarget(target1); - this.addTarget(new RavagerOfTheFellsTarget()); - // Rule only shown on the night side - this.setRuleVisible(false); - } - - public RavagerOfTheFellsAbility(final RavagerOfTheFellsAbility ability) { - super(ability); - } - - @Override - public RavagerOfTheFellsAbility copy() { - return new RavagerOfTheFellsAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.TRANSFORMED; - } - - @Override - public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { - Permanent currentSourceObject = (Permanent) getSourceObjectIfItStillExists(game); - if (currentSourceObject != null && currentSourceObject.isNightCard()) { - return true; - } - return super.isInUseableZone(game, source, event); - } - - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getTargetId().equals(sourceId)) { - Permanent permanent = game.getPermanent(sourceId); - if (permanent != null && permanent.isTransformed()) { - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever this creature transforms into Ravager of the Fells, it deals 2 damage to target opponent and 2 damage to up to one target creature that player controls."; - } - -} - -class RavagerOfTheFellsEffect extends OneShotEffect { - - public RavagerOfTheFellsEffect() { - super(Outcome.Damage); - } - - public RavagerOfTheFellsEffect(final RavagerOfTheFellsEffect effect) { - super(effect); - } - - @Override - public RavagerOfTheFellsEffect copy() { - return new RavagerOfTheFellsEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getTargets().get(0).getFirstTarget()); - if (player != null) { - player.damage(2, source.getSourceId(), game, false, true); - } - Permanent creature = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (creature != null) { - creature.damage(2, source.getSourceId(), game, false, true); - } - return true; - } - -} - -class RavagerOfTheFellsTarget extends TargetPermanent { - - public RavagerOfTheFellsTarget() { - super(0, 1, new FilterCreaturePermanent(), false); - } - - public RavagerOfTheFellsTarget(final RavagerOfTheFellsTarget target) { - super(target); - } - - @Override - public boolean canTarget(UUID id, Ability source, Game game) { - UUID firstTarget = source.getFirstTarget(); - Permanent permanent = game.getPermanent(id); - if (firstTarget != null && permanent != null && permanent.getControllerId().equals(firstTarget)) { - return super.canTarget(id, source, game); - } - return false; - } - - @Override - public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { - Set availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); - Set possibleTargets = new HashSet<>(); - MageObject object = game.getObject(sourceId); - - for (StackObject item: game.getState().getStack()) { - if (item.getId().equals(sourceId)) { - object = item; - } - if (item.getSourceId().equals(sourceId)) { - object = item; - } - } - - if (object instanceof StackObject) { - UUID playerId = ((StackObject)object).getStackAbility().getFirstTarget(); - for (UUID targetId : availablePossibleTargets) { - Permanent permanent = game.getPermanent(targetId); - if(permanent != null && permanent.getControllerId().equals(playerId)){ - possibleTargets.add(targetId); - } - } - } - return possibleTargets; - } - - @Override - public RavagerOfTheFellsTarget copy() { - return new RavagerOfTheFellsTarget(this); - } } diff --git a/Mage.Sets/src/mage/sets/darkascension/RavagerOfTheFells.java b/Mage.Sets/src/mage/sets/darkascension/RavagerOfTheFells.java index 4a0cd73206e..84b6c9c713a 100644 --- a/Mage.Sets/src/mage/sets/darkascension/RavagerOfTheFells.java +++ b/Mage.Sets/src/mage/sets/darkascension/RavagerOfTheFells.java @@ -27,24 +27,36 @@ */ package mage.sets.darkascension; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; import mage.abilities.TriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; -import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.TargetController; import mage.constants.Zone; - - +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.common.TargetOpponent; /** * @@ -52,8 +64,6 @@ import mage.constants.Zone; */ public class RavagerOfTheFells extends CardImpl { - private static final String rule = "Whenever this creature transforms into Ravager of the Fells, it deals 2 damage to target opponent and 2 damage to up to one target creature that player controls"; - public RavagerOfTheFells(UUID ownerId) { super(ownerId, 140, "Ravager of the Fells", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, ""); this.expansionSetCode = "DKA"; @@ -71,7 +81,7 @@ public class RavagerOfTheFells extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Whenever this creature transforms into Ravager of the Fells, it deals 2 damage to target opponent and 2 damage to up to one target creature that player controls. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect(rule))); + this.addAbility(new RavagerOfTheFellsAbility()); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Ravager of the Fells. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); @@ -87,3 +97,136 @@ public class RavagerOfTheFells extends CardImpl { return new RavagerOfTheFells(this); } } + +class RavagerOfTheFellsAbility extends TriggeredAbilityImpl { + + public RavagerOfTheFellsAbility() { + super(Zone.BATTLEFIELD, new RavagerOfTheFellsEffect(), false); + Target target1 = new TargetOpponent(); + this.addTarget(target1); + this.addTarget(new RavagerOfTheFellsTarget()); + } + + public RavagerOfTheFellsAbility(final RavagerOfTheFellsAbility ability) { + super(ability); + } + + @Override + public RavagerOfTheFellsAbility copy() { + return new RavagerOfTheFellsAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRANSFORMED; + } + + @Override + public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { + Permanent currentSourceObject = (Permanent) getSourceObjectIfItStillExists(game); + if (currentSourceObject != null && currentSourceObject.isNightCard()) { + return true; + } + return super.isInUseableZone(game, source, event); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getTargetId().equals(sourceId)) { + Permanent permanent = game.getPermanent(sourceId); + if (permanent != null && permanent.isTransformed()) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever this creature transforms into Ravager of the Fells, it deals 2 damage to target opponent and 2 damage to up to one target creature that player controls."; + } + +} + +class RavagerOfTheFellsEffect extends OneShotEffect { + + public RavagerOfTheFellsEffect() { + super(Outcome.Damage); + } + + public RavagerOfTheFellsEffect(final RavagerOfTheFellsEffect effect) { + super(effect); + } + + @Override + public RavagerOfTheFellsEffect copy() { + return new RavagerOfTheFellsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getTargets().get(0).getFirstTarget()); + if (player != null) { + player.damage(2, source.getSourceId(), game, false, true); + } + Permanent creature = game.getPermanent(source.getTargets().get(1).getFirstTarget()); + if (creature != null) { + creature.damage(2, source.getSourceId(), game, false, true); + } + return true; + } + +} + +class RavagerOfTheFellsTarget extends TargetPermanent { + + public RavagerOfTheFellsTarget() { + super(0, 1, new FilterCreaturePermanent(), false); + } + + public RavagerOfTheFellsTarget(final RavagerOfTheFellsTarget target) { + super(target); + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + UUID firstTarget = source.getFirstTarget(); + Permanent permanent = game.getPermanent(id); + if (firstTarget != null && permanent != null && permanent.getControllerId().equals(firstTarget)) { + return super.canTarget(id, source, game); + } + return false; + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + Set availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); + Set possibleTargets = new HashSet<>(); + MageObject object = game.getObject(sourceId); + + for (StackObject item : game.getState().getStack()) { + if (item.getId().equals(sourceId)) { + object = item; + } + if (item.getSourceId().equals(sourceId)) { + object = item; + } + } + + if (object instanceof StackObject) { + UUID playerId = ((StackObject) object).getStackAbility().getFirstTarget(); + for (UUID targetId : availablePossibleTargets) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null && permanent.getControllerId().equals(playerId)) { + possibleTargets.add(targetId); + } + } + } + return possibleTargets; + } + + @Override + public RavagerOfTheFellsTarget copy() { + return new RavagerOfTheFellsTarget(this); + } +} diff --git a/Mage.Sets/src/mage/sets/darkascension/WerewolfRansacker.java b/Mage.Sets/src/mage/sets/darkascension/WerewolfRansacker.java index bf1a2905c5d..d360a4b34d0 100644 --- a/Mage.Sets/src/mage/sets/darkascension/WerewolfRansacker.java +++ b/Mage.Sets/src/mage/sets/darkascension/WerewolfRansacker.java @@ -33,11 +33,9 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -75,7 +73,7 @@ public class WerewolfRansacker extends CardImpl { this.toughness = new MageInt(4); // Whenever this creature transforms into Werewolf Ransacker, you may destroy target artifact. If that artifact is put into a graveyard this way, Werewolf Ransacker deals 3 damage to that artifact's controller. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect(WerewolfRansackerAbility.RULE_TEXT))); + this.addAbility(new WerewolfRansackerAbility()); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Werewolf Ransacker. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); @@ -93,9 +91,9 @@ public class WerewolfRansacker extends CardImpl { } class WerewolfRansackerAbility extends TriggeredAbilityImpl { - + public static final String RULE_TEXT = "Whenever this creature transforms into Werewolf Ransacker, you may destroy target artifact. If that artifact is put into a graveyard this way, Werewolf Ransacker deals 3 damage to that artifact's controller"; - + public WerewolfRansackerAbility() { super(Zone.BATTLEFIELD, new WerewolfRansackerEffect(), true); Target target = new TargetPermanent(new FilterArtifactPermanent()); @@ -159,8 +157,9 @@ class WerewolfRansackerEffect extends OneShotEffect { affectedTargets++; if (game.getState().getZone(permanent.getId()) == Zone.GRAVEYARD) { Player player = game.getPlayer(permanent.getControllerId()); - if (player != null) + if (player != null) { player.damage(3, source.getSourceId(), game, false, true); + } } } } diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AvacynianMissionaries.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AvacynianMissionaries.java index 2c9fc4f748c..74d87e41f56 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AvacynianMissionaries.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AvacynianMissionaries.java @@ -29,28 +29,15 @@ package mage.sets.shadowsoverinnistrad; import java.util.UUID; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; -import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; import mage.abilities.condition.common.EquippedSourceCondition; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; -import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.TargetController; import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.target.common.TargetCreaturePermanent; -import mage.util.CardUtil; /** * @@ -73,11 +60,6 @@ public class AvacynianMissionaries extends CardImpl { this.addAbility(new TransformAbility()); this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), TargetController.YOU, new EquippedSourceCondition(), false)); - // When this creature transforms into Lunarch Inquisitors, you may exile another target creature until Lunarch Inquisitors leaves the battlefield. - Ability ability = new LunarchInquisitorsAbility(); - ability.addTarget(new TargetCreaturePermanent()); - ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); - this.addAbility(ability); } public AvacynianMissionaries(final AvacynianMissionaries card) { @@ -89,80 +71,3 @@ public class AvacynianMissionaries extends CardImpl { return new AvacynianMissionaries(this); } } - -class LunarchInquisitorsAbility extends TriggeredAbilityImpl { - - public LunarchInquisitorsAbility() { - super(Zone.BATTLEFIELD, new LunarchInquisitorsExileEffect(), true); - // Rule only shown on the night side - this.setRuleVisible(false); - } - - public LunarchInquisitorsAbility(final LunarchInquisitorsAbility ability) { - super(ability); - } - - @Override - public LunarchInquisitorsAbility copy() { - return new LunarchInquisitorsAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.TRANSFORMED; - } - - @Override - public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { - Permanent currentSourceObject = (Permanent) getSourceObjectIfItStillExists(game); - if (currentSourceObject != null && currentSourceObject.isNightCard()) { - return true; - } - return super.isInUseableZone(game, source, event); - } - - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getTargetId().equals(sourceId)) { - Permanent permanent = game.getPermanent(sourceId); - if (permanent != null && permanent.isTransformed()) { - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever this creature transforms into Lunarch Inquisitors, you may exile another target creature until Lunarch Inquisitors leaves the battlefield."; - } -} - -class LunarchInquisitorsExileEffect extends OneShotEffect { - - public LunarchInquisitorsExileEffect() { - super(Outcome.Benefit); - this.staticText = "exile target creature until {this} leaves the battlefield"; - } - - public LunarchInquisitorsExileEffect(final LunarchInquisitorsExileEffect effect) { - super(effect); - } - - @Override - public LunarchInquisitorsExileEffect copy() { - return new LunarchInquisitorsExileEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - // If Lunarch Inquisitors leaves the battlefield before its triggered ability resolves, - // the target won't be exiled. - if (permanent != null) { - return new ExileTargetEffect(CardUtil.getCardExileZoneId(game, source), permanent.getIdName()).apply(game, source); - } - return false; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AwokenHorror.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AwokenHorror.java index 0f864b229c2..a1705b9cb75 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AwokenHorror.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AwokenHorror.java @@ -29,12 +29,18 @@ package mage.sets.shadowsoverinnistrad; import java.util.UUID; import mage.MageInt; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.InfoEffect; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.ReturnToHandFromBattlefieldAllEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; /** * @@ -42,8 +48,6 @@ import mage.constants.Zone; */ public class AwokenHorror extends CardImpl { - private static final String rule = "Whenever this creature transforms into Awoken Horrow, return all non-Horror creatures to their owners' hands"; - public AwokenHorror(UUID ownerId) { super(ownerId, 92, "Awoken Horror", Rarity.RARE, new CardType[]{CardType.CREATURE}, ""); this.expansionSetCode = "SOI"; @@ -56,7 +60,7 @@ public class AwokenHorror extends CardImpl { this.nightCard = true; // When this creature transforms into Awoken Horrow, return all non-Horror creatures to their owners' hands. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect(rule))); + this.addAbility(new AwokenHorrorAbility()); } public AwokenHorror(final AwokenHorror card) { @@ -68,3 +72,55 @@ public class AwokenHorror extends CardImpl { return new AwokenHorror(this); } } + +class AwokenHorrorAbility extends TriggeredAbilityImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Horror creatures"); + + static { + filter.add(Predicates.not(new SubtypePredicate("Horror"))); + } + + public AwokenHorrorAbility() { + super(Zone.BATTLEFIELD, new ReturnToHandFromBattlefieldAllEffect(filter), false); + } + + public AwokenHorrorAbility(final AwokenHorrorAbility ability) { + super(ability); + } + + @Override + public AwokenHorrorAbility copy() { + return new AwokenHorrorAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRANSFORMED; + } + +// @Override +// public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { +// Permanent currentSourceObject = (Permanent) getSourceObjectIfItStillExists(game); +// if (currentSourceObject != null && currentSourceObject.isTransformed()) { +// // hard to check if the not transformed source hat the ability. But if it was transformed it probably had it, but maybe no perfect solution +// return true; +// } +// return false; +// } + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getTargetId().equals(sourceId)) { + Permanent permanent = game.getPermanent(sourceId); + if (permanent != null && permanent.isTransformed()) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever this creature transforms into Awoken Horrow, return all non-Horror creatures to their owners' hands."; + } +} diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/LunarchInquisitors.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/LunarchInquisitors.java index 1eb05772650..179f45dc05e 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/LunarchInquisitors.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/LunarchInquisitors.java @@ -29,12 +29,23 @@ package mage.sets.shadowsoverinnistrad; import java.util.UUID; import mage.MageInt; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.InfoEffect; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.util.CardUtil; /** * @@ -57,7 +68,10 @@ public class LunarchInquisitors extends CardImpl { this.nightCard = true; // When this creature transforms into Lunarch Inquisitors, you may exile another target creature until Lunarch Inquisitors leaves the battlefield. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect(rule))); + Ability ability = new LunarchInquisitorsAbility(); + ability.addTarget(new TargetCreaturePermanent()); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); + this.addAbility(ability); } public LunarchInquisitors(final LunarchInquisitors card) { @@ -69,3 +83,79 @@ public class LunarchInquisitors extends CardImpl { return new LunarchInquisitors(this); } } + +class LunarchInquisitorsAbility extends TriggeredAbilityImpl { + + public LunarchInquisitorsAbility() { + super(Zone.BATTLEFIELD, new LunarchInquisitorsExileEffect(), true); + // Rule only shown on the night side + this.setRuleVisible(false); + } + + public LunarchInquisitorsAbility(final LunarchInquisitorsAbility ability) { + super(ability); + } + + @Override + public LunarchInquisitorsAbility copy() { + return new LunarchInquisitorsAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRANSFORMED; + } + + @Override + public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { + Permanent currentSourceObject = (Permanent) getSourceObjectIfItStillExists(game); + if (currentSourceObject != null && currentSourceObject.isNightCard()) { + return true; + } + return super.isInUseableZone(game, source, event); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getTargetId().equals(sourceId)) { + Permanent permanent = game.getPermanent(sourceId); + if (permanent != null && permanent.isTransformed()) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever this creature transforms into Lunarch Inquisitors, you may exile another target creature until Lunarch Inquisitors leaves the battlefield."; + } +} + +class LunarchInquisitorsExileEffect extends OneShotEffect { + + public LunarchInquisitorsExileEffect() { + super(Outcome.Benefit); + this.staticText = "exile target creature until {this} leaves the battlefield"; + } + + public LunarchInquisitorsExileEffect(final LunarchInquisitorsExileEffect effect) { + super(effect); + } + + @Override + public LunarchInquisitorsExileEffect copy() { + return new LunarchInquisitorsExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + // If Lunarch Inquisitors leaves the battlefield before its triggered ability resolves, + // the target won't be exiled. + if (permanent != null) { + return new ExileTargetEffect(CardUtil.getCardExileZoneId(game, source), permanent.getIdName()).apply(game, source); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ThingInTheIce.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ThingInTheIce.java index 6f5f5dee27d..96c1431df0a 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ThingInTheIce.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ThingInTheIce.java @@ -29,15 +29,12 @@ package mage.sets.shadowsoverinnistrad; import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.ReturnToHandFromBattlefieldAllEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; @@ -46,16 +43,10 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.FilterSpell; -import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.filter.predicate.mageobject.SubtypePredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; /** * @@ -99,8 +90,6 @@ public class ThingInTheIce extends CardImpl { ability.addEffect(effect); this.addAbility(ability); - // When this creature transforms into Awoken Horrow, return all non-Horror creatures to their owners' hands. - this.addAbility(new AwokenHorrorAbility()); } public ThingInTheIce(final ThingInTheIce card) { @@ -112,58 +101,3 @@ public class ThingInTheIce extends CardImpl { return new ThingInTheIce(this); } } - -class AwokenHorrorAbility extends TriggeredAbilityImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Horror creatures"); - - static { - filter.add(Predicates.not(new SubtypePredicate("Horror"))); - } - - public AwokenHorrorAbility() { - super(Zone.BATTLEFIELD, new ReturnToHandFromBattlefieldAllEffect(filter), false); - // Rule only shown on the night side - this.setRuleVisible(false); - } - - public AwokenHorrorAbility(final AwokenHorrorAbility ability) { - super(ability); - } - - @Override - public AwokenHorrorAbility copy() { - return new AwokenHorrorAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.TRANSFORMED; - } - - @Override - public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { - Permanent currentSourceObject = (Permanent) getSourceObjectIfItStillExists(game); - if (currentSourceObject != null && currentSourceObject.isNightCard()) { - return true; - } - return super.isInUseableZone(game, source, event); - } - - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getTargetId().equals(sourceId)) { - Permanent permanent = game.getPermanent(sourceId); - if (permanent != null && permanent.isTransformed()) { - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever this creature transforms into Awoken Horrow, return all non-Horror creatures to their owners' hands."; - } -} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/WerewolfRansackerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/WerewolfRansackerTest.java index 798ae387a0b..92484919e88 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/WerewolfRansackerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/WerewolfRansackerTest.java @@ -19,11 +19,11 @@ public class WerewolfRansackerTest extends CardTestPlayerBase { setStopAt(2, PhaseStep.BEGIN_COMBAT); execute(); - assertLife(playerA, 20); - assertLife(playerB, 17); assertPermanentCount(playerB, "Ornithopter", 0); assertPermanentCount(playerA, "Afflicted Deserter", 0); assertPermanentCount(playerA, "Werewolf Ransacker", 1); + assertLife(playerA, 20); + assertLife(playerB, 17); } @Test @@ -69,5 +69,5 @@ public class WerewolfRansackerTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Ornithopter", 0); assertPermanentCount(playerA, "Afflicted Deserter", 1); assertPermanentCount(playerA, "Werewolf Ransacker", 0); - } + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/ThingInTheIceTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/ThingInTheIceTest.java index cb37349f42f..045b838f7bd 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/ThingInTheIceTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/ThingInTheIceTest.java @@ -6,30 +6,41 @@ import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - *Defender - -Thing in the Ice enters the battlefield with four ice counters on it. - -Whenever you cast an instant or sorcery spell, remove an ice counter from Thing in the Ice. Then if it has no ice counters on it, transform it. -When this creature transforms into Awoken Horror, return all non-Horror creatures to their owners' hands. + * Defender + * + * Thing in the Ice enters the battlefield with four ice counters on it. + * + * Whenever you cast an instant or sorcery spell, remove an ice counter from + * Thing in the Ice. Then if it has no ice counters on it, transform it. When + * this creature transforms into Awoken Horror, return all non-Horror creatures + * to their owners' hands. + * * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public class ThingInTheIceTest extends CardTestPlayerBase { - + /** * Reported bug: When Thing in the Ice transforms, it bounces Clue tokens. - **/ + * + */ @Test public void testClueTokens() { - - addCard(Zone.BATTLEFIELD, playerA, "Tireless Tracker", 1); + // Whenever a land enters the battlefield under your control, investigate. (Put a colorless Clue artifact token onto the battlefield with "{2}, Sacrifice this artifact: Draw a card.") + // Whenever you sacrifice a Clue, put a +1/+1 counter on Tireless Tracker. + addCard(Zone.BATTLEFIELD, playerA, "Tireless Tracker", 1); // Human, Scout 3/2 addCard(Zone.HAND, playerA, "Forest", 1); + // Defender + // Thing in the Ice enters the battlefield with four ice counters on it. + // Whenever you cast an instant or sorcery spell, remove an ice counter from Thing in the Ice. Then if it has no ice counters on it, transform it. + // When this creature transforms into Awoken Horrow, return all non-Horror creatures to their owners' hands. addCard(Zone.BATTLEFIELD, playerB, "Thing in the Ice", 1); + // Target creature gains haste until end of turn. + // Draw a card. addCard(Zone.HAND, playerB, "Expedite", 4); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 4); - + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest"); // creates a clue - + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Expedite"); addTarget(playerB, "Thing in the Ice"); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Expedite"); @@ -38,10 +49,10 @@ public class ThingInTheIceTest extends CardTestPlayerBase { addTarget(playerB, "Thing in the Ice"); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Expedite"); addTarget(playerB, "Thing in the Ice"); // remove all 4 ice counters to transform it - + setStopAt(2, PhaseStep.BEGIN_COMBAT); execute(); - + assertPermanentCount(playerA, "Clue", 1); assertHandCount(playerA, "Tireless Tracker", 1); // returned to hand assertPermanentCount(playerA, "Tireless Tracker", 0); diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 9dd6cc256ee..191264b0645 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -1167,6 +1167,9 @@ public abstract class AbilityImpl implements Ability { public MageObject getSourceObjectIfItStillExists(Game game) { MageObject currentObject = game.getObject(getSourceId()); if (currentObject != null) { + if (sourceObject == null) { + setSourceObject(currentObject, game); + } MageObjectReference mor = new MageObjectReference(currentObject, game); if (mor.getZoneChangeCounter() == getSourceObjectZoneChangeCounter()) { // source object has meanwhile not changed zone diff --git a/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlTargetEffect.java index 4e3ee10d2c6..a3851a7c350 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlTargetEffect.java @@ -31,6 +31,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; +import mage.cards.Cards; import mage.cards.CardsImpl; import mage.constants.Outcome; import mage.constants.Zone; @@ -78,20 +79,30 @@ public class ReturnToBattlefieldUnderOwnerControlTargetEffect extends OneShotEff public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - Card card = null; + Cards cardsToMove = new CardsImpl(); if (fromExileZone) { UUID exilZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); if (exilZoneId != null) { ExileZone exileZone = game.getExile().getExileZone(exilZoneId); - if (exileZone != null && getTargetPointer().getFirst(game, source) != null) { - card = exileZone.get(getTargetPointer().getFirst(game, source), game); + if (exileZone != null) { + for (UUID cardId : getTargetPointer().getTargets(game, source)) { + Card card = exileZone.get(cardId, game); + if (card != null) { + cardsToMove.add(card); + } + } } } } else { - card = game.getCard(getTargetPointer().getFirst(game, source)); + for (UUID cardId : getTargetPointer().getTargets(game, source)) { + Card card = game.getCard(cardId); + if (card != null) { + cardsToMove.add(card); + } + } } - if (card != null) { - controller.moveCards(new CardsImpl(card).getCards(game), + if (!cardsToMove.isEmpty()) { + controller.moveCards(cardsToMove.getCards(game), Zone.BATTLEFIELD, source, game, tapped, false, true, null); return true; }