Modal double-faced cards - improved support with copy effects (fixed that copied token has abilities from both sides, closes #10146, closes #8476);

This commit is contained in:
Oleg Agafonov 2024-05-26 13:01:36 +04:00
parent 0e39d6a833
commit 6b86b1053f
3 changed files with 168 additions and 24 deletions

View file

@ -205,7 +205,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
}
// create token and modify all attributes permanently (without game usage)
Token token = CopyTokenFunction.createTokenCopy(copyFrom, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
Token token = CopyTokenFunction.createTokenCopy(copyFrom, game); // needed so that entersBattlefield triggered abilities see the attributes (e.g. Master Biomancer)
applier.apply(game, token, source, targetId);
if (becomesArtifact) {
token.addCardType(CardType.ARTIFACT);

View file

@ -43,32 +43,40 @@ public class CopyTokenFunction {
if (target == null) {
throw new IllegalArgumentException("Target can't be null");
}
// A copy contains only the attributes of the basic card or basic Token that's the base of the permanent
// else gained abililies would be copied too.
target.setEntersTransformed(source instanceof Permanent && ((Permanent) source).isTransformed());
MageObject sourceObj;
// from another token
// apply transformed status on ETB
target.setEntersTransformed(source instanceof Permanent && ((Permanent) source).isTransformed());
// 707.8a
// If an effect creates a token that is a copy of a transforming permanent or a transforming double-faced
// card not on the battlefield, the resulting token is a transforming token that has both a front face
// and a back face. The characteristics of each face are determined by the copiable values of the same
// face of the permanent it is a copy of, as modified by any other copy effects that apply to that permanent.
// If the token is a copy of a transforming permanent with its back face up, the token enters the battlefield
// with its back face up. This rule does not apply to tokens that are created with their own set of
// characteristics and enter the battlefield as a copy of a transforming permanent due to a replacement effect.
// from token permanent
if (source instanceof PermanentToken) {
// create token from another token
Token sourceToken = ((PermanentToken) source).getToken();
sourceObj = sourceToken;
target.setCopySourceCard(((PermanentToken) source).getToken().getCopySourceCard());
Token sourceObj = ((PermanentToken) source).getToken();
target.setCopySourceCard(sourceObj.getCopySourceCard()); // must link with original card
// main side
copyToToken(target, sourceObj, game);
CardUtil.copySetAndCardNumber(target, source);
if (sourceToken.getBackFace() != null) {
copyToToken(target.getBackFace(), sourceToken.getBackFace(), game);
CardUtil.copySetAndCardNumber(target.getBackFace(), sourceToken.getBackFace());
// second side
if (sourceObj.getBackFace() != null) {
copyToToken(target.getBackFace(), sourceObj.getBackFace(), game);
CardUtil.copySetAndCardNumber(target.getBackFace(), sourceObj.getBackFace());
}
return;
}
// from a permanent
// from non-token permanent
if (source instanceof PermanentCard) {
// create token from non-token permanent
// face down must hide all info
// apply face down status
PermanentCard sourcePermanent = (PermanentCard) source;
BecomesFaceDownCreatureEffect.FaceDownType faceDownType = BecomesFaceDownCreatureEffect.findFaceDownType(game, sourcePermanent);
if (faceDownType != null) {
@ -76,15 +84,18 @@ public class CopyTokenFunction {
return;
}
sourceObj = source.getMainCard();
target.setCopySourceCard((Card) sourceObj);
Card sourceObj = source.getMainCard();
target.setCopySourceCard(sourceObj);
// main side
copyToToken(target, sourceObj, game);
CardUtil.copySetAndCardNumber(target, sourceObj);
if (((Card) sourceObj).isTransformable()) {
copyToToken(target.getBackFace(), ((Card) sourceObj).getSecondCardFace(), game);
CardUtil.copySetAndCardNumber(target.getBackFace(), ((Card) sourceObj).getSecondCardFace());
// second side
if (sourceObj.isTransformable()) {
copyToToken(target.getBackFace(), sourceObj.getSecondCardFace(), game);
CardUtil.copySetAndCardNumber(target.getBackFace(), sourceObj.getSecondCardFace());
}
// apply prototyped status
if (((PermanentCard) source).isPrototyped()){
Abilities<Ability> abilities = source.getAbilities();
for (Ability ability : abilities){
@ -96,12 +107,13 @@ public class CopyTokenFunction {
return;
}
// from another object like card (example: Embalm ability)
sourceObj = source;
// from another card (example: Embalm ability)
Card sourceObj = CardUtil.getDefaultCardSideForBattlefield(game, source.getMainCard());
target.setCopySourceCard(source);
// main side
copyToToken(target, sourceObj, game);
CardUtil.copySetAndCardNumber(target, sourceObj);
// second side
if (source.isTransformable()) {
if (target.getBackFace() == null) {
// if you catch this then a weird use case here: card with single face copy another token with double face??