Transform: all DFC can transform now

This commit is contained in:
Hans Mackowiak
2025-09-20 14:32:30 +02:00
parent ea293a46b1
commit 90bd0c73d0
8 changed files with 18 additions and 59 deletions

View File

@@ -168,21 +168,7 @@ public final class CardRules implements ICardCharacteristics {
} }
public boolean isTransformable() { public boolean isTransformable() {
if (CardSplitType.Transform == getSplitType()) { return CardSplitType.Transform == getSplitType() || CardSplitType.Modal == getSplitType();
return true;
}
if (CardSplitType.Modal != getSplitType()) {
return false;
}
for (ICardFace face : getAllFaces()) {
for (String spell : face.getAbilities()) {
if (spell.contains("AB$ SetState") && spell.contains("Mode$ Transform")) {
return true;
}
}
// TODO check keywords if needed
}
return false;
} }
public ICardFace getWSpecialize() { public ICardFace getWSpecialize() {

View File

@@ -156,7 +156,7 @@ public class PaperToken implements InventoryItemFromSet, IPaperCard {
return false; return false;
CardSplitType cst = this.cardRules.getSplitType(); CardSplitType cst = this.cardRules.getSplitType();
//expand this on future for other tokens that has other backsides besides transform.. //expand this on future for other tokens that has other backsides besides transform..
return cst == CardSplitType.Transform; return cst == CardSplitType.Transform || cst == CardSplitType.Modal;
} }
@Override @Override

View File

@@ -220,10 +220,6 @@ public class GameAction {
//copied.setGamePieceType(GamePieceType.COPIED_SPELL); //copied.setGamePieceType(GamePieceType.COPIED_SPELL);
} }
if (c.isTransformed()) {
copied.incrementTransformedTimestamp();
}
if (cause != null && cause.isSpell() && c.equals(cause.getHostCard())) { if (cause != null && cause.isSpell() && c.equals(cause.getHostCard())) {
copied.setCastSA(cause); copied.setCastSA(cause);
copied.setSplitStateToPlayAbility(cause); copied.setSplitStateToPlayAbility(cause);

View File

@@ -993,9 +993,6 @@ public final class GameActionUtil {
oldCard.setBackSide(false); oldCard.setBackSide(false);
oldCard.setState(oldCard.getFaceupCardStateName(), true); oldCard.setState(oldCard.getFaceupCardStateName(), true);
oldCard.unanimateBestow(); oldCard.unanimateBestow();
if (ability.isDisturb() || ability.hasParam("CastTransformed")) {
oldCard.undoIncrementTransformedTimestamp();
}
if (ability.hasParam("Prototype")) { if (ability.hasParam("Prototype")) {
oldCard.removeCloneState(oldCard.getPrototypeTimestamp()); oldCard.removeCloneState(oldCard.getPrototypeTimestamp());

View File

@@ -287,22 +287,17 @@ public class CopyPermanentEffect extends TokenEffectBase {
int id = newOwner == null ? 0 : newOwner.getGame().nextCardId(); int id = newOwner == null ? 0 : newOwner.getGame().nextCardId();
// need to create a physical card first, i need the original card faces // need to create a physical card first, i need the original card faces
copy = CardFactory.getCard(original.getPaperCard(), newOwner, id, host.getGame()); copy = CardFactory.getCard(original.getPaperCard(), newOwner, id, host.getGame());
copy.setStates(CardFactory.getCloneStates(original, copy, sa));
// force update the now set State
if (original.isTransformable()) { if (original.isTransformable()) {
copy.setState(original.isTransformed() ? CardStateName.Backside : CardStateName.Original, true, true);
// 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, // 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 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. // 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. // 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. // 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.
copy.setBackSide(original.isBackSide()); copy.setBackSide(original.isBackSide());
if (original.isTransformed()) {
copy.incrementTransformedTimestamp();
}
}
copy.setStates(CardFactory.getCloneStates(original, copy, sa));
// force update the now set State
if (original.isTransformable()) {
copy.setState(original.isTransformed() ? CardStateName.Backside : CardStateName.Original, true, true);
} else { } else {
copy.setState(copy.getCurrentStateName(), true, true); copy.setState(copy.getCurrentStateName(), true, true);
} }

View File

@@ -257,7 +257,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
private long worldTimestamp = -1; private long worldTimestamp = -1;
private long bestowTimestamp = -1; private long bestowTimestamp = -1;
private long transformedTimestamp = 0; private long transformedTimestamp = -1;
private long prototypeTimestamp = -1; private long prototypeTimestamp = -1;
private long mutatedTimestamp = -1; private long mutatedTimestamp = -1;
private int timesMutated = 0; private int timesMutated = 0;
@@ -425,8 +425,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
public long getPrototypeTimestamp() { return prototypeTimestamp; } public long getPrototypeTimestamp() { return prototypeTimestamp; }
public long getTransformedTimestamp() { return transformedTimestamp; } public long getTransformedTimestamp() { return transformedTimestamp; }
public void incrementTransformedTimestamp() { this.transformedTimestamp++; } public void setTransformedTimestamp(long ts) { this.transformedTimestamp = ts; }
public void undoIncrementTransformedTimestamp() { this.transformedTimestamp--; }
// The following methods are used to selectively update certain view components (text, // The following methods are used to selectively update certain view components (text,
// P/T, card types) in order to avoid card flickering due to aggressive full update // P/T, card types) in order to avoid card flickering due to aggressive full update
@@ -696,7 +695,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(this); final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(this);
getGame().getTriggerHandler().runTrigger(TriggerType.Transformed, runParams, false); getGame().getTriggerHandler().runTrigger(TriggerType.Transformed, runParams, false);
} }
incrementTransformedTimestamp(); setTransformedTimestamp(ts);
return retResult; return retResult;
} else if (mode.equals("Flip")) { } else if (mode.equals("Flip")) {
@@ -1070,7 +1069,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
} }
public final boolean isDoubleFaced() { public final boolean isDoubleFaced() {
return isTransformable() || isMeldable() || isModal(); return isTransformable() || isMeldable();
} }
public final boolean isFlipCard() { public final boolean isFlipCard() {
@@ -1132,7 +1131,10 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
} }
public final boolean isTransformed() { public final boolean isTransformed() {
return getTransformedTimestamp() != 0; if (isMeldable() || hasMergedCard()) {
return false;
}
return this.isTransformable() && isBackSide();
} }
public final boolean isFlipped() { public final boolean isFlipped() {
@@ -7638,9 +7640,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
if (sa.isBestow()) { if (sa.isBestow()) {
animateBestow(); animateBestow();
} }
if (sa.isDisturb() || sa.hasParam("CastTransformed")) {
incrementTransformedTimestamp();
}
if (sa.hasParam("Prototype") && prototypeTimestamp == -1) { if (sa.hasParam("Prototype") && prototypeTimestamp == -1) {
long next = game.getNextTimestamp(); long next = game.getNextTimestamp();
addCloneState(CardFactory.getCloneStates(this, this, sa), next); addCloneState(CardFactory.getCloneStates(this, this, sa), next);

View File

@@ -131,9 +131,7 @@ public class CardCopyService {
c.setState(in.getCurrentStateName(), false); c.setState(in.getCurrentStateName(), false);
c.setRules(in.getRules()); c.setRules(in.getRules());
if (in.isTransformed()) { c.setBackSide(in.isBackSide());
c.incrementTransformedTimestamp();
}
return c; return c;
} }
@@ -168,9 +166,6 @@ public class CardCopyService {
// The characteristics of its front and back face are determined by the copiable values of the same face of the spell it is a copy of, as modified by any other copy effects. // The characteristics of its front and back face are determined by the copiable values of the same face of the spell it is a copy of, as modified by any other copy effects.
// If the spell it is a copy of has its back face up, the copy is created with its back face up. The token thats put onto the battlefield as that spell resolves is a transforming token. // If the spell it is a copy of has its back face up, the copy is created with its back face up. The token thats put onto the battlefield as that spell resolves is a transforming token.
to.setBackSide(copyFrom.isBackSide()); to.setBackSide(copyFrom.isBackSide());
if (copyFrom.isTransformed()) {
to.incrementTransformedTimestamp();
}
} else if (fromIsTransformedCard) { } else if (fromIsTransformedCard) {
copyState(copyFrom, copyFrom.getCurrentStateName(), to, CardStateName.Original); copyState(copyFrom, copyFrom.getCurrentStateName(), to, CardStateName.Original);
} else { } else {
@@ -274,9 +269,6 @@ public class CardCopyService {
} }
newCopy.setFlipped(copyFrom.isFlipped()); newCopy.setFlipped(copyFrom.isFlipped());
newCopy.setBackSide(copyFrom.isBackSide()); newCopy.setBackSide(copyFrom.isBackSide());
if (copyFrom.isTransformed()) {
newCopy.incrementTransformedTimestamp();
}
if (newCopy.hasAlternateState()) { if (newCopy.hasAlternateState()) {
newCopy.setState(copyFrom.getCurrentStateName(), false, true); newCopy.setState(copyFrom.getCurrentStateName(), false, true);
} }

View File

@@ -87,22 +87,16 @@ public class CardFactory {
// need to create a physical card first, i need the original card faces // need to create a physical card first, i need the original card faces
final Card copy = getCard(original.getPaperCard(), controller, id, game); final Card copy = getCard(original.getPaperCard(), controller, id, game);
copy.setStates(getCloneStates(original, copy, sourceSA));
// force update the now set State
if (original.isTransformable()) { if (original.isTransformable()) {
copy.setState(original.isTransformed() ? CardStateName.Backside : CardStateName.Original, true, true);
// 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, // 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 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. // 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. // 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. // 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.
copy.setBackSide(original.isBackSide()); copy.setBackSide(original.isBackSide());
if (original.isTransformed()) {
copy.incrementTransformedTimestamp();
}
}
copy.setStates(getCloneStates(original, copy, sourceSA));
// force update the now set State
if (original.isTransformable()) {
copy.setState(original.isTransformed() ? CardStateName.Backside : CardStateName.Original, true, true);
} else { } else {
copy.setState(copy.getCurrentStateName(), true, true); copy.setState(copy.getCurrentStateName(), true, true);
} }