implement [MKM] Cryptic Coat (#12164) and Cloak ability

This commit is contained in:
Susucre 2024-06-06 12:47:07 +02:00 committed by GitHub
parent 8172616449
commit ab280ad2ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 235 additions and 29 deletions

View file

@ -111,32 +111,36 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl {
new TurnFaceUpAbility(turnFaceUpCosts, faceDownType == FaceDownType.MEGAMORPHED)
.setCostAdjuster(costAdjuster)
);
}
switch (faceDownType) {
case MORPHED:
case MEGAMORPHED:
switch (faceDownType) {
case MORPHED:
case MEGAMORPHED:
if (turnFaceUpCosts != null) {
// face up rules replace for cost hide
this.additionalAbilities.add(new SimpleStaticAbility(Zone.ALL, new InfoEffect(
"Turn it face up any time for its morph cost."
)));
break;
case DISGUISED:
case CLOAKED:
// ward
this.additionalAbilities.add(new WardAbility(new ManaCostsImpl<>("{2}")));
}
break;
case DISGUISED:
case CLOAKED:
// Ward {2} -- should not be dependent on turnFaceUpCosts.
this.additionalAbilities.add(new WardAbility(new ManaCostsImpl<>("{2}")));
if (turnFaceUpCosts != null) {
// face up rules replace for cost hide
this.additionalAbilities.add(new SimpleStaticAbility(Zone.ALL, new InfoEffect(
"Turn it face up any time for its disguise/cloaked cost."
)));
break;
case MANUAL:
case MANIFESTED:
// no face up abilities
break;
default:
throw new IllegalArgumentException("Un-supported face down type: " + faceDownType);
}
}
break;
case MANUAL:
case MANIFESTED:
// no face up abilities
break;
default:
throw new IllegalArgumentException("Un-supported face down type: " + faceDownType);
}
staticText = "{this} becomes a 2/2 face-down creature, with no text, no name, no subtypes, and no mana cost";
@ -209,6 +213,9 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl {
case DISGUISED:
permanent.setDisguised(true);
break;
case CLOAKED:
permanent.setCloaked(true);
break;
default:
throw new UnsupportedOperationException("FaceDownType not yet supported: " + faceDownType);
}
@ -228,6 +235,8 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl {
return BecomesFaceDownCreatureEffect.FaceDownType.DISGUISED;
} else if (permanent.isManifested()) {
return BecomesFaceDownCreatureEffect.FaceDownType.MANIFESTED;
} else if (permanent.isCloaked()) {
return BecomesFaceDownCreatureEffect.FaceDownType.CLOAKED;
} else if (permanent.isFaceDown(game)) {
return BecomesFaceDownCreatureEffect.FaceDownType.MANUAL;
} else {
@ -326,7 +335,7 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl {
tokenName = TokenRepository.XMAGE_IMAGE_NAME_FACE_DOWN_MANIFEST;
break;
case CLOAKED:
tokenName = "TODO-CLOAKED";
tokenName = TokenRepository.XMAGE_IMAGE_NAME_FACE_DOWN_CLOAK;
break;
case MANUAL:
tokenName = TokenRepository.XMAGE_IMAGE_NAME_FACE_DOWN_MANUAL;

View file

@ -18,7 +18,7 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.Set;
import java.util.*;
/**
* Manifest
@ -65,6 +65,7 @@ public class ManifestEffect extends OneShotEffect {
private final DynamicValue amount;
private final boolean isPlural;
private final boolean cloakNotManifest;
public ManifestEffect(int amount) {
this(StaticValue.get(amount), amount > 1);
@ -75,9 +76,14 @@ public class ManifestEffect extends OneShotEffect {
}
private ManifestEffect(DynamicValue amount, boolean isPlural) {
this(amount, isPlural, false);
}
private ManifestEffect(DynamicValue amount, boolean isPlural, boolean cloakNotManifest) {
super(Outcome.PutCreatureInPlay);
this.amount = amount;
this.isPlural = isPlural;
this.cloakNotManifest = cloakNotManifest;
this.staticText = setText();
}
@ -85,6 +91,7 @@ public class ManifestEffect extends OneShotEffect {
super(effect);
this.amount = effect.amount;
this.isPlural = effect.isPlural;
this.cloakNotManifest = effect.cloakNotManifest;
}
@Override
@ -100,12 +107,16 @@ public class ManifestEffect extends OneShotEffect {
}
int manifestAmount = amount.calculate(game, source, this);
return doManifestCards(game, source, controller, controller.getLibrary().getTopCards(game, manifestAmount));
return !doManifestCards(game, source, controller, controller.getLibrary().getTopCards(game, manifestAmount), cloakNotManifest).isEmpty();
}
public static boolean doManifestCards(Game game, Ability source, Player manifestPlayer, Set<Card> cardsToManifest) {
public static List<Permanent> doManifestCards(Game game, Ability source, Player manifestPlayer, Set<Card> cardsToManifest) {
return doManifestCards(game, source, manifestPlayer, cardsToManifest, false);
}
public static List<Permanent> doManifestCards(Game game, Ability source, Player manifestPlayer, Set<Card> cardsToManifest, boolean cloakNotManifest) {
if (cardsToManifest.isEmpty()) {
return false;
return Collections.emptyList();
}
// prepare source ability
@ -132,9 +143,10 @@ public class ManifestEffect extends OneShotEffect {
// zcc + 1 for use case with Rally the Ancestors (see related test)
MageObjectReference objectReference = new MageObjectReference(battlefieldCard.getId(), battlefieldCard.getZoneChangeCounter(game) + 1, game);
game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource);
game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, cloakNotManifest ? FaceDownType.CLOAKED : FaceDownType.MANIFESTED), newSource);
}
List<Permanent> manifested = new ArrayList<>();
// move cards to battlefield as face down
// TODO: possible buggy for multiple cards, see rule 701.34e - it require manifest one by one (card to check: Omarthis, Ghostfire Initiate)
manifestPlayer.moveCards(cardsToManifest, Zone.BATTLEFIELD, source, game, false, true, false, null);
@ -145,18 +157,25 @@ public class ManifestEffect extends OneShotEffect {
if (permanent != null) {
// TODO: permanent already has manifested status, so code can be deleted later
// TODO: add test with battlefield trigger/watcher (must not see normal card, must not see face down status without manifest)
permanent.setManifested(true);
if (cloakNotManifest) {
permanent.setCloaked(true);
} else {
permanent.setManifested(true);
}
manifested.add(permanent);
} else {
// TODO: looks buggy, card can't be moved to battlefield, but face down effect already active
// or it can be face down on another move to battlefield
}
}
return true;
return manifested;
}
private String setText() {
StringBuilder sb = new StringBuilder("manifest the top ");
StringBuilder sb = new StringBuilder();
sb.append(cloakNotManifest ? "cloak" : "manifest");
sb.append(" the top ");
if (isPlural) {
sb.append(CardUtil.numberToText(amount.toString())).append(" cards ");
} else {

View file

@ -40,7 +40,7 @@ public class ManifestTargetPlayerEffect extends OneShotEffect {
return false;
}
return ManifestEffect.doManifestCards(game, source, targetPlayer, targetPlayer.getLibrary().getTopCards(game, amount));
return !ManifestEffect.doManifestCards(game, source, targetPlayer, targetPlayer.getLibrary().getTopCards(game, amount)).isEmpty();
}
private String setText() {