Implement 6 cmc pws (except Teferi) and rin (#6611)

[M21] Implement 6 cmc pws (except Teferi) and rin
This commit is contained in:
htrajan 2020-06-06 19:13:20 -07:00 committed by GitHub
parent d1da9ad843
commit a897df7c79
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 681 additions and 134 deletions

View file

@ -154,7 +154,7 @@
|Generate|TOK:5ED|Serf|||SerfToken|
|Generate|TOK:5ED|Snake|||SerpentGeneratorSnakeToken|
|Generate|TOK:5ED|Thrull|||BreedingPitBlackInsectToken|
|Generate|TOK:6ED|Cat|||WaitingInTheWeedsCatToken|
|Generate|TOK:6ED|Cat|||GreenCatToken|
|Generate|TOK:6ED|Citizen|||CitizenToken|
|Generate|TOK:6ED|Djinn|||DjinnToken|
|Generate|TOK:6ED|Goblin|||GoblinToken|
@ -1147,7 +1147,7 @@
|Generate|TOK:THS|Soldier|1||SoldierToken|
|Generate|TOK:THS|Soldier|2||SoldierToken|
|Generate|TOK:TMP|Beast|||CarnivoreToken|
|Generate|TOK:TMP|Hound|||HoundToken|
|Generate|TOK:TMP|Dog|||GreenDogToken|
|Generate|TOK:TMP|Pegasus|||PegasusToken|
|Generate|TOK:TMP|Reflection|||ReflectionToken|
|Generate|TOK:TMP|Saproling|||SaprolingToken|

View file

@ -0,0 +1,113 @@
package mage.cards.b;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author htrajan
*/
public final class BasriDevotedPaladin extends CardImpl {
public BasriDevotedPaladin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{W}{W}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.BASRI);
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: Put a +1/+1 counter on up to one target creature. It gains vigilance until end of turn.
Ability ability = new LoyaltyAbility(new AddCountersTargetEffect(
CounterType.P1P1.createInstance()
).setText("Put a +1/+1 counter on up to one target creature"), 1);
ability.addEffect(new GainAbilityTargetEffect(
VigilanceAbility.getInstance(), Duration.EndOfTurn
).setText("It gains vigilance until end of turn"));
ability.addTarget(new TargetCreaturePermanent(0, 1));
this.addAbility(ability);
// 1: Whenever a creature attacks this turn, put a +1/+1 counter on it.
this.addAbility(new LoyaltyAbility(new CreateDelayedTriggeredAbilityEffect(new BasriDevotedPaladinTriggeredAbility()), -1));
// 6: Creatures you control get +2/+2 and gain flying until end of turn.
Effect effect = new BoostControlledEffect(2, 2, Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE);
effect.setText("Creatures you control get +2/+2");
LoyaltyAbility ultimateAbility = new LoyaltyAbility(effect, -6);
effect = new GainAbilityControlledEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE);
effect.setText("and gain flying until end of turn");
ultimateAbility.addEffect(effect);
this.addAbility(ultimateAbility);
}
private BasriDevotedPaladin(final BasriDevotedPaladin card) {
super(card);
}
@Override
public BasriDevotedPaladin copy() {
return new BasriDevotedPaladin(this);
}
}
class BasriDevotedPaladinTriggeredAbility extends DelayedTriggeredAbility {
public BasriDevotedPaladinTriggeredAbility() {
super(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), Duration.EndOfTurn, false);
}
public BasriDevotedPaladinTriggeredAbility(BasriDevotedPaladinTriggeredAbility ability) {
super(ability);
}
@Override
public BasriDevotedPaladinTriggeredAbility copy() {
return new BasriDevotedPaladinTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ATTACKER_DECLARED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(event.getSourceId());
if (permanent != null) {
for (Effect effect : getEffects()) {
effect.setTargetPointer(new FixedTarget(permanent, game));
}
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever a creature attacks this turn, put a +1/+1 counter on it.";
}
}

View file

@ -0,0 +1,75 @@
package mage.cards.c;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.CastCardFromGraveyardThenExileItEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamagePlayersEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.continuous.CastFromHandWithoutPayingManaCostEffect;
import mage.abilities.effects.common.discard.DiscardHandControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
/**
*
* @author htrajan
*/
public final class ChandraFlamesCatalyst extends CardImpl {
private static final FilterCard filter = new FilterCard();
static {
filter.add(new ColorPredicate(ObjectColor.RED));
filter.add(Predicates.or(CardType.INSTANT.getPredicate(), CardType.SORCERY.getPredicate()));
}
public ChandraFlamesCatalyst(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{R}{R}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.CHANDRA);
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// +1: Chandra, Flame's Catalyst deals 3 damage to each opponent.
this.addAbility(new LoyaltyAbility(new DamagePlayersEffect(3, TargetController.OPPONENT), 1));
// 2: You may cast target red instant or sorcery card from your graveyard. If that spell would be put into your graveyard this turn, exile it instead.
CastCardFromGraveyardThenExileItEffect minusEffect = new CastCardFromGraveyardThenExileItEffect();
minusEffect.setText("You may cast target red instant or sorcery card from your graveyard. If that spell would be put into your graveyard this turn, exile it instead");
Ability ability = new LoyaltyAbility(minusEffect, -2);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
// 8: Discard your hand, then draw seven cards. Until end of turn, you may cast spells from your hand without paying their mana costs.
Effect discardHandEffect = new DiscardHandControllerEffect();
Effect drawEffect = new DrawCardSourceControllerEffect(7);
drawEffect.setText(", then draw seven cards");
Effect castSpellsFromHandEffect = new CastFromHandWithoutPayingManaCostEffect(
StaticFilters.FILTER_CARD_NON_LAND, true, Duration.EndOfTurn);
castSpellsFromHandEffect.setText("Until end of turn, you may cast spells from your hand without paying their mana costs");
Ability ultimateAbility = new LoyaltyAbility(discardHandEffect, -8);
ultimateAbility.addEffect(drawEffect);
ultimateAbility.addEffect(castSpellsFromHandEffect);
this.addAbility(ultimateAbility);
}
private ChandraFlamesCatalyst(final ChandraFlamesCatalyst card) {
super(card);
}
@Override
public ChandraFlamesCatalyst copy() {
return new ChandraFlamesCatalyst(this);
}
}

View file

@ -0,0 +1,107 @@
package mage.cards.g;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.DamageAsThoughNotBlockedAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageWithPowerFromOneToAnotherTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.*;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author htrajan
*/
public final class GarrukSavageHerald extends CardImpl {
public GarrukSavageHerald(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{G}{G}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.GARRUK);
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// +1: Reveal the top card of your library. If it's a creature card, put it into your hand. Otherwise, put it on the bottom of your library.
this.addAbility(new LoyaltyAbility(new GarrukSavageHeraldEffect(), 1));
// 2: Target creature you control deals damage equal to its power to another target creature.
DamageWithPowerFromOneToAnotherTargetEffect effect = new DamageWithPowerFromOneToAnotherTargetEffect();
effect.setText("Target creature you control deals damage equal to its power to another target creature");
Ability minusAbility = new LoyaltyAbility(effect, -2);
TargetControlledCreaturePermanent controlledCreature = new TargetControlledCreaturePermanent();
controlledCreature.setTargetTag(1);
minusAbility.addTarget(controlledCreature);
FilterCreaturePermanent filter = new FilterCreaturePermanent("Another creature: damage dealt to");
filter.add(new AnotherTargetPredicate(2));
TargetCreaturePermanent anotherTargetCreature = new TargetCreaturePermanent(filter);
minusAbility.addTarget(anotherTargetCreature);
this.addAbility(minusAbility);
// 7: Until end of turn, creatures you control gain "You may have this creature assign its combat damage as though it weren't blocked."
ContinuousEffect ultimateEffect = new GainAbilityControlledEffect(DamageAsThoughNotBlockedAbility.getInstance(), Duration.EndOfTurn);
ultimateEffect.setText("Until end of turn, creatures you control gain \"You may have this creature assign its combat damage as though it weren't blocked.\"");
this.addAbility(new LoyaltyAbility(ultimateEffect, -7));
}
private GarrukSavageHerald(final GarrukSavageHerald card) {
super(card);
}
@Override
public GarrukSavageHerald copy() {
return new GarrukSavageHerald(this);
}
}
class GarrukSavageHeraldEffect extends OneShotEffect {
GarrukSavageHeraldEffect() {
super(Outcome.Benefit);
staticText = "reveal the top card of your library. If it's a creature card, " +
"put it into your hand. Otherwise, put it on the bottom of your library";
}
private GarrukSavageHeraldEffect(final GarrukSavageHeraldEffect effect) {
super(effect);
}
@Override
public GarrukSavageHeraldEffect copy() {
return new GarrukSavageHeraldEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Card card = player.getLibrary().getFromTop(game);
if (card == null) {
return false;
}
player.revealCards(source, new CardsImpl(card), game);
if (card.isCreature()) {
return player.moveCards(card, Zone.HAND, source, game);
} else {
return player.putCardsOnBottomOfLibrary(card, game, source, false);
}
}
}

View file

@ -5,32 +5,19 @@ import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.*;
import mage.abilities.effects.common.GetEmblemEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.common.FilterInstantOrSorceryCard;
import mage.game.Game;
import mage.game.command.emblems.JaceTelepathUnboundEmblem;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
@ -57,7 +44,9 @@ public final class JaceTelepathUnbound extends CardImpl {
this.addAbility(ability);
// -3: You may cast target instant or sorcery card from your graveyard this turn. If that card would be put into your graveyard this turn, exile it instead.
ability = new LoyaltyAbility(new JaceTelepathUnboundEffect(), -3);
CastCardFromGraveyardThenExileItEffect minusEffect = new CastCardFromGraveyardThenExileItEffect();
minusEffect.setText("You may cast target instant or sorcery card from your graveyard this turn. If that card would be put into your graveyard this turn, exile it instead");
ability = new LoyaltyAbility(minusEffect, -3);
ability.addTarget(new TargetCardInYourGraveyard(new FilterInstantOrSorceryCard()));
this.addAbility(ability);
@ -74,104 +63,3 @@ public final class JaceTelepathUnbound extends CardImpl {
return new JaceTelepathUnbound(this);
}
}
class JaceTelepathUnboundEffect extends OneShotEffect {
JaceTelepathUnboundEffect() {
super(Outcome.Benefit);
this.staticText = "You may cast target instant or sorcery card from your graveyard this turn. If that card would be put into your graveyard this turn, exile it instead";
}
JaceTelepathUnboundEffect(final JaceTelepathUnboundEffect effect) {
super(effect);
}
@Override
public JaceTelepathUnboundEffect copy() {
return new JaceTelepathUnboundEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Card card = game.getCard(this.getTargetPointer().getFirst(game, source));
if (card != null) {
ContinuousEffect effect = new JaceTelepathUnboundCastFromGraveyardEffect();
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
game.addEffect(effect, source);
effect = new JaceTelepathUnboundReplacementEffect(card.getId());
game.addEffect(effect, source);
return true;
}
return false;
}
}
class JaceTelepathUnboundCastFromGraveyardEffect extends AsThoughEffectImpl {
JaceTelepathUnboundCastFromGraveyardEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
}
JaceTelepathUnboundCastFromGraveyardEffect(final JaceTelepathUnboundCastFromGraveyardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public JaceTelepathUnboundCastFromGraveyardEffect copy() {
return new JaceTelepathUnboundCastFromGraveyardEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return objectId.equals(this.getTargetPointer().getFirst(game, source)) && affectedControllerId.equals(source.getControllerId());
}
}
class JaceTelepathUnboundReplacementEffect extends ReplacementEffectImpl {
private final UUID cardId;
JaceTelepathUnboundReplacementEffect(UUID cardId) {
super(Duration.EndOfTurn, Outcome.Exile);
this.cardId = cardId;
staticText = "If that card would be put into your graveyard this turn, exile it instead";
}
JaceTelepathUnboundReplacementEffect(final JaceTelepathUnboundReplacementEffect effect) {
super(effect);
this.cardId = effect.cardId;
}
@Override
public JaceTelepathUnboundReplacementEffect copy() {
return new JaceTelepathUnboundReplacementEffect(this);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
Card card = game.getCard(this.cardId);
if (controller != null && card != null) {
controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.STACK, true);
return true;
}
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
return zEvent.getToZone() == Zone.GRAVEYARD
&& zEvent.getTargetId().equals(this.cardId);
}
}

View file

@ -0,0 +1,117 @@
package mage.cards.l;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.LoseLifeTargetControllerEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetOpponent;
import java.util.UUID;
/**
*
* @author htrajan
*/
public final class LilianaDeathMage extends CardImpl {
public LilianaDeathMage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{B}{B}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.LILIANA);
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: Return up to one target creature card from your graveyard to your hand.
Ability plusAbility = new LoyaltyAbility(new LilianaDeathMagePlusEffect(), 1);
plusAbility.addTarget(new TargetCardInYourGraveyard(0, 1, StaticFilters.FILTER_CARD_CREATURE));
this.addAbility(plusAbility);
// 3: Destroy target creature. Its controller loses 2 life.
Ability minusAbility = new LoyaltyAbility(new DestroyTargetEffect(), -3);
minusAbility.addTarget(new TargetCreaturePermanent());
minusAbility.addEffect(new LoseLifeTargetControllerEffect(2));
this.addAbility(minusAbility);
// 7: Target opponent loses 2 life for each creature card in their graveyard.
Ability ultimateAbility = new LoyaltyAbility(new LilianaDeathMageUltimateEffect(), -7);
ultimateAbility.addTarget(new TargetOpponent());
this.addAbility(ultimateAbility);
}
private LilianaDeathMage(final LilianaDeathMage card) {
super(card);
}
@Override
public LilianaDeathMage copy() {
return new LilianaDeathMage(this);
}
}
class LilianaDeathMagePlusEffect extends OneShotEffect {
LilianaDeathMagePlusEffect() {
super(Outcome.Benefit);
staticText = "Return up to one target creature card from your graveyard to your hand";
}
private LilianaDeathMagePlusEffect(LilianaDeathMagePlusEffect effect) {
super(effect);
}
@Override
public LilianaDeathMagePlusEffect copy() {
return new LilianaDeathMagePlusEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null || !player.chooseUse(Outcome.Benefit, "Return a creature card from your graveyard to your hand?", source, game)) {
return false;
}
Card card = game.getCard(source.getTargets().get(0).getFirstTarget());
if (card == null) {
return false;
}
return player.moveCards(card, Zone.HAND, source, game);
}
}
class LilianaDeathMageUltimateEffect extends OneShotEffect {
LilianaDeathMageUltimateEffect() {
super(Outcome.Damage);
staticText = "Target opponent loses 2 life for each creature card in their graveyard";
}
private LilianaDeathMageUltimateEffect(LilianaDeathMageUltimateEffect effect) {
super(effect);
}
@Override
public LilianaDeathMageUltimateEffect copy() {
return new LilianaDeathMageUltimateEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player opponent = game.getPlayer(source.getFirstTarget());
if (opponent != null) {
int amount = opponent.getGraveyard().count(StaticFilters.FILTER_CARD_CREATURE, game);
opponent.loseLife(amount * 2, game, false);
}
return true;
}
}

View file

@ -11,7 +11,7 @@ import mage.constants.TurnPhase;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.token.DogToken;
import mage.game.permanent.token.GreenDogToken;
import java.util.UUID;
@ -44,7 +44,7 @@ public final class MongrelPack extends CardImpl {
class MongrelPackAbility extends ZoneChangeTriggeredAbility {
MongrelPackAbility() {
super(Zone.BATTLEFIELD, Zone.GRAVEYARD, new CreateTokenEffect(new DogToken(), 4), "When {this} dies during combat, ", false);
super(Zone.BATTLEFIELD, Zone.GRAVEYARD, new CreateTokenEffect(new GreenDogToken(), 4), "When {this} dies during combat, ", false);
}
private MongrelPackAbility(MongrelPackAbility ability) {

View file

@ -0,0 +1,91 @@
package mage.cards.r;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterPermanent;
import mage.filter.FilterSpell;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.permanent.token.GreenCatToken;
import mage.game.permanent.token.WhiteDogToken;
import mage.target.common.TargetAnyTarget;
import java.util.UUID;
/**
*
* @author htrajan
*/
public final class RinAndSeriInseparable extends CardImpl {
private static final FilterSpell dogSpellFilter = new FilterSpell("a Dog spell");
private static final FilterSpell catSpellFilter = new FilterSpell("a Cat spell");
private static final FilterPermanent dogPermanentFilter = new FilterControlledCreaturePermanent("Dogs you control");
private static final FilterPermanent catPermanentFilter = new FilterControlledCreaturePermanent("Cats you control");
static {
dogSpellFilter.add(SubType.DOG.getPredicate());
catSpellFilter.add(SubType.CAT.getPredicate());
dogPermanentFilter.add(SubType.DOG.getPredicate());
catPermanentFilter.add(SubType.CAT.getPredicate());
}
public RinAndSeriInseparable(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}{W}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.DOG);
this.subtype.add(SubType.CAT);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Whenever you cast a Dog spell, create a 1/1 green Cat creature token.
this.addAbility(new SpellCastControllerTriggeredAbility(
new CreateTokenEffect(new GreenCatToken()), dogSpellFilter, false
));
// Whenever you cast a Cat spell, create a 1/1 white Dog creature token.
this.addAbility(new SpellCastControllerTriggeredAbility(
new CreateTokenEffect(new WhiteDogToken()), catSpellFilter, false
));
// {R}{G}{W}: Rin and Seri, Inseparable deals damage to any target equal to the number of Dogs you control. You gain life equal to the number of Cats you control.
DynamicValue dogCount = new PermanentsOnBattlefieldCount(dogPermanentFilter);
Effect damageEffect = new DamageTargetEffect(dogCount);
damageEffect.setText("{source} deals damage to any target equal to the number of Dogs you control");
DynamicValue catCount = new PermanentsOnBattlefieldCount(catPermanentFilter);
Effect lifeGainEffect = new GainLifeEffect(catCount);
lifeGainEffect.setText("You gain life equal to the number of Cats you control");
Ability ability = new SimpleActivatedAbility(damageEffect, new ManaCostsImpl("{R}{G}{W}"));
ability.addEffect(lifeGainEffect);
ability.addTarget(new TargetAnyTarget());
ability.addHint(new ValueHint("Dogs you control", dogCount));
ability.addHint(new ValueHint("Cats you control", catCount));
this.addAbility(ability);
}
private RinAndSeriInseparable(final RinAndSeriInseparable card) {
super(card);
}
@Override
public RinAndSeriInseparable copy() {
return new RinAndSeriInseparable(this);
}
}

View file

@ -14,7 +14,7 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.token.Token;
import mage.game.permanent.token.WaitingInTheWeedsCatToken;
import mage.game.permanent.token.GreenCatToken;
import mage.players.Player;
/**
@ -68,7 +68,7 @@ class WaitingInTheWeedsEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Token token = new WaitingInTheWeedsCatToken();
Token token = new GreenCatToken();
int amount = game.getBattlefield().getAllActivePermanents(filter, playerId, game).size();
token.putOntoBattlefield(amount, game, source.getSourceId(), playerId);
}

View file

@ -36,16 +36,20 @@ public final class CoreSet2021 extends ExpansionSet {
cards.add(new SetCardInfo("Azusa, Lost but Seeking", 173, Rarity.RARE, mage.cards.a.AzusaLostButSeeking.class));
cards.add(new SetCardInfo("Bad Deal", 89, Rarity.UNCOMMON, mage.cards.b.BadDeal.class));
cards.add(new SetCardInfo("Baneslayer Angel", 4, Rarity.MYTHIC, mage.cards.b.BaneslayerAngel.class));
cards.add(new SetCardInfo("Basri, Devoted Paladin", 320, Rarity.MYTHIC, mage.cards.b.BasriDevotedPaladin.class));
cards.add(new SetCardInfo("Chandra, Flame's Catalyst", 332, Rarity.MYTHIC, mage.cards.c.ChandraFlamesCatalyst.class));
cards.add(new SetCardInfo("Chandra's Firemaw", 333, Rarity.RARE, mage.cards.c.ChandrasFiremaw.class));
cards.add(new SetCardInfo("Containment Priest", 314, Rarity.RARE, mage.cards.c.ContainmentPriest.class));
cards.add(new SetCardInfo("Double Vision", 142, Rarity.RARE, mage.cards.d.DoubleVision.class));
cards.add(new SetCardInfo("Fierce Empath", 181, Rarity.UNCOMMON, mage.cards.f.FierceEmpath.class));
cards.add(new SetCardInfo("Gadrak, the Crown-Scourge", 146, Rarity.RARE, mage.cards.g.GadrakTheCrownScourge.class));
cards.add(new SetCardInfo("Garruk, Savage Herald", 336, Rarity.MYTHIC, mage.cards.g.GarrukSavageHerald.class));
cards.add(new SetCardInfo("Grim Tutor", 103, Rarity.MYTHIC, mage.cards.g.GrimTutor.class));
cards.add(new SetCardInfo("Historian of Zhalfir", 325, Rarity.UNCOMMON, mage.cards.h.HistorianOfZhalfir.class));
cards.add(new SetCardInfo("Indulging Patrician", 219, Rarity.UNCOMMON, mage.cards.i.IndulgingPatrician.class));
cards.add(new SetCardInfo("Island", 310, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Jeskai Elder", 53, Rarity.UNCOMMON, mage.cards.j.JeskaiElder.class));
cards.add(new SetCardInfo("Liliana, Death Mage", 328, Rarity.MYTHIC, mage.cards.l.LilianaDeathMage.class));
cards.add(new SetCardInfo("Liliana's Scrounger", 330, Rarity.UNCOMMON, mage.cards.l.LilianasScrounger.class));
cards.add(new SetCardInfo("Llanowar Visionary", 193, Rarity.COMMON, mage.cards.l.LlanowarVisionary.class));
cards.add(new SetCardInfo("Mangara, the Diplomat", 27, Rarity.MYTHIC, mage.cards.m.MangaraTheDiplomat.class));
@ -54,6 +58,7 @@ public final class CoreSet2021 extends ExpansionSet {
cards.add(new SetCardInfo("Peer into the Abyss", 117, Rarity.RARE, mage.cards.p.PeerIntoTheAbyss.class));
cards.add(new SetCardInfo("Quirion Dryad", 198, Rarity.UNCOMMON, mage.cards.q.QuirionDryad.class));
cards.add(new SetCardInfo("Rain of Revelation", 61, Rarity.UNCOMMON, mage.cards.r.RainOfRevelation.class));
cards.add(new SetCardInfo("Rin and Seri, Inseparable", 278, Rarity.MYTHIC, mage.cards.r.RinAndSeriInseparable.class));
cards.add(new SetCardInfo("Runed Halo", 32, Rarity.RARE, mage.cards.r.RunedHalo.class));
cards.add(new SetCardInfo("Shipwreck Dowser", 71, Rarity.UNCOMMON, mage.cards.s.ShipwreckDowser.class));
cards.add(new SetCardInfo("Sigiled Contender", 323, Rarity.UNCOMMON, mage.cards.s.SigiledContender.class));

View file

@ -0,0 +1,115 @@
package mage.abilities.effects;
import mage.abilities.Ability;
import mage.cards.Card;
import mage.constants.AsThoughEffectType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
public class CastCardFromGraveyardThenExileItEffect extends OneShotEffect {
public CastCardFromGraveyardThenExileItEffect() {
super(Outcome.Benefit);
}
CastCardFromGraveyardThenExileItEffect(final CastCardFromGraveyardThenExileItEffect effect) {
super(effect);
}
@Override
public CastCardFromGraveyardThenExileItEffect copy() {
return new CastCardFromGraveyardThenExileItEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Card card = game.getCard(this.getTargetPointer().getFirst(game, source));
if (card != null) {
ContinuousEffect effect = new CastCardFromGraveyardEffect();
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
game.addEffect(effect, source);
effect = new ExileReplacementEffect(card.getId());
game.addEffect(effect, source);
return true;
}
return false;
}
}
class CastCardFromGraveyardEffect extends AsThoughEffectImpl {
CastCardFromGraveyardEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
this.staticText = "You may cast target card from your graveyard";
}
CastCardFromGraveyardEffect(final CastCardFromGraveyardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public CastCardFromGraveyardEffect copy() {
return new CastCardFromGraveyardEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return objectId.equals(this.getTargetPointer().getFirst(game, source)) && affectedControllerId.equals(source.getControllerId());
}
}
class ExileReplacementEffect extends ReplacementEffectImpl {
private final UUID cardId;
ExileReplacementEffect(UUID cardId) {
super(Duration.EndOfTurn, Outcome.Exile);
this.cardId = cardId;
this.staticText = "If that card would be put into your graveyard this turn, exile it instead";
}
ExileReplacementEffect(final ExileReplacementEffect effect) {
super(effect);
this.cardId = effect.cardId;
}
@Override
public ExileReplacementEffect copy() {
return new ExileReplacementEffect(this);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
Card card = game.getCard(this.cardId);
if (controller != null && card != null) {
return controller.moveCards(card, Zone.EXILED, source, game);
}
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
return zEvent.getToZone() == Zone.GRAVEYARD
&& zEvent.getTargetId().equals(this.cardId);
}
}

View file

@ -28,10 +28,14 @@ public class CastFromHandWithoutPayingManaCostEffect extends ContinuousEffectImp
}
public CastFromHandWithoutPayingManaCostEffect(FilterCard filter, boolean fromHand) {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
this(filter, fromHand, Duration.WhileOnBattlefield);
}
public CastFromHandWithoutPayingManaCostEffect(FilterCard filter, boolean fromHand, Duration duration) {
super(duration, Outcome.Detriment);
this.filter = filter;
this.fromHand = fromHand;
staticText = "You may cast " + filter.getMessage()
this.staticText = "You may cast " + filter.getMessage()
+ (fromHand ? " from your hand" : "")
+ " without paying their mana costs";
}

View file

@ -391,6 +391,7 @@ public enum SubType {
ARLINN("Arlinn", SubTypeSet.PlaneswalkerType),
ASHIOK("Ashiok", SubTypeSet.PlaneswalkerType),
AURRA("Aurra", SubTypeSet.PlaneswalkerType, true), // Star Wars
BASRI("Basri", SubTypeSet.PlaneswalkerType),
BOLAS("Bolas", SubTypeSet.PlaneswalkerType),
CALIX("Calix", SubTypeSet.PlaneswalkerType),
CHANDRA("Chandra", SubTypeSet.PlaneswalkerType),

View file

@ -9,9 +9,9 @@ import mage.constants.SubType;
*
* @author spjspj
*/
public final class WaitingInTheWeedsCatToken extends TokenImpl {
public final class GreenCatToken extends TokenImpl {
public WaitingInTheWeedsCatToken() {
public GreenCatToken() {
super("Cat", "1/1 green Cat creature token");
cardType.add(CardType.CREATURE);
color.setGreen(true);
@ -20,11 +20,11 @@ public final class WaitingInTheWeedsCatToken extends TokenImpl {
toughness = new MageInt(1);
}
public WaitingInTheWeedsCatToken(final WaitingInTheWeedsCatToken token) {
public GreenCatToken(final GreenCatToken token) {
super(token);
}
public WaitingInTheWeedsCatToken copy() {
return new WaitingInTheWeedsCatToken(this);
public GreenCatToken copy() {
return new GreenCatToken(this);
}
}

View file

@ -7,9 +7,9 @@ import mage.constants.SubType;
/**
* @author spjspj
*/
public final class DogToken extends TokenImpl {
public final class GreenDogToken extends TokenImpl {
public DogToken() {
public GreenDogToken() {
super("Dog", "1/1 green Dog creature token");
cardType.add(CardType.CREATURE);
subtype.add(SubType.DOG);
@ -19,11 +19,11 @@ public final class DogToken extends TokenImpl {
toughness = new MageInt(1);
}
private DogToken(final DogToken token) {
private GreenDogToken(final GreenDogToken token) {
super(token);
}
public DogToken copy() {
return new DogToken(this);
public GreenDogToken copy() {
return new GreenDogToken(this);
}
}

View file

@ -0,0 +1,31 @@
package mage.game.permanent.token;
import mage.MageInt;
import mage.constants.CardType;
import mage.constants.SubType;
/**
*
* @author htrajan
*/
public final class WhiteDogToken extends TokenImpl {
public WhiteDogToken() {
super("Dog", "1/1 white Dog creature token");
cardType.add(CardType.CREATURE);
subtype.add(SubType.DOG);
color.setWhite(true);
power = new MageInt(1);
toughness = new MageInt(1);
}
private WhiteDogToken(final WhiteDogToken token) {
super(token);
}
public WhiteDogToken copy() {
return new WhiteDogToken(this);
}
}