Implement DFC tokens for Incubate (#10231)

* remove incubate skip

* initial implementation of DFC tokens

* separate incubator back face to separate class

* small refactor to token copy function

* token copies now have back faces as well

* effects which modify token copies now correctly apply to both faces

* add skip for exception

* tokens now enter transformed correctly

* [MOC] remove skip for incubate

* fix verify failure
This commit is contained in:
Evan Kranzler 2023-04-27 11:03:25 -04:00 committed by GitHub
parent f8d23ff56b
commit 726e289646
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 540 additions and 156 deletions

View file

@ -246,6 +246,10 @@ public interface MageObject extends MageItem, Serializable, Copyable<MageObject>
getSuperType().add(superType);
}
default void removeSuperType(SuperType superType) {
getSuperType().remove(superType);
}
default boolean isBasic() {
return getSuperType().contains(SuperType.BASIC);
}

View file

@ -17,12 +17,12 @@ import mage.constants.*;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.EmptyToken;
import mage.game.permanent.token.Token;
import mage.target.targetpointer.FixedTarget;
import mage.target.targetpointer.FixedTargets;
import mage.util.CardUtil;
import mage.util.functions.CopyApplier;
import mage.util.functions.CopyTokenFunction;
import mage.util.functions.EmptyCopyApplier;
import java.util.*;
@ -200,14 +200,13 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
}
// create token and modify all attributes permanently (without game usage)
EmptyToken token = new EmptyToken();
CardUtil.copyTo(token).from(copyFrom, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
Token token = CopyTokenFunction.createTokenCopy(copyFrom, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
applier.apply(game, token, source, targetId);
if (becomesArtifact) {
token.addCardType(CardType.ARTIFACT);
}
if (isntLegendary) {
token.getSuperType().remove(SuperType.LEGENDARY);
token.removeSuperType(SuperType.LEGENDARY);
}
if (startingLoyalty != -1) {
@ -238,7 +237,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
token.addSubType(additionalSubType);
}
if (color != null) {
token.getColor().setColor(color);
token.setColor(color);
}
additionalAbilities.stream().forEach(token::addAbility);
if (permanentModifier != null) {

View file

@ -13,9 +13,9 @@ import mage.constants.TimingRule;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.token.EmptyToken;
import mage.game.permanent.token.Token;
import mage.players.Player;
import mage.util.CardUtil;
import mage.util.functions.CopyTokenFunction;
import java.util.stream.Collectors;
@ -87,11 +87,10 @@ class EmbalmEffect extends OneShotEffect {
}
// create token and modify all attributes permanently (without game usage)
EmptyToken token = new EmptyToken();
CardUtil.copyTo(token).from(card, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
token.getColor().setColor(ObjectColor.WHITE);
Token token = CopyTokenFunction.createTokenCopy(card, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
token.setColor(ObjectColor.WHITE);
token.addSubType(SubType.ZOMBIE);
token.getManaCost().clear();
token.clearManaCost();
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.EMBALMED_CREATURE, token.getId(), source, controller.getId()));
token.putOntoBattlefield(1, game, source, controller.getId(), false, false, null);
// Probably it makes sense to remove also the Embalm ability (it's not shown on the token cards).

View file

@ -17,9 +17,9 @@ import mage.constants.TimingRule;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.EmptyToken;
import mage.game.permanent.token.Token;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import mage.util.functions.CopyTokenFunction;
import java.util.HashSet;
import java.util.Iterator;
@ -85,8 +85,7 @@ class EncoreEffect extends OneShotEffect {
if (card == null) {
return false;
}
EmptyToken token = new EmptyToken();
CardUtil.copyTo(token).from(card, game);
Token token = CopyTokenFunction.createTokenCopy(card, game);
Set<MageObjectReference> addedTokens = new HashSet<>();
int opponentCount = OpponentsCount.instance.calculate(game, source, this);
if (opponentCount < 1) {

View file

@ -13,9 +13,9 @@ import mage.constants.TimingRule;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.token.EmptyToken;
import mage.game.permanent.token.Token;
import mage.players.Player;
import mage.util.CardUtil;
import mage.util.functions.CopyTokenFunction;
import java.util.stream.Collectors;
@ -91,11 +91,10 @@ class EternalizeEffect extends OneShotEffect {
}
// create token and modify all attributes permanently (without game usage)
EmptyToken token = new EmptyToken();
CardUtil.copyTo(token).from(card, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
token.getColor().setColor(ObjectColor.BLACK);
Token token = CopyTokenFunction.createTokenCopy(card, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
token.setColor(ObjectColor.BLACK);
token.addSubType(SubType.ZOMBIE);
token.getManaCost().clear();
token.clearManaCost();
token.removePTCDA();
token.setPower(4);
token.setToughness(4);

View file

@ -1,5 +1,6 @@
package mage.abilities.keyword;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.SimpleStaticAbility;
@ -9,6 +10,7 @@ import mage.constants.*;
import mage.game.Game;
import mage.game.MageObjectAttribute;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import mage.game.stack.Spell;
import mage.util.CardUtil;
@ -38,7 +40,7 @@ public class TransformAbility extends SimpleStaticAbility {
return "";
}
public static void transformPermanent(Permanent permanent, Card sourceCard, Game game, Ability source) {
public static void transformPermanent(Permanent permanent, MageObject sourceCard, Game game, Ability source) {
if (sourceCard == null) {
return;
}
@ -58,9 +60,10 @@ public class TransformAbility extends SimpleStaticAbility {
for (SuperType type : sourceCard.getSuperType()) {
permanent.addSuperType(type);
}
if (sourceCard instanceof Card) {
permanent.setExpansionSetCode(((Card) sourceCard).getExpansionSetCode());
}
CardUtil.copySetAndCardNumber(permanent, sourceCard);
permanent.getAbilities().clear();
for (Ability ability : sourceCard.getAbilities()) {
// source == null -- call from init card (e.g. own abilities)
@ -144,7 +147,12 @@ class TransformEffect extends ContinuousEffectImpl {
return true;
}
Card card = permanent.getSecondCardFace();
MageObject card;
if (permanent instanceof PermanentToken) {
card = ((PermanentToken) permanent).getToken().getBackFace();
} else {
card = permanent.getSecondCardFace();
}
if (card == null) {
return false;

View file

@ -18,11 +18,10 @@ import mage.constants.TimingRule;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.command.Emblem;
import mage.game.permanent.token.EmptyToken;
import mage.game.permanent.token.Token;
import mage.game.permanent.token.custom.CreatureToken;
import mage.util.CardUtil;
import mage.util.RandomUtil;
import mage.util.functions.CopyTokenFunction;
import java.util.List;
@ -79,7 +78,7 @@ class MomirEffect extends OneShotEffect {
}
// search for a random non custom set creature
EmptyToken token = null;
Token token = null;
while (!options.isEmpty()) {
int index = RandomUtil.nextInt(options.size());
ExpansionSet expansionSet = Sets.findSet(options.get(index).getSetCode());
@ -88,8 +87,7 @@ class MomirEffect extends OneShotEffect {
} else {
Card card = options.get(index).getCard();
if (card != null) {
token = new EmptyToken();
CardUtil.copyTo(token).from(card, game);
token = CopyTokenFunction.createTokenCopy(card, game);
break;
} else {
options.remove(index);

View file

@ -609,7 +609,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
return true;
}
private Card getOtherFace() {
protected MageObject getOtherFace() {
return transformed ? this.getMainCard() : this.getMainCard().getSecondCardFace();
}

View file

@ -5,6 +5,7 @@ import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.keyword.ChangelingAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.constants.EmptyNames;
import mage.game.Game;
@ -28,6 +29,9 @@ public class PermanentToken extends PermanentImpl {
this.power = new MageInt(token.getPower().getModifiedBaseValue());
this.toughness = new MageInt(token.getToughness().getModifiedBaseValue());
this.copyFromToken(this.token, game, false); // needed to have at this time (e.g. for subtypes for entersTheBattlefield replacement effects)
if (this.token.isEntersTransformed()) {
TransformAbility.transformPermanent(this, this.token.getBackFace(), game, null);
}
// token's ZCC must be synced with original token to keep abilities settings
// Example: kicker ability and kicked status
@ -50,6 +54,14 @@ public class PermanentToken extends PermanentImpl {
this.toughness.resetToBaseValue();
}
@Override
public int getManaValue() {
if (this.isTransformed()) {
return token.getManaValue();
}
return super.getManaValue();
}
@Override
public String getName() {
if (name.isEmpty()) {
@ -121,6 +133,16 @@ public class PermanentToken extends PermanentImpl {
return this;
}
@Override
public boolean isTransformable() {
return token.getBackFace() != null;
}
@Override
protected MageObject getOtherFace() {
return this.transformed ? token : this.token.getBackFace();
}
@Override
public String getCardNumber() {
return token.getOriginalCardNumber();

View file

@ -1,4 +1,3 @@
package mage.game.permanent.token;
/**
@ -7,7 +6,14 @@ package mage.game.permanent.token;
public final class EmptyToken extends TokenImpl {
public EmptyToken() {
this(false);
}
public EmptyToken(boolean withBackFace) {
super(" Token", "");
if (withBackFace) {
this.backFace = new EmptyToken();
}
}
public EmptyToken(final EmptyToken token) {

View file

@ -1,5 +1,9 @@
package mage.game.permanent.token;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.constants.CardType;
import mage.constants.SubType;
@ -14,9 +18,12 @@ public final class IncubatorToken extends TokenImpl {
super("Incubator Token", "Incubator artifact token with \"{2}: Transform this artifact.\"");
cardType.add(CardType.ARTIFACT);
subtype.add(SubType.INCUBATOR);
this.backFace = new Phyrexian00Token();
// TODO: Implement this correctly
this.addAbility(new TransformAbility());
this.addAbility(new SimpleActivatedAbility(
new TransformSourceEffect().setText("transform this artifact"), new GenericManaCost(2)
));
availableImageSetCodes = Arrays.asList("MOM");
}

View file

@ -0,0 +1,33 @@
package mage.game.permanent.token;
import mage.MageInt;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.Arrays;
/**
* @author TheElk801
*/
public class Phyrexian00Token extends TokenImpl {
Phyrexian00Token() {
super("Phyrexian Token", "0/0 Phyrexian artifact creature token");
cardType.add(CardType.ARTIFACT);
cardType.add(CardType.CREATURE);
subtype.add(SubType.PHYREXIAN);
power = new MageInt(0);
toughness = new MageInt(0);
availableImageSetCodes = Arrays.asList("MOM");
}
public Phyrexian00Token(final Phyrexian00Token token) {
super(token);
}
public Phyrexian00Token copy() {
return new Phyrexian00Token(this);
}
}

View file

@ -2,6 +2,7 @@
package mage.game.permanent.token;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.cards.Card;
import mage.game.Game;
@ -58,4 +59,14 @@ public interface Token extends MageObject {
void setCopySourceCard(Card copySourceCard);
void setExpansionSetCodeForImage(String code);
Token getBackFace();
void setColor(ObjectColor color);
void clearManaCost();
void setEntersTransformed(boolean entersTransformed);
boolean isEntersTransformed();
}

View file

@ -3,6 +3,7 @@ package mage.game.permanent.token;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectImpl;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.effects.Effect;
@ -12,9 +13,7 @@ import mage.cards.Card;
import mage.cards.repository.TokenInfo;
import mage.cards.repository.TokenRepository;
import mage.cards.repository.TokenType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.constants.*;
import mage.game.Game;
import mage.game.command.CommandObject;
import mage.game.events.CreateTokenEvent;
@ -45,21 +44,8 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
// list of set codes token images are available for
protected List<String> availableImageSetCodes = new ArrayList<>(); // TODO: delete
public enum Type {
FIRST(1),
SECOND(2);
int code;
Type(int code) {
this.code = code;
}
int getCode() {
return this.code;
}
}
protected Token backFace = null;
private boolean entersTransformed = false;
public TokenImpl() {
}
@ -69,7 +55,7 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
this.description = description;
}
public TokenImpl(final TokenImpl token) {
protected TokenImpl(final TokenImpl token) {
super(token);
this.description = token.description;
this.tokenType = token.tokenType;
@ -78,6 +64,8 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
this.originalExpansionSetCode = token.originalExpansionSetCode;
this.copySourceCard = token.copySourceCard; // will never be changed
this.availableImageSetCodes = token.availableImageSetCodes;
this.backFace = token.backFace != null ? token.backFace.copy() : null;
this.entersTransformed = token.entersTransformed;
}
@Override
@ -98,11 +86,17 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
ability.setSourceId(this.getId());
abilities.add(ability);
abilities.addAll(ability.getSubAbilities());
if (backFace != null) {
backFace.addAbility(ability);
}
}
// Directly from PermanentImpl
@Override
public void removeAbility(Ability abilityToRemove) {
if (backFace != null) {
backFace.removeAbility(abilityToRemove);
}
if (abilityToRemove == null) {
return;
}
@ -127,6 +121,9 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
}
abilitiesToRemove.forEach(a -> removeAbility(a));
if (backFace != null) {
backFace.removeAbilities(abilitiesToRemove);
}
}
@Override
@ -389,11 +386,17 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
@Override
public void setPower(int power) {
if (this.backFace != null) {
this.backFace.setPower(power);
}
this.power = new MageInt(power);
}
@Override
public void setToughness(int toughness) {
if (this.backFace != null) {
this.backFace.setToughness(toughness);
}
this.toughness = new MageInt(toughness);
}
@ -426,6 +429,21 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
return originalExpansionSetCode;
}
@Override
public void setStartingLoyalty(int startingLoyalty) {
if (backFace != null) {
backFace.setStartingLoyalty(startingLoyalty);
}
super.setStartingLoyalty(startingLoyalty);
}
public void setStartingDefense(int intArg) {
if (backFace != null) {
backFace.setStartingDefense(intArg);
}
super.setStartingDefense(intArg);
}
@Override
public void setOriginalExpansionSetCode(String originalExpansionSetCode) {
// TODO: delete
@ -451,4 +469,167 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
// TODO: delete
setOriginalExpansionSetCode(code);
}
@Override
public Token getBackFace() {
return backFace;
}
public void retainAllArtifactSubTypes(Game game) {
if (backFace != null) {
backFace.retainAllArtifactSubTypes(game);
}
super.retainAllArtifactSubTypes(game);
}
public void retainAllEnchantmentSubTypes(Game game) {
if (backFace != null) {
backFace.retainAllEnchantmentSubTypes(game);
}
super.retainAllEnchantmentSubTypes(game);
}
public void addSuperType(SuperType superType) {
if (backFace != null) {
backFace.addSuperType(superType);
}
super.addSuperType(superType);
}
public void removeSuperType(SuperType superType) {
if (backFace != null) {
backFace.removeSuperType(superType);
}
super.removeSuperType(superType);
}
public void addCardType(CardType... cardTypes) {
if (backFace != null) {
backFace.addCardType(cardTypes);
}
super.addCardType(cardTypes);
}
public void removeCardType(CardType... cardTypes) {
if (backFace != null) {
backFace.removeCardType(cardTypes);
}
super.removeCardType(cardTypes);
}
public void removeAllCardTypes() {
if (backFace != null) {
backFace.removeAllCardTypes();
}
super.removeAllCardTypes();
}
public void removeAllCardTypes(Game game) {
if (backFace != null) {
backFace.removeAllCardTypes(game);
}
super.removeAllCardTypes(game);
}
public void addSubType(SubType... subTypes) {
if (backFace != null) {
backFace.addSubType(subTypes);
}
super.addSubType(subTypes);
}
public void removeAllSubTypes(Game game, SubTypeSet subTypeSet) {
if (backFace != null) {
backFace.removeAllSubTypes(game, subTypeSet);
}
super.removeAllSubTypes(game, subTypeSet);
}
public void removeAllSubTypes(Game game) {
if (backFace != null) {
backFace.removeAllSubTypes(game);
}
super.removeAllSubTypes(game);
}
public void retainAllLandSubTypes(Game game) {
if (backFace != null) {
backFace.retainAllLandSubTypes(game);
}
super.retainAllLandSubTypes(game);
}
public void removeAllCreatureTypes(Game game) {
if (backFace != null) {
backFace.removeAllCreatureTypes(game);
}
super.removeAllCreatureTypes(game);
}
public void removeAllCreatureTypes() {
if (backFace != null) {
backFace.removeAllCreatureTypes();
}
super.removeAllCreatureTypes();
}
public void removeSubType(Game game, SubType subType) {
if (backFace != null) {
backFace.removeSubType(game, subType);
}
super.removeSubType(game, subType);
}
public void setIsAllCreatureTypes(boolean value) {
if (backFace != null) {
backFace.setIsAllCreatureTypes(value);
}
super.setIsAllCreatureTypes(value);
}
public void removePTCDA() {
if (backFace != null) {
backFace.removePTCDA();
}
super.removePTCDA();
}
public String getName() {
if (backFace != null) {
backFace.getName();
}
return super.getName();
}
public void setName(String name) {
if (backFace != null) {
backFace.setName(name);
}
super.setName(name);
}
public void setColor(ObjectColor color) {
if (backFace != null) {
backFace.setColor(color);
}
this.getColor().setColor(color);
}
@Override
public void clearManaCost() {
if (backFace != null) {
backFace.clearManaCost();
}
this.getManaCost().clear();
}
@Override
public void setEntersTransformed(boolean entersTransformed) {
this.entersTransformed = entersTransformed;
}
@Override
public boolean isEntersTransformed() {
return this.entersTransformed && this.backFace != null;
}
}

View file

@ -25,12 +25,13 @@ import mage.game.events.CopiedStackObjectEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import mage.game.permanent.token.EmptyToken;
import mage.game.permanent.token.Token;
import mage.players.Player;
import mage.util.CardUtil;
import mage.util.GameLog;
import mage.util.ManaUtil;
import mage.util.SubTypes;
import mage.util.functions.CopyTokenFunction;
import mage.util.functions.StackObjectCopyApplier;
import org.apache.log4j.Logger;
@ -275,8 +276,7 @@ public class Spell extends StackObjectImpl implements Card {
UUID permId;
boolean flag;
if (isCopy()) {
EmptyToken token = new EmptyToken();
CardUtil.copyTo(token).from(card, game, this);
Token token = CopyTokenFunction.createTokenCopy(card, game, this);
// The token that a resolving copy of a spell becomes isnt said to have been created. (2020-09-25)
if (token.putOntoBattlefield(1, game, ability, getControllerId(), false, false, null, false)) {
permId = token.getLastAddedTokenIds().stream().findFirst().orElse(null);
@ -343,8 +343,7 @@ public class Spell extends StackObjectImpl implements Card {
return false;
}
} else if (isCopy()) {
EmptyToken token = new EmptyToken();
CardUtil.copyTo(token).from(card, game, this);
Token token = CopyTokenFunction.createTokenCopy(card, game, this);
// The token that a resolving copy of a spell becomes isnt said to have been created. (2020-09-25)
token.putOntoBattlefield(1, game, ability, getControllerId(), false, false, null, false);
return true;

View file

@ -42,7 +42,6 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.TargetCard;
import mage.target.targetpointer.FixedTarget;
import mage.util.functions.CopyTokenFunction;
import org.apache.log4j.Logger;
import java.io.UnsupportedEncodingException;
@ -474,17 +473,6 @@ public final class CardUtil {
spellAbility.getManaCostsToPay().addAll(adjustedCost);
}
/**
* Returns function that copies params\abilities from one card to
* {@link Token}.
*
* @param target
* @return
*/
public static CopyTokenFunction copyTo(Token target) {
return new CopyTokenFunction(target);
}
/**
* Converts an integer number to string Numbers > 20 will be returned as
* digits
@ -1821,6 +1809,9 @@ public final class CardUtil {
needSetCode = ((Card) copyFromObject).getExpansionSetCode();
needCardNumber = ((Card) copyFromObject).getCardNumber();
needTokenType = 0;
} else if (copyFromObject instanceof Token) {
// TODO: make this work
return;
} else {
throw new IllegalStateException("Unsupported copyFromObject class: " + copyFromObject.getClass().getSimpleName());
}

View file

@ -7,64 +7,95 @@ import mage.cards.Card;
import mage.constants.CardType;
import mage.constants.SuperType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import mage.game.permanent.PermanentToken;
import mage.game.permanent.token.EmptyToken;
import mage.game.permanent.token.Token;
import mage.game.stack.Spell;
/**
* @author nantuko
*/
public class CopyTokenFunction implements Function<Token, Card> {
public class CopyTokenFunction {
protected Token target;
protected final Token target;
public CopyTokenFunction(Token target) {
private CopyTokenFunction(Token target) {
if (target == null) {
throw new IllegalArgumentException("Target can't be null");
}
this.target = target;
}
@Override
public Token apply(Card source, Game game) {
public static Token createTokenCopy(Card source, Game game) {
return createTokenCopy(source, game, null);
}
public static Token createTokenCopy(Card source, Game game, Spell spell) {
return new CopyTokenFunction(new EmptyToken(source.isTransformable())).from(source, game, spell);
}
public void apply(Card source, Game game) {
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.
MageObject sourceObj = source;
target.setEntersTransformed(source instanceof Permanent && ((Permanent) source).isTransformed());
MageObject sourceObj;
if (source instanceof PermanentToken) {
// create token from another token
sourceObj = ((PermanentToken) source).getToken();
Token sourceToken = ((PermanentToken) source).getToken();
sourceObj = sourceToken;
copyToToken(target, sourceObj, game);
if (sourceToken.getBackFace() != null) {
target.getBackFace().setOriginalExpansionSetCode(sourceToken.getOriginalExpansionSetCode());
target.getBackFace().setOriginalCardNumber(sourceToken.getOriginalCardNumber());
target.getBackFace().setCopySourceCard(sourceToken.getBackFace().getCopySourceCard());
copyToToken(target.getBackFace(), sourceToken.getBackFace(), game);
}
// to show the source image, the original values have to be used
target.setOriginalExpansionSetCode(((Token) sourceObj).getOriginalExpansionSetCode());
target.setOriginalCardNumber(((Token) sourceObj).getOriginalCardNumber());
target.setOriginalExpansionSetCode(sourceToken.getOriginalExpansionSetCode());
target.setOriginalCardNumber(sourceToken.getOriginalCardNumber());
target.setCopySourceCard(((PermanentToken) source).getToken().getCopySourceCard());
} else if (source instanceof PermanentCard) {
return;
}
if (source instanceof PermanentCard) {
// create token from non-token permanent
if (((PermanentCard) source).isMorphed() || ((PermanentCard) source).isManifested()) {
MorphAbility.setPermanentToFaceDownCreature(target, game);
return target;
} else {
if (((PermanentCard) source).isTransformed() && source.getSecondCardFace() != null) {
sourceObj = ((PermanentCard) source).getSecondCardFace();
} else {
sourceObj = ((PermanentCard) source).getCard();
}
target.setOriginalExpansionSetCode(source.getExpansionSetCode());
target.setOriginalCardNumber(source.getCardNumber());
target.setCopySourceCard((Card) sourceObj);
return;
}
} else {
// create token from non-permanent object like card (example: Embalm ability)
sourceObj = ((PermanentCard) source).getMainCard();
copyToToken(target, sourceObj, game);
if (((Card) sourceObj).isTransformable()) {
target.getBackFace().setOriginalExpansionSetCode(source.getExpansionSetCode());
target.getBackFace().setOriginalCardNumber(source.getCardNumber());
target.getBackFace().setCopySourceCard(((Card) sourceObj).getSecondCardFace());
copyToToken(target.getBackFace(), ((Card) sourceObj).getSecondCardFace(), game);
}
target.setOriginalExpansionSetCode(source.getExpansionSetCode());
target.setOriginalCardNumber(source.getCardNumber());
target.setCopySourceCard(source);
target.setCopySourceCard((Card) sourceObj);
return;
}
sourceObj = source;
copyToToken(target, sourceObj, game);
if (source.isTransformable()) {
target.getBackFace().setOriginalExpansionSetCode(source.getExpansionSetCode());
target.getBackFace().setOriginalCardNumber(source.getCardNumber());
target.getBackFace().setCopySourceCard(source.getSecondCardFace());
copyToToken(target.getBackFace(), source.getSecondCardFace(), game);
}
// create token from non-permanent object like card (example: Embalm ability)
target.setOriginalExpansionSetCode(source.getExpansionSetCode());
target.setOriginalCardNumber(source.getCardNumber());
target.setCopySourceCard(source);
}
private static Token copyToToken(Token target, MageObject sourceObj, Game game) {
// modify all attributes permanently (without game usage)
target.setName(sourceObj.getName());
target.getColor().setColor(sourceObj.getColor());
@ -101,11 +132,7 @@ public class CopyTokenFunction implements Function<Token, Card> {
return target;
}
public Token from(Card source, Game game) {
return from(source, game, null);
}
public Token from(Card source, Game game, Spell spell) {
private Token from(Card source, Game game, Spell spell) {
apply(source, game);
// token's ZCC must be synced with original card to keep abilities settings

View file

@ -1,11 +0,0 @@
package mage.util.functions;
import mage.game.Game;
/**
* @author nantuko
*/
@FunctionalInterface
public interface Function<X, Y> {
X apply(Y in, Game game);
}