remove TransformAbility

This commit is contained in:
jmlundeen 2025-12-06 14:57:54 -06:00
parent 2bcbb30954
commit 2a75aa3acc
38 changed files with 118 additions and 365 deletions

View file

@ -4,7 +4,6 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.BecomesFaceDownCreatureEffect;
import mage.abilities.icon.*;
import mage.abilities.keyword.TransformAbility;
import mage.cards.*;
import mage.cards.decks.Deck;
import mage.cards.repository.CardInfo;
@ -13,34 +12,26 @@ import mage.cards.repository.ExpansionInfo;
import mage.cards.repository.ExpansionRepository;
import mage.client.MageFrame;
import mage.client.cards.BigCard;
import mage.client.game.PlayAreaPanel;
import mage.client.game.PlayerPanelExt;
import mage.client.themes.ThemeType;
import mage.client.util.*;
import mage.client.util.Event;
import mage.client.util.GUISizeHelper;
import mage.client.util.Listener;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.constants.Zone;
import mage.counters.Counter;
import mage.counters.CounterType;
import mage.designations.CitysBlessing;
import mage.designations.Monarch;
import mage.game.*;
import mage.game.FakeGame;
import mage.game.FakeMatch;
import mage.game.Game;
import mage.game.command.Dungeon;
import mage.game.command.Emblem;
import mage.game.command.Plane;
import mage.game.match.*;
import mage.game.mulligan.Mulligan;
import mage.game.mulligan.MulliganType;
import mage.game.match.Match;
import mage.game.permanent.PermanentCard;
import mage.game.permanent.PermanentMeld;
import mage.game.permanent.PermanentToken;
import mage.game.permanent.token.IncubatorToken;
import mage.game.permanent.token.Phyrexian00Token;
import mage.game.permanent.token.Token;
import mage.game.permanent.token.ZombieToken;
import mage.players.Player;
import mage.players.StubPlayer;
import mage.util.CardUtil;
@ -52,8 +43,8 @@ import org.mage.card.arcane.CardPanel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.*;
import java.util.List;
/**
* App GUI: debug only, testing card renders and manipulations
@ -150,8 +141,8 @@ public class TestCardRenderDialog extends MageDialog {
}
if (transform) {
// need direct transform call to keep other side info (original)
TransformAbility.transformPermanent(permanent, game, null);
permanent.setTransformed(true);
permanent.reset(game);
}
if (damage > 0) permanent.damage(damage, controllerId, null, game);

View file

@ -11,7 +11,6 @@ import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardSetInfo;
import mage.cards.DoubleFacedCardHalf;
@ -112,7 +111,7 @@ class AccursedWitchReturnTransformedEffect extends OneShotEffect {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue("attachTo:" + card.getOtherSide().getId(), attachTo.getId());
if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) {
attachTo.addAttachment(card.getOtherSide().getId(), source, game);
@ -120,6 +119,7 @@ class AccursedWitchReturnTransformedEffect extends OneShotEffect {
return true;
}
}
class InfectiousCurseCostReductionEffect extends CostModificationEffectImpl {
InfectiousCurseCostReductionEffect() {

View file

@ -16,7 +16,6 @@ import mage.abilities.hint.ConditionHint;
import mage.abilities.hint.Hint;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.mana.BlackManaAbility;
import mage.cards.*;
import mage.constants.*;
@ -191,7 +190,7 @@ class AclazotzDeepestBetrayalTransformEffect extends OneShotEffect {
if (controller == null || card == null) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, true, null);
return true;
}

View file

@ -11,7 +11,6 @@ import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect;
import mage.abilities.effects.keyword.ScryEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
@ -94,7 +93,7 @@ class BiolumeEggEffect extends OneShotEffect {
}
Card card = game.getCard(getTargetPointer().getFirst(game, source));
if (card != null) {
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + card.getId(), Boolean.TRUE);
controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, true, null);
}
return true;

View file

@ -5,10 +5,10 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -86,7 +86,7 @@ class ContainmentPriestReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (((ZoneChangeEvent) event).getToZone() == Zone.BATTLEFIELD) {
Object entersTransformed = game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + event.getTargetId());
Object entersTransformed = game.getState().getValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + event.getTargetId());
Card card = game.getCard(event.getTargetId());
if (card != null && entersTransformed instanceof Boolean && (Boolean) entersTransformed && card.getSecondCardFace() != null) {
card = card.getSecondCardFace();

View file

@ -12,7 +12,6 @@ import mage.abilities.effects.common.RemoveAllCountersSourceEffect;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
@ -97,7 +96,7 @@ class EdgarCharmedGroomEffect extends OneShotEffect {
if (controller == null || card == null) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, true, null);
return true;
}

View file

@ -13,7 +13,6 @@ import mage.abilities.effects.keyword.SurveilEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.abilities.keyword.FlashbackAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
@ -115,7 +114,7 @@ class EsperOriginsEffect extends OneShotEffect {
Card card = spell.getMainCard();
player.moveCards(card, Zone.EXILED, source, game);
game.setEnterWithCounters(card.getId(), new Counters(CounterType.FINALITY.createInstance()));
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + card.getId(), Boolean.TRUE);
player.moveCards(
card, Zone.BATTLEFIELD, source, game, false,
false, true, null

View file

@ -9,7 +9,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.PutOnLibrarySourceEffect;
import mage.abilities.effects.keyword.SurveilEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
@ -95,7 +94,7 @@ class GarlandKnightOfCorneliaEffect extends OneShotEffect {
if (player == null || card == null) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + card.getId(), Boolean.TRUE);
return player.moveCards(card, Zone.BATTLEFIELD, source, game);
}
}

View file

@ -11,7 +11,6 @@ import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.FightTargetSourceEffect;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
@ -120,7 +119,7 @@ class GoldenGuardianReturnTransformedEffect extends OneShotEffect {
if (controller == null || game.getState().getZone(source.getSourceId()) != Zone.GRAVEYARD) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
Card card = game.getCard(source.getSourceId());
return card != null && controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}

View file

@ -7,7 +7,6 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.CardType;
@ -16,8 +15,7 @@ import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.filter.predicate.permanent.TransformedPredicate;
import mage.filter.predicate.permanent.TransformablePredicate;
import java.util.UUID;
@ -27,18 +25,13 @@ import java.util.UUID;
public final class GrimlockDinobotLeader extends TransformingDoubleFacedCard {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Dinosaurs and Vehicles you control");
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("Transformers creatures");
static {
filter.add(Predicates.<MageObject>or(
SubType.DINOSAUR.getPredicate(),
SubType.VEHICLE.getPredicate())
);
}
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("Transformers creatures");
static {
filter2.add(Predicates.not(SubType.DINOSAUR.getPredicate()));
filter2.add(Predicates.not(SubType.VEHICLE.getPredicate()));
filter2.add(Predicates.or(new AbilityPredicate(TransformAbility.class), TransformedPredicate.instance));
filter2.add(TransformablePredicate.instance);
}
public GrimlockDinobotLeader(UUID ownerId, CardSetInfo setInfo) {

View file

@ -11,7 +11,6 @@ import mage.abilities.effects.common.continuous.BoostEquippedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EquipAbility;
import mage.abilities.keyword.MenaceAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
@ -89,7 +88,7 @@ class HarvestHandReturnTransformedEffect extends OneShotEffect {
if (controller == null || card == null) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
return true;
}

View file

@ -1,4 +1,3 @@
package mage.cards.j;
import mage.abilities.Ability;
@ -11,7 +10,6 @@ import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.mana.AnyColorManaAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
@ -95,7 +93,7 @@ class JourneyToEternityReturnTransformedSourceEffect extends OneShotEffect {
if (zone == Zone.BATTLEFIELD || !zone.isPublicZone()) {
return true;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, false, null);
}
return true;

View file

@ -6,7 +6,6 @@ import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
@ -111,7 +110,7 @@ class ReturnLoyalCatharEffect extends OneShotEffect {
}
Card card = game.getCard(getTargetPointer().getFirst(game, source));
if (card != null) {
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + card.getId(), Boolean.TRUE);
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}
return true;

View file

@ -5,10 +5,10 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -88,7 +88,7 @@ class ContainmentPriestReplacementEffect extends ReplacementEffectImpl {
if (((ZoneChangeEvent) event).getToZone() == Zone.BATTLEFIELD) {
Card card = game.getCard(event.getTargetId());
if (card != null) {
Object entersTransformed = game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + event.getTargetId());
Object entersTransformed = game.getState().getValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + event.getTargetId());
if (entersTransformed instanceof Boolean && (Boolean) entersTransformed && card.getSecondCardFace() != null) {
card = card.getSecondCardFace();
}

View file

@ -14,7 +14,6 @@ import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.hint.Hint;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.mana.RedManaAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
@ -105,7 +104,7 @@ class OjerAxonilDeepestMightTransformEffect extends OneShotEffect {
if (controller == null || card == null) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, true, null);
return true;
}

View file

@ -12,7 +12,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.hint.common.PermanentsYouControlHint;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.mana.GreenManaAbility;
import mage.cards.*;
import mage.cards.g.GishathSunsAvatar;
@ -96,7 +95,7 @@ class OjerKaslemDeepestGrowthTransformEffect extends OneShotEffect {
if (controller == null || card == null) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, true, null);
return true;
}

View file

@ -14,7 +14,6 @@ import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.effects.common.counter.RemoveCounterSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.ReboundAbility;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.mana.BlueManaAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
@ -167,7 +166,7 @@ class OjerPakpatiqDeepestEpochTrigger extends OneShotEffect {
if (controller == null || card == null) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.setEnterWithCounters(card.getId(), new Counters().addCounter(CounterType.TIME.createInstance(3)));
controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, true, null);
return true;

View file

@ -10,7 +10,6 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.abilities.mana.WhiteManaAbility;
import mage.cards.Card;
@ -94,7 +93,7 @@ class OjerTaqDeepestFoundationTransformEffect extends OneShotEffect {
if (controller == null || card == null) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, true, null);
return true;
}

View file

@ -4,16 +4,15 @@ import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.LivingMetalAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.keyword.BolsterEffect;
import mage.abilities.keyword.LivingMetalAbility;
import mage.abilities.keyword.MoreThanMeetsTheEyeAbility;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
@ -106,7 +105,7 @@ class OptimusPrimeHeroEffect extends OneShotEffect {
if (backSide == null) {
return true;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + backSide.getId(), true);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + backSide.getId(), true);
controller.moveCards(backSide, Zone.BATTLEFIELD, source, game);
return true;
}

View file

@ -9,7 +9,6 @@ import mage.abilities.effects.common.PermanentsEnterBattlefieldTappedEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardSetInfo;
import mage.cards.DoubleFacedCardHalf;
@ -116,7 +115,7 @@ class RadiantGraceEffect extends OneShotEffect {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue("attachTo:" + card.getOtherSide().getId(), player.getId());
if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) {
player.addAttachment(card.getId(), source, game);

View file

@ -7,7 +7,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.combat.AttacksIfAbleAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
@ -82,7 +81,7 @@ class SkinInvasionEffect extends OneShotEffect {
Card card = game.getCard(source.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (card != null && controller != null) {
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
return true;
}

View file

@ -8,7 +8,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.MillCardsTargetEffect;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.keyword.SkulkAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
@ -96,7 +95,7 @@ class StartledAwakeReturnTransformedEffect extends OneShotEffect {
if (backSide == null) {
return true;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + backSide.getId(), true);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + backSide.getId(), true);
controller.moveCards(backSide, Zone.BATTLEFIELD, source, game);
return true;
}

View file

@ -6,7 +6,6 @@ import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardSetInfo;
import mage.cards.DoubleFacedCardHalf;
@ -107,7 +106,7 @@ class VengefulStranglerEffect extends OneShotEffect {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue("attachTo:" + card.getOtherSide().getId(), permanent);
if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) {
permanent.addAttachment(card.getOtherSide().getId(), source, game);

View file

@ -859,7 +859,7 @@ public class TransformTest extends CardTestPlayerBase {
assertLife(playerB, 20);
assertGraveyardCount(playerA, dressDown, 1);
assertPermanentCount(playerA, huntmasterOfTheFells, 1);
assertPermanentCount(playerA, 6+1+1);
assertPermanentCount(playerA, 6 + 1 + 1);
}
@Test
@ -924,4 +924,32 @@ public class TransformTest extends CardTestPlayerBase {
assertPermanentCount(playerA, baithookAngler, 1);
assertTrue(getPermanent(baithookAngler, playerA).isTapped());
}
/**
* Test that copying a TDFC will not leave and return transformed
*/
@Test
public void testCloneCantReturnTransformed() {
addCard(Zone.BATTLEFIELD, playerA, azusasManyJourneys);
addCard(Zone.HAND, playerA, "Clever Impersonator@impersonator");
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clever Impersonator");
setChoice(playerA, true); // Choose to copy
setChoice(playerA, azusasManyJourneys);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
addCounters(1, PhaseStep.PRECOMBAT_MAIN, playerA, "@impersonator", CounterType.LORE, 2);
setChoice(playerA, "II"); // order triggers
setStrictChooseMode(true);
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
execute();
assertPermanentCount(playerA, azusasManyJourneys, 1);
assertPermanentCount(playerA, likenessOfTheSeeker, 0);
assertPermanentCount(playerA, "Clever Impersonator", 0);
assertExileCount(playerA, "Clever Impersonator", 1);
}
}

View file

@ -2297,31 +2297,14 @@ public class VerifyCardDataTest {
fail(card, "abilities", "transforming double-faced card should not have abilities on the main card");
}
// TODO: remove after transform ability removed
// special check: new DFC implementation should not have transform ability
if (card instanceof DoubleFacedCardHalf && card.getAbilities().containsClass(TransformAbility.class)
&& !card.getAbilities().containsClass(DayboundAbility.class)
&& !card.getAbilities().containsClass(CraftAbility.class)
&& !card.getAbilities().containsClass(SiegeAbility.class)) {
fail(card, "abilities", "new transforming double-faced card should not have transform ability");
}
// special check: Werewolves front ability should only be on front and vice versa
if (card.getAbilities().containsClass(WerewolfFrontTriggeredAbility.class) && (card.isNightCard() || (card instanceof DoubleFacedCardHalf && ((DoubleFacedCardHalf) card).isBackSide()))) {
if (card.getAbilities().containsClass(WerewolfFrontTriggeredAbility.class) && (card instanceof DoubleFacedCardHalf && ((DoubleFacedCardHalf) card).isBackSide())) {
fail(card, "abilities", "card is a back face werewolf with a front face ability");
}
if (card.getAbilities().containsClass(WerewolfBackTriggeredAbility.class) && (!card.isNightCard() && (card instanceof DoubleFacedCardHalf && !((DoubleFacedCardHalf) card).isBackSide()))) {
if (card.getAbilities().containsClass(WerewolfBackTriggeredAbility.class) && (card instanceof DoubleFacedCardHalf && !((DoubleFacedCardHalf) card).isBackSide())) {
fail(card, "abilities", "card is a front face werewolf with a back face ability");
}
// special check: transform ability in TDFC should only be on front and vice versa
if (card.getSecondCardFace() != null && !card.isNightCard() && !card.getAbilities().containsClass(TransformAbility.class)) {
fail(card, "abilities", "double-faced cards should have transform ability on the front");
}
if (card.getSecondCardFace() != null && card.isNightCard() && card.getAbilities().containsClass(TransformAbility.class)) {
fail(card, "abilities", "double-faced cards should not have transform ability on the back");
}
// special check: back side in TDFC must be only night card
if (card.getSecondCardFace() != null && !card.getSecondCardFace().isNightCard()) {
fail(card, "abilities", "the back face of a double-faced card should be nightCard = true");

View file

@ -5,9 +5,9 @@ import mage.abilities.Ability;
import mage.abilities.StaticAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.constants.*;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -21,7 +21,6 @@ public class SiegeAbility extends StaticAbility {
public SiegeAbility() {
super(Zone.ALL, null);
this.addSubAbility(new TransformAbility());
this.addSubAbility(new SiegeDefeatedTriggeredAbility());
}

View file

@ -1,16 +1,13 @@
package mage.abilities.common;
import mage.MageIdentifier;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.*;
import mage.constants.SpellAbilityCastMode;
import mage.constants.SpellAbilityType;
import mage.game.Game;
import mage.game.stack.Spell;
import java.util.Set;
import java.util.UUID;
@ -21,7 +18,6 @@ import java.util.UUID;
public class SpellTransformedAbility extends SpellAbility {
protected final String manaCost; //This variable is only used for rules text
private boolean ignoreTransformEffect; // TODO: temporary while converting tdfc
public SpellTransformedAbility(Card card, String manaCost) {
super(card.getSecondFaceSpellAbility());
@ -37,11 +33,6 @@ public class SpellTransformedAbility extends SpellAbility {
this.clearManaCosts();
this.clearManaCostsToPay();
this.addCost(new ManaCostsImpl<>(manaCost));
if (!(card instanceof TransformingDoubleFacedCard)) {
this.addSubAbility(new TransformAbility());
} else {
ignoreTransformEffect = true;
}
}
public SpellTransformedAbility(final SpellAbility ability) {
@ -54,13 +45,11 @@ public class SpellTransformedAbility extends SpellAbility {
this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
this.setSpellAbilityCastMode(SpellAbilityCastMode.TRANSFORMED);
//when casting this way, the card must have the TransformAbility from elsewhere
}
protected SpellTransformedAbility(final SpellTransformedAbility ability) {
super(ability);
this.manaCost = ability.manaCost;
this.ignoreTransformEffect = ability.ignoreTransformEffect;
}
@Override
@ -71,14 +60,7 @@ public class SpellTransformedAbility extends SpellAbility {
@Override
public boolean activate(Game game, Set<MageIdentifier> allowedIdentifiers, boolean noMana) {
if (super.activate(game, allowedIdentifiers, noMana)) {
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + getSourceId(), Boolean.TRUE);
if (ignoreTransformEffect) {
return true;
}
// TODO: must be removed after transform cards (one side) migrated to MDF engine (multiple sides)
TransformedEffect effect = new TransformedEffect();
game.addEffect(effect, this);
effect.apply(game, this); //Apply the effect immediately
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + getSourceId(), Boolean.TRUE);
return true;
}
return false;
@ -95,31 +77,3 @@ public class SpellTransformedAbility extends SpellAbility {
return ActivationStatus.getFalse();
}
}
class TransformedEffect extends ContinuousEffectImpl {
public TransformedEffect() {
super(Duration.WhileOnStack, Layer.CopyEffects_1, SubLayer.CopyEffects_1a, Outcome.BecomeCreature);
staticText = "";
}
private TransformedEffect(final TransformedEffect effect) {
super(effect);
}
@Override
public TransformedEffect copy() {
return new TransformedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getSpell(source.getSourceId());
if (spell == null || spell.getCard().getSecondCardFace() == null) {
return false;
}
// simulate another side as new card (another code part in spell constructor)
TransformAbility.transformCardSpellDynamic(spell, spell.getCard().getSecondCardFace(), game);
return true;
}
}

View file

@ -1,13 +1,10 @@
package mage.abilities.effects;
import java.util.Locale;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -18,6 +15,9 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInGraveyard;
import java.util.Locale;
import java.util.UUID;
/**
* Cards with the Aura subtype don't change the zone they are in, if there is no
* valid target on the battlefield. Also, when entering the battlefield and it
@ -184,7 +184,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
return false;
}
// in case of transformable enchantments
if (Boolean.TRUE.equals(game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()))
if (Boolean.TRUE.equals(game.getState().getValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + card.getId()))
&& card.getSecondCardFace() != null) {
card = card.getSecondCardFace();
}

View file

@ -9,6 +9,7 @@ import mage.abilities.costs.common.ExileSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
@ -59,7 +60,6 @@ public class CraftAbility extends ActivatedAbilityImpl {
super(Zone.BATTLEFIELD, new CraftEffect(), new ManaCostsImpl<>(manaString));
this.addCost(new ExileSourceCost());
this.addCost(new CraftCost(target));
this.addSubAbility(new TransformAbility());
this.timing = TimingRule.SORCERY;
this.manaString = manaString;
this.description = description;
@ -173,7 +173,7 @@ class CraftEffect extends OneShotEffect {
if (player == null || card == null || card.getZoneChangeCounter(game) != source.getStackMomentSourceZCC() + 1) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
player.moveCards(card, Zone.BATTLEFIELD, source, game);
return true;
}

View file

@ -15,7 +15,6 @@ public class DayboundAbility extends StaticAbility {
public DayboundAbility() {
super(Zone.BATTLEFIELD, new DayboundEffect());
this.addHint(DayNightHint.instance);
this.addSubAbility(new TransformAbility());
}
private DayboundAbility(final DayboundAbility ability) {

View file

@ -1,177 +0,0 @@
package mage.abilities.keyword;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.cards.Card;
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;
/**
* @author nantuko
*/
public class TransformAbility extends SimpleStaticAbility {
// this state value controls if a permanent enters the battlefield already transformed
public static final String VALUE_KEY_ENTER_TRANSFORMED = "EnterTransformed";
public TransformAbility() {
super(Zone.BATTLEFIELD, new TransformEffect());
}
private TransformAbility(final TransformAbility ability) {
super(ability);
}
@Override
public TransformAbility copy() {
return new TransformAbility(this);
}
@Override
public String getRule() {
return "";
}
/**
* Apply transform effect to permanent (copy characteristic and other things)
*/
public static boolean transformPermanent(Permanent permanent, Game game, Ability source) {
MageObject sourceCard = findSourceObjectForTransform(permanent);
if (sourceCard == null) {
return false;
}
permanent.setTransformed(true);
permanent.setName(sourceCard.getName());
permanent.getColor(game).setColor(sourceCard.getColor(game));
permanent.getManaCost().clear();
permanent.getManaCost().add(sourceCard.getManaCost().copy());
permanent.removeAllCardTypes(game);
for (CardType type : sourceCard.getCardType(game)) {
permanent.addCardType(game, type);
}
permanent.removeAllSubTypes(game);
permanent.copySubTypesFrom(game, sourceCard);
permanent.removeAllSuperTypes(game);
for (SuperType type : sourceCard.getSuperType(game)) {
permanent.addSuperType(game, type);
}
CardUtil.copySetAndCardNumber(permanent, sourceCard);
permanent.getAbilities().clear();
for (Ability ability : sourceCard.getAbilities()) {
// source == null -- call from init card (e.g. own abilities)
// source != null -- from apply effect
permanent.addAbility(ability, source == null ? permanent.getId() : source.getSourceId(), game, true);
}
permanent.getPower().setModifiedBaseValue(sourceCard.getPower().getValue());
permanent.getToughness().setModifiedBaseValue(sourceCard.getToughness().getValue());
permanent.setStartingLoyalty(sourceCard.getStartingLoyalty());
permanent.setStartingDefense(sourceCard.getStartingDefense());
return true;
}
private static MageObject findSourceObjectForTransform(Permanent permanent) {
if (permanent == null) {
return null;
}
// copies can't transform
if (permanent.isCopy()) {
return null;
}
if (permanent instanceof PermanentToken) {
return ((PermanentToken) permanent).getToken().getBackFace();
} else {
return permanent.getSecondCardFace();
}
}
public static Card transformCardSpellStatic(Card mainSide, Card otherSide, Game game) {
// workaround to simulate transformed card on the stack (example: disturb ability)
// prepare static attributes
// TODO: must be removed after transform cards (one side) migrated to MDF engine (multiple sides)
Card newCard = mainSide.copy();
newCard.setName(otherSide.getName());
// mana value must be from main side only
newCard.getManaCost().clear();
newCard.getManaCost().add(mainSide.getManaCost().copy());
game.getState().getCardState(newCard.getId()).clearAbilities();
for (Ability ability : otherSide.getAbilities()) {
game.getState().addOtherAbility(newCard, ability);
}
newCard.getPower().setModifiedBaseValue(otherSide.getPower().getValue());
newCard.getToughness().setModifiedBaseValue(otherSide.getToughness().getValue());
return newCard;
}
public static void transformCardSpellDynamic(Spell spell, Card otherSide, Game game) {
// workaround to simulate transformed card on the stack (example: disturb ability)
// prepare dynamic attributes
// TODO: must be removed after transform cards (one side) migrated to MDF engine (multiple sides)
MageObjectAttribute moa = game.getState().getCreateMageObjectAttribute(spell.getCard(), game);
moa.getColor().setColor(otherSide.getColor(game));
moa.getCardType().clear();
moa.getCardType().addAll(otherSide.getCardType(game));
moa.getSuperType().clear();
moa.getSuperType().addAll(otherSide.getSuperType(game));
moa.getSubtype().clear();
moa.getSubtype().addAll(otherSide.getSubtype(game));
game.getState().getCardState(spell.getCard().getId()).clearAbilities();
for (Ability ability : otherSide.getAbilities()) {
game.getState().addOtherAbility(spell.getCard(), ability);
}
}
}
class TransformEffect extends ContinuousEffectImpl {
TransformEffect() {
super(Duration.WhileOnBattlefield, Layer.CopyEffects_1, SubLayer.CopyEffects_1a, Outcome.BecomeCreature);
staticText = "";
}
private TransformEffect(final TransformEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent == null) {
return false;
}
// only for transformed permanents
if (!permanent.isTransformed()) {
return false;
}
return TransformAbility.transformPermanent(permanent, game, source);
}
@Override
public TransformEffect copy() {
return new TransformEffect(this);
}
@Override
public String getText(Mode mode) {
return "";
}
}

View file

@ -8,6 +8,9 @@ import java.util.UUID;
public abstract class TransformingDoubleFacedCard extends DoubleFacedCard {
// this state value controls if a permanent enters the battlefield already transformed
public static final String VALUE_KEY_ENTER_TRANSFORMED = "EnterTransformed";
public TransformingDoubleFacedCard(
UUID ownerId, CardSetInfo setInfo,
CardType[] typesLeft, SubType[] subTypesLeft, String costsLeft,

View file

@ -1,8 +1,10 @@
package mage.constants;
import mage.abilities.Ability;
import mage.abilities.keyword.TransformAbility;
import mage.cards.*;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.TransformingDoubleFacedCard;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@ -93,7 +95,7 @@ public enum PutCards {
if (card instanceof TransformingDoubleFacedCard) {
card = ((TransformingDoubleFacedCard) card).getRightHalfCard();
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId(), Boolean.TRUE);
game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + card.getId(), Boolean.TRUE);
case BATTLEFIELD:
case EXILED:
case HAND:
@ -131,7 +133,7 @@ public enum PutCards {
case SHUFFLE:
return player.shuffleCardsToLibrary(cards, game, source);
case BATTLEFIELD_TRANSFORMED:
cards.stream().forEach(uuid -> game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + uuid, Boolean.TRUE));
cards.stream().forEach(uuid -> game.getState().setValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + uuid, Boolean.TRUE));
case BATTLEFIELD:
case EXILED:
case HAND:

View file

@ -0,0 +1,19 @@
package mage.filter.predicate.permanent;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
public enum TransformablePredicate implements Predicate<Permanent> {
instance;
@Override
public boolean apply(Permanent input, Game game) {
return input.isTransformable();
}
@Override
public String toString() {
return "Transformable";
}
}

View file

@ -1,7 +1,6 @@
package mage.game;
import mage.abilities.Ability;
import mage.abilities.keyword.TransformAbility;
import mage.cards.*;
import mage.constants.Outcome;
import mage.constants.Zone;
@ -91,8 +90,7 @@ public final class ZonesHandler {
Card card = game.getCard(info.event.getTargetId());
if (card instanceof DoubleFacedCard || card instanceof DoubleFacedCardHalf) {
boolean forceToMainSide = false;
// TODO: move transform key or have some other identifier after tdfc rework
Boolean enterTransformed = (Boolean) game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId());
Boolean enterTransformed = (Boolean) game.getState().getValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + card.getId());
if (enterTransformed == null) {
enterTransformed = false;
}
@ -296,7 +294,7 @@ public final class ZonesHandler {
game.getPermanentsEntering().remove(permanent.getId());
break;
default:
throw new UnsupportedOperationException("to Zone " + toZone.toString() + " not supported yet");
throw new UnsupportedOperationException("to Zone " + toZone + " not supported yet");
}
}
@ -376,15 +374,13 @@ public final class ZonesHandler {
isGoodToMove = true;
} else if (event.getToZone().equals(Zone.BATTLEFIELD)) {
// non-permanents can't move to battlefield
// TODO: possible bug with Nightbound, search all usage of getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED and insert additional check Ability.checkCard
// TODO: possible bug with Nightbound, search all usage of getValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED and insert additional check Ability.checkCard
/*
* 712.14a. If a spell or ability puts a transforming double-faced card onto the battlefield "transformed"
* or "converted," it enters the battlefield with its back face up. If a player is instructed to put a card
* that isn't a transforming double-faced card onto the battlefield transformed or converted, that card stays in
* its current zone.
* 712.14a. If a spell or ability puts a double-faced card onto the battlefield "transformed" or "converted,"
* it enters the battlefield with its back face up. If a player is instructed to put a card that isn't a double-faced card
* onto the battlefield transformed or converted, that card stays in its current zone.
*/
// TODO: remove after tdfc rework
boolean wantToTransform = Boolean.TRUE.equals(game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()));
boolean wantToTransform = Boolean.TRUE.equals(game.getState().getValue(TransformingDoubleFacedCard.VALUE_KEY_ENTER_TRANSFORMED + card.getId()));
if (wantToTransform && !(card instanceof DoubleFacedCardHalf)) {
isGoodToMove = card.isTransformable() && card.getSecondCardFace().isPermanent(game);
} else {

View file

@ -3,7 +3,6 @@ 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;
@ -18,7 +17,6 @@ public final class IncubatorToken extends TokenImpl {
subtype.add(SubType.INCUBATOR);
this.backFace = new Phyrexian00Token();
this.addAbility(new TransformAbility());
this.addAbility(new SimpleActivatedAbility(
new TransformSourceEffect().setText("transform this artifact"), new GenericManaCost(2)
));

View file

@ -8,7 +8,6 @@ import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.keyword.BestowAbility;
import mage.abilities.keyword.PrototypeAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.*;
import mage.constants.*;
import mage.counters.Counter;
@ -81,11 +80,6 @@ public class Spell extends StackObjectImpl implements Card {
Card affectedCard = card;
// TODO: must be removed after transform cards (one side) migrated to MDF engine (multiple sides)
if (ability.getSpellAbilityCastMode().isTransformed() && affectedCard.getSecondCardFace() != null) {
// simulate another side as new card (another code part in continues effect from disturb ability)
affectedCard = TransformAbility.transformCardSpellStatic(card, card.getSecondCardFace(), game);
}
if (ability instanceof PrototypeAbility) {
affectedCard = ((PrototypeAbility) ability).prototypeCardSpell(card);
this.prototyped = true;

View file

@ -4110,7 +4110,7 @@ public abstract class PlayerImpl implements Player, Serializable {
TransformingDoubleFacedCard mainCard = (TransformingDoubleFacedCard) object;
getPlayableFromObjectSingle(game, fromZone, mainCard.getLeftHalfCard(), mainCard.getLeftHalfCard().getAbilities(game), availableMana, output);
getPlayableFromObjectSingle(game, fromZone, mainCard, mainCard.getSharedAbilities(game), availableMana, output);
} else if (object instanceof CardWithSpellOption) {
} else if (object instanceof CardWithSpellOption) {
// adventure must use different card characteristics for different spells (main or adventure)
CardWithSpellOption cardWithSpellOption = (CardWithSpellOption) object;
getPlayableFromObjectSingle(game, fromZone, cardWithSpellOption.getSpellCard(), cardWithSpellOption.getSpellCard().getAbilities(game), availableMana, output);
@ -4952,16 +4952,6 @@ public abstract class PlayerImpl implements Player, Serializable {
for (Card card : cards) {
fromZone = game.getState().getZone(card.getId());
// 712.14a. If a spell or ability puts a transforming double-faced card onto the battlefield "transformed"
// or "converted," it enters the battlefield with its back face up. If a player is instructed to put a card
// that isn't a transforming double-faced card onto the battlefield transformed or converted, that card stays in
// its current zone.
// TODO: can probably remove/change after tdfc rework, should only be sending transformed side
Boolean enterTransformed = (Boolean) game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId());
if (enterTransformed != null && enterTransformed && !card.isTransformable() && !(card instanceof TransformingDoubleFacedCardHalf)) {
continue;
}
// 303.4g. If an Aura is entering the battlefield and there is no legal object or player for it to enchant,
// the Aura remains in its current zone, unless that zone is the stack. In that case, the Aura is put into
// its owner's graveyard instead of entering the battlefield. If the Aura is a token, it isn't created.