mirror of
https://github.com/correl/mage.git
synced 2025-01-15 19:13:24 +00:00
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:
parent
f8d23ff56b
commit
726e289646
30 changed files with 540 additions and 156 deletions
Mage.Sets/src/mage
cards
b
e
g
h
m
p
s
sets
Mage.Tests/src/test/java/org/mage/test/cards/copy
Mage/src/main/java/mage
MageObject.java
abilities
effects/common
keyword
game
util
|
@ -55,7 +55,7 @@ public final class BrimazBlightOfOreskos extends CardImpl {
|
||||||
|
|
||||||
// At the beginning of each end step, if a Phyrexian died under your control this turn, proliferate.
|
// At the beginning of each end step, if a Phyrexian died under your control this turn, proliferate.
|
||||||
this.addAbility(new BeginningOfEndStepTriggeredAbility(
|
this.addAbility(new BeginningOfEndStepTriggeredAbility(
|
||||||
new ProliferateEffect(), TargetController.ANY,
|
new ProliferateEffect(false), TargetController.ANY,
|
||||||
BrimazBlightOfOreskosCondition.instance, false
|
BrimazBlightOfOreskosCondition.instance, false
|
||||||
), new BrimazBlightOfOreskosWatcher());
|
), new BrimazBlightOfOreskosWatcher());
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,11 @@ import mage.game.Game;
|
||||||
import mage.game.events.CreateTokenEvent;
|
import mage.game.events.CreateTokenEvent;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
|
||||||
import mage.game.permanent.token.Token;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.util.CardUtil;
|
|
||||||
import mage.util.functions.CopyApplier;
|
import mage.util.functions.CopyApplier;
|
||||||
|
import mage.util.functions.CopyTokenFunction;
|
||||||
import mage.util.functions.EmptyCopyApplier;
|
import mage.util.functions.EmptyCopyApplier;
|
||||||
import mage.watchers.Watcher;
|
import mage.watchers.Watcher;
|
||||||
|
|
||||||
|
@ -145,8 +144,7 @@ class EsixFractalBloomEffect extends ReplacementEffectImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create token and modify all attributes permanently (without game usage)
|
// create token and modify all attributes permanently (without game usage)
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(copyFromPermanent, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
||||||
CardUtil.copyTo(token).from(copyFromPermanent, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
|
||||||
applier.apply(game, token, source, permanent.getId());
|
applier.apply(game, token, source, permanent.getId());
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,11 @@ import mage.constants.*;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetCardInYourGraveyard;
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
import mage.target.targetpointer.FixedTargets;
|
import mage.target.targetpointer.FixedTargets;
|
||||||
import mage.util.CardUtil;
|
import mage.util.functions.CopyTokenFunction;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -83,12 +83,11 @@ class GodPharaohsGiftEffect extends OneShotEffect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// create token and modify all attributes permanently (without game usage)
|
// create token and modify all attributes permanently (without game usage)
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(cardChosen, game);
|
||||||
CardUtil.copyTo(token).from(cardChosen, game);
|
|
||||||
token.removePTCDA();
|
token.removePTCDA();
|
||||||
token.setPower(4);
|
token.setPower(4);
|
||||||
token.setToughness(4);
|
token.setToughness(4);
|
||||||
token.getColor().setColor(ObjectColor.BLACK);
|
token.setColor(ObjectColor.BLACK);
|
||||||
token.removeAllCreatureTypes();
|
token.removeAllCreatureTypes();
|
||||||
token.addSubType(SubType.ZOMBIE);
|
token.addSubType(SubType.ZOMBIE);
|
||||||
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
||||||
|
|
|
@ -12,12 +12,12 @@ import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.common.FilterCreatureCard;
|
import mage.filter.common.FilterCreatureCard;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
import mage.target.common.TargetCardInYourGraveyard;
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
import mage.target.targetadjustment.TargetAdjuster;
|
import mage.target.targetadjustment.TargetAdjuster;
|
||||||
import mage.util.CardUtil;
|
import mage.util.functions.CopyTokenFunction;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -91,12 +91,11 @@ class HourOfEternityEffect extends OneShotEffect {
|
||||||
for (Card card : cardsToExile) {
|
for (Card card : cardsToExile) {
|
||||||
if (game.getState().getZone(card.getId()) == Zone.EXILED) {
|
if (game.getState().getZone(card.getId()) == Zone.EXILED) {
|
||||||
// create token and modify all attributes permanently (without game usage)
|
// create token and modify all attributes permanently (without game usage)
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(card, game);
|
||||||
CardUtil.copyTo(token).from(card, game);
|
|
||||||
token.removePTCDA();
|
token.removePTCDA();
|
||||||
token.setPower(4);
|
token.setPower(4);
|
||||||
token.setToughness(4);
|
token.setToughness(4);
|
||||||
token.getColor().setColor(ObjectColor.BLACK);
|
token.setColor(ObjectColor.BLACK);
|
||||||
token.removeAllCreatureTypes();
|
token.removeAllCreatureTypes();
|
||||||
token.addSubType(SubType.ZOMBIE);
|
token.addSubType(SubType.ZOMBIE);
|
||||||
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
||||||
|
|
|
@ -15,11 +15,11 @@ import mage.filter.common.FilterArtifactPermanent;
|
||||||
import mage.filter.common.FilterControlledArtifactPermanent;
|
import mage.filter.common.FilterControlledArtifactPermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.common.TargetControlledPermanent;
|
import mage.target.common.TargetControlledPermanent;
|
||||||
import mage.util.CardUtil;
|
import mage.util.functions.CopyTokenFunction;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -79,8 +79,7 @@ class MechanizedProductionEffect extends OneShotEffect {
|
||||||
if (sourceObject != null && sourceObject.getAttachedTo() != null) {
|
if (sourceObject != null && sourceObject.getAttachedTo() != null) {
|
||||||
Permanent enchantedArtifact = game.getPermanentOrLKIBattlefield(sourceObject.getAttachedTo());
|
Permanent enchantedArtifact = game.getPermanentOrLKIBattlefield(sourceObject.getAttachedTo());
|
||||||
if (enchantedArtifact != null) {
|
if (enchantedArtifact != null) {
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(enchantedArtifact, game);
|
||||||
CardUtil.copyTo(token).from(enchantedArtifact, game);
|
|
||||||
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
||||||
}
|
}
|
||||||
Map<String, Integer> countNames = new HashMap<>();
|
Map<String, Integer> countNames = new HashMap<>();
|
||||||
|
|
|
@ -104,7 +104,7 @@ class MyrkulLordOfBonesEffect extends OneShotEffect {
|
||||||
return new CreateTokenCopyTargetEffect().setSavedPermanent(
|
return new CreateTokenCopyTargetEffect().setSavedPermanent(
|
||||||
new PermanentCard(CardUtil.getDefaultCardSideForBattlefield(game, card), source.getControllerId(), game)
|
new PermanentCard(CardUtil.getDefaultCardSideForBattlefield(game, card), source.getControllerId(), game)
|
||||||
).setPermanentModifier((token, g) -> {
|
).setPermanentModifier((token, g) -> {
|
||||||
token.getCardType().clear();
|
token.removeAllCardTypes();
|
||||||
token.addCardType(CardType.ENCHANTMENT);
|
token.addCardType(CardType.ENCHANTMENT);
|
||||||
token.retainAllEnchantmentSubTypes(g);
|
token.retainAllEnchantmentSubTypes(g);
|
||||||
}).apply(game, source);
|
}).apply(game, source);
|
||||||
|
|
|
@ -23,10 +23,11 @@ import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||||
import mage.game.ExileZone;
|
import mage.game.ExileZone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.targetpointer.FixedTargets;
|
import mage.target.targetpointer.FixedTargets;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
import mage.util.functions.CopyTokenFunction;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -99,8 +100,7 @@ class PhantomSteedEffect extends OneShotEffect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (Card card : exileZone.getCards(game)) {
|
for (Card card : exileZone.getCards(game)) {
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(card, game);
|
||||||
CardUtil.copyTo(token).from(card, game);
|
|
||||||
token.addSubType(SubType.ILLUSION);
|
token.addSubType(SubType.ILLUSION);
|
||||||
token.putOntoBattlefield(1, game, source, source.getControllerId(), true, true);
|
token.putOntoBattlefield(1, game, source, source.getControllerId(), true, true);
|
||||||
List<Permanent> permanents = token
|
List<Permanent> permanents = token
|
||||||
|
|
|
@ -21,10 +21,10 @@ import mage.constants.Zone;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetCard;
|
import mage.target.TargetCard;
|
||||||
import mage.util.CardUtil;
|
import mage.util.functions.CopyTokenFunction;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ -149,8 +149,7 @@ class PrototypePortalCreateTokenEffect extends OneShotEffect {
|
||||||
if (!permanent.getImprinted().isEmpty()) {
|
if (!permanent.getImprinted().isEmpty()) {
|
||||||
Card card = game.getCard(permanent.getImprinted().get(0));
|
Card card = game.getCard(permanent.getImprinted().get(0));
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(card, game);
|
||||||
CardUtil.copyTo(token).from(card, game);
|
|
||||||
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@ import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
import mage.util.CardUtil;
|
import mage.util.functions.CopyTokenFunction;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ -62,8 +62,7 @@ class SpittingImageEffect extends OneShotEffect {
|
||||||
permanent = (Permanent) game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD);
|
permanent = (Permanent) game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD);
|
||||||
}
|
}
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(permanent, game);
|
||||||
CardUtil.copyTo(token).from(permanent, game);
|
|
||||||
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,11 @@ import mage.cards.ExpansionSet;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.SetType;
|
import mage.constants.SetType;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
*/
|
*/
|
||||||
public final class MarchOfTheMachine extends ExpansionSet {
|
public final class MarchOfTheMachine extends ExpansionSet {
|
||||||
|
|
||||||
private static final List<String> unfinished = Arrays.asList("Assimilate Essence", "Blighted Burgeoning", "Bloated Processor", "Chrome Host Seedshark", "Compleated Huntmaster", "Converter Beast", "Corruption of Towashi", "Elesh Norn", "The Argent Etchings", "Elvish Vatkeeper", "Essence of Orthodoxy", "Eyes of Gitaxias", "Furnace Gremlin", "Gift of Compleation", "Glissa, Herald of Predation", "Glistening Dawn", "Ichor Drinker", "Infected Defector", "Injector Crocodile", "Marauding Dreadship", "Merciless Repurposing", "Norn's Inquisitor", "Phyrexian Awakening", "Progenitor Exarch", "Sculpted Perfection", "Searing Barb", "Sunder the Gateway", "Sunfall", "Tangled Skyline", "Tiller of Flesh", "Traumatic Revelation");
|
|
||||||
|
|
||||||
private static final MarchOfTheMachine instance = new MarchOfTheMachine();
|
private static final MarchOfTheMachine instance = new MarchOfTheMachine();
|
||||||
|
|
||||||
public static MarchOfTheMachine getInstance() {
|
public static MarchOfTheMachine getInstance() {
|
||||||
|
@ -488,8 +483,6 @@ public final class MarchOfTheMachine extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Zimone and Dina", 318, Rarity.MYTHIC, mage.cards.z.ZimoneAndDina.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Zimone and Dina", 318, Rarity.MYTHIC, mage.cards.z.ZimoneAndDina.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Zurgo and Ojutai", 258, Rarity.MYTHIC, mage.cards.z.ZurgoAndOjutai.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Zurgo and Ojutai", 258, Rarity.MYTHIC, mage.cards.z.ZurgoAndOjutai.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Zurgo and Ojutai", 319, Rarity.MYTHIC, mage.cards.z.ZurgoAndOjutai.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Zurgo and Ojutai", 319, Rarity.MYTHIC, mage.cards.z.ZurgoAndOjutai.class, NON_FULL_USE_VARIOUS));
|
||||||
|
|
||||||
cards.removeIf(setCardInfo -> unfinished.contains(setCardInfo.getName())); // remove when mechanic is implemented
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
|
|
|
@ -4,16 +4,11 @@ import mage.cards.ExpansionSet;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.SetType;
|
import mage.constants.SetType;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
*/
|
*/
|
||||||
public final class MarchOfTheMachineCommander extends ExpansionSet {
|
public final class MarchOfTheMachineCommander extends ExpansionSet {
|
||||||
|
|
||||||
private static final List<String> unfinished = Arrays.asList("Blight Titan", "Brimaz, Blight of Oreskos", "Excise the Imperfect");
|
|
||||||
|
|
||||||
private static final MarchOfTheMachineCommander instance = new MarchOfTheMachineCommander();
|
private static final MarchOfTheMachineCommander instance = new MarchOfTheMachineCommander();
|
||||||
|
|
||||||
public static MarchOfTheMachineCommander getInstance() {
|
public static MarchOfTheMachineCommander getInstance() {
|
||||||
|
@ -367,7 +362,5 @@ public final class MarchOfTheMachineCommander extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Workshop Elders", 245, Rarity.RARE, mage.cards.w.WorkshopElders.class));
|
cards.add(new SetCardInfo("Workshop Elders", 245, Rarity.RARE, mage.cards.w.WorkshopElders.class));
|
||||||
cards.add(new SetCardInfo("Worthy Knight", 217, Rarity.RARE, mage.cards.w.WorthyKnight.class));
|
cards.add(new SetCardInfo("Worthy Knight", 217, Rarity.RARE, mage.cards.w.WorthyKnight.class));
|
||||||
cards.add(new SetCardInfo("Yawgmoth's Vile Offering", 271, Rarity.RARE, mage.cards.y.YawgmothsVileOffering.class));
|
cards.add(new SetCardInfo("Yawgmoth's Vile Offering", 271, Rarity.RARE, mage.cards.y.YawgmothsVileOffering.class));
|
||||||
|
|
||||||
cards.removeIf(setCardInfo -> unfinished.contains(setCardInfo.getName())); // remove when mechanic is implemented
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
package org.mage.test.cards.copy;
|
||||||
|
|
||||||
|
import mage.ObjectColor;
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class TokenCopyTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
private static final String rite = "Rite of Replication";
|
||||||
|
private static final String prowler = "Kessig Prowler";
|
||||||
|
private static final String predator = "Sinuous Predator";
|
||||||
|
private static final String brink = "Back from the Brink";
|
||||||
|
|
||||||
|
private void checkProwlers(int prowlerCount, int predatorCount) {
|
||||||
|
assertPermanentCount(playerA, prowler, prowlerCount);
|
||||||
|
assertPermanentCount(playerA, predator, predatorCount);
|
||||||
|
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
|
||||||
|
switch (permanent.getName()) {
|
||||||
|
case prowler:
|
||||||
|
Assert.assertEquals("Power of " + prowler + " should be 2", 2, permanent.getPower().getValue());
|
||||||
|
Assert.assertEquals("Toughness of " + prowler + " should be 1", 1, permanent.getToughness().getValue());
|
||||||
|
Assert.assertEquals(prowler + " should be green", ObjectColor.GREEN, permanent.getColor(currentGame));
|
||||||
|
Assert.assertTrue(prowler + " should be a Werewolf", permanent.hasSubtype(SubType.WEREWOLF, currentGame));
|
||||||
|
Assert.assertTrue(prowler + " should be a Horror", permanent.hasSubtype(SubType.HORROR, currentGame));
|
||||||
|
Assert.assertFalse(prowler + " should not be an Eldrazi", permanent.hasSubtype(SubType.ELDRAZI, currentGame));
|
||||||
|
Assert.assertEquals(prowler + " should have mana value 1", 1, permanent.getManaValue());
|
||||||
|
Assert.assertFalse(prowler + " should not be transformed", permanent.isTransformed());
|
||||||
|
break;
|
||||||
|
case predator:
|
||||||
|
Assert.assertEquals("Power of " + predator + " should be 4", 4, permanent.getPower().getValue());
|
||||||
|
Assert.assertEquals("Toughness of " + predator + " should be 4", 4, permanent.getToughness().getValue());
|
||||||
|
Assert.assertTrue(predator + " should be colorless", permanent.getColor(currentGame).isColorless());
|
||||||
|
Assert.assertTrue(predator + " should be an Eldrazi", permanent.hasSubtype(SubType.ELDRAZI, currentGame));
|
||||||
|
Assert.assertTrue(predator + " should be a Werewolf", permanent.hasSubtype(SubType.WEREWOLF, currentGame));
|
||||||
|
Assert.assertFalse(predator + " should not be a Horror", permanent.hasSubtype(SubType.HORROR, currentGame));
|
||||||
|
Assert.assertEquals(predator + " should have mana value 1", 1, permanent.getManaValue());
|
||||||
|
Assert.assertTrue(prowler + " should be transformed", permanent.isTransformed());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopyDFC() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, prowler);
|
||||||
|
addCard(Zone.HAND, playerA, rite);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rite, prowler);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, rite, 1);
|
||||||
|
checkProwlers(1 + 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopyDFCAndTransform() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 5 + 5 + 4);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, prowler);
|
||||||
|
addCard(Zone.HAND, playerA, rite);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rite, prowler);
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{4}{G}");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{4}{G}");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, rite, 1);
|
||||||
|
checkProwlers(0, 1 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopyTransformedDFC() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 5 + 4);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, prowler);
|
||||||
|
addCard(Zone.HAND, playerA, rite);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{4}{G}");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rite, predator);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, rite, 1);
|
||||||
|
checkProwlers(0, 1 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBackFromTheBrink() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 6 + 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, brink);
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, prowler);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Exile");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertExileCount(playerA, prowler, 1);
|
||||||
|
checkProwlers(1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBackFromTheBrinkTransform() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 6 + 1 + 5);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, brink);
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, prowler);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Exile");
|
||||||
|
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{4}{G}");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertExileCount(playerA, prowler, 1);
|
||||||
|
checkProwlers(0, 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -246,6 +246,10 @@ public interface MageObject extends MageItem, Serializable, Copyable<MageObject>
|
||||||
getSuperType().add(superType);
|
getSuperType().add(superType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void removeSuperType(SuperType superType) {
|
||||||
|
getSuperType().remove(superType);
|
||||||
|
}
|
||||||
|
|
||||||
default boolean isBasic() {
|
default boolean isBasic() {
|
||||||
return getSuperType().contains(SuperType.BASIC);
|
return getSuperType().contains(SuperType.BASIC);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,12 @@ import mage.constants.*;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
|
||||||
import mage.game.permanent.token.Token;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
import mage.target.targetpointer.FixedTarget;
|
||||||
import mage.target.targetpointer.FixedTargets;
|
import mage.target.targetpointer.FixedTargets;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
import mage.util.functions.CopyApplier;
|
import mage.util.functions.CopyApplier;
|
||||||
|
import mage.util.functions.CopyTokenFunction;
|
||||||
import mage.util.functions.EmptyCopyApplier;
|
import mage.util.functions.EmptyCopyApplier;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -200,14 +200,13 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create token and modify all attributes permanently (without game usage)
|
// create token and modify all attributes permanently (without game usage)
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(copyFrom, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
||||||
CardUtil.copyTo(token).from(copyFrom, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
|
||||||
applier.apply(game, token, source, targetId);
|
applier.apply(game, token, source, targetId);
|
||||||
if (becomesArtifact) {
|
if (becomesArtifact) {
|
||||||
token.addCardType(CardType.ARTIFACT);
|
token.addCardType(CardType.ARTIFACT);
|
||||||
}
|
}
|
||||||
if (isntLegendary) {
|
if (isntLegendary) {
|
||||||
token.getSuperType().remove(SuperType.LEGENDARY);
|
token.removeSuperType(SuperType.LEGENDARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startingLoyalty != -1) {
|
if (startingLoyalty != -1) {
|
||||||
|
@ -238,7 +237,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
|
||||||
token.addSubType(additionalSubType);
|
token.addSubType(additionalSubType);
|
||||||
}
|
}
|
||||||
if (color != null) {
|
if (color != null) {
|
||||||
token.getColor().setColor(color);
|
token.setColor(color);
|
||||||
}
|
}
|
||||||
additionalAbilities.stream().forEach(token::addAbility);
|
additionalAbilities.stream().forEach(token::addAbility);
|
||||||
if (permanentModifier != null) {
|
if (permanentModifier != null) {
|
||||||
|
|
|
@ -13,9 +13,9 @@ import mage.constants.TimingRule;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.CardUtil;
|
import mage.util.functions.CopyTokenFunction;
|
||||||
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -87,11 +87,10 @@ class EmbalmEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create token and modify all attributes permanently (without game usage)
|
// create token and modify all attributes permanently (without game usage)
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(card, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
||||||
CardUtil.copyTo(token).from(card, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
token.setColor(ObjectColor.WHITE);
|
||||||
token.getColor().setColor(ObjectColor.WHITE);
|
|
||||||
token.addSubType(SubType.ZOMBIE);
|
token.addSubType(SubType.ZOMBIE);
|
||||||
token.getManaCost().clear();
|
token.clearManaCost();
|
||||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.EMBALMED_CREATURE, token.getId(), source, controller.getId()));
|
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.EMBALMED_CREATURE, token.getId(), source, controller.getId()));
|
||||||
token.putOntoBattlefield(1, game, source, controller.getId(), false, false, null);
|
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).
|
// Probably it makes sense to remove also the Embalm ability (it's not shown on the token cards).
|
||||||
|
|
|
@ -17,9 +17,9 @@ import mage.constants.TimingRule;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
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.FixedTarget;
|
||||||
import mage.util.CardUtil;
|
import mage.util.functions.CopyTokenFunction;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -85,8 +85,7 @@ class EncoreEffect extends OneShotEffect {
|
||||||
if (card == null) {
|
if (card == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(card, game);
|
||||||
CardUtil.copyTo(token).from(card, game);
|
|
||||||
Set<MageObjectReference> addedTokens = new HashSet<>();
|
Set<MageObjectReference> addedTokens = new HashSet<>();
|
||||||
int opponentCount = OpponentsCount.instance.calculate(game, source, this);
|
int opponentCount = OpponentsCount.instance.calculate(game, source, this);
|
||||||
if (opponentCount < 1) {
|
if (opponentCount < 1) {
|
||||||
|
|
|
@ -13,9 +13,9 @@ import mage.constants.TimingRule;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.CardUtil;
|
import mage.util.functions.CopyTokenFunction;
|
||||||
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -91,11 +91,10 @@ class EternalizeEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create token and modify all attributes permanently (without game usage)
|
// create token and modify all attributes permanently (without game usage)
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(card, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
||||||
CardUtil.copyTo(token).from(card, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
token.setColor(ObjectColor.BLACK);
|
||||||
token.getColor().setColor(ObjectColor.BLACK);
|
|
||||||
token.addSubType(SubType.ZOMBIE);
|
token.addSubType(SubType.ZOMBIE);
|
||||||
token.getManaCost().clear();
|
token.clearManaCost();
|
||||||
token.removePTCDA();
|
token.removePTCDA();
|
||||||
token.setPower(4);
|
token.setPower(4);
|
||||||
token.setToughness(4);
|
token.setToughness(4);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package mage.abilities.keyword;
|
package mage.abilities.keyword;
|
||||||
|
|
||||||
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
@ -9,6 +10,7 @@ import mage.constants.*;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.MageObjectAttribute;
|
import mage.game.MageObjectAttribute;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.game.permanent.PermanentToken;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
|
@ -38,7 +40,7 @@ public class TransformAbility extends SimpleStaticAbility {
|
||||||
return "";
|
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) {
|
if (sourceCard == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -58,9 +60,10 @@ public class TransformAbility extends SimpleStaticAbility {
|
||||||
for (SuperType type : sourceCard.getSuperType()) {
|
for (SuperType type : sourceCard.getSuperType()) {
|
||||||
permanent.addSuperType(type);
|
permanent.addSuperType(type);
|
||||||
}
|
}
|
||||||
|
if (sourceCard instanceof Card) {
|
||||||
|
permanent.setExpansionSetCode(((Card) sourceCard).getExpansionSetCode());
|
||||||
|
}
|
||||||
CardUtil.copySetAndCardNumber(permanent, sourceCard);
|
CardUtil.copySetAndCardNumber(permanent, sourceCard);
|
||||||
|
|
||||||
permanent.getAbilities().clear();
|
permanent.getAbilities().clear();
|
||||||
for (Ability ability : sourceCard.getAbilities()) {
|
for (Ability ability : sourceCard.getAbilities()) {
|
||||||
// source == null -- call from init card (e.g. own abilities)
|
// source == null -- call from init card (e.g. own abilities)
|
||||||
|
@ -144,7 +147,12 @@ class TransformEffect extends ContinuousEffectImpl {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Card card = permanent.getSecondCardFace();
|
MageObject card;
|
||||||
|
if (permanent instanceof PermanentToken) {
|
||||||
|
card = ((PermanentToken) permanent).getToken().getBackFace();
|
||||||
|
} else {
|
||||||
|
card = permanent.getSecondCardFace();
|
||||||
|
}
|
||||||
|
|
||||||
if (card == null) {
|
if (card == null) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -18,11 +18,10 @@ import mage.constants.TimingRule;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.command.Emblem;
|
import mage.game.command.Emblem;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
|
||||||
import mage.game.permanent.token.Token;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.game.permanent.token.custom.CreatureToken;
|
import mage.game.permanent.token.custom.CreatureToken;
|
||||||
import mage.util.CardUtil;
|
|
||||||
import mage.util.RandomUtil;
|
import mage.util.RandomUtil;
|
||||||
|
import mage.util.functions.CopyTokenFunction;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -79,7 +78,7 @@ class MomirEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
// search for a random non custom set creature
|
// search for a random non custom set creature
|
||||||
EmptyToken token = null;
|
Token token = null;
|
||||||
while (!options.isEmpty()) {
|
while (!options.isEmpty()) {
|
||||||
int index = RandomUtil.nextInt(options.size());
|
int index = RandomUtil.nextInt(options.size());
|
||||||
ExpansionSet expansionSet = Sets.findSet(options.get(index).getSetCode());
|
ExpansionSet expansionSet = Sets.findSet(options.get(index).getSetCode());
|
||||||
|
@ -88,8 +87,7 @@ class MomirEffect extends OneShotEffect {
|
||||||
} else {
|
} else {
|
||||||
Card card = options.get(index).getCard();
|
Card card = options.get(index).getCard();
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
token = new EmptyToken();
|
token = CopyTokenFunction.createTokenCopy(card, game);
|
||||||
CardUtil.copyTo(token).from(card, game);
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
options.remove(index);
|
options.remove(index);
|
||||||
|
|
|
@ -609,7 +609,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Card getOtherFace() {
|
protected MageObject getOtherFace() {
|
||||||
return transformed ? this.getMainCard() : this.getMainCard().getSecondCardFace();
|
return transformed ? this.getMainCard() : this.getMainCard().getSecondCardFace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.mana.ManaCost;
|
import mage.abilities.costs.mana.ManaCost;
|
||||||
import mage.abilities.keyword.ChangelingAbility;
|
import mage.abilities.keyword.ChangelingAbility;
|
||||||
|
import mage.abilities.keyword.TransformAbility;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.constants.EmptyNames;
|
import mage.constants.EmptyNames;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
@ -28,6 +29,9 @@ public class PermanentToken extends PermanentImpl {
|
||||||
this.power = new MageInt(token.getPower().getModifiedBaseValue());
|
this.power = new MageInt(token.getPower().getModifiedBaseValue());
|
||||||
this.toughness = new MageInt(token.getToughness().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)
|
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
|
// token's ZCC must be synced with original token to keep abilities settings
|
||||||
// Example: kicker ability and kicked status
|
// Example: kicker ability and kicked status
|
||||||
|
@ -50,6 +54,14 @@ public class PermanentToken extends PermanentImpl {
|
||||||
this.toughness.resetToBaseValue();
|
this.toughness.resetToBaseValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getManaValue() {
|
||||||
|
if (this.isTransformed()) {
|
||||||
|
return token.getManaValue();
|
||||||
|
}
|
||||||
|
return super.getManaValue();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
if (name.isEmpty()) {
|
if (name.isEmpty()) {
|
||||||
|
@ -121,6 +133,16 @@ public class PermanentToken extends PermanentImpl {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTransformable() {
|
||||||
|
return token.getBackFace() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MageObject getOtherFace() {
|
||||||
|
return this.transformed ? token : this.token.getBackFace();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCardNumber() {
|
public String getCardNumber() {
|
||||||
return token.getOriginalCardNumber();
|
return token.getOriginalCardNumber();
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.game.permanent.token;
|
package mage.game.permanent.token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,7 +6,14 @@ package mage.game.permanent.token;
|
||||||
public final class EmptyToken extends TokenImpl {
|
public final class EmptyToken extends TokenImpl {
|
||||||
|
|
||||||
public EmptyToken() {
|
public EmptyToken() {
|
||||||
|
this(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmptyToken(boolean withBackFace) {
|
||||||
super(" Token", "");
|
super(" Token", "");
|
||||||
|
if (withBackFace) {
|
||||||
|
this.backFace = new EmptyToken();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmptyToken(final EmptyToken token) {
|
public EmptyToken(final EmptyToken token) {
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package mage.game.permanent.token;
|
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.CardType;
|
||||||
import mage.constants.SubType;
|
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.\"");
|
super("Incubator Token", "Incubator artifact token with \"{2}: Transform this artifact.\"");
|
||||||
cardType.add(CardType.ARTIFACT);
|
cardType.add(CardType.ARTIFACT);
|
||||||
subtype.add(SubType.INCUBATOR);
|
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");
|
availableImageSetCodes = Arrays.asList("MOM");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
package mage.game.permanent.token;
|
package mage.game.permanent.token;
|
||||||
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
@ -58,4 +59,14 @@ public interface Token extends MageObject {
|
||||||
void setCopySourceCard(Card copySourceCard);
|
void setCopySourceCard(Card copySourceCard);
|
||||||
|
|
||||||
void setExpansionSetCodeForImage(String code);
|
void setExpansionSetCodeForImage(String code);
|
||||||
|
|
||||||
|
Token getBackFace();
|
||||||
|
|
||||||
|
void setColor(ObjectColor color);
|
||||||
|
|
||||||
|
void clearManaCost();
|
||||||
|
|
||||||
|
void setEntersTransformed(boolean entersTransformed);
|
||||||
|
|
||||||
|
boolean isEntersTransformed();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package mage.game.permanent.token;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.MageObjectImpl;
|
import mage.MageObjectImpl;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
|
@ -12,9 +13,7 @@ import mage.cards.Card;
|
||||||
import mage.cards.repository.TokenInfo;
|
import mage.cards.repository.TokenInfo;
|
||||||
import mage.cards.repository.TokenRepository;
|
import mage.cards.repository.TokenRepository;
|
||||||
import mage.cards.repository.TokenType;
|
import mage.cards.repository.TokenType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.*;
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.command.CommandObject;
|
import mage.game.command.CommandObject;
|
||||||
import mage.game.events.CreateTokenEvent;
|
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
|
// list of set codes token images are available for
|
||||||
protected List<String> availableImageSetCodes = new ArrayList<>(); // TODO: delete
|
protected List<String> availableImageSetCodes = new ArrayList<>(); // TODO: delete
|
||||||
|
|
||||||
public enum Type {
|
protected Token backFace = null;
|
||||||
|
private boolean entersTransformed = false;
|
||||||
FIRST(1),
|
|
||||||
SECOND(2);
|
|
||||||
|
|
||||||
int code;
|
|
||||||
|
|
||||||
Type(int code) {
|
|
||||||
this.code = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getCode() {
|
|
||||||
return this.code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TokenImpl() {
|
public TokenImpl() {
|
||||||
}
|
}
|
||||||
|
@ -69,7 +55,7 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TokenImpl(final TokenImpl token) {
|
protected TokenImpl(final TokenImpl token) {
|
||||||
super(token);
|
super(token);
|
||||||
this.description = token.description;
|
this.description = token.description;
|
||||||
this.tokenType = token.tokenType;
|
this.tokenType = token.tokenType;
|
||||||
|
@ -78,6 +64,8 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
||||||
this.originalExpansionSetCode = token.originalExpansionSetCode;
|
this.originalExpansionSetCode = token.originalExpansionSetCode;
|
||||||
this.copySourceCard = token.copySourceCard; // will never be changed
|
this.copySourceCard = token.copySourceCard; // will never be changed
|
||||||
this.availableImageSetCodes = token.availableImageSetCodes;
|
this.availableImageSetCodes = token.availableImageSetCodes;
|
||||||
|
this.backFace = token.backFace != null ? token.backFace.copy() : null;
|
||||||
|
this.entersTransformed = token.entersTransformed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -98,11 +86,17 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
||||||
ability.setSourceId(this.getId());
|
ability.setSourceId(this.getId());
|
||||||
abilities.add(ability);
|
abilities.add(ability);
|
||||||
abilities.addAll(ability.getSubAbilities());
|
abilities.addAll(ability.getSubAbilities());
|
||||||
|
if (backFace != null) {
|
||||||
|
backFace.addAbility(ability);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Directly from PermanentImpl
|
// Directly from PermanentImpl
|
||||||
@Override
|
@Override
|
||||||
public void removeAbility(Ability abilityToRemove) {
|
public void removeAbility(Ability abilityToRemove) {
|
||||||
|
if (backFace != null) {
|
||||||
|
backFace.removeAbility(abilityToRemove);
|
||||||
|
}
|
||||||
if (abilityToRemove == null) {
|
if (abilityToRemove == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -127,6 +121,9 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
abilitiesToRemove.forEach(a -> removeAbility(a));
|
abilitiesToRemove.forEach(a -> removeAbility(a));
|
||||||
|
if (backFace != null) {
|
||||||
|
backFace.removeAbilities(abilitiesToRemove);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -389,11 +386,17 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPower(int power) {
|
public void setPower(int power) {
|
||||||
|
if (this.backFace != null) {
|
||||||
|
this.backFace.setPower(power);
|
||||||
|
}
|
||||||
this.power = new MageInt(power);
|
this.power = new MageInt(power);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setToughness(int toughness) {
|
public void setToughness(int toughness) {
|
||||||
|
if (this.backFace != null) {
|
||||||
|
this.backFace.setToughness(toughness);
|
||||||
|
}
|
||||||
this.toughness = new MageInt(toughness);
|
this.toughness = new MageInt(toughness);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,6 +429,21 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
||||||
return originalExpansionSetCode;
|
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
|
@Override
|
||||||
public void setOriginalExpansionSetCode(String originalExpansionSetCode) {
|
public void setOriginalExpansionSetCode(String originalExpansionSetCode) {
|
||||||
// TODO: delete
|
// TODO: delete
|
||||||
|
@ -451,4 +469,167 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
||||||
// TODO: delete
|
// TODO: delete
|
||||||
setOriginalExpansionSetCode(code);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,13 @@ import mage.game.events.CopiedStackObjectEvent;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
import mage.game.events.ZoneChangeEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.PermanentCard;
|
import mage.game.permanent.PermanentCard;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
import mage.util.GameLog;
|
import mage.util.GameLog;
|
||||||
import mage.util.ManaUtil;
|
import mage.util.ManaUtil;
|
||||||
import mage.util.SubTypes;
|
import mage.util.SubTypes;
|
||||||
|
import mage.util.functions.CopyTokenFunction;
|
||||||
import mage.util.functions.StackObjectCopyApplier;
|
import mage.util.functions.StackObjectCopyApplier;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
@ -275,8 +276,7 @@ public class Spell extends StackObjectImpl implements Card {
|
||||||
UUID permId;
|
UUID permId;
|
||||||
boolean flag;
|
boolean flag;
|
||||||
if (isCopy()) {
|
if (isCopy()) {
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(card, game, this);
|
||||||
CardUtil.copyTo(token).from(card, game, this);
|
|
||||||
// The token that a resolving copy of a spell becomes isn’t said to have been “created.” (2020-09-25)
|
// The token that a resolving copy of a spell becomes isn’t said to have been “created.” (2020-09-25)
|
||||||
if (token.putOntoBattlefield(1, game, ability, getControllerId(), false, false, null, false)) {
|
if (token.putOntoBattlefield(1, game, ability, getControllerId(), false, false, null, false)) {
|
||||||
permId = token.getLastAddedTokenIds().stream().findFirst().orElse(null);
|
permId = token.getLastAddedTokenIds().stream().findFirst().orElse(null);
|
||||||
|
@ -343,8 +343,7 @@ public class Spell extends StackObjectImpl implements Card {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (isCopy()) {
|
} else if (isCopy()) {
|
||||||
EmptyToken token = new EmptyToken();
|
Token token = CopyTokenFunction.createTokenCopy(card, game, this);
|
||||||
CardUtil.copyTo(token).from(card, game, this);
|
|
||||||
// The token that a resolving copy of a spell becomes isn’t said to have been “created.” (2020-09-25)
|
// The token that a resolving copy of a spell becomes isn’t said to have been “created.” (2020-09-25)
|
||||||
token.putOntoBattlefield(1, game, ability, getControllerId(), false, false, null, false);
|
token.putOntoBattlefield(1, game, ability, getControllerId(), false, false, null, false);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -42,7 +42,6 @@ import mage.players.Player;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
import mage.target.TargetCard;
|
import mage.target.TargetCard;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
import mage.target.targetpointer.FixedTarget;
|
||||||
import mage.util.functions.CopyTokenFunction;
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
@ -474,17 +473,6 @@ public final class CardUtil {
|
||||||
spellAbility.getManaCostsToPay().addAll(adjustedCost);
|
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
|
* Converts an integer number to string Numbers > 20 will be returned as
|
||||||
* digits
|
* digits
|
||||||
|
@ -1821,6 +1809,9 @@ public final class CardUtil {
|
||||||
needSetCode = ((Card) copyFromObject).getExpansionSetCode();
|
needSetCode = ((Card) copyFromObject).getExpansionSetCode();
|
||||||
needCardNumber = ((Card) copyFromObject).getCardNumber();
|
needCardNumber = ((Card) copyFromObject).getCardNumber();
|
||||||
needTokenType = 0;
|
needTokenType = 0;
|
||||||
|
} else if (copyFromObject instanceof Token) {
|
||||||
|
// TODO: make this work
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Unsupported copyFromObject class: " + copyFromObject.getClass().getSimpleName());
|
throw new IllegalStateException("Unsupported copyFromObject class: " + copyFromObject.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,64 +7,95 @@ import mage.cards.Card;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SuperType;
|
import mage.constants.SuperType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.PermanentCard;
|
import mage.game.permanent.PermanentCard;
|
||||||
import mage.game.permanent.PermanentToken;
|
import mage.game.permanent.PermanentToken;
|
||||||
|
import mage.game.permanent.token.EmptyToken;
|
||||||
import mage.game.permanent.token.Token;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author nantuko
|
* @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) {
|
if (target == null) {
|
||||||
throw new IllegalArgumentException("Target can't be null");
|
throw new IllegalArgumentException("Target can't be null");
|
||||||
}
|
}
|
||||||
this.target = target;
|
this.target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static Token createTokenCopy(Card source, Game game) {
|
||||||
public Token apply(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) {
|
if (target == null) {
|
||||||
throw new IllegalArgumentException("Target can't be 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
|
// 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.
|
// else gained abililies would be copied too.
|
||||||
|
target.setEntersTransformed(source instanceof Permanent && ((Permanent) source).isTransformed());
|
||||||
MageObject sourceObj = source;
|
MageObject sourceObj;
|
||||||
if (source instanceof PermanentToken) {
|
if (source instanceof PermanentToken) {
|
||||||
// create token from another token
|
// 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
|
// to show the source image, the original values have to be used
|
||||||
target.setOriginalExpansionSetCode(((Token) sourceObj).getOriginalExpansionSetCode());
|
target.setOriginalExpansionSetCode(sourceToken.getOriginalExpansionSetCode());
|
||||||
target.setOriginalCardNumber(((Token) sourceObj).getOriginalCardNumber());
|
target.setOriginalCardNumber(sourceToken.getOriginalCardNumber());
|
||||||
target.setCopySourceCard(((PermanentToken) source).getToken().getCopySourceCard());
|
target.setCopySourceCard(((PermanentToken) source).getToken().getCopySourceCard());
|
||||||
} else if (source instanceof PermanentCard) {
|
return;
|
||||||
|
}
|
||||||
|
if (source instanceof PermanentCard) {
|
||||||
// create token from non-token permanent
|
// create token from non-token permanent
|
||||||
if (((PermanentCard) source).isMorphed() || ((PermanentCard) source).isManifested()) {
|
if (((PermanentCard) source).isMorphed() || ((PermanentCard) source).isManifested()) {
|
||||||
MorphAbility.setPermanentToFaceDownCreature(target, game);
|
MorphAbility.setPermanentToFaceDownCreature(target, game);
|
||||||
return target;
|
return;
|
||||||
} 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);
|
|
||||||
}
|
}
|
||||||
} else {
|
sourceObj = ((PermanentCard) source).getMainCard();
|
||||||
// create token from non-permanent object like card (example: Embalm ability)
|
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.setOriginalExpansionSetCode(source.getExpansionSetCode());
|
||||||
target.setOriginalCardNumber(source.getCardNumber());
|
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)
|
// modify all attributes permanently (without game usage)
|
||||||
target.setName(sourceObj.getName());
|
target.setName(sourceObj.getName());
|
||||||
target.getColor().setColor(sourceObj.getColor());
|
target.getColor().setColor(sourceObj.getColor());
|
||||||
|
@ -101,11 +132,7 @@ public class CopyTokenFunction implements Function<Token, Card> {
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Token from(Card source, Game game) {
|
private Token from(Card source, Game game, Spell spell) {
|
||||||
return from(source, game, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Token from(Card source, Game game, Spell spell) {
|
|
||||||
apply(source, game);
|
apply(source, game);
|
||||||
|
|
||||||
// token's ZCC must be synced with original card to keep abilities settings
|
// token's ZCC must be synced with original card to keep abilities settings
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
Loading…
Reference in a new issue