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

View file

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

View file

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

View file

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

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

View file

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

View file

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

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("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));

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