diff --git a/Mage.Common/src/main/java/mage/view/LookedAtView.java b/Mage.Common/src/main/java/mage/view/LookedAtView.java index 17af1a0e8ae..9b45e2be0bc 100644 --- a/Mage.Common/src/main/java/mage/view/LookedAtView.java +++ b/Mage.Common/src/main/java/mage/view/LookedAtView.java @@ -2,9 +2,12 @@ package mage.view; +import mage.MageObject; import mage.cards.Card; import mage.cards.Cards; import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.PermanentCard; import java.io.Serializable; @@ -20,7 +23,12 @@ public class LookedAtView implements Serializable { public LookedAtView(String name, Cards cards, Game game) { this.name = name; for (Card card: cards.getCards(game)) { - this.cards.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt())); + if (card instanceof PermanentCard && card.isFaceDown(game)) { + MageObject trueCard = ((Permanent) card).getBasicMageObject(); + this.cards.put(card.getId(), new SimpleCardView(trueCard.getId(), trueCard.getExpansionSetCode(), trueCard.getCardNumber(), trueCard.getUsesVariousArt())); + } else { + this.cards.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt())); + } } } diff --git a/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java b/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java index b376c793db0..2a30d6f84ec 100644 --- a/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java +++ b/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -11,8 +10,6 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; @@ -24,6 +21,8 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author fireshoes @@ -87,10 +86,7 @@ class AvenSoulgazerLookFaceDownEffect extends OneShotEffect { } Permanent faceDownCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); if (faceDownCreature != null) { - Permanent copyFaceDown = faceDownCreature.copy(); - copyFaceDown.setFaceDown(false, game); - Cards cards = new CardsImpl(copyFaceDown); - player.lookAtCards("face down card - " + mageObject.getName(), cards, game); + player.lookAtCards("face down cards " + mageObject.getName(), faceDownCreature, game); } else { return false; } diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfTheLens.java b/Mage.Sets/src/mage/cards/k/KeeperOfTheLens.java index c2ccc49f9fd..e71ad0d6307 100644 --- a/Mage.Sets/src/mage/cards/k/KeeperOfTheLens.java +++ b/Mage.Sets/src/mage/cards/k/KeeperOfTheLens.java @@ -2,22 +2,12 @@ package mage.cards.k; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.ActivatedAbilityImpl; -import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.LookAtOpponentFaceDownCreaturesAnyTimeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; -import mage.constants.*; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.card.FaceDownPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.constants.CardType; +import mage.constants.SubType; import java.util.UUID; @@ -33,8 +23,7 @@ public final class KeeperOfTheLens extends CardImpl { this.toughness = new MageInt(2); // You may look at face-down creatures you don't control. - // TODO: this should be a static abilitie and not use activated abilities (because it could than be restriced) - this.addAbility(new KeeperOfTheLensLookFaceDownAbility()); + this.addAbility(new SimpleStaticAbility(new LookAtOpponentFaceDownCreaturesAnyTimeEffect())); } private KeeperOfTheLens(final KeeperOfTheLens card) { @@ -46,69 +35,3 @@ public final class KeeperOfTheLens extends CardImpl { return new KeeperOfTheLens(this); } } - -class KeeperOfTheLensLookFaceDownAbility extends ActivatedAbilityImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face down creature you don't control"); - - static { - filter.add(FaceDownPredicate.instance); - filter.add(TargetController.NOT_YOU.getControllerPredicate()); - } - - public KeeperOfTheLensLookFaceDownAbility() { - super(Zone.BATTLEFIELD, new KeeperOfTheLensLookFaceDownEffect(), new GenericManaCost(0)); - this.usesStack = false; - this.addTarget(new TargetCreaturePermanent(filter).withNotTarget(true)); - } - - private KeeperOfTheLensLookFaceDownAbility(final KeeperOfTheLensLookFaceDownAbility ability) { - super(ability); - } - - @Override - public KeeperOfTheLensLookFaceDownAbility copy() { - return new KeeperOfTheLensLookFaceDownAbility(this); - } - -} - -class KeeperOfTheLensLookFaceDownEffect extends OneShotEffect { - - KeeperOfTheLensLookFaceDownEffect() { - super(Outcome.Benefit); - this.staticText = "You may look at face-down creatures you don't control any time"; - } - - private KeeperOfTheLensLookFaceDownEffect(final KeeperOfTheLensLookFaceDownEffect effect) { - super(effect); - } - - @Override - public KeeperOfTheLensLookFaceDownEffect copy() { - return new KeeperOfTheLensLookFaceDownEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject mageObject = game.getObject(source); - if (controller == null || mageObject == null) { - return false; - } - Permanent faceDownCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (faceDownCreature != null) { - Permanent copyFaceDown = faceDownCreature.copy(); - copyFaceDown.setFaceDown(false, game); - Cards cards = new CardsImpl(copyFaceDown); - Player player = game.getPlayer(faceDownCreature.getControllerId()); - controller.lookAtCards("face down card - " + mageObject.getName(), cards, game); - if (player != null) { - game.informPlayers(controller.getLogName() + " looks at a face down creature of " + player.getLogName()); - } - } else { - return false; - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/l/LensOfClarity.java b/Mage.Sets/src/mage/cards/l/LensOfClarity.java index ae79ef9fdb1..3ac9ed6911d 100644 --- a/Mage.Sets/src/mage/cards/l/LensOfClarity.java +++ b/Mage.Sets/src/mage/cards/l/LensOfClarity.java @@ -1,27 +1,15 @@ package mage.cards.l; -import java.util.UUID; -import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.ActivatedAbilityImpl; -import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.LookAtOpponentFaceDownCreaturesAnyTimeEffect; +import mage.abilities.effects.common.continuous.LookAtTopCardOfLibraryAnyTimeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.card.FaceDownPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; /** * @@ -33,9 +21,9 @@ public final class LensOfClarity extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); // You may look at the top card of your library and at face-down creatures you don't control. - // TODO: this efffects should be a static abilities and not use activated abilities (because it could than be restriced) - this.addAbility(new LensOfClarityLookLibraryAbility()); - this.addAbility(new LensOfClarityLookFaceDownAbility()); + Ability ability = new SimpleStaticAbility(new LookAtTopCardOfLibraryAnyTimeEffect().setText("you may look at the top card of your library")); + ability.addEffect(new LookAtOpponentFaceDownCreaturesAnyTimeEffect().setText("at face-down creatures you don't control any time").concatBy(" and ")); + this.addAbility(ability); } private LensOfClarity(final LensOfClarity card) { @@ -47,124 +35,3 @@ public final class LensOfClarity extends CardImpl { return new LensOfClarity(this); } } - -class LensOfClarityLookLibraryAbility extends ActivatedAbilityImpl { - - public LensOfClarityLookLibraryAbility() { - super(Zone.BATTLEFIELD, new LensOfClarityLookLibraryEffect(), new GenericManaCost(0)); - this.usesStack = false; - } - - private LensOfClarityLookLibraryAbility(final LensOfClarityLookLibraryAbility ability) { - super(ability); - } - - @Override - public LensOfClarityLookLibraryAbility copy() { - return new LensOfClarityLookLibraryAbility(this); - } - -} - -class LensOfClarityLookLibraryEffect extends OneShotEffect { - - LensOfClarityLookLibraryEffect() { - super(Outcome.Neutral); - this.staticText = "You may look at the top card of your library"; - } - - private LensOfClarityLookLibraryEffect(final LensOfClarityLookLibraryEffect effect) { - super(effect); - } - - @Override - public LensOfClarityLookLibraryEffect copy() { - return new LensOfClarityLookLibraryEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject mageObject = game.getObject(source); - if (controller == null || mageObject == null) { - return false; - } - - Card card = controller.getLibrary().getFromTop(game); - if (card != null) { - Cards cards = new CardsImpl(card); - controller.lookAtCards("top card of library - " + controller.getName(), cards, game); - game.informPlayers(controller.getLogName() + " looks at the top card of their library"); - } else { - return false; - } - - return true; - } -} - -class LensOfClarityLookFaceDownAbility extends ActivatedAbilityImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face down creature you don't control"); - - static { - filter.add(FaceDownPredicate.instance); - filter.add(TargetController.NOT_YOU.getControllerPredicate()); - } - - public LensOfClarityLookFaceDownAbility() { - super(Zone.BATTLEFIELD, new LensOfClarityLookFaceDownEffect(), new GenericManaCost(0)); - this.usesStack = false; - this.addTarget(new TargetCreaturePermanent(filter).withNotTarget(true)); - } - - private LensOfClarityLookFaceDownAbility(final LensOfClarityLookFaceDownAbility ability) { - super(ability); - } - - @Override - public LensOfClarityLookFaceDownAbility copy() { - return new LensOfClarityLookFaceDownAbility(this); - } - -} - -class LensOfClarityLookFaceDownEffect extends OneShotEffect { - - LensOfClarityLookFaceDownEffect() { - super(Outcome.Benefit); - this.staticText = "You may look at face-down creatures you don't control"; - } - - private LensOfClarityLookFaceDownEffect(final LensOfClarityLookFaceDownEffect effect) { - super(effect); - } - - @Override - public LensOfClarityLookFaceDownEffect copy() { - return new LensOfClarityLookFaceDownEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller= game.getPlayer(source.getControllerId()); - MageObject mageObject = game.getObject(source); - if (controller == null || mageObject == null) { - return false; - } - Permanent faceDownCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (faceDownCreature != null) { - Permanent copyFaceDown = faceDownCreature.copy(); - copyFaceDown.setFaceDown(false, game); - Cards cards = new CardsImpl(copyFaceDown); - Player player = game.getPlayer(faceDownCreature.getControllerId()); - controller.lookAtCards("face down card - " + mageObject.getName(), cards, game); - if (player != null) { - game.informPlayers(controller.getLogName() + " looks at a face down creature of " + player.getLogName()); - } - } else { - return false; - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/l/LumberingLaundry.java b/Mage.Sets/src/mage/cards/l/LumberingLaundry.java new file mode 100644 index 00000000000..c40b5706c49 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LumberingLaundry.java @@ -0,0 +1,44 @@ +package mage.cards.l; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.LookAtOpponentFaceDownCreaturesAnyTimeEffect; +import mage.abilities.keyword.DisguiseAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author notgreat + */ +public final class LumberingLaundry extends CardImpl { + + public LumberingLaundry(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); + + this.subtype.add(SubType.GOLEM); + this.power = new MageInt(4); + this.toughness = new MageInt(5); + + // {2}: Until end of turn, you may look at face-down creatures you don't control any time. + this.addAbility(new SimpleActivatedAbility(new LookAtOpponentFaceDownCreaturesAnyTimeEffect(Duration.EndOfTurn), new ManaCostsImpl<>("{2}"))); + + // Disguise {5} + this.addAbility(new DisguiseAbility(this, new ManaCostsImpl<>("{5}"))); + + } + + private LumberingLaundry(final LumberingLaundry card) { + super(card); + } + + @Override + public LumberingLaundry copy() { + return new LumberingLaundry(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RevealingWind.java b/Mage.Sets/src/mage/cards/r/RevealingWind.java index c98334baf07..e57804aa3c8 100644 --- a/Mage.Sets/src/mage/cards/r/RevealingWind.java +++ b/Mage.Sets/src/mage/cards/r/RevealingWind.java @@ -1,7 +1,6 @@ package mage.cards.r; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; @@ -9,8 +8,6 @@ import mage.abilities.effects.common.PreventAllDamageByAllPermanentsEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; @@ -22,6 +19,8 @@ import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author LevelX2 @@ -82,8 +81,7 @@ class RevealingWindEffect extends OneShotEffect { if (controller.chooseTarget(outcome, target, source, game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null) { - Cards cards = new CardsImpl(card); - controller.lookAtCards(sourceObject.getName(), cards, game); + controller.lookAtCards(sourceObject.getName(), card, game); game.informPlayers(controller.getLogName() + " look at a face-down attacking creature"); } } diff --git a/Mage.Sets/src/mage/cards/s/SmokeTeller.java b/Mage.Sets/src/mage/cards/s/SmokeTeller.java index 4216523e188..6218bc6d059 100644 --- a/Mage.Sets/src/mage/cards/s/SmokeTeller.java +++ b/Mage.Sets/src/mage/cards/s/SmokeTeller.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -10,11 +9,9 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; 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.card.FaceDownPredicate; @@ -23,6 +20,8 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author LevelX2 @@ -84,10 +83,7 @@ class SmokeTellerLookFaceDownEffect extends OneShotEffect { } Permanent faceDownCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); if (faceDownCreature != null) { - Permanent copyFaceDown = faceDownCreature.copy(); - copyFaceDown.setFaceDown(false, game); - Cards cards = new CardsImpl(copyFaceDown); - player.lookAtCards("face down card - " + mageObject.getName(), cards, game); + player.lookAtCards("face down card - " + mageObject.getName(), faceDownCreature, game); } else { return false; } diff --git a/Mage.Sets/src/mage/cards/s/SpyNetwork.java b/Mage.Sets/src/mage/cards/s/SpyNetwork.java index 53703b76e27..036591054f7 100644 --- a/Mage.Sets/src/mage/cards/s/SpyNetwork.java +++ b/Mage.Sets/src/mage/cards/s/SpyNetwork.java @@ -8,8 +8,6 @@ import mage.abilities.effects.common.LookLibraryControllerEffect; import mage.abilities.effects.common.LookLibraryTopCardTargetPlayerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.filter.common.FilterCreaturePermanent; @@ -114,10 +112,7 @@ class SpyNetworkFaceDownEffect extends OneShotEffect { } Permanent faceDownCreature = game.getPermanent(target.getFirstTarget()); if (faceDownCreature != null) { - Permanent copyFaceDown = faceDownCreature.copy(); - copyFaceDown.setFaceDown(false, game); - Cards cards = new CardsImpl(copyFaceDown); - controller.lookAtCards("face down card - " + mageObject.getName(), cards, game); + controller.lookAtCards("face down card - " + mageObject.getName(), faceDownCreature, game); game.informPlayers(controller.getLogName() + " looks at a face down creature controlled by " + player.getLogName()); } } diff --git a/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java b/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java index 93c2ee6da25..c3ef905ec7d 100644 --- a/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java +++ b/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java @@ -185,6 +185,7 @@ public final class MurdersAtKarlovManor extends ExpansionSet { cards.add(new SetCardInfo("Long Goodbye", 92, Rarity.UNCOMMON, mage.cards.l.LongGoodbye.class)); cards.add(new SetCardInfo("Lost in the Maze", 64, Rarity.RARE, mage.cards.l.LostInTheMaze.class)); cards.add(new SetCardInfo("Loxodon Eavesdropper", 168, Rarity.COMMON, mage.cards.l.LoxodonEavesdropper.class)); + cards.add(new SetCardInfo("Lumbering Laundry", 253, Rarity.UNCOMMON, mage.cards.l.LumberingLaundry.class)); cards.add(new SetCardInfo("Lush Portico", 263, Rarity.RARE, mage.cards.l.LushPortico.class)); cards.add(new SetCardInfo("Macabre Reconstruction", 93, Rarity.COMMON, mage.cards.m.MacabreReconstruction.class)); cards.add(new SetCardInfo("Magnetic Snuffler", 254, Rarity.UNCOMMON, mage.cards.m.MagneticSnuffler.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/LookAtOpponentFaceDownCreaturesAnyTimeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/LookAtOpponentFaceDownCreaturesAnyTimeEffect.java new file mode 100644 index 00000000000..ebc7eb65b35 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/LookAtOpponentFaceDownCreaturesAnyTimeEffect.java @@ -0,0 +1,59 @@ +package mage.abilities.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.*; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.card.FaceDownPredicate; +import mage.game.Game; +import mage.players.Player; + +/** + * @author notgreat + */ +public class LookAtOpponentFaceDownCreaturesAnyTimeEffect extends ContinuousEffectImpl { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face-down creatures you don't control"); + + static { + filter.add(FaceDownPredicate.instance); + filter.add(TargetController.NOT_YOU.getControllerPredicate()); + } + + public LookAtOpponentFaceDownCreaturesAnyTimeEffect() { + this(Duration.WhileOnBattlefield); + } + + public LookAtOpponentFaceDownCreaturesAnyTimeEffect(Duration duration) { + super(duration, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit); + staticText = (duration.toString().isEmpty() ? "" : duration.toString() + ", ") + "you may look at face-down creatures you don't control any time"; + } + + protected LookAtOpponentFaceDownCreaturesAnyTimeEffect(final LookAtOpponentFaceDownCreaturesAnyTimeEffect effect) { + super(effect); + } + + //Based on LookAtTopCardOfLibraryAnyTimeEffect + @Override + public boolean apply(Game game, Ability source) { + if (game.inCheckPlayableState()) { // Ignored - see https://github.com/magefree/mage/issues/6994 + return false; + } + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Cards cards = new CardsImpl(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); + if (cards.isEmpty()) { + return false; + } + controller.lookAtCards(source, "Face Down Creatures", cards, game); + return true; + } + + @Override + public LookAtOpponentFaceDownCreaturesAnyTimeEffect copy() { + return new LookAtOpponentFaceDownCreaturesAnyTimeEffect(this); + } +}