Implemented Jace, Mirror Mage

This commit is contained in:
Evan Kranzler 2020-08-26 18:48:59 -04:00
parent c84c17a455
commit 6903dad861
7 changed files with 169 additions and 5 deletions

View file

@ -0,0 +1,134 @@
package mage.cards.j;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.condition.common.KickedCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
import mage.abilities.effects.keyword.ScryEffect;
import mage.cards.Card;
import mage.cards.CardsImpl;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.keyword.KickerAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
/**
* @author TheElk801
*/
public final class JaceMirrorMage extends CardImpl {
public JaceMirrorMage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{U}{U}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.JACE);
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// Kicker {2}
this.addAbility(new KickerAbility(new ManaCostsImpl<>("{2}")));
// When Jace, Mirror Mage enters the battlefield, if Jace was kicked, create a token that's a copy of Jace, Mirror Mage except it's not legendary and its starting loyalty is 1.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new JaceMirrorMageCopyEffect()),
KickedCondition.instance, "When {this} enters the battlefield, if {this} was kicked, " +
"create a token that's a copy of {this} except it's not legendary and its starting loyalty is 1."
));
// +1: Scry 2.
this.addAbility(new LoyaltyAbility(new ScryEffect(2), 1));
// 0: Draw a card and reveal it. Remove a number of loyalty counters equal to that card's converted mana cost from Jace, Mirror Mage.
this.addAbility(new LoyaltyAbility(new JaceMirrorMageDrawEffect(), 0));
}
private JaceMirrorMage(final JaceMirrorMage card) {
super(card);
}
@Override
public JaceMirrorMage copy() {
return new JaceMirrorMage(this);
}
}
class JaceMirrorMageCopyEffect extends OneShotEffect {
JaceMirrorMageCopyEffect() {
super(Outcome.Benefit);
}
private JaceMirrorMageCopyEffect(final JaceMirrorMageCopyEffect effect) {
super(effect);
}
@Override
public JaceMirrorMageCopyEffect copy() {
return new JaceMirrorMageCopyEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (permanent == null) {
return false;
}
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, false, 1);
effect.setTargetPointer(new FixedTarget(source.getSourceId(), game));
effect.setIsntLegendary(true);
effect.setStartingLoyalty(1);
return effect.apply(game, source);
}
}
class JaceMirrorMageDrawEffect extends OneShotEffect {
JaceMirrorMageDrawEffect() {
super(Outcome.Benefit);
staticText = "draw a card and reveal it. Remove a number of loyalty counters equal to that card's converted mana cost from {this}";
}
private JaceMirrorMageDrawEffect(final JaceMirrorMageDrawEffect effect) {
super(effect);
}
@Override
public JaceMirrorMageDrawEffect copy() {
return new JaceMirrorMageDrawEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
// TODO: Make this and similar effects work with draw replacement correctly
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Card card = player.getLibrary().getFromTop(game);
player.drawCards(1, source.getSourceId(), game);
player.revealCards(source, new CardsImpl(card), game);
if (card == null || card.getConvertedManaCost() == 0) {
return true;
}
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
if (permanent == null) {
return true;
}
permanent.removeCounters(CounterType.LOYALTY.createInstance(card.getConvertedManaCost()), game);
return true;
}
}

View file

@ -26,5 +26,6 @@ public final class ZendikarRising extends ExpansionSet {
this.ratioBoosterMythic = 8; this.ratioBoosterMythic = 8;
this.maxCardNumberInBooster = 280; this.maxCardNumberInBooster = 280;
cards.add(new SetCardInfo("Jace, Mirror Mage", 63, Rarity.MYTHIC, mage.cards.j.JaceMirrorMage.class));
} }
} }

View file

@ -4,6 +4,7 @@ import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import mage.abilities.Abilities; import mage.abilities.Abilities;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCost;
@ -65,6 +66,8 @@ public interface MageObject extends MageItem, Serializable {
int getStartingLoyalty(); int getStartingLoyalty();
void setStartingLoyalty(int startingLoyalty);
void adjustCosts(Ability ability, Game game); void adjustCosts(Ability ability, Game game);
void adjustTargets(Ability ability, Game game); void adjustTargets(Ability ability, Game game);

View file

@ -1,6 +1,7 @@
package mage; package mage;
import java.util.*; import java.util.*;
import mage.abilities.Abilities; import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl; import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -160,6 +161,15 @@ public abstract class MageObjectImpl implements MageObject {
return 0; return 0;
} }
@Override
public void setStartingLoyalty(int startingLoyalty) {
for (Ability ab : getAbilities()) {
if (ab instanceof PlaneswalkerEntersWithLoyaltyCountersAbility) {
((PlaneswalkerEntersWithLoyaltyCountersAbility) ab).setStartingLoyalty(startingLoyalty);
}
}
}
@Override @Override
public ObjectColor getColor(Game game) { public ObjectColor getColor(Game game) {
return color; return color;
@ -307,7 +317,7 @@ public abstract class MageObjectImpl implements MageObject {
*/ */
@Override @Override
public void removePTCDA() { public void removePTCDA() {
for (Iterator<Ability> iter = this.getAbilities().iterator(); iter.hasNext();) { for (Iterator<Ability> iter = this.getAbilities().iterator(); iter.hasNext(); ) {
Ability ability = iter.next(); Ability ability = iter.next();
for (Effect effect : ability.getEffects()) { for (Effect effect : ability.getEffects()) {
if (effect instanceof ContinuousEffect && ((ContinuousEffect) effect).getSublayer() == SubLayer.CharacteristicDefining_7a) { if (effect instanceof ContinuousEffect && ((ContinuousEffect) effect).getSublayer() == SubLayer.CharacteristicDefining_7a) {

View file

@ -9,12 +9,11 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.counters.CounterType; import mage.counters.CounterType;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public class PlaneswalkerEntersWithLoyaltyCountersAbility extends EntersBattlefieldAbility { public class PlaneswalkerEntersWithLoyaltyCountersAbility extends EntersBattlefieldAbility {
private final int startingLoyalty; private int startingLoyalty;
public PlaneswalkerEntersWithLoyaltyCountersAbility(int loyalty) { public PlaneswalkerEntersWithLoyaltyCountersAbility(int loyalty) {
super(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(loyalty))); super(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(loyalty)));
@ -31,6 +30,12 @@ public class PlaneswalkerEntersWithLoyaltyCountersAbility extends EntersBattlefi
return startingLoyalty; return startingLoyalty;
} }
public void setStartingLoyalty(int startingLoyalty) {
this.startingLoyalty = startingLoyalty;
this.getEffects().clear();
this.addEffect(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(startingLoyalty)));
}
@Override @Override
public PlaneswalkerEntersWithLoyaltyCountersAbility copy() { public PlaneswalkerEntersWithLoyaltyCountersAbility copy() {
return new PlaneswalkerEntersWithLoyaltyCountersAbility(this); return new PlaneswalkerEntersWithLoyaltyCountersAbility(this);

View file

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -46,6 +47,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
private ObjectColor color; private ObjectColor color;
private boolean useLKI = false; private boolean useLKI = false;
private boolean isntLegendary = false; private boolean isntLegendary = false;
private int startingLoyalty = -1;
private final List<Ability> additionalAbilities = new ArrayList(); private final List<Ability> additionalAbilities = new ArrayList();
public CreateTokenCopyTargetEffect(boolean useLKI) { public CreateTokenCopyTargetEffect(boolean useLKI) {
@ -176,6 +178,10 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
if (isntLegendary) { if (isntLegendary) {
token.getSuperType().remove(SuperType.LEGENDARY); token.getSuperType().remove(SuperType.LEGENDARY);
} }
if (startingLoyalty!=-1){
token.setStartingLoyalty(startingLoyalty);
}
if (additionalCardType != null && !token.getCardType().contains(additionalCardType)) { if (additionalCardType != null && !token.getCardType().contains(additionalCardType)) {
token.addCardType(additionalCardType); token.addCardType(additionalCardType);
} }
@ -288,6 +294,10 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
this.hasHaste = hasHaste; this.hasHaste = hasHaste;
} }
public void setStartingLoyalty(int startingLoyalty) {
this.startingLoyalty = startingLoyalty;
}
public void exileTokensCreatedAtNextEndStep(Game game, Ability source) { public void exileTokensCreatedAtNextEndStep(Game game, Ability source) {
for (Permanent tokenPermanent : addedTokenPermanents) { for (Permanent tokenPermanent : addedTokenPermanents) {
ExileTargetEffect exileEffect = new ExileTargetEffect(null, "", Zone.BATTLEFIELD); ExileTargetEffect exileEffect = new ExileTargetEffect(null, "", Zone.BATTLEFIELD);

View file

@ -53,6 +53,7 @@ Ingest|new|
Islandcycling|cost| Islandcycling|cost|
Islandwalk|new| Islandwalk|new|
Jump-start|card| Jump-start|card|
Kicker|cost|
Level up|cost| Level up|cost|
Lifelink|instance| Lifelink|instance|
Living weapon|new| Living weapon|new|