From 9094303aa7239d51a381b6eecdd246206006949c Mon Sep 17 00:00:00 2001 From: jeffwadsworth Date: Tue, 26 Nov 2019 16:31:54 -0600 Subject: [PATCH] Fixed #6053 --- .../mage/cards/w/WallOfStolenIdentity.java | 287 ++++++------------ 1 file changed, 94 insertions(+), 193 deletions(-) diff --git a/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java b/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java index 1a61f9d5a7..7efedbe8aa 100644 --- a/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java +++ b/Mage.Sets/src/mage/cards/w/WallOfStolenIdentity.java @@ -3,36 +3,39 @@ package mage.cards.w; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CopyPermanentEffect; -import mage.abilities.effects.common.SendOptionUsedEventEffect; -import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.DefenderAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; 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.TargetPermanent; -import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FixedTarget; import mage.util.functions.ApplyToPermanent; -import mage.watchers.Watcher; - import java.util.UUID; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.ContinuousRuleModifyingEffect; +import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.filter.common.FilterCreaturePermanent; +import mage.target.Target; +import mage.target.targetpointer.FixedTarget; /** * @author TheElk801 */ public final class WallOfStolenIdentity extends CardImpl { + final static private String rule = "You may have Wall of Stolen Identity enter the battlefield as a copy of any " + + "creature on the battlefield, except it's a wall in addition to its other types and it has defender. " + + "When you do, tap the copied creature and it doesn't untap during its " + + "controller's untap step for as long as you control {this}"; + public WallOfStolenIdentity(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); @@ -42,9 +45,13 @@ public final class WallOfStolenIdentity extends CardImpl { this.toughness = new MageInt(0); // You may have Wall of Stolen Identity enter the battlefield as a copy of any creature on the battlefield, except it's a wall in addition to its other types and it has defender. When you do, tap the copied creature and it doesn't untap during its controller's untap step for as long as you control Wall of Stolen Identity. - this.addAbility(new EntersBattlefieldAbility( - new WallOfStolenIdentityETBEffect(), true - ), new WallOfStolenIdentityWatcher()); + Ability ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new EntersBattlefieldEffect( + new WallOfStolenIdentityCopyEffect(), + rule, + true)); + this.addAbility(ability); } private WallOfStolenIdentity(final WallOfStolenIdentity card) { @@ -57,203 +64,97 @@ public final class WallOfStolenIdentity extends CardImpl { } } -class WallOfStolenIdentityETBEffect extends OneShotEffect { +class WallOfStolenIdentityCopyEffect extends OneShotEffect { - private static final ApplyToPermanent applier = new ApplyToPermanent() { + private static final String rule2 = "When you do, tap the copied creature and it doesn't untap during its " + + "controller's untap step for as long as you control {this}."; - @Override - public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - return this.apply(game, (MageObject) permanent, source, copyToObjectId); - } - - @Override - public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - mageObject.getAbilities().add(DefenderAbility.getInstance()); - mageObject.getSubtype(game).add(SubType.WALL); - return true; - } - }; - private static final Effect activater = new SendOptionUsedEventEffect(); - - WallOfStolenIdentityETBEffect() { - super(Outcome.Benefit); - staticText = "as a copy of any creature on the battlefield, except it's a Wall in addition to its other types " + - "and it has defender. When you do, tap the copied creature and it doesn't untap during " + - "its controller's untap step for as long as you control {this}."; + public WallOfStolenIdentityCopyEffect() { + super(Outcome.Copy); + staticText = rule2; } - private WallOfStolenIdentityETBEffect(final WallOfStolenIdentityETBEffect effect) { + public WallOfStolenIdentityCopyEffect(final WallOfStolenIdentityCopyEffect effect) { super(effect); } - @Override - public WallOfStolenIdentityETBEffect copy() { - return new WallOfStolenIdentityETBEffect(this); - } - @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { - return false; + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + permanent = game.getPermanentEntering(source.getSourceId()); } - TargetPermanent target = new TargetCreaturePermanent(0, 1); - target.setNotTarget(true); - if (!player.choose(outcome, target, source.getSourceId(), game)) { - return false; + final Permanent sourcePermanent = permanent; + if (controller != null + && sourcePermanent != null) { + Target target = new TargetPermanent(new FilterCreaturePermanent("target creature (you copy from)")); + target.setRequired(true); + if (source instanceof SimpleStaticAbility) { + target = new TargetPermanent(new FilterCreaturePermanent("creature (you copy from)")); + target.setRequired(false); + target.setNotTarget(true); + } + if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) { + controller.choose(Outcome.Copy, target, source.getSourceId(), game); + Permanent copyFromPermanent = game.getPermanent(target.getFirstTarget()); + if (copyFromPermanent != null) { + game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, new ApplyToPermanent() { + @Override + public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + permanent.getSubtype(game).add(SubType.WALL); + permanent.getAbilities().add(DefenderAbility.getInstance()); + return true; + } + + @Override + public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { + mageObject.getSubtype(game).add(SubType.WALL); + mageObject.getAbilities().add(DefenderAbility.getInstance()); + return true; + } + + }); + + copyFromPermanent.tap(game); + // Incredibly, you can't just add a fixed target to a continuousrulemodifyingeffect, thus the workaround. + ContinuousRuleModifyingEffect effect = new DontUntapInControllersUntapStepSourceEffect(); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); + ContinuousEffect effect2 = new GainAbilityTargetEffect(ability, Duration.Custom); + ConditionalContinuousEffect conditionalEffect = new ConditionalContinuousEffect( + effect2, new WallOfStolenIdentityCondition(source, source.getControllerId()), ""); + conditionalEffect.setTargetPointer(new FixedTarget(target.getFirstTarget())); + game.addEffect(conditionalEffect, source); + return true; + } + } } - Effect effect = new CopyPermanentEffect(null, applier, true); - effect.setTargetPointer(new FixedTarget(target.getFirstTarget(), game)); - effect.apply(game, source); - DelayedTriggeredAbility ability = new WallOfStolenIdentityReflexiveTriggeredAbility(); - ability.getEffects() - .stream() - .forEach(e -> e.setTargetPointer(new FixedTarget(target.getFirstTarget(), game))); - game.addDelayedTriggeredAbility(ability, source); - return activater.apply(game, source); + return false; + } + + @Override + public WallOfStolenIdentityCopyEffect copy() { + return new WallOfStolenIdentityCopyEffect(this); } } +class WallOfStolenIdentityCondition implements Condition { -class WallOfStolenIdentityReflexiveTriggeredAbility extends DelayedTriggeredAbility { + // Checks for when it leaves play or changes control + private final Ability ability; + private final UUID controllerId; - WallOfStolenIdentityReflexiveTriggeredAbility() { - super(new TapTargetEffect(), Duration.OneUse, true); - this.addEffect(new WallOfStolenIdentityUntapEffect()); - } - - private WallOfStolenIdentityReflexiveTriggeredAbility(final WallOfStolenIdentityReflexiveTriggeredAbility ability) { - super(ability); + public WallOfStolenIdentityCondition(Ability ability, UUID controllerId) { + this.ability = ability; + this.controllerId = controllerId; } @Override - public WallOfStolenIdentityReflexiveTriggeredAbility copy() { - return new WallOfStolenIdentityReflexiveTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.OPTION_USED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals(this.getControllerId()) - && event.getSourceId().equals(this.getSourceId()); - } - - @Override - public String getRule() { - return "When you do, tap the copied creature and it doesn't untap during " + - "its controller's untap step for as long as you control {this}."; - } -} - -class WallOfStolenIdentityUntapEffect extends ContinuousRuleModifyingEffectImpl { - - WallOfStolenIdentityUntapEffect() { - super(Duration.Custom, Outcome.Detriment, false, false); - } - - private WallOfStolenIdentityUntapEffect(final WallOfStolenIdentityUntapEffect effect) { - super(effect); - } - - @Override - public WallOfStolenIdentityUntapEffect copy() { - return new WallOfStolenIdentityUntapEffect(this); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UNTAP - || event.getType() == GameEvent.EventType.ZONE_CHANGE - || event.getType() == GameEvent.EventType.LOST_CONTROL; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - // Source must be on the battlefield (it's neccessary to check here because if as response to the enter - // the battlefield triggered ability the source dies (or will be exiled), then the ZONE_CHANGE or LOST_CONTROL - // event will happen before this effect is applied ever) - MageObject sourceObject = source.getSourceObjectIfItStillExists(game); - if (!(sourceObject instanceof Permanent) - || !((Permanent) sourceObject).isControlledBy(source.getControllerId())) { - discard(); - return false; - } - switch (event.getType()) { - case ZONE_CHANGE: - // end effect if source does a zone move - if (event.getTargetId().equals(source.getSourceId())) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - discard(); - return false; - } - } - break; - case UNTAP: - // prevent to untap the target creature - if (game.getTurn().getStepType() == PhaseStep.UNTAP - && event.getTargetId().equals(targetPointer.getFirst(game, source))) { - Permanent targetCreature = game.getPermanent(targetPointer.getFirst(game, source)); - if (targetCreature != null) { - return targetCreature.isControlledBy(game.getActivePlayerId()); - } else { - discard(); - return false; - } - } - break; - case LOST_CONTROL: - // end effect if source control is changed - if (event.getTargetId().equals(source.getSourceId())) { - discard(); - return false; - } - break; + public boolean apply(Game game, Ability source) { + Permanent permanentSource = game.getPermanent(ability.getSourceId()); + if (permanentSource != null) { + return permanentSource.getControllerId() == controllerId; } return false; } } - -class WallOfStolenIdentityWatcher extends Watcher { - - WallOfStolenIdentityWatcher() { - super(WatcherScope.CARD); - } - - private WallOfStolenIdentityWatcher(WallOfStolenIdentityWatcher watcher) { - super(watcher); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.LOST_CONTROL - && event.getPlayerId().equals(controllerId) - && event.getTargetId().equals(sourceId)) { - condition = true; - game.replaceEvent(event); - return; - } - if (event.getType() == GameEvent.EventType.ZONE_CHANGE - && event.getTargetId().equals(sourceId)) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - condition = true; - game.replaceEvent(event); - } - } - } - - @Override - public void reset() { - //don't reset condition each turn - only when this leaves the battlefield - } - - @Override - public WallOfStolenIdentityWatcher copy() { - return new WallOfStolenIdentityWatcher(this); - } -}