diff --git a/forge-core/src/main/java/forge/card/CardRules.java b/forge-core/src/main/java/forge/card/CardRules.java index 4e1b6de6b48..2a9bb30ba4b 100644 --- a/forge-core/src/main/java/forge/card/CardRules.java +++ b/forge-core/src/main/java/forge/card/CardRules.java @@ -168,21 +168,7 @@ public final class CardRules implements ICardCharacteristics { } public boolean isTransformable() { - if (CardSplitType.Transform == 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; + return CardSplitType.Transform == getSplitType() || CardSplitType.Modal == getSplitType(); } public ICardFace getWSpecialize() { diff --git a/forge-core/src/main/java/forge/item/PaperToken.java b/forge-core/src/main/java/forge/item/PaperToken.java index 76f94634093..f60c5befe5c 100644 --- a/forge-core/src/main/java/forge/item/PaperToken.java +++ b/forge-core/src/main/java/forge/item/PaperToken.java @@ -156,7 +156,7 @@ public class PaperToken implements InventoryItemFromSet, IPaperCard { return false; CardSplitType cst = this.cardRules.getSplitType(); //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 diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index efae785c646..b759be95564 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -220,10 +220,6 @@ public class GameAction { //copied.setGamePieceType(GamePieceType.COPIED_SPELL); } - if (c.isTransformed()) { - copied.incrementTransformedTimestamp(); - } - if (cause != null && cause.isSpell() && c.equals(cause.getHostCard())) { copied.setCastSA(cause); copied.setSplitStateToPlayAbility(cause); diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index b5a8fe681e1..b7e2ec6d469 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -993,9 +993,6 @@ public final class GameActionUtil { oldCard.setBackSide(false); oldCard.setState(oldCard.getFaceupCardStateName(), true); oldCard.unanimateBestow(); - if (ability.isDisturb() || ability.hasParam("CastTransformed")) { - oldCard.undoIncrementTransformedTimestamp(); - } if (ability.hasParam("Prototype")) { oldCard.removeCloneState(oldCard.getPrototypeTimestamp()); diff --git a/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java index 7345e824bb1..771909901ab 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java @@ -287,22 +287,17 @@ public class CopyPermanentEffect extends TokenEffectBase { int id = newOwner == null ? 0 : newOwner.getGame().nextCardId(); // need to create a physical card first, i need the original card faces 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()) { + 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, // 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. 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 { copy.setState(copy.getCurrentStateName(), true, true); } diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 3264e0ee5ae..246b405263b 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -257,7 +257,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr private long worldTimestamp = -1; private long bestowTimestamp = -1; - private long transformedTimestamp = 0; + private long transformedTimestamp = -1; private long prototypeTimestamp = -1; private long mutatedTimestamp = -1; private int timesMutated = 0; @@ -425,8 +425,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr public long getPrototypeTimestamp() { return prototypeTimestamp; } public long getTransformedTimestamp() { return transformedTimestamp; } - public void incrementTransformedTimestamp() { this.transformedTimestamp++; } - public void undoIncrementTransformedTimestamp() { this.transformedTimestamp--; } + public void setTransformedTimestamp(long ts) { this.transformedTimestamp = ts; } // 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 @@ -696,7 +695,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr final Map runParams = AbilityKey.mapFromCard(this); getGame().getTriggerHandler().runTrigger(TriggerType.Transformed, runParams, false); } - incrementTransformedTimestamp(); + setTransformedTimestamp(ts); return retResult; } else if (mode.equals("Flip")) { @@ -1070,7 +1069,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr } public final boolean isDoubleFaced() { - return isTransformable() || isMeldable() || isModal(); + return isTransformable() || isMeldable(); } public final boolean isFlipCard() { @@ -1132,7 +1131,10 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr } public final boolean isTransformed() { - return getTransformedTimestamp() != 0; + if (isMeldable() || hasMergedCard()) { + return false; + } + return this.isTransformable() && isBackSide(); } public final boolean isFlipped() { @@ -7638,9 +7640,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr if (sa.isBestow()) { animateBestow(); } - if (sa.isDisturb() || sa.hasParam("CastTransformed")) { - incrementTransformedTimestamp(); - } if (sa.hasParam("Prototype") && prototypeTimestamp == -1) { long next = game.getNextTimestamp(); addCloneState(CardFactory.getCloneStates(this, this, sa), next); diff --git a/forge-game/src/main/java/forge/game/card/CardCopyService.java b/forge-game/src/main/java/forge/game/card/CardCopyService.java index 3cd81c703ce..ebf6c3a6009 100644 --- a/forge-game/src/main/java/forge/game/card/CardCopyService.java +++ b/forge-game/src/main/java/forge/game/card/CardCopyService.java @@ -131,9 +131,7 @@ public class CardCopyService { c.setState(in.getCurrentStateName(), false); c.setRules(in.getRules()); - if (in.isTransformed()) { - c.incrementTransformedTimestamp(); - } + c.setBackSide(in.isBackSide()); 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. // If the spell it is a copy of has its back face up, the copy is created with its back face up. The token that’s put onto the battlefield as that spell resolves is a transforming token. to.setBackSide(copyFrom.isBackSide()); - if (copyFrom.isTransformed()) { - to.incrementTransformedTimestamp(); - } } else if (fromIsTransformedCard) { copyState(copyFrom, copyFrom.getCurrentStateName(), to, CardStateName.Original); } else { @@ -274,9 +269,6 @@ public class CardCopyService { } newCopy.setFlipped(copyFrom.isFlipped()); newCopy.setBackSide(copyFrom.isBackSide()); - if (copyFrom.isTransformed()) { - newCopy.incrementTransformedTimestamp(); - } if (newCopy.hasAlternateState()) { newCopy.setState(copyFrom.getCurrentStateName(), false, true); } diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index c902781cfaa..690b1535942 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -87,22 +87,16 @@ public class CardFactory { // need to create a physical card first, i need the original card faces final Card copy = getCard(original.getPaperCard(), controller, id, game); + 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); // 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. 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 { copy.setState(copy.getCurrentStateName(), true, true); }