mirror of
https://github.com/correl/mage.git
synced 2025-01-12 19:25:44 +00:00
[STX] Implemented Manifestation Sage
This commit is contained in:
parent
8996daeb82
commit
b6ca0ca222
6 changed files with 187 additions and 108 deletions
|
@ -13,15 +13,13 @@ import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.counters.CounterType;
|
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||||
import mage.filter.predicate.mageobject.SharesColorPredicate;
|
import mage.filter.predicate.mageobject.SharesColorPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.FractalToken;
|
import mage.game.permanent.token.QuandrixToken;
|
||||||
import mage.game.permanent.token.Token;
|
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetCardInLibrary;
|
import mage.target.common.TargetCardInLibrary;
|
||||||
|
|
||||||
|
@ -48,7 +46,9 @@ public final class KasminaEnigmaSage extends CardImpl {
|
||||||
this.addAbility(new LoyaltyAbility(new ScryEffect(1), 2));
|
this.addAbility(new LoyaltyAbility(new ScryEffect(1), 2));
|
||||||
|
|
||||||
// −X: Create a 0/0 green and blue Fractal creature token. Put X +1/+1 counters on it.
|
// −X: Create a 0/0 green and blue Fractal creature token. Put X +1/+1 counters on it.
|
||||||
this.addAbility(new LoyaltyAbility(new KasminaEnigmaSageTokenEffect()));
|
this.addAbility(new LoyaltyAbility(QuandrixToken.getEffect(
|
||||||
|
GetXLoyaltyValue.instance, "Put X +1/+1 counters on it"
|
||||||
|
)));
|
||||||
|
|
||||||
// −8: Search your library for an instant or sorcery card that shares a color with this planeswalker, exile that card, then shuffle. You may cast that card without paying its mana cost.
|
// −8: Search your library for an instant or sorcery card that shares a color with this planeswalker, exile that card, then shuffle. You may cast that card without paying its mana cost.
|
||||||
this.addAbility(new LoyaltyAbility(new KasminaEnigmaSageSearchEffect(), -8));
|
this.addAbility(new LoyaltyAbility(new KasminaEnigmaSageSearchEffect(), -8));
|
||||||
|
@ -106,40 +106,6 @@ class KasminaEnigmaSageGainAbilitiesEffect extends ContinuousEffectImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class KasminaEnigmaSageTokenEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
KasminaEnigmaSageTokenEffect() {
|
|
||||||
super(Outcome.Benefit);
|
|
||||||
staticText = "create a 0/0 green and blue Fractal creature token. Put X +1/+1 counters on it";
|
|
||||||
}
|
|
||||||
|
|
||||||
private KasminaEnigmaSageTokenEffect(final KasminaEnigmaSageTokenEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public KasminaEnigmaSageTokenEffect copy() {
|
|
||||||
return new KasminaEnigmaSageTokenEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Token token = new FractalToken();
|
|
||||||
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
|
||||||
int loyalty = GetXLoyaltyValue.instance.calculate(game, source, this);
|
|
||||||
if (loyalty < 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for (UUID tokenId : token.getLastAddedTokenIds()) {
|
|
||||||
Permanent permanent = game.getPermanent(tokenId);
|
|
||||||
if (permanent != null) {
|
|
||||||
permanent.addCounters(CounterType.P1P1.createInstance(loyalty), source.getControllerId(), source, game);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class KasminaEnigmaSageSearchEffect extends OneShotEffect {
|
class KasminaEnigmaSageSearchEffect extends OneShotEffect {
|
||||||
|
|
||||||
KasminaEnigmaSageSearchEffect() {
|
KasminaEnigmaSageSearchEffect() {
|
||||||
|
|
|
@ -5,7 +5,10 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.hint.Hint;
|
||||||
import mage.abilities.keyword.FlyingAbility;
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
|
@ -13,15 +16,15 @@ import mage.counters.CounterType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.common.FilterOwnedCard;
|
import mage.filter.common.FilterOwnedCard;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.token.QuandrixToken;
|
||||||
import mage.game.permanent.token.FractalToken;
|
|
||||||
import mage.game.permanent.token.Token;
|
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetCard;
|
import mage.target.TargetCard;
|
||||||
import mage.target.common.TargetCardInExile;
|
import mage.target.common.TargetCardInExile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
|
@ -45,9 +48,10 @@ public final class KianneDeanOfSubstance extends ModalDoubleFacesCard {
|
||||||
));
|
));
|
||||||
|
|
||||||
// {4}{G}: Create a 0/0 green and blue Fractal creature token. Put a +1/+1 counter on it for each different mana value among nonland cards you own in exile with study counters on them.
|
// {4}{G}: Create a 0/0 green and blue Fractal creature token. Put a +1/+1 counter on it for each different mana value among nonland cards you own in exile with study counters on them.
|
||||||
this.getLeftHalfCard().addAbility(new SimpleActivatedAbility(
|
this.getLeftHalfCard().addAbility(new SimpleActivatedAbility(QuandrixToken.getEffect(
|
||||||
new KianneDeanOfSubstanceTokenEffect(), new ManaCostsImpl("{4}{G}")
|
KianneDeanOfSubstanceValue.instance, "Put a +1/+1 counter on it for each different mana value " +
|
||||||
));
|
"among nonland cards you own in exile with study counters on them"
|
||||||
|
), new ManaCostsImpl("{4}{G}")).addHint(KianneDeanOfSubstanceHint.instance));
|
||||||
|
|
||||||
// 2.
|
// 2.
|
||||||
// Imbraham, Dean of Theory
|
// Imbraham, Dean of Theory
|
||||||
|
@ -114,48 +118,62 @@ class KianneDeanOfSubstanceExileEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class KianneDeanOfSubstanceTokenEffect extends OneShotEffect {
|
enum KianneDeanOfSubstanceValue implements DynamicValue {
|
||||||
|
instance;
|
||||||
KianneDeanOfSubstanceTokenEffect() {
|
|
||||||
super(Outcome.Benefit);
|
|
||||||
staticText = "create a 0/0 green and blue Fractal creature token. Put a +1/+1 counter on it " +
|
|
||||||
"for each different mana value among nonland cards you own in exile with study counters on them";
|
|
||||||
}
|
|
||||||
|
|
||||||
private KianneDeanOfSubstanceTokenEffect(final KianneDeanOfSubstanceTokenEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KianneDeanOfSubstanceTokenEffect copy() {
|
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||||
return new KianneDeanOfSubstanceTokenEffect(this);
|
return game
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Token token = new FractalToken();
|
|
||||||
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
|
||||||
int exileCount = game
|
|
||||||
.getExile()
|
.getExile()
|
||||||
.getAllCards(game)
|
.getAllCards(game)
|
||||||
.stream()
|
.stream()
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.filter(card -> card.isOwnedBy(source.getControllerId()))
|
.filter(card -> card.isOwnedBy(sourceAbility.getControllerId()))
|
||||||
|
.filter(card -> card.getCounters(game).containsKey(CounterType.STUDY))
|
||||||
.map(MageObject::getConvertedManaCost)
|
.map(MageObject::getConvertedManaCost)
|
||||||
.distinct()
|
.distinct()
|
||||||
.mapToInt(x -> 1)
|
.mapToInt(x -> 1)
|
||||||
.sum();
|
.sum();
|
||||||
if (exileCount < 1) {
|
}
|
||||||
return true;
|
|
||||||
|
@Override
|
||||||
|
public KianneDeanOfSubstanceValue copy() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum KianneDeanOfSubstanceHint implements Hint {
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText(Game game, Ability ability) {
|
||||||
|
List<Integer> values = game.getExile()
|
||||||
|
.getAllCards(game)
|
||||||
|
.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(card -> card.isOwnedBy(ability.getControllerId()))
|
||||||
|
.filter(card -> card.getCounters(game).containsKey(CounterType.STUDY))
|
||||||
|
.map(MageObject::getConvertedManaCost)
|
||||||
|
.distinct()
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
String message = "" + values.size();
|
||||||
|
if (values.size() > 0) {
|
||||||
|
message += " (";
|
||||||
|
message += values.stream().map(i -> "" + i).reduce((a, b) -> a + ", " + b).orElse("");
|
||||||
|
message += ')';
|
||||||
}
|
}
|
||||||
for (UUID tokenId : token.getLastAddedTokenIds()) {
|
return "Mana values of cards exiled with study counters: " + message;
|
||||||
Permanent permanent = game.getPermanent(tokenId);
|
}
|
||||||
if (permanent == null) {
|
|
||||||
continue;
|
@Override
|
||||||
}
|
public KianneDeanOfSubstanceHint copy() {
|
||||||
permanent.addCounters(CounterType.P1P1.createInstance(exileCount), source.getControllerId(), source, game);
|
return instance;
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
42
Mage.Sets/src/mage/cards/m/ManifestationSage.java
Normal file
42
Mage.Sets/src/mage/cards/m/ManifestationSage.java
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package mage.cards.m;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.dynamicvalue.common.CardsInControllerHandCount;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.game.permanent.token.QuandrixToken;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class ManifestationSage extends CardImpl {
|
||||||
|
|
||||||
|
public ManifestationSage(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G/U}{G/U}{G/U}{G/U}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.HUMAN);
|
||||||
|
this.subtype.add(SubType.WIZARD);
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
|
// When Manifestation Sage enters the battlefield, create a 0/0 green and blue Fractal creature token. Put X +1/+1 counters on it, where X is the number of cards in your hand.
|
||||||
|
this.addAbility(new EntersBattlefieldTriggeredAbility(QuandrixToken.getEffect(
|
||||||
|
CardsInControllerHandCount.instance, "Put X +1/+1 counters on it, " +
|
||||||
|
"where X is the number of cards in your hand"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ManifestationSage(final ManifestationSage card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ManifestationSage copy() {
|
||||||
|
return new ManifestationSage(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -83,6 +83,7 @@ public final class StrixhavenSchoolOfMages extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Lorehold Pledgemage", 201, Rarity.COMMON, mage.cards.l.LoreholdPledgemage.class));
|
cards.add(new SetCardInfo("Lorehold Pledgemage", 201, Rarity.COMMON, mage.cards.l.LoreholdPledgemage.class));
|
||||||
cards.add(new SetCardInfo("Mage Hunter", 76, Rarity.UNCOMMON, mage.cards.m.MageHunter.class));
|
cards.add(new SetCardInfo("Mage Hunter", 76, Rarity.UNCOMMON, mage.cards.m.MageHunter.class));
|
||||||
cards.add(new SetCardInfo("Magma Opus", 203, Rarity.MYTHIC, mage.cards.m.MagmaOpus.class));
|
cards.add(new SetCardInfo("Magma Opus", 203, Rarity.MYTHIC, mage.cards.m.MagmaOpus.class));
|
||||||
|
cards.add(new SetCardInfo("Manifestation Sage", 205, Rarity.RARE, mage.cards.m.ManifestationSage.class));
|
||||||
cards.add(new SetCardInfo("Mountain", 372, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Mountain", 372, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Multiple Choice", 48, Rarity.RARE, mage.cards.m.MultipleChoice.class));
|
cards.add(new SetCardInfo("Multiple Choice", 48, Rarity.RARE, mage.cards.m.MultipleChoice.class));
|
||||||
cards.add(new SetCardInfo("Necroblossom Snarl", 269, Rarity.RARE, mage.cards.n.NecroblossomSnarl.class));
|
cards.add(new SetCardInfo("Necroblossom Snarl", 269, Rarity.RARE, mage.cards.n.NecroblossomSnarl.class));
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
package mage.game.permanent.token;
|
|
||||||
|
|
||||||
import mage.MageInt;
|
|
||||||
import mage.constants.CardType;
|
|
||||||
import mage.constants.SubType;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author TheElk801
|
|
||||||
*/
|
|
||||||
public final class FractalToken extends TokenImpl {
|
|
||||||
|
|
||||||
public FractalToken() {
|
|
||||||
super("Fractal", "0/0 green and blue Fractal creature token");
|
|
||||||
cardType.add(CardType.CREATURE);
|
|
||||||
subtype.add(SubType.FRACTAL);
|
|
||||||
color.setGreen(true);
|
|
||||||
color.setBlue(true);
|
|
||||||
power = new MageInt(0);
|
|
||||||
toughness = new MageInt(0);
|
|
||||||
|
|
||||||
availableImageSetCodes = Arrays.asList("STX");
|
|
||||||
}
|
|
||||||
|
|
||||||
private FractalToken(final FractalToken token) {
|
|
||||||
super(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FractalToken copy() {
|
|
||||||
return new FractalToken(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
package mage.game.permanent.token;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class QuandrixToken extends TokenImpl {
|
||||||
|
|
||||||
|
public QuandrixToken() {
|
||||||
|
super("Fractal", "0/0 green and blue Fractal creature token");
|
||||||
|
cardType.add(CardType.CREATURE);
|
||||||
|
subtype.add(SubType.FRACTAL);
|
||||||
|
color.setGreen(true);
|
||||||
|
color.setBlue(true);
|
||||||
|
power = new MageInt(0);
|
||||||
|
toughness = new MageInt(0);
|
||||||
|
|
||||||
|
availableImageSetCodes = Arrays.asList("STX");
|
||||||
|
}
|
||||||
|
|
||||||
|
private QuandrixToken(final QuandrixToken token) {
|
||||||
|
super(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuandrixToken copy() {
|
||||||
|
return new QuandrixToken(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QuandrixTokenEffect getEffect(DynamicValue xValue, String text) {
|
||||||
|
return new QuandrixTokenEffect(xValue, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class QuandrixTokenEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
private final DynamicValue xValue;
|
||||||
|
|
||||||
|
private QuandrixTokenEffect(DynamicValue xValue, String text) {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
this.xValue = xValue;
|
||||||
|
this.staticText = "create a 0/0 green and blue Fractal creature token. " + text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private QuandrixTokenEffect(final QuandrixTokenEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
this.xValue = effect.xValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QuandrixTokenEffect copy() {
|
||||||
|
return new QuandrixTokenEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Token token = new QuandrixToken();
|
||||||
|
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
||||||
|
int value = xValue.calculate(game, source, this);
|
||||||
|
if (value < 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (UUID tokenId : token.getLastAddedTokenIds()) {
|
||||||
|
Permanent permanent = game.getPermanent(tokenId);
|
||||||
|
if (permanent == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
permanent.addCounters(CounterType.P1P1.createInstance(value), source.getControllerId(), source, game);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue