Fix looking at face-down creatures; implement [MKM] Lumbering Laundry (#12479)

This commit is contained in:
ssk97 2024-06-18 19:23:50 -07:00 committed by GitHub
parent 1b3ac1fc7f
commit 32d7122e59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 137 additions and 250 deletions

View file

@ -2,9 +2,12 @@
package mage.view; package mage.view;
import mage.MageObject;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.Cards; import mage.cards.Cards;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import java.io.Serializable; import java.io.Serializable;
@ -20,7 +23,12 @@ public class LookedAtView implements Serializable {
public LookedAtView(String name, Cards cards, Game game) { public LookedAtView(String name, Cards cards, Game game) {
this.name = name; this.name = name;
for (Card card: cards.getCards(game)) { 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()));
}
} }
} }

View file

@ -1,7 +1,6 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -11,8 +10,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
@ -24,6 +21,8 @@ import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
* *
* @author fireshoes * @author fireshoes
@ -87,10 +86,7 @@ class AvenSoulgazerLookFaceDownEffect extends OneShotEffect {
} }
Permanent faceDownCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); Permanent faceDownCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
if (faceDownCreature != null) { if (faceDownCreature != null) {
Permanent copyFaceDown = faceDownCreature.copy(); player.lookAtCards("face down cards " + mageObject.getName(), faceDownCreature, game);
copyFaceDown.setFaceDown(false, game);
Cards cards = new CardsImpl(copyFaceDown);
player.lookAtCards("face down card - " + mageObject.getName(), cards, game);
} else { } else {
return false; return false;
} }

View file

@ -2,22 +2,12 @@
package mage.cards.k; package mage.cards.k;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.Ability; import mage.abilities.effects.common.continuous.LookAtOpponentFaceDownCreaturesAnyTimeEffect;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards; import mage.constants.CardType;
import mage.cards.CardsImpl; import mage.constants.SubType;
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 java.util.UUID; import java.util.UUID;
@ -33,8 +23,7 @@ public final class KeeperOfTheLens extends CardImpl {
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
// You may look at face-down creatures you don't control. // 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 SimpleStaticAbility(new LookAtOpponentFaceDownCreaturesAnyTimeEffect()));
this.addAbility(new KeeperOfTheLensLookFaceDownAbility());
} }
private KeeperOfTheLens(final KeeperOfTheLens card) { private KeeperOfTheLens(final KeeperOfTheLens card) {
@ -46,69 +35,3 @@ public final class KeeperOfTheLens extends CardImpl {
return new KeeperOfTheLens(this); 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;
}
}

View file

@ -1,27 +1,15 @@
package mage.cards.l; package mage.cards.l;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.ActivatedAbilityImpl; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.continuous.LookAtOpponentFaceDownCreaturesAnyTimeEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.LookAtTopCardOfLibraryAnyTimeEffect;
import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController; import java.util.UUID;
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;
/** /**
* *
@ -33,9 +21,9 @@ public final class LensOfClarity extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); 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. // 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) Ability ability = new SimpleStaticAbility(new LookAtTopCardOfLibraryAnyTimeEffect().setText("you may look at the top card of your library"));
this.addAbility(new LensOfClarityLookLibraryAbility()); ability.addEffect(new LookAtOpponentFaceDownCreaturesAnyTimeEffect().setText("at face-down creatures you don't control any time").concatBy(" and "));
this.addAbility(new LensOfClarityLookFaceDownAbility()); this.addAbility(ability);
} }
private LensOfClarity(final LensOfClarity card) { private LensOfClarity(final LensOfClarity card) {
@ -47,124 +35,3 @@ public final class LensOfClarity extends CardImpl {
return new LensOfClarity(this); 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;
}
}

View file

@ -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);
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.r; package mage.cards.r;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
@ -9,8 +8,6 @@ import mage.abilities.effects.common.PreventAllDamageByAllPermanentsEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
@ -22,6 +19,8 @@ import mage.players.Player;
import mage.target.Target; import mage.target.Target;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
* *
* @author LevelX2 * @author LevelX2
@ -82,8 +81,7 @@ class RevealingWindEffect extends OneShotEffect {
if (controller.chooseTarget(outcome, target, source, game)) { if (controller.chooseTarget(outcome, target, source, game)) {
Card card = game.getCard(target.getFirstTarget()); Card card = game.getCard(target.getFirstTarget());
if (card != null) { if (card != null) {
Cards cards = new CardsImpl(card); controller.lookAtCards(sourceObject.getName(), card, game);
controller.lookAtCards(sourceObject.getName(), cards, game);
game.informPlayers(controller.getLogName() + " look at a face-down attacking creature"); game.informPlayers(controller.getLogName() + " look at a face-down attacking creature");
} }
} }

View file

@ -1,7 +1,6 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -10,11 +9,9 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.card.FaceDownPredicate; import mage.filter.predicate.card.FaceDownPredicate;
@ -23,6 +20,8 @@ import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
* *
* @author LevelX2 * @author LevelX2
@ -84,10 +83,7 @@ class SmokeTellerLookFaceDownEffect extends OneShotEffect {
} }
Permanent faceDownCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); Permanent faceDownCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
if (faceDownCreature != null) { if (faceDownCreature != null) {
Permanent copyFaceDown = faceDownCreature.copy(); player.lookAtCards("face down card - " + mageObject.getName(), faceDownCreature, game);
copyFaceDown.setFaceDown(false, game);
Cards cards = new CardsImpl(copyFaceDown);
player.lookAtCards("face down card - " + mageObject.getName(), cards, game);
} else { } else {
return false; return false;
} }

View file

@ -8,8 +8,6 @@ import mage.abilities.effects.common.LookLibraryControllerEffect;
import mage.abilities.effects.common.LookLibraryTopCardTargetPlayerEffect; import mage.abilities.effects.common.LookLibraryTopCardTargetPlayerEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
@ -114,10 +112,7 @@ class SpyNetworkFaceDownEffect extends OneShotEffect {
} }
Permanent faceDownCreature = game.getPermanent(target.getFirstTarget()); Permanent faceDownCreature = game.getPermanent(target.getFirstTarget());
if (faceDownCreature != null) { if (faceDownCreature != null) {
Permanent copyFaceDown = faceDownCreature.copy(); controller.lookAtCards("face down card - " + mageObject.getName(), faceDownCreature, game);
copyFaceDown.setFaceDown(false, game);
Cards cards = new CardsImpl(copyFaceDown);
controller.lookAtCards("face down card - " + mageObject.getName(), cards, game);
game.informPlayers(controller.getLogName() + " looks at a face down creature controlled by " + player.getLogName()); game.informPlayers(controller.getLogName() + " looks at a face down creature controlled by " + player.getLogName());
} }
} }

View file

@ -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("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("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("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("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("Macabre Reconstruction", 93, Rarity.COMMON, mage.cards.m.MacabreReconstruction.class));
cards.add(new SetCardInfo("Magnetic Snuffler", 254, Rarity.UNCOMMON, mage.cards.m.MagneticSnuffler.class)); cards.add(new SetCardInfo("Magnetic Snuffler", 254, Rarity.UNCOMMON, mage.cards.m.MagneticSnuffler.class));

View file

@ -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);
}
}