forked from External/mage
Merge pull request 'master' (#39) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 15m40s
All checks were successful
/ build_release (push) Successful in 15m40s
Reviewed-on: #39
This commit is contained in:
commit
220763b685
68 changed files with 2739 additions and 235 deletions
64
Mage.Sets/src/mage/cards/a/AangsJourney.java
Normal file
64
Mage.Sets/src/mage/cards/a/AangsJourney.java
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.condition.common.KickedCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
|
||||
import mage.abilities.keyword.KickerAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.target.common.TargetCardAndOrCardInLibrary;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AangsJourney extends CardImpl {
|
||||
|
||||
private static final Predicate<Card> predicate = Predicates.and(
|
||||
SuperType.BASIC.getPredicate(),
|
||||
CardType.LAND.getPredicate()
|
||||
);
|
||||
|
||||
public AangsJourney(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}");
|
||||
|
||||
this.subtype.add(SubType.LESSON);
|
||||
|
||||
// Kicker {2}
|
||||
this.addAbility(new KickerAbility("{2}"));
|
||||
|
||||
// Search your library for a basic land card. If this spell was kicked, instead search your library for a basic land card and a Shrine card. Reveal those cards, put them into your hand, then shuffle.
|
||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new SearchLibraryPutInHandEffect(new TargetCardAndOrCardInLibrary(
|
||||
predicate, SubType.SHRINE.getPredicate(),
|
||||
"a basic land card and/or a Shrine card"
|
||||
), true),
|
||||
new SearchLibraryPutInHandEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true),
|
||||
KickedCondition.ONCE, "search your library for a basic land card. If this spell was kicked, " +
|
||||
"instead search your library for a basic land card and a Shrine card. " +
|
||||
"Reveal those cards, put them into your hand, then shuffle"
|
||||
));
|
||||
|
||||
// You gain 2 life.
|
||||
this.getSpellAbility().addEffect(new GainLifeEffect(2).concatBy("<br>"));
|
||||
}
|
||||
|
||||
private AangsJourney(final AangsJourney card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AangsJourney copy() {
|
||||
return new AangsJourney(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -57,6 +57,12 @@ class AlpineMoonEffect extends ContinuousEffectImpl {
|
|||
this.staticText = "lands your opponents control with the chosen name "
|
||||
+ "lose all land types and abilities, "
|
||||
+ "and they gain \"{T}: Add one mana of any color.\"";
|
||||
addDependedToType(DependencyType.BecomeMountain);
|
||||
addDependedToType(DependencyType.BecomeForest);
|
||||
addDependedToType(DependencyType.BecomeIsland);
|
||||
addDependedToType(DependencyType.BecomeSwamp);
|
||||
addDependedToType(DependencyType.BecomePlains);
|
||||
addDependedToType(DependencyType.BecomeNonbasicLand);
|
||||
}
|
||||
|
||||
private AlpineMoonEffect(final AlpineMoonEffect effect) {
|
||||
|
|
@ -84,9 +90,6 @@ class AlpineMoonEffect extends ContinuousEffectImpl {
|
|||
for (Permanent land : game.getBattlefield().getActivePermanents(filter2, source.getControllerId(), game)) {
|
||||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
// 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects
|
||||
// So the ability removing has to be done before Layer 6
|
||||
land.removeAllAbilities(source.getSourceId(), game);
|
||||
land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType);
|
||||
break;
|
||||
case AbilityAddingRemovingEffects_6:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
|
|
@ -16,6 +15,8 @@ import mage.filter.predicate.mageobject.ColorPredicate;
|
|||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
|
|
@ -29,7 +30,7 @@ public final class AnHavvaConstable extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// An-Havva Constable's toughness is equal to 1 plus the number of green creatures on the battlefield.
|
||||
this.addAbility(new SimpleStaticAbility(new AnHavvaConstableEffect()));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AnHavvaConstableEffect()));
|
||||
}
|
||||
|
||||
private AnHavvaConstable(final AnHavvaConstable card) {
|
||||
|
|
@ -72,7 +73,7 @@ class AnHavvaConstableEffect extends ContinuousEffectImpl {
|
|||
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("green creatures");
|
||||
filter.add(new ColorPredicate(ObjectColor.GREEN));
|
||||
int numberOfGreenCreatures = game.getBattlefield().count(filter, source.getSourceId(), source, game);
|
||||
int numberOfGreenCreatures = game.getBattlefield().count(filter, source.getControllerId(), source, game);
|
||||
|
||||
mageObject.getToughness().setModifiedBaseValue(1 + numberOfGreenCreatures);
|
||||
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ class BottleCapBlastEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
UUID target = getTargetPointer().getFirst(game, source);
|
||||
Player player = game.getPlayer(target);
|
||||
UUID targetId = getTargetPointer().getFirst(game, source);
|
||||
Player player = game.getPlayer(targetId);
|
||||
if (player != null) {
|
||||
player.damage(5, source, game);
|
||||
return true;
|
||||
|
|
@ -72,11 +72,10 @@ class BottleCapBlastEffect extends OneShotEffect {
|
|||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), 5);
|
||||
permanent.damage(5, source.getSourceId(), source, game);
|
||||
if (lethal < 5) {
|
||||
int excess = permanent.damageWithExcess(5, source, game);
|
||||
if (excess > 0) {
|
||||
new TreasureToken().putOntoBattlefield(
|
||||
5 - lethal, game, source, source.getControllerId(), true, false
|
||||
excess, game, source, source.getControllerId(), true, false
|
||||
);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.keyword.DiscoverEffect;
|
||||
|
|
@ -9,19 +7,18 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jimga150
|
||||
*/
|
||||
public final class ContestOfClaws extends CardImpl {
|
||||
|
|
@ -29,14 +26,10 @@ public final class ContestOfClaws extends CardImpl {
|
|||
public ContestOfClaws(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}");
|
||||
|
||||
|
||||
// Target creature you control deals damage equal to its power to another target creature. If excess damage was dealt this way, discover X, where X is that excess damage.
|
||||
this.getSpellAbility().addEffect(new ContestOfClawsDamageEffect());
|
||||
Target target = new TargetControlledCreaturePermanent().setTargetTag(1);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
|
||||
Target target2 = new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2);
|
||||
this.getSpellAbility().addTarget(target2);
|
||||
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1));
|
||||
this.getSpellAbility().addTarget(new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2));
|
||||
}
|
||||
|
||||
private ContestOfClaws(final ContestOfClaws card) {
|
||||
|
|
@ -74,22 +67,13 @@ class ContestOfClawsDamageEffect extends OneShotEffect {
|
|||
if (ownCreature == null || targetCreature == null) {
|
||||
return false;
|
||||
}
|
||||
int damage = ownCreature.getPower().getValue();
|
||||
int lethalDamage = targetCreature.getLethalDamage(source.getSourceId(), game);
|
||||
targetCreature.damage(damage, ownCreature.getId(), source, game, false, true);
|
||||
|
||||
if (damage < lethalDamage){
|
||||
return true;
|
||||
int excess = targetCreature.damageWithExcess( ownCreature.getPower().getValue(), ownCreature.getId(), source, game);
|
||||
if (excess > 0) {
|
||||
Optional.ofNullable(source)
|
||||
.map(Controllable::getControllerId)
|
||||
.map(game::getPlayer)
|
||||
.ifPresent(player -> DiscoverEffect.doDiscover(player, excess, game, source));
|
||||
}
|
||||
int discoverValue = damage - lethalDamage;
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
|
||||
if (player == null){
|
||||
// If somehow this case is hit, the damage still technically happened, so i guess it applied?
|
||||
return true;
|
||||
}
|
||||
DiscoverEffect.doDiscover(player, discoverValue, game, source);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class DarkImpostorContinuousEffect extends ContinuousEffectImpl {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source));
|
||||
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source, 1));
|
||||
if (permanent == null || exileZone == null || exileZone.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
|
@ -16,14 +15,14 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.common.FilterLandCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.target.common.TargetCardInGraveyard;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ class EvraHalcyonWitnessEffect extends OneShotEffect {
|
|||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null && player.isLifeTotalCanChange()) {
|
||||
Permanent perm = game.getPermanent(source.getSourceId());
|
||||
if (perm != null) {
|
||||
if (perm != null && perm.isCreature(game)) {
|
||||
int amount = perm.getPower().getValue();
|
||||
int life = player.getLife();
|
||||
if (life == amount) {
|
||||
|
|
|
|||
158
Mage.Sets/src/mage/cards/f/FireLordSozin.java
Normal file
158
Mage.Sets/src/mage/cards/f/FireLordSozin.java
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
package mage.cards.f;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.keyword.FirebendingAbility;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.predicate.card.OwnerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInGraveyard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class FireLordSozin extends CardImpl {
|
||||
|
||||
public FireLordSozin(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.NOBLE);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(5);
|
||||
this.color.setBlack(true);
|
||||
this.nightCard = true;
|
||||
|
||||
// Menace
|
||||
this.addAbility(new MenaceAbility());
|
||||
|
||||
// Firebending 3
|
||||
this.addAbility(new FirebendingAbility(3));
|
||||
|
||||
// Whenever Fire Lord Sozin deals combat damage to a player, you may pay {X}. When you do, put any number of target creature cards with total mana value X or less from that player's graveyard onto the battlefield under your control.
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new FireLordSozinEffect()));
|
||||
}
|
||||
|
||||
private FireLordSozin(final FireLordSozin card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FireLordSozin copy() {
|
||||
return new FireLordSozin(this);
|
||||
}
|
||||
}
|
||||
|
||||
class FireLordSozinEffect extends OneShotEffect {
|
||||
|
||||
FireLordSozinEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "you may pay {X}. When you do, put any number of target creature cards with " +
|
||||
"total mana value X or less from that player's graveyard onto the battlefield under your control";
|
||||
}
|
||||
|
||||
private FireLordSozinEffect(final FireLordSozinEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FireLordSozinEffect copy() {
|
||||
return new FireLordSozinEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
if (controller == null || !controller.chooseUse(Outcome.BoostCreature, "Pay {X}?", source, game)) {
|
||||
return false;
|
||||
}
|
||||
int xValue = controller.announceX(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source, true);
|
||||
ManaCosts cost = new ManaCostsImpl<>("{X}");
|
||||
cost.add(new GenericManaCost(xValue));
|
||||
if (!cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
return false;
|
||||
}
|
||||
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false);
|
||||
ability.addTarget(new FireLordSozinTarget((UUID) getValue("damagedPlayer"), xValue));
|
||||
game.fireReflexiveTriggeredAbility(ability, source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class FireLordSozinTarget extends TargetCardInGraveyard {
|
||||
|
||||
private final int xValue;
|
||||
|
||||
private static final FilterCard makeFilter(UUID ownerId, int xValue) {
|
||||
FilterCard filter = new FilterCreatureCard("creature cards with total mana value " + xValue + " or less from that player's graveyard");
|
||||
filter.add(new OwnerIdPredicate(ownerId));
|
||||
return filter;
|
||||
}
|
||||
|
||||
FireLordSozinTarget(UUID ownerId, int xValue) {
|
||||
super(0, Integer.MAX_VALUE, makeFilter(ownerId, xValue), false);
|
||||
this.xValue = xValue;
|
||||
}
|
||||
|
||||
private FireLordSozinTarget(final FireLordSozinTarget target) {
|
||||
super(target);
|
||||
this.xValue = target.xValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FireLordSozinTarget copy() {
|
||||
return new FireLordSozinTarget(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
|
||||
return super.canTarget(playerId, id, source, game)
|
||||
&& CardUtil.checkCanTargetTotalValueLimit(this.getTargets(), id, MageObject::getManaValue, xValue, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
|
||||
return CardUtil.checkPossibleTargetsTotalValueLimit(
|
||||
this.getTargets(),
|
||||
super.possibleTargets(sourceControllerId, source, game),
|
||||
MageObject::getManaValue, xValue, game
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage(Game game) {
|
||||
// shows selected total
|
||||
int selectedValue = this.getTargets().stream()
|
||||
.map(game::getObject)
|
||||
.filter(Objects::nonNull)
|
||||
.mapToInt(MageObject::getManaValue)
|
||||
.sum();
|
||||
return super.getMessage(game) + " (selected total mana value " + selectedValue + ")";
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@ import mage.util.CardUtil;
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ciaccona007
|
||||
*/
|
||||
public final class GoblinNegotiation extends CardImpl {
|
||||
|
|
@ -62,13 +61,11 @@ class GoblinNegotiationEffect extends OneShotEffect {
|
|||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
int damage = CardUtil.getSourceCostsTag(game, source, "X", 0);
|
||||
int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), damage);
|
||||
permanent.damage(damage, source.getSourceId(), source, game);
|
||||
if (damage > lethal) {
|
||||
new GoblinToken().putOntoBattlefield(
|
||||
damage - lethal, game, source, source.getControllerId()
|
||||
int excess = permanent.damageWithExcess(
|
||||
CardUtil.getSourceCostsTag(game, source, "X", 0), source, game
|
||||
);
|
||||
if (excess > 0) {
|
||||
new GoblinToken().putOntoBattlefield(excess, game, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
72
Mage.Sets/src/mage/cards/h/HakodaSelflessCommander.java
Normal file
72
Mage.Sets/src/mage/cards/h/HakodaSelflessCommander.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
package mage.cards.h;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
|
||||
import mage.abilities.effects.common.continuous.LookAtTopCardOfLibraryAnyTimeEffect;
|
||||
import mage.abilities.effects.common.continuous.PlayFromTopOfLibraryEffect;
|
||||
import mage.abilities.keyword.IndestructibleAbility;
|
||||
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.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class HakodaSelflessCommander extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard(SubType.ALLY, "Ally spells");
|
||||
|
||||
public HakodaSelflessCommander(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.WARRIOR);
|
||||
this.subtype.add(SubType.ALLY);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Vigilance
|
||||
this.addAbility(VigilanceAbility.getInstance());
|
||||
|
||||
// You may look at the top card of your library any time.
|
||||
this.addAbility(new SimpleStaticAbility(new LookAtTopCardOfLibraryAnyTimeEffect()));
|
||||
|
||||
// You may cast Ally spells from the top of your library.
|
||||
this.addAbility(new SimpleStaticAbility(new PlayFromTopOfLibraryEffect(filter)));
|
||||
|
||||
// Sacrifice Hakoda: Creatures you control get +0/+5 and gain indestructible until end of turn.
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
new BoostControlledEffect(0, 5, Duration.EndOfTurn)
|
||||
.setText("creatures you control get +0/+5"),
|
||||
new SacrificeSourceCost()
|
||||
);
|
||||
ability.addEffect(new GainAbilityAllEffect(
|
||||
IndestructibleAbility.getInstance(), Duration.EndOfTurn,
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURE
|
||||
).setText("and gain indestructible until end of turn"));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private HakodaSelflessCommander(final HakodaSelflessCommander card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HakodaSelflessCommander copy() {
|
||||
return new HakodaSelflessCommander(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ 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.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
|
|
@ -29,6 +30,8 @@ public final class HaruHiddenTalent extends CardImpl {
|
|||
|
||||
public HaruHiddenTalent(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.PEASANT);
|
||||
this.subtype.add(SubType.ALLY);
|
||||
|
|
|
|||
|
|
@ -60,13 +60,11 @@ class HellToPayEffect extends OneShotEffect {
|
|||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
int damage = CardUtil.getSourceCostsTag(game, source, "X", 0);
|
||||
int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), damage);
|
||||
permanent.damage(damage, source.getSourceId(), source, game);
|
||||
if (damage > lethal) {
|
||||
new TreasureToken().putOntoBattlefield(
|
||||
damage - lethal, game, source, source.getControllerId(), true, false
|
||||
int excess = permanent.damageWithExcess(
|
||||
CardUtil.getSourceCostsTag(game, source, "X", 0), source, game
|
||||
);
|
||||
if (excess > 0) {
|
||||
new TreasureToken().putOntoBattlefield(excess, game, source, source.getControllerId(), true, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
84
Mage.Sets/src/mage/cards/h/HowToStartARiot.java
Normal file
84
Mage.Sets/src/mage/cards/h/HowToStartARiot.java
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
package mage.cards.h;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostAllEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.SecondTargetPointer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class HowToStartARiot extends CardImpl {
|
||||
|
||||
public HowToStartARiot(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
|
||||
|
||||
this.subtype.add(SubType.LESSON);
|
||||
|
||||
// Target creature gains menace until end of turn.
|
||||
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(new MenaceAbility(false)));
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
|
||||
// Creatures target player controls get +2/+0 until end of turn.
|
||||
this.getSpellAbility().addEffect(new HowToStartARiotEffect());
|
||||
this.getSpellAbility().addTarget(new TargetPlayer());
|
||||
}
|
||||
|
||||
private HowToStartARiot(final HowToStartARiot card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HowToStartARiot copy() {
|
||||
return new HowToStartARiot(this);
|
||||
}
|
||||
}
|
||||
|
||||
class HowToStartARiotEffect extends OneShotEffect {
|
||||
|
||||
HowToStartARiotEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.setTargetPointer(new SecondTargetPointer());
|
||||
staticText = "creatures target player controls get +2/+0 until end of turn";
|
||||
this.concatBy("<br>");
|
||||
}
|
||||
|
||||
private HowToStartARiotEffect(final HowToStartARiotEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HowToStartARiotEffect copy() {
|
||||
return new HowToStartARiotEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
filter.add(new ControllerIdPredicate(player.getId()));
|
||||
game.addEffect(new BoostAllEffect(
|
||||
2, 0, Duration.EndOfTurn, filter, false
|
||||
), source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -55,14 +55,13 @@ class LacerateFleshEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), 4);
|
||||
permanent.damage(4, source.getSourceId(), source, game);
|
||||
if (lethal < 4) {
|
||||
new BloodToken().putOntoBattlefield(4 - lethal, game, source);
|
||||
int excess = permanent.damageWithExcess(4, source, game);
|
||||
if (excess > 0) {
|
||||
new BloodToken().putOntoBattlefield(excess, game, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
72
Mage.Sets/src/mage/cards/l/LongFengGrandSecretariat.java
Normal file
72
Mage.Sets/src/mage/cards/l/LongFengGrandSecretariat.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
package mage.cards.l;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.ObjectSourcePlayer;
|
||||
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class LongFengGrandSecretariat extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterControlledPermanent("another creature you control or a land you control");
|
||||
|
||||
static {
|
||||
filter.add(LongFengGrandSecretariatPredicate.instance);
|
||||
}
|
||||
|
||||
public LongFengGrandSecretariat(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B/G}{B/G}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.ADVISOR);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Whenever another creature you control or a land you control is put into a graveyard from the battlefield, put a +1/+1 counter on target creature you control.
|
||||
Ability ability = new PutIntoGraveFromBattlefieldAllTriggeredAbility(
|
||||
new AddCountersTargetEffect(CounterType.P1P1.createInstance()),
|
||||
false, filter, false
|
||||
);
|
||||
ability.addTarget(new TargetControlledCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private LongFengGrandSecretariat(final LongFengGrandSecretariat card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LongFengGrandSecretariat copy() {
|
||||
return new LongFengGrandSecretariat(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum LongFengGrandSecretariatPredicate implements ObjectSourcePlayerPredicate<MageObject> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectSourcePlayer<MageObject> input, Game game) {
|
||||
return input.getObject().isLand(game)
|
||||
|| input.getObject().isCreature(game)
|
||||
&& AnotherPredicate.instance.apply(input, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -126,36 +126,22 @@ class MegatronDestructiveForceReflexiveEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent sourcePermanent = source.getSourcePermanentOrLKI(game);
|
||||
if (sourcePermanent == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
||||
int excess = value - lethal;
|
||||
if (excess <= 0) {
|
||||
// no excess damage.
|
||||
permanent.damage(value, source.getSourceId(), source, game);
|
||||
int excess = permanent.damageWithExcess(value, source, game);
|
||||
if (excess < 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// excess damage. dealing excess to controller's instead. And convert Megatron.
|
||||
permanent.damage(lethal, source.getSourceId(), source, game);
|
||||
Player player = game.getPlayer(permanent.getControllerId());
|
||||
if (player != null) {
|
||||
player.damage(excess, source, game);
|
||||
}
|
||||
new TransformSourceEffect().apply(game, source);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
132
Mage.Sets/src/mage/cards/m/MomoFriendlyFlier.java
Normal file
132
Mage.Sets/src/mage/cards/m/MomoFriendlyFlier.java
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.decorator.ConditionalCostModificationEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
|
||||
import mage.abilities.hint.ConditionHint;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class MomoFriendlyFlier extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard();
|
||||
private static final FilterPermanent filter2 = new FilterControlledCreaturePermanent("another creature you control with flying");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(SubType.LEMUR.getPredicate()));
|
||||
filter.add(new AbilityPredicate(FlyingAbility.class));
|
||||
filter2.add(new AbilityPredicate(FlyingAbility.class));
|
||||
}
|
||||
|
||||
public MomoFriendlyFlier(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.LEMUR);
|
||||
this.subtype.add(SubType.BAT);
|
||||
this.subtype.add(SubType.ALLY);
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// The first non-Lemur creature spell with flying you cast during each of your turns costs {1} less to cast.
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalCostModificationEffect(
|
||||
new SpellsCostReductionControllerEffect(filter, 1), MomoFriendlyFlierCondition.instance,
|
||||
"the first non-Lemur creature spell with flying you cast during each of your turns costs {1} less to cast"
|
||||
)).addHint(MomoFriendlyFlierCondition.getHint()), new MomoFriendlyFlierWatcher());
|
||||
|
||||
// Whenever another creature you control with flying enters, Momo gets +1/+1 until end of turn.
|
||||
this.addAbility(new EntersBattlefieldAllTriggeredAbility(
|
||||
new BoostSourceEffect(1, 1, Duration.EndOfTurn), filter2
|
||||
));
|
||||
}
|
||||
|
||||
private MomoFriendlyFlier(final MomoFriendlyFlier card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MomoFriendlyFlier copy() {
|
||||
return new MomoFriendlyFlier(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum MomoFriendlyFlierCondition implements Condition {
|
||||
instance;
|
||||
private static final Hint hint = new ConditionHint(
|
||||
instance, "You haven't cast a non-Lemur creature spell with flying during your turn yet"
|
||||
);
|
||||
|
||||
public static Hint getHint() {
|
||||
return hint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return game.isActivePlayer(source.getControllerId())
|
||||
&& !MomoFriendlyFlierWatcher.checkPlayer(game, source);
|
||||
}
|
||||
}
|
||||
|
||||
class MomoFriendlyFlierWatcher extends Watcher {
|
||||
|
||||
private final Set<UUID> set = new HashSet<>();
|
||||
|
||||
MomoFriendlyFlierWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() != GameEvent.EventType.SPELL_CAST) {
|
||||
return;
|
||||
}
|
||||
Spell spell = game.getSpell(event.getTargetId());
|
||||
if (spell != null
|
||||
&& spell.isCreature(game)
|
||||
&& !spell.hasSubtype(SubType.LEMUR, game)
|
||||
&& spell.getAbilities(game).containsClass(FlyingAbility.class)) {
|
||||
set.add(spell.getControllerId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
set.clear();
|
||||
}
|
||||
|
||||
static boolean checkPlayer(Game game, Ability source) {
|
||||
return game
|
||||
.getState()
|
||||
.getWatcher(MomoFriendlyFlierWatcher.class)
|
||||
.set
|
||||
.contains(source.getControllerId());
|
||||
}
|
||||
}
|
||||
|
|
@ -80,9 +80,8 @@ class NahirisWarcraftingEffect extends OneShotEffect {
|
|||
if (player == null || permanent == null) {
|
||||
return false;
|
||||
}
|
||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
||||
int excess = permanent.damage(5, source, game) - lethal;
|
||||
if (excess <= 0) {
|
||||
int excess = permanent.damageWithExcess(5, source, game);
|
||||
if (excess < 1) {
|
||||
return true;
|
||||
}
|
||||
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, excess));
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package mage.cards.o;
|
|||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -61,10 +60,8 @@ class OrbitalPlungeEffect extends OneShotEffect {
|
|||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
||||
permanent.damage(6, source.getSourceId(), source, game);
|
||||
if (lethal < 6) {
|
||||
new CreateTokenEffect(new LanderToken()).apply(game, source);
|
||||
if (permanent.damageWithExcess(6, source, game) > 0) {
|
||||
new LanderToken().putOntoBattlefield(1, game, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,15 +7,18 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.EachTargetPointer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL;
|
||||
|
||||
|
|
@ -47,6 +50,7 @@ class RamThroughEffect extends OneShotEffect {
|
|||
|
||||
RamThroughEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.setTargetPointer(new EachTargetPointer());
|
||||
staticText = "Target creature you control deals damage equal to its power to target creature you don't control. " +
|
||||
"If the creature you control has trample, excess damage is dealt to that creature's controller instead.";
|
||||
}
|
||||
|
|
@ -62,29 +66,31 @@ class RamThroughEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
if (source.getTargets().size() != 2) {
|
||||
throw new IllegalStateException("It must have two targets, but found " + source.getTargets().size());
|
||||
}
|
||||
|
||||
Permanent myPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
Permanent anotherPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||
|
||||
if (myPermanent == null || anotherPermanent == null) {
|
||||
List<Permanent> permanents = this
|
||||
.getTargetPointer()
|
||||
.getTargets(game, source)
|
||||
.stream()
|
||||
.map(game::getPermanent)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
if (permanents.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
int power = myPermanent.getPower().getValue();
|
||||
Permanent permanent = permanents.get(0);
|
||||
int power = permanent.getPower().getValue();
|
||||
if (power < 1) {
|
||||
return false;
|
||||
}
|
||||
if (!myPermanent.getAbilities().containsKey(TrampleAbility.getInstance().getId())) {
|
||||
return anotherPermanent.damage(power, myPermanent.getId(), source, game, false, true) > 0;
|
||||
Permanent creature = permanents.get(1);
|
||||
if (!permanent.hasAbility(TrampleAbility.getInstance(), game)) {
|
||||
return creature.damage(power, permanent.getId(), source, game) > 0;
|
||||
}
|
||||
int lethal = anotherPermanent.getLethalDamage(myPermanent.getId(), game);
|
||||
lethal = Math.min(lethal, power);
|
||||
anotherPermanent.damage(lethal, myPermanent.getId(), source, game);
|
||||
Player player = game.getPlayer(anotherPermanent.getControllerId());
|
||||
if (player != null && lethal < power) {
|
||||
player.damage(power - lethal, myPermanent.getId(), source, game);
|
||||
int excess = creature.damageWithExcess(power, permanent.getId(), source, game);
|
||||
if (excess > 0) {
|
||||
Optional.ofNullable(creature)
|
||||
.map(Controllable::getControllerId)
|
||||
.map(game::getPlayer)
|
||||
.ifPresent(player -> player.damage(excess, permanent.getId(), source, game));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
72
Mage.Sets/src/mage/cards/r/RazorRings.java
Normal file
72
Mage.Sets/src/mage/cards/r/RazorRings.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
package mage.cards.r;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetAttackingOrBlockingCreature;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class RazorRings extends CardImpl {
|
||||
|
||||
public RazorRings(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
|
||||
|
||||
// Razor Rings deals 4 damage to target attacking or blocking creature. You gain life equal to the excess damage dealt this way.
|
||||
this.getSpellAbility().addEffect(new RazorRingsEffect());
|
||||
this.getSpellAbility().addTarget(new TargetAttackingOrBlockingCreature());
|
||||
}
|
||||
|
||||
private RazorRings(final RazorRings card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RazorRings copy() {
|
||||
return new RazorRings(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RazorRingsEffect extends OneShotEffect {
|
||||
|
||||
RazorRingsEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "{this} deals 4 damage to target attacking or blocking creature. " +
|
||||
"You gain life equal to the excess damage dealt this way";
|
||||
}
|
||||
|
||||
private RazorRingsEffect(final RazorRingsEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RazorRingsEffect copy() {
|
||||
return new RazorRingsEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
int excess = permanent.damageWithExcess(4, source, game);
|
||||
if (excess > 0) {
|
||||
Optional.ofNullable(source)
|
||||
.map(Controllable::getControllerId)
|
||||
.map(game::getPlayer)
|
||||
.ifPresent(player -> player.gainLife(excess, game, source));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -129,7 +129,6 @@ class RexCyberhoundContinuousEffect extends ContinuousEffectImpl {
|
|||
for (Ability ability : card.getAbilities(game)) {
|
||||
if (ability.isActivatedAbility()) {
|
||||
ActivatedAbility copyAbility = (ActivatedAbility) ability.copy();
|
||||
copyAbility.setMaxActivationsPerTurn(1);
|
||||
perm.addAbility(copyAbility, source.getSourceId(), game, true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
71
Mage.Sets/src/mage/cards/s/SerpentOfThePass.java
Normal file
71
Mage.Sets/src/mage/cards/s/SerpentOfThePass.java
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.common.CardsInControllerGraveyardCondition;
|
||||
import mage.abilities.decorator.ConditionalAsThoughEffect;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||
import mage.abilities.effects.common.continuous.CastAsThoughItHadFlashSourceEffect;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class SerpentOfThePass extends CardImpl {
|
||||
|
||||
private static final Condition condition = new CardsInControllerGraveyardCondition(3, new FilterCard(SubType.LESSON));
|
||||
private static final Hint hint = new ValueHint(
|
||||
"Lesson cards in your graveyard", new CardsInControllerGraveyardCount(new FilterCard(SubType.LESSON))
|
||||
);
|
||||
private static final FilterCard filter = new FilterCard("noncreature, nonland card");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(CardType.CREATURE.getPredicate()));
|
||||
filter.add(Predicates.not(CardType.LAND.getPredicate()));
|
||||
}
|
||||
|
||||
private static final DynamicValue xValue = new CardsInControllerGraveyardCount(filter);
|
||||
private static final Hint hint2 = new ValueHint("Noncreature, nonland cards in your graveyard", xValue);
|
||||
|
||||
public SerpentOfThePass(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}");
|
||||
|
||||
this.subtype.add(SubType.SERPENT);
|
||||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// If there are three or more Lesson cards in your graveyard, you may cast this spell as though it had flash.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new ConditionalAsThoughEffect(
|
||||
new CastAsThoughItHadFlashSourceEffect(Duration.EndOfGame), condition
|
||||
).setText("if there are three or more Lesson cards in your graveyard, " +
|
||||
"you may cast this spell as though it had flash.")).addHint(hint));
|
||||
|
||||
// This spell costs {1} less to cast for each noncreature, nonland card in your graveyard.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue)
|
||||
).setRuleAtTheTop(true).addHint(hint2));
|
||||
}
|
||||
|
||||
private SerpentOfThePass(final SerpentOfThePass card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SerpentOfThePass copy() {
|
||||
return new SerpentOfThePass(this);
|
||||
}
|
||||
}
|
||||
75
Mage.Sets/src/mage/cards/s/SokkaLateralStrategist.java
Normal file
75
Mage.Sets/src/mage/cards/s/SokkaLateralStrategist.java
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class SokkaLateralStrategist extends CardImpl {
|
||||
|
||||
public SokkaLateralStrategist(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W/U}{W/U}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.WARRIOR);
|
||||
this.subtype.add(SubType.ALLY);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Vigilance
|
||||
this.addAbility(VigilanceAbility.getInstance());
|
||||
|
||||
// Whenever Sokka and at least one other creature attack, draw a card.
|
||||
this.addAbility(new SokkaLateralStrategistTriggeredAbility());
|
||||
}
|
||||
|
||||
private SokkaLateralStrategist(final SokkaLateralStrategist card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SokkaLateralStrategist copy() {
|
||||
return new SokkaLateralStrategist(this);
|
||||
}
|
||||
}
|
||||
|
||||
class SokkaLateralStrategistTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
SokkaLateralStrategistTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1));
|
||||
this.setTriggerPhrase("Whenever {this} and at least one other creature attack, ");
|
||||
}
|
||||
|
||||
private SokkaLateralStrategistTriggeredAbility(final SokkaLateralStrategistTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SokkaLateralStrategistTriggeredAbility copy() {
|
||||
return new SokkaLateralStrategistTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
return game.getCombat().getAttackers().size() >= 2 && game.getCombat().getAttackers().contains(getSourceId());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +1,31 @@
|
|||
|
||||
package mage.cards.s;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.keyword.FearAbility;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.ManaWasSpentCondition;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.SacrificeSourceUnlessConditionEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.abilities.keyword.FearAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class SquealingDevil extends CardImpl {
|
||||
|
|
@ -76,25 +74,23 @@ class SquealingDevilEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null || !player.chooseUse(Outcome.BoostCreature, "Pay {X}?", source, game)) {
|
||||
return false;
|
||||
}
|
||||
int xValue = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to boost)", game, source, true);
|
||||
ManaCosts cost = new ManaCostsImpl<>("{X}");
|
||||
if (player != null) {
|
||||
if (player.chooseUse(Outcome.BoostCreature, "Pay " + cost.getText() + "?", source, game)) {
|
||||
int costX = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to boost)", game, source, true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (permanent != null && permanent.isCreature(game)) {
|
||||
ContinuousEffect effect = new BoostTargetEffect(costX, 0, Duration.EndOfTurn);
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
game.addEffect(effect, source);
|
||||
cost.add(new GenericManaCost(xValue));
|
||||
if (!cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
game.addEffect(new BoostTargetEffect(xValue, 0, Duration.EndOfTurn)
|
||||
.setTargetPointer(new FixedTarget(permanent, game)), source);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SquealingDevilEffect copy() {
|
||||
|
|
|
|||
|
|
@ -78,14 +78,19 @@ class StalwartSuccessorTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
int zccOffset = 0;
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent == null) {
|
||||
permanent = game.getPermanentEntering(event.getTargetId());
|
||||
zccOffset = 1;
|
||||
}
|
||||
if (permanent == null
|
||||
|| !permanent.isCreature(game)
|
||||
|| !permanent.isControlledBy(getControllerId())
|
||||
|| !StalwartSuccessorWatcher.checkCreature(permanent, event, game)) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().setTargetPointer(new FixedTarget(permanent, game));
|
||||
this.getEffects().setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game) + zccOffset));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -101,6 +106,11 @@ class StalwartSuccessorWatcher extends Watcher {
|
|||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.COUNTERS_ADDED) {
|
||||
if (game.getPermanent(event.getTargetId()) == null) {
|
||||
// permanent entering
|
||||
Permanent permanent = game.getPermanentEntering(event.getTargetId());
|
||||
map.putIfAbsent(new MageObjectReference(event.getTargetId(), permanent.getZoneChangeCounter(game) + 1, game), event.getId());
|
||||
}
|
||||
map.putIfAbsent(new MageObjectReference(event.getTargetId(), game), event.getId());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
85
Mage.Sets/src/mage/cards/t/TheRiseOfSozin.java
Normal file
85
Mage.Sets/src/mage/cards/t/TheRiseOfSozin.java
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SagaAbility;
|
||||
import mage.abilities.effects.Effects;
|
||||
import mage.abilities.effects.common.ChooseACardNameEffect;
|
||||
import mage.abilities.effects.common.DestroyAllEffect;
|
||||
import mage.abilities.effects.common.ExileSagaAndReturnTransformedEffect;
|
||||
import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect;
|
||||
import mage.abilities.keyword.TransformAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SagaChapter;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetOpponent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class TheRiseOfSozin extends CardImpl {
|
||||
|
||||
public TheRiseOfSozin(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{B}{B}");
|
||||
|
||||
this.subtype.add(SubType.SAGA);
|
||||
this.secondSideCardClazz = mage.cards.f.FireLordSozin.class;
|
||||
|
||||
// (As this Saga enters and after your draw step, add a lore counter.)
|
||||
SagaAbility sagaAbility = new SagaAbility(this);
|
||||
|
||||
// I -- Destroy all creatures.
|
||||
sagaAbility.addChapterEffect(
|
||||
this, SagaChapter.CHAPTER_I, new DestroyAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES)
|
||||
);
|
||||
|
||||
// II -- Choose a card name. Search target opponent's graveyard, hand, and library for up to four cards with that name and exile them. Then that player shuffles.
|
||||
sagaAbility.addChapterEffect(
|
||||
this, SagaChapter.CHAPTER_II,
|
||||
new Effects(
|
||||
new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL), new TheRiseOfSozinEffect()
|
||||
), new TargetOpponent()
|
||||
);
|
||||
|
||||
// III -- Exile this Saga, then return it to the battlefield transformed under your control.
|
||||
this.addAbility(new TransformAbility());
|
||||
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, new ExileSagaAndReturnTransformedEffect());
|
||||
this.addAbility(sagaAbility);
|
||||
}
|
||||
|
||||
private TheRiseOfSozin(final TheRiseOfSozin card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheRiseOfSozin copy() {
|
||||
return new TheRiseOfSozin(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TheRiseOfSozinEffect extends SearchTargetGraveyardHandLibraryForCardNameAndExileEffect {
|
||||
|
||||
TheRiseOfSozinEffect() {
|
||||
super(true, "target opponent's", "up to four cards with that name", false, 4);
|
||||
}
|
||||
|
||||
private TheRiseOfSozinEffect(final TheRiseOfSozinEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheRiseOfSozinEffect copy() {
|
||||
return new TheRiseOfSozinEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
String chosenCardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
|
||||
return applySearchAndExile(game, source, chosenCardName, getTargetPointer().getFirst(game, source));
|
||||
}
|
||||
}
|
||||
|
|
@ -60,8 +60,7 @@ class TorchTheWitnessEffect extends OneShotEffect {
|
|||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
||||
if (lethal < permanent.damage(2 * CardUtil.getSourceCostsTag(game, source, "X", 0), source, game)) {
|
||||
if (permanent.damageWithExcess(2 * CardUtil.getSourceCostsTag(game, source, "X", 0), source, game) > 0) {
|
||||
InvestigateEffect.doInvestigate(source.getControllerId(), 1, game, source);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class TreeOfPerditionEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player opponent = game.getPlayer(source.getFirstTarget());
|
||||
Permanent perm = game.getPermanent(source.getSourceId());
|
||||
if (perm == null || opponent == null || !opponent.isLifeTotalCanChange()) {
|
||||
if (perm == null || opponent == null || !opponent.isLifeTotalCanChange() || !perm.isCreature(game)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class TreeOfRedemptionEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent perm = game.getPermanent(source.getSourceId());
|
||||
if (perm == null || player == null || !player.isLifeTotalCanChange()) {
|
||||
if (perm == null || player == null || !player.isLifeTotalCanChange() || !perm.isCreature(game)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,10 +67,10 @@ class UnleashTheInfernoEffect extends OneShotEffect {
|
|||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), 7);
|
||||
permanent.damage(7, source, game);
|
||||
int excess = 7 - lethal;
|
||||
if (excess > 0) {
|
||||
int excess = permanent.damageWithExcess(7, source, game);
|
||||
if (excess < 1) {
|
||||
return true;
|
||||
}
|
||||
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(new DestroyTargetEffect(), false);
|
||||
FilterPermanent filter = new FilterArtifactOrEnchantmentPermanent(
|
||||
"artifact or enchantment an opponent controls with mana value less than or equal to " + excess
|
||||
|
|
@ -79,7 +79,6 @@ class UnleashTheInfernoEffect extends OneShotEffect {
|
|||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, excess + 1));
|
||||
ability.addTarget(new TargetPermanent(filter));
|
||||
game.fireReflexiveTriggeredAbility(ability, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.PlayLandOrCastSpellTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
|
|
@ -14,7 +17,6 @@ import mage.cards.Card;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
|
@ -142,14 +144,16 @@ class UriangerAugureltPlayEffect extends AsThoughEffectImpl {
|
|||
if (card.isLand(game)) {
|
||||
return true;
|
||||
}
|
||||
// TODO: This should ideally apply the reduction while the spell is being cast because effects that increase the cost apply first
|
||||
Optional.ofNullable(source)
|
||||
.map(Controllable::getControllerId)
|
||||
.map(game::getPlayer)
|
||||
.ifPresent(player -> player.setCastSourceIdWithAlternateMana(
|
||||
card.getId(), CardUtil.reduceCost(card.getManaCost(), 2),
|
||||
null, MageIdentifier.UriangerAugureltAlternateCast
|
||||
));
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
ManaCosts<ManaCost> newCost = CardUtil.reduceCost(card.getManaCost(), 2);
|
||||
if (newCost.isEmpty()) {
|
||||
newCost.add(new GenericManaCost(0));
|
||||
}
|
||||
controller.setCastSourceIdWithAlternateMana(
|
||||
card.getId(), newCost, null, MageIdentifier.UriangerAugureltAlternateCast
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,11 +14,13 @@ import mage.constants.CardType;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetAnyTarget;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -91,14 +93,11 @@ class VikyaScorchingStalwartEffect extends OneShotEffect {
|
|||
if (!permanent.isCreature(game)) {
|
||||
return permanent.damage(amount, source, game) > 0;
|
||||
}
|
||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
||||
permanent.damage(amount, source.getSourceId(), source, game);
|
||||
if (lethal >= amount) {
|
||||
return true;
|
||||
}
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
player.drawCards(1, source, game);
|
||||
if (permanent.damageWithExcess(amount, source, game) > 0) {
|
||||
Optional.ofNullable(source)
|
||||
.map(Controllable::getControllerId)
|
||||
.map(game::getPlayer)
|
||||
.ifPresent(player -> player.drawCards(1, source, game));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,26 @@
|
|||
package mage.cards.w;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.ElfWarriorToken;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.EachTargetPointer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author bwsinger
|
||||
*/
|
||||
public final class WindswiftSlice extends CardImpl {
|
||||
|
|
@ -48,6 +49,7 @@ class WindswiftSliceEffect extends OneShotEffect {
|
|||
|
||||
WindswiftSliceEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.setTargetPointer(new EachTargetPointer());
|
||||
staticText = "Target creature you control deals damage equal to its power to target " +
|
||||
"creature you don't control. Create a number of 1/1 green Elf Warrior creature " +
|
||||
"tokens equal to the amount of excess damage dealt this way.";
|
||||
|
|
@ -64,27 +66,26 @@ class WindswiftSliceEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent myPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
Permanent anotherPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||
|
||||
if (myPermanent == null || anotherPermanent == null) {
|
||||
List<Permanent> permanents = this
|
||||
.getTargetPointer()
|
||||
.getTargets(game, source)
|
||||
.stream()
|
||||
.map(game::getPermanent)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
if (permanents.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int power = myPermanent.getPower().getValue();
|
||||
Permanent permanent = permanents.get(0);
|
||||
int power = permanent.getPower().getValue();
|
||||
if (power < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int lethal = anotherPermanent.getLethalDamage(myPermanent.getId(), game);
|
||||
lethal = Math.min(lethal, power);
|
||||
|
||||
anotherPermanent.damage(power, myPermanent.getId(), source, game);
|
||||
|
||||
if (lethal < power) {
|
||||
new ElfWarriorToken().putOntoBattlefield(power - lethal, game, source, source.getControllerId());
|
||||
Permanent creature = permanents.get(1);
|
||||
int excess = creature.damageWithExcess(power, permanent.getId(), source, game);
|
||||
if (excess > 0) {
|
||||
new ElfWarriorToken().putOntoBattlefield(excess, game, source);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet {
|
|||
|
||||
cards.add(new SetCardInfo("Aang's Iceberg", 336, Rarity.RARE, mage.cards.a.AangsIceberg.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Aang's Iceberg", 5, Rarity.RARE, mage.cards.a.AangsIceberg.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Aang's Journey", 1, Rarity.COMMON, mage.cards.a.AangsJourney.class));
|
||||
cards.add(new SetCardInfo("Aang, Master of Elements", 207, Rarity.MYTHIC, mage.cards.a.AangMasterOfElements.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Aang, Master of Elements", 363, Rarity.MYTHIC, mage.cards.a.AangMasterOfElements.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Aang, the Last Airbender", 4, Rarity.UNCOMMON, mage.cards.a.AangTheLastAirbender.class));
|
||||
|
|
@ -55,6 +56,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Epic Downfall", 96, Rarity.UNCOMMON, mage.cards.e.EpicDownfall.class));
|
||||
cards.add(new SetCardInfo("Fated Firepower", 132, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fated Firepower", 341, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fire Lord Sozin", 117, Rarity.MYTHIC, mage.cards.f.FireLordSozin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fire Lord Sozin", 356, Rarity.MYTHIC, mage.cards.f.FireLordSozin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fire Lord Zuko", 221, Rarity.RARE, mage.cards.f.FireLordZuko.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fire Lord Zuko", 360, Rarity.RARE, mage.cards.f.FireLordZuko.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fire Nation Attacks", 133, Rarity.UNCOMMON, mage.cards.f.FireNationAttacks.class));
|
||||
|
|
@ -63,15 +66,19 @@ public final class AvatarTheLastAirbender extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("First-Time Flyer", 49, Rarity.COMMON, mage.cards.f.FirstTimeFlyer.class));
|
||||
cards.add(new SetCardInfo("Flexible Waterbender", 50, Rarity.COMMON, mage.cards.f.FlexibleWaterbender.class));
|
||||
cards.add(new SetCardInfo("Flopsie, Bumi's Buddy", 179, Rarity.UNCOMMON, mage.cards.f.FlopsieBumisBuddy.class));
|
||||
cards.add(new SetCardInfo("Forest", 286, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Forest", 291, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Geyser Leaper", 52, Rarity.COMMON, mage.cards.g.GeyserLeaper.class));
|
||||
cards.add(new SetCardInfo("Giant Koi", 53, Rarity.COMMON, mage.cards.g.GiantKoi.class));
|
||||
cards.add(new SetCardInfo("Glider Kids", 21, Rarity.COMMON, mage.cards.g.GliderKids.class));
|
||||
cards.add(new SetCardInfo("Hakoda, Selfless Commander", 366, Rarity.RARE, mage.cards.h.HakodaSelflessCommander.class));
|
||||
cards.add(new SetCardInfo("Haru, Hidden Talent", 182, Rarity.UNCOMMON, mage.cards.h.HaruHiddenTalent.class));
|
||||
cards.add(new SetCardInfo("Heartless Act", 103, Rarity.UNCOMMON, mage.cards.h.HeartlessAct.class));
|
||||
cards.add(new SetCardInfo("Hei Bai, Spirit of Balance", 225, Rarity.UNCOMMON, mage.cards.h.HeiBaiSpiritOfBalance.class));
|
||||
cards.add(new SetCardInfo("Hog-Monkey", 104, Rarity.COMMON, mage.cards.h.HogMonkey.class));
|
||||
cards.add(new SetCardInfo("How to Start a Riot", 140, Rarity.COMMON, mage.cards.h.HowToStartARiot.class));
|
||||
cards.add(new SetCardInfo("Iguana Parrot", 56, Rarity.COMMON, mage.cards.i.IguanaParrot.class));
|
||||
cards.add(new SetCardInfo("Island", 283, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Island", 288, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("It'll Quench Ya!", 58, Rarity.COMMON, mage.cards.i.ItllQuenchYa.class));
|
||||
cards.add(new SetCardInfo("Jeong Jeong's Deserters", 25, Rarity.COMMON, mage.cards.j.JeongJeongsDeserters.class));
|
||||
|
|
@ -82,20 +89,26 @@ public final class AvatarTheLastAirbender extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Katara, the Fearless", 350, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Katara, the Fearless", 361, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Lightning Strike", 146, Rarity.COMMON, mage.cards.l.LightningStrike.class));
|
||||
cards.add(new SetCardInfo("Long Feng, Grand Secretariat", 233, Rarity.UNCOMMON, mage.cards.l.LongFengGrandSecretariat.class));
|
||||
cards.add(new SetCardInfo("Master Pakku", 63, Rarity.UNCOMMON, mage.cards.m.MasterPakku.class));
|
||||
cards.add(new SetCardInfo("Master Piandao", 28, Rarity.UNCOMMON, mage.cards.m.MasterPiandao.class));
|
||||
cards.add(new SetCardInfo("Merchant of Many Hats", 110, Rarity.COMMON, mage.cards.m.MerchantOfManyHats.class));
|
||||
cards.add(new SetCardInfo("Momo, Friendly Flier", 29, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Momo, Friendly Flier", 317, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mongoose Lizard", 148, Rarity.COMMON, mage.cards.m.MongooseLizard.class));
|
||||
cards.add(new SetCardInfo("Mountain", 285, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mountain", 290, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ostrich-Horse", 188, Rarity.COMMON, mage.cards.o.OstrichHorse.class));
|
||||
cards.add(new SetCardInfo("Otter-Penguin", 67, Rarity.COMMON, mage.cards.o.OtterPenguin.class));
|
||||
cards.add(new SetCardInfo("Ozai's Cruelty", 113, Rarity.UNCOMMON, mage.cards.o.OzaisCruelty.class));
|
||||
cards.add(new SetCardInfo("Path to Redemption", 31, Rarity.COMMON, mage.cards.p.PathToRedemption.class));
|
||||
cards.add(new SetCardInfo("Pillar Launch", 189, Rarity.COMMON, mage.cards.p.PillarLaunch.class));
|
||||
cards.add(new SetCardInfo("Plains", 282, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 287, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Pretending Poxbearers", 237, Rarity.COMMON, mage.cards.p.PretendingPoxbearers.class));
|
||||
cards.add(new SetCardInfo("Rabaroo Troop", 32, Rarity.COMMON, mage.cards.r.RabarooTroop.class));
|
||||
cards.add(new SetCardInfo("Raucous Audience", 190, Rarity.COMMON, mage.cards.r.RaucousAudience.class));
|
||||
cards.add(new SetCardInfo("Razor Rings", 33, Rarity.COMMON, mage.cards.r.RazorRings.class));
|
||||
cards.add(new SetCardInfo("Rebellious Captives", 191, Rarity.COMMON, mage.cards.r.RebelliousCaptives.class));
|
||||
cards.add(new SetCardInfo("Redirect Lightning", 151, Rarity.RARE, mage.cards.r.RedirectLightning.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Redirect Lightning", 343, Rarity.RARE, mage.cards.r.RedirectLightning.class, NON_FULL_USE_VARIOUS));
|
||||
|
|
@ -103,12 +116,17 @@ public final class AvatarTheLastAirbender extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Rough Rhino Cavalry", 152, Rarity.COMMON, mage.cards.r.RoughRhinoCavalry.class));
|
||||
cards.add(new SetCardInfo("Rowdy Snowballers", 68, Rarity.COMMON, mage.cards.r.RowdySnowballers.class));
|
||||
cards.add(new SetCardInfo("Saber-Tooth Moose-Lion", 194, Rarity.COMMON, mage.cards.s.SaberToothMooseLion.class));
|
||||
cards.add(new SetCardInfo("Serpent of the Pass", 70, Rarity.UNCOMMON, mage.cards.s.SerpentOfThePass.class));
|
||||
cards.add(new SetCardInfo("Sokka's Haiku", 71, Rarity.UNCOMMON, mage.cards.s.SokkasHaiku.class));
|
||||
cards.add(new SetCardInfo("Sokka, Bold Boomeranger", 240, Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sokka, Bold Boomeranger", 383, Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sokka, Lateral Strategist", 241, Rarity.UNCOMMON, mage.cards.s.SokkaLateralStrategist.class));
|
||||
cards.add(new SetCardInfo("Southern Air Temple", 36, Rarity.UNCOMMON, mage.cards.s.SouthernAirTemple.class));
|
||||
cards.add(new SetCardInfo("Suki, Kyoshi Warrior", 243, Rarity.UNCOMMON, mage.cards.s.SukiKyoshiWarrior.class));
|
||||
cards.add(new SetCardInfo("Swamp", 284, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Swamp", 289, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Rise of Sozin", 117, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Rise of Sozin", 356, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Toph, the Blind Bandit", 198, Rarity.UNCOMMON, mage.cards.t.TophTheBlindBandit.class));
|
||||
cards.add(new SetCardInfo("Toph, the First Metalbender", 247, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Toph, the First Metalbender", 353, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS));
|
||||
|
|
|
|||
|
|
@ -24,51 +24,85 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet {
|
|||
super("Avatar: The Last Airbender Eternal", "TLE", ExpansionSet.buildDate(2025, 11, 21), SetType.SUPPLEMENTAL);
|
||||
this.blockName = "Avatar: The Last Airbender"; // for sorting in GUI
|
||||
this.rotationSet = true;
|
||||
this.hasBasicLands = false;
|
||||
this.hasBasicLands = true;
|
||||
|
||||
cards.add(new SetCardInfo("Aang's Defense", 211, Rarity.COMMON, mage.cards.a.AangsDefense.class));
|
||||
cards.add(new SetCardInfo("Aang, Air Nomad", 210, Rarity.RARE, mage.cards.a.AangAirNomad.class));
|
||||
cards.add(new SetCardInfo("Aang's Defense", 211, Rarity.COMMON, mage.cards.a.AangsDefense.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Aang's Defense", 266, Rarity.COMMON, mage.cards.a.AangsDefense.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Aang, Air Nomad", 210, Rarity.RARE, mage.cards.a.AangAirNomad.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Aang, Air Nomad", 265, Rarity.RARE, mage.cards.a.AangAirNomad.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Aang, Airbending Master", 74, Rarity.MYTHIC, mage.cards.a.AangAirbendingMaster.class));
|
||||
cards.add(new SetCardInfo("Aardvark Sloth", 212, Rarity.COMMON, mage.cards.a.AardvarkSloth.class));
|
||||
cards.add(new SetCardInfo("Aardvark Sloth", 212, Rarity.COMMON, mage.cards.a.AardvarkSloth.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Aardvark Sloth", 267, Rarity.COMMON, mage.cards.a.AardvarkSloth.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Allied Teamwork", 213, Rarity.RARE, mage.cards.a.AlliedTeamwork.class));
|
||||
cards.add(new SetCardInfo("Appa, Aang's Companion", 214, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class));
|
||||
cards.add(new SetCardInfo("Appa, Aang's Companion", 214, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Appa, Aang's Companion", 268, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Bumi, Eclectic Earthbender", 248, Rarity.RARE, mage.cards.b.BumiEclecticEarthbender.class));
|
||||
cards.add(new SetCardInfo("Capital Guard", 234, Rarity.COMMON, mage.cards.c.CapitalGuard.class));
|
||||
cards.add(new SetCardInfo("Capital Guard", 234, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Capital Guard", 277, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Deny Entry", 222, Rarity.COMMON, mage.cards.d.DenyEntry.class));
|
||||
cards.add(new SetCardInfo("Dragon Moose", 235, Rarity.COMMON, mage.cards.d.DragonMoose.class));
|
||||
cards.add(new SetCardInfo("Dragon Moose", 235, Rarity.COMMON, mage.cards.d.DragonMoose.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Dragon Moose", 278, Rarity.COMMON, mage.cards.d.DragonMoose.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Earthbending Student", 249, Rarity.UNCOMMON, mage.cards.e.EarthbendingStudent.class));
|
||||
cards.add(new SetCardInfo("Eel-Hounds", 250, Rarity.UNCOMMON, mage.cards.e.EelHounds.class));
|
||||
cards.add(new SetCardInfo("Elephant-Rat", 228, Rarity.COMMON, mage.cards.e.ElephantRat.class));
|
||||
cards.add(new SetCardInfo("Explore", 259, Rarity.COMMON, mage.cards.e.Explore.class));
|
||||
cards.add(new SetCardInfo("Explosive Shot", 236, Rarity.COMMON, mage.cards.e.ExplosiveShot.class));
|
||||
cards.add(new SetCardInfo("Explosive Shot", 236, Rarity.COMMON, mage.cards.e.ExplosiveShot.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Explosive Shot", 279, Rarity.COMMON, mage.cards.e.ExplosiveShot.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Feed the Swarm", 257, Rarity.COMMON, mage.cards.f.FeedTheSwarm.class));
|
||||
cards.add(new SetCardInfo("Fire Nation Ambushers", 229, Rarity.COMMON, mage.cards.f.FireNationAmbushers.class));
|
||||
cards.add(new SetCardInfo("Fire Nation Archers", 237, Rarity.RARE, mage.cards.f.FireNationArchers.class));
|
||||
cards.add(new SetCardInfo("Fire Nation Sentinels", 230, Rarity.RARE, mage.cards.f.FireNationSentinels.class));
|
||||
cards.add(new SetCardInfo("Fire Nation Soldier", 238, Rarity.COMMON, mage.cards.f.FireNationSoldier.class));
|
||||
cards.add(new SetCardInfo("Fire Nation's Conquest", 239, Rarity.UNCOMMON, mage.cards.f.FireNationsConquest.class));
|
||||
cards.add(new SetCardInfo("Fire Nation Soldier", 238, Rarity.COMMON, mage.cards.f.FireNationSoldier.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fire Nation Soldier", 280, Rarity.COMMON, mage.cards.f.FireNationSoldier.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fire Nation's Conquest", 239, Rarity.UNCOMMON, mage.cards.f.FireNationsConquest.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Fire Nation's Conquest", 281, Rarity.UNCOMMON, mage.cards.f.FireNationsConquest.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Flying Dolphin-Fish", 223, Rarity.COMMON, mage.cards.f.FlyingDolphinFish.class));
|
||||
cards.add(new SetCardInfo("Force of Negation", 13, Rarity.MYTHIC, mage.cards.f.ForceOfNegation.class));
|
||||
cards.add(new SetCardInfo("Frog-Squirrels", 251, Rarity.COMMON, mage.cards.f.FrogSquirrels.class));
|
||||
cards.add(new SetCardInfo("Gilacorn", 231, Rarity.COMMON, mage.cards.g.Gilacorn.class));
|
||||
cards.add(new SetCardInfo("Hippo-Cows", 252, Rarity.COMMON, mage.cards.h.HippoCows.class));
|
||||
cards.add(new SetCardInfo("Iroh, Firebending Instructor", 240, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class));
|
||||
cards.add(new SetCardInfo("Katara, Heroic Healer", 215, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class));
|
||||
cards.add(new SetCardInfo("Iroh, Firebending Instructor", 240, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Iroh, Firebending Instructor", 282, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Katara, Heroic Healer", 215, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Katara, Heroic Healer", 269, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Katara, Waterbending Master", 93, Rarity.MYTHIC, mage.cards.k.KataraWaterbendingMaster.class));
|
||||
cards.add(new SetCardInfo("Komodo Rhino", 241, Rarity.COMMON, mage.cards.k.KomodoRhino.class));
|
||||
cards.add(new SetCardInfo("Komodo Rhino", 241, Rarity.COMMON, mage.cards.k.KomodoRhino.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Komodo Rhino", 283, Rarity.COMMON, mage.cards.k.KomodoRhino.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kyoshi Warrior Guard", 216, Rarity.COMMON, mage.cards.k.KyoshiWarriorGuard.class));
|
||||
cards.add(new SetCardInfo("Lion Vulture", 232, Rarity.RARE, mage.cards.l.LionVulture.class));
|
||||
cards.add(new SetCardInfo("Lost in the Spirit World", 224, Rarity.UNCOMMON, mage.cards.l.LostInTheSpiritWorld.class));
|
||||
cards.add(new SetCardInfo("Loyal Fire Sage", 242, Rarity.UNCOMMON, mage.cards.l.LoyalFireSage.class));
|
||||
cards.add(new SetCardInfo("Match the Odds", 253, Rarity.UNCOMMON, mage.cards.m.MatchTheOdds.class));
|
||||
cards.add(new SetCardInfo("Mechanical Glider", 256, Rarity.COMMON, mage.cards.m.MechanicalGlider.class));
|
||||
cards.add(new SetCardInfo("Momo, Rambunctious Rascal", 217, Rarity.UNCOMMON, mage.cards.m.MomoRambunctiousRascal.class));
|
||||
cards.add(new SetCardInfo("Momo, Rambunctious Rascal", 217, Rarity.UNCOMMON, mage.cards.m.MomoRambunctiousRascal.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Momo, Rambunctious Rascal", 270, Rarity.UNCOMMON, mage.cards.m.MomoRambunctiousRascal.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mountain", 289, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mountain", 290, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mountain", 291, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mountain", 292, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mountain", 293, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mountain", 294, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mountain", 295, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mountain", 296, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Path to Redemption", 271, Rarity.COMMON, mage.cards.p.PathToRedemption.class));
|
||||
cards.add(new SetCardInfo("Plains", 297, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 298, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 299, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 300, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 301, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 302, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 303, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Plains", 304, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Purple Pentapus", 233, Rarity.COMMON, mage.cards.p.PurplePentapus.class));
|
||||
cards.add(new SetCardInfo("Razor Rings", 272, Rarity.COMMON, mage.cards.r.RazorRings.class));
|
||||
cards.add(new SetCardInfo("Roku's Mastery", 243, Rarity.UNCOMMON, mage.cards.r.RokusMastery.class));
|
||||
cards.add(new SetCardInfo("Run Amok", 258, Rarity.COMMON, mage.cards.r.RunAmok.class));
|
||||
cards.add(new SetCardInfo("Run Amok", 258, Rarity.COMMON, mage.cards.r.RunAmok.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Run Amok", 284, Rarity.COMMON, mage.cards.r.RunAmok.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Seismic Tutelage", 254, Rarity.RARE, mage.cards.s.SeismicTutelage.class));
|
||||
cards.add(new SetCardInfo("Sledding Otter-Penguin", 218, Rarity.COMMON, mage.cards.s.SleddingOtterPenguin.class));
|
||||
cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 219, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class));
|
||||
cards.add(new SetCardInfo("Sledding Otter-Penguin", 218, Rarity.COMMON, mage.cards.s.SleddingOtterPenguin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sledding Otter-Penguin", 273, Rarity.COMMON, mage.cards.s.SleddingOtterPenguin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 219, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 274, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("The Cabbage Merchant", 134, Rarity.RARE, mage.cards.t.TheCabbageMerchant.class));
|
||||
cards.add(new SetCardInfo("The Great Henge", 41, Rarity.MYTHIC, mage.cards.t.TheGreatHenge.class));
|
||||
cards.add(new SetCardInfo("The Terror of Serpent's Pass", 225, Rarity.RARE, mage.cards.t.TheTerrorOfSerpentsPass.class));
|
||||
|
|
@ -77,14 +111,20 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Thriving Heath", 262, Rarity.COMMON, mage.cards.t.ThrivingHeath.class));
|
||||
cards.add(new SetCardInfo("Thriving Isle", 263, Rarity.COMMON, mage.cards.t.ThrivingIsle.class));
|
||||
cards.add(new SetCardInfo("Thriving Moor", 264, Rarity.COMMON, mage.cards.t.ThrivingMoor.class));
|
||||
cards.add(new SetCardInfo("Tundra Wall", 220, Rarity.COMMON, mage.cards.t.TundraWall.class));
|
||||
cards.add(new SetCardInfo("Tundra Wall", 220, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tundra Wall", 275, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Turtle-Seals", 226, Rarity.COMMON, mage.cards.t.TurtleSeals.class));
|
||||
cards.add(new SetCardInfo("Warship Scout", 244, Rarity.COMMON, mage.cards.w.WarshipScout.class));
|
||||
cards.add(new SetCardInfo("Warship Scout", 244, Rarity.COMMON, mage.cards.w.WarshipScout.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Warship Scout", 285, Rarity.COMMON, mage.cards.w.WarshipScout.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Water Whip", 227, Rarity.RARE, mage.cards.w.WaterWhip.class));
|
||||
cards.add(new SetCardInfo("Wolf Cove Villager", 221, Rarity.COMMON, mage.cards.w.WolfCoveVillager.class));
|
||||
cards.add(new SetCardInfo("Zhao, the Seething Flame", 245, Rarity.UNCOMMON, mage.cards.z.ZhaoTheSeethingFlame.class));
|
||||
cards.add(new SetCardInfo("Zuko's Offense", 247, Rarity.COMMON, mage.cards.z.ZukosOffense.class));
|
||||
cards.add(new SetCardInfo("Zuko, Avatar Hunter", 246, Rarity.RARE, mage.cards.z.ZukoAvatarHunter.class));
|
||||
cards.add(new SetCardInfo("Wolf Cove Villager", 221, Rarity.COMMON, mage.cards.w.WolfCoveVillager.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Wolf Cove Villager", 276, Rarity.COMMON, mage.cards.w.WolfCoveVillager.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Zhao, the Seething Flame", 245, Rarity.UNCOMMON, mage.cards.z.ZhaoTheSeethingFlame.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Zhao, the Seething Flame", 286, Rarity.UNCOMMON, mage.cards.z.ZhaoTheSeethingFlame.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Zuko's Offense", 247, Rarity.COMMON, mage.cards.z.ZukosOffense.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Zuko's Offense", 288, Rarity.COMMON, mage.cards.z.ZukosOffense.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Zuko, Avatar Hunter", 246, Rarity.RARE, mage.cards.z.ZukoAvatarHunter.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Zuko, Avatar Hunter", 287, Rarity.RARE, mage.cards.z.ZukoAvatarHunter.class, NON_FULL_USE_VARIOUS));
|
||||
|
||||
cards.removeIf(setCardInfo -> unfinished.contains(setCardInfo.getName()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
package org.mage.test.cards.continuous;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.permanent.Permanent;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class AddCardSubtypeAllEffectTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Kudo, King Among Bears
|
||||
{G}{W}
|
||||
Legendary Creature — Bear
|
||||
Other creatures have base power and toughness 2/2 and are Bears in addition to their other types.
|
||||
2/2
|
||||
*/
|
||||
private static final String kudo = "Kudo, King Among Bears";
|
||||
|
||||
/*
|
||||
Fugitive Wizard
|
||||
{U}
|
||||
Creature — Human Wizard
|
||||
1/1
|
||||
*/
|
||||
private static final String fugitive = "Fugitive Wizard";
|
||||
|
||||
@Test
|
||||
public void testAddCardSubtypeAllEffect() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, fugitive, 3);
|
||||
addCard(Zone.BATTLEFIELD, playerB, fugitive, 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, kudo);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Savannah", 2);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
|
||||
if (permanent.getName().equals(fugitive)) {
|
||||
assertTrue(permanent.hasSubtype(SubType.BEAR, currentGame));
|
||||
assertTrue(permanent.hasSubtype(SubType.WIZARD, currentGame));
|
||||
assertTrue(permanent.hasSubtype(SubType.HUMAN, currentGame));
|
||||
assertEquals(2, permanent.getPower().getModifiedBaseValue());
|
||||
assertEquals(2, permanent.getToughness().getModifiedBaseValue());
|
||||
}
|
||||
}
|
||||
|
||||
assertSubtype(kudo, SubType.BEAR);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package org.mage.test.cards.continuous;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class BecomesColorEffectTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Ancient Kavu
|
||||
{3}{R}
|
||||
Creature — Kavu
|
||||
{2}: This creature becomes colorless until end of turn.
|
||||
Those with the ability to change their nature survived Phyrexia’s biological attacks. Everything else died.
|
||||
3/3
|
||||
*/
|
||||
String kavu = "Ancient Kavu";
|
||||
/*
|
||||
Alchor's Tomb
|
||||
{4}
|
||||
Artifact
|
||||
{2}, {T}: Target permanent you control becomes the color of your choice. (This effect lasts indefinitely.)
|
||||
*/
|
||||
String alchorsTomb = "Alchor's Tomb";
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testBecomesColorSource() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, kavu);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
|
||||
checkColor("Ancient Kavu is red", 1, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "R", true);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}: {this}");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkColor("Ancient Kavu is colorless", 1, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "C", true);
|
||||
checkColor("Ancient Kavu is red again", 2, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "R", true);
|
||||
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBecomesColorTarget() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, kavu);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, alchorsTomb);
|
||||
|
||||
checkColor("Ancient Kavu is red", 1, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "R", true);
|
||||
// make Ancient Kavu green
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}, {T}: Target permanent", kavu);
|
||||
setChoice(playerA, "Green");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkColor("Ancient Kavu is green", 1, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "G", true);
|
||||
checkColor("Ancient Kavu is still green the following turn", 2, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "G", true);
|
||||
// activate Ancient Kavu's ability to override green color until end of turn
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}: {this}");
|
||||
checkColor("Ancient Kavu is colorless", 3, PhaseStep.POSTCOMBAT_MAIN, playerA, kavu, "C", true);
|
||||
// next turn it should be green again
|
||||
checkColor("Ancient Kavu is green again", 4, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "G", true);
|
||||
|
||||
setStopAt(4, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package org.mage.test.cards.continuous;
|
||||
|
||||
import mage.ObjectColor;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.mageobject.PowerPredicate;
|
||||
import mage.filter.predicate.mageobject.ToughnessPredicate;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class BecomesCreatureEffectTest extends CardTestPlayerBase {
|
||||
/*
|
||||
Ambush Commander
|
||||
{3}{G}{G}
|
||||
Creature — Elf
|
||||
Forests you control are 1/1 green Elf creatures that are still lands.
|
||||
{1}{G}, Sacrifice an Elf: Target creature gets +3/+3 until end of turn.
|
||||
2/2
|
||||
*/
|
||||
String ambushCommander = "Ambush Commander";
|
||||
/*
|
||||
Dryad Arbor
|
||||
Land Creature — Forest Dryad
|
||||
1/1
|
||||
*/
|
||||
String dryadArbor = "Dryad Arbor";
|
||||
/*
|
||||
Frogify
|
||||
{1}{U}
|
||||
Enchantment — Aura
|
||||
Enchant creature
|
||||
Enchanted creature loses all abilities and is a blue Frog creature with base power and toughness 1/1.
|
||||
(It loses all other card types and creature types.)
|
||||
*/
|
||||
String frogify = "Frogify";
|
||||
@Test
|
||||
public void testBecomesCreatureAllEffect() {
|
||||
FilterPermanent filter = new FilterPermanent();
|
||||
filter.add(CardType.CREATURE.getPredicate());
|
||||
filter.add(SubType.ELF.getPredicate());
|
||||
filter.add(new PowerPredicate(ComparisonType.EQUAL_TO, 1));
|
||||
filter.add(new ToughnessPredicate(ComparisonType.EQUAL_TO, 1));
|
||||
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, dryadArbor);
|
||||
addCard(Zone.HAND, playerA, ambushCommander);
|
||||
|
||||
runCode("Check forests are not 1/1 Elves", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
int numElves = game.getBattlefield().getActivePermanents(filter, player.getId(), game).size();
|
||||
Assert.assertEquals("No 1/1 elves should be present", 0, numElves);
|
||||
});
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ambushCommander);
|
||||
runCode("Check forests are 1/1 Elves", 1, PhaseStep.BEGIN_COMBAT, playerA, (info, player, game) -> {
|
||||
int numElves = game.getBattlefield().getActivePermanents(filter, player.getId(), game).size();
|
||||
// 5 forests + dryad arbor
|
||||
Assert.assertEquals("There should be 6 1/1 elves present", 6, numElves);
|
||||
});
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBecomesCreatureAttachedEffect() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, dryadArbor);
|
||||
addCard(Zone.HAND, playerA, frogify);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, frogify, dryadArbor);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertAbilities(playerA, dryadArbor, Collections.emptyList());
|
||||
assertPowerToughness(playerA, dryadArbor, 1, 1);
|
||||
assertType(dryadArbor, CardType.CREATURE, SubType.FROG);
|
||||
assertNotSubtype(dryadArbor, SubType.DRYAD);
|
||||
assertNotType(dryadArbor, CardType.LAND);
|
||||
assertColor(playerA, dryadArbor, ObjectColor.BLUE, true);
|
||||
assertColor(playerA, dryadArbor, ObjectColor.GREEN, false);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package org.mage.test.cards.continuous;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class BecomesCreatureIfVehicleEffectTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Aerial Modification
|
||||
{4}{W}
|
||||
Enchantment — Aura
|
||||
Enchant creature or Vehicle
|
||||
As long as enchanted permanent is a Vehicle, it’s a creature in addition to its other types.
|
||||
Enchanted creature gets +2/+2 and has flying.
|
||||
*/
|
||||
String aerialMod = "Aerial Modification";
|
||||
/*
|
||||
Goliath Truck
|
||||
{4}
|
||||
Artifact — Vehicle
|
||||
Stowage — Whenever this Vehicle attacks, put two +1/+1 counters on another target attacking creature.
|
||||
Crew 2 (Tap any number of creatures you control with total power 2 or more: This Vehicle becomes an artifact creature until end of turn.)
|
||||
4/4
|
||||
*/
|
||||
String goliathTruck = "Goliath Truck";
|
||||
|
||||
@Test
|
||||
public void testBecomesCreatureIfVehicleEffect() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, goliathTruck);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.HAND, playerA, aerialMod);
|
||||
|
||||
checkType("Goliath Truck is not a creature", 1, PhaseStep.PRECOMBAT_MAIN, playerA, goliathTruck, CardType.CREATURE, false);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aerialMod, goliathTruck);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertType(goliathTruck, CardType.CREATURE, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -157,4 +157,29 @@ public class EmblemsTest extends CardTestPlayerBase {
|
|||
assertHandCount(playerA, 0);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJayaFieryNegotiator() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Jaya, Fiery Negotiator");
|
||||
addCard(Zone.HAND, playerA, "Wrenn's Resolve");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||
addCard(Zone.LIBRARY, playerA, "Lightning Bolt", 2);
|
||||
skipInitShuffling();
|
||||
|
||||
addCounters(1, PhaseStep.UPKEEP, playerA, "Jaya, Fiery Negotiator", CounterType.LOYALTY, 6);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-8: You get an emblem");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wrenn's Resolve");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
setChoice(playerA, false, 2);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertExileCount(playerA, 6 - 1);
|
||||
assertLife(playerB, 20 - 3 * 3);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package org.mage.test.cards.single._5ed;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class AnHavvaConstableTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
An-Havva Constable
|
||||
{1}{G}{G}
|
||||
Creature — Human
|
||||
An-Havva Constable’s toughness is equal to 1 plus the number of green creatures on the battlefield.
|
||||
2/1+*
|
||||
*/
|
||||
private static final String constable = "An-Havva Constable";
|
||||
/*
|
||||
Bear Cub
|
||||
{1}{G}
|
||||
Creature — Bear
|
||||
2/2
|
||||
*/
|
||||
private static final String cub = "Bear Cub";
|
||||
@Test
|
||||
public void testAnHavva() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
addCard(Zone.BATTLEFIELD, playerA, constable);
|
||||
addCard(Zone.HAND, playerA, constable);
|
||||
addCard(Zone.BATTLEFIELD, playerA, cub, 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, cub, 3);
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||
|
||||
checkPT("An-Havva Constable has toughness 7", 1, PhaseStep.PRECOMBAT_MAIN, playerA, constable, 2, 1 + 6);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", cub);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPT("An-Havva Constable has toughness 6", 1, PhaseStep.PRECOMBAT_MAIN, playerA, constable, 2, 1 + 5);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
playerA.getHand().getCards(currentGame).stream()
|
||||
.filter(card -> card.getName().equals(constable))
|
||||
.findFirst().
|
||||
ifPresent(card -> Assert.assertEquals(6, card.getToughness().getValue()));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package org.mage.test.cards.single.avr;
|
||||
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class DarkImpostorTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Dark Impostor
|
||||
{2}{B}
|
||||
Creature — Vampire Assassin
|
||||
|
||||
{4}{B}{B}: Exile target creature and put a +1/+1 counter on this creature.
|
||||
|
||||
This creature has all activated abilities of all creature cards exiled with it.
|
||||
2/2
|
||||
*/
|
||||
public static final String darkImposter = "Dark Impostor";
|
||||
/*
|
||||
Deathrite Shaman
|
||||
{B/G}
|
||||
Creature — Elf Shaman
|
||||
|
||||
{T}: Exile target land card from a graveyard. Add one mana of any color.
|
||||
|
||||
{B}, {T}: Exile target instant or sorcery card from a graveyard. Each opponent loses 2 life.
|
||||
|
||||
{G}, {T}: Exile target creature card from a graveyard. You gain 2 life.
|
||||
|
||||
1/2
|
||||
*/
|
||||
public static final String deathriteShaman = "Deathrite Shaman";
|
||||
|
||||
@Test
|
||||
public void testDarkImpostor() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, darkImposter);
|
||||
addCard(Zone.BATTLEFIELD, playerA, deathriteShaman);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{4}{B}{B}");
|
||||
addTarget(playerA, deathriteShaman);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertAbilityCount(playerA, darkImposter, SimpleActivatedAbility.class, 4); // own ability + 3 other from deathrite
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package org.mage.test.cards.single.c13;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class ActOfAuthorityEffectTest extends CardTestPlayerBase {
|
||||
/*
|
||||
Act of Authority
|
||||
{1}{W}{W}
|
||||
Enchantment
|
||||
When this enchantment enters, you may exile target artifact or enchantment.
|
||||
At the beginning of your upkeep, you may exile target artifact or enchantment. If you do, its controller gains control of this enchantment.
|
||||
*/
|
||||
private static final String actOfAuthority = "Act of Authority";
|
||||
|
||||
@Test
|
||||
public void testActOfAuthority() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, actOfAuthority);
|
||||
addCard(Zone.BATTLEFIELD, playerB, actOfAuthority + "@actB");
|
||||
|
||||
setChoice(playerA, true); // upkeep
|
||||
addTarget(playerA, "@actB");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerB, actOfAuthority, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package org.mage.test.cards.single.dft;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class AatchikEmeraldRadianTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Aatchik, Emerald Radian
|
||||
{3}{B}{B}{G}
|
||||
Legendary Creature — Insect Druid
|
||||
When Aatchik enters, create a 1/1 green Insect creature token for each artifact and/or creature card in your graveyard.
|
||||
Whenever another Insect you control dies, put a +1/+1 counter on Aatchik. Each opponent loses 1 life.
|
||||
3/3
|
||||
*/
|
||||
private static final String aatchik = "Aatchik, Emerald Radian";
|
||||
|
||||
/*
|
||||
Springheart Nantuko
|
||||
{1}{G}
|
||||
Enchantment Creature — Insect Monk
|
||||
Bestow {1}{G}
|
||||
Enchanted creature gets +1/+1.
|
||||
Landfall — Whenever a land you control enters, you may pay {1}{G} if this permanent is attached to a creature you control.
|
||||
If you do, create a token that’s a copy of that creature. If you didn’t create a token this way, create a 1/1 green Insect creature token.
|
||||
1/1
|
||||
*/
|
||||
private static final String nantuko = "Springheart Nantuko";
|
||||
|
||||
@Test
|
||||
public void testOpponentCreatingTokens() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, aatchik);
|
||||
addCard(Zone.BATTLEFIELD, playerB, aatchik);
|
||||
addCard(Zone.GRAVEYARD, playerA, aatchik);
|
||||
addCard(Zone.GRAVEYARD, playerB, aatchik);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Bayou", 9);
|
||||
addCard(Zone.HAND, playerA, nantuko);
|
||||
addCard(Zone.HAND, playerA, "Bayou");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, nantuko + " using bestow");
|
||||
addTarget(playerA, aatchik);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bayou");
|
||||
setChoice(playerA, true);
|
||||
setChoice(playerA, aatchik);
|
||||
setChoice(playerA, "When {this} enters");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertTokenCount(playerB, "Insect Token", 0);
|
||||
assertTokenCount(playerA, "Insect Token", 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package org.mage.test.cards.single.dis;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.UntapAllControllerEffect;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class ExperimentKrajTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Experiment Kraj
|
||||
{2}{G}{G}{U}{U}
|
||||
Legendary Creature — Ooze Mutant
|
||||
|
||||
Experiment Kraj has all activated abilities of each other creature with a +1/+1 counter on it.
|
||||
|
||||
{T}: Put a +1/+1 counter on target creature.
|
||||
*/
|
||||
private static final String experimentKraj = "Experiment Kraj";
|
||||
/*
|
||||
Stoneforge Mystic
|
||||
{1}{W}
|
||||
Creature — Kor Artificer
|
||||
|
||||
When this creature enters, you may search your library for an Equipment card, reveal it, put it into your hand, then shuffle.
|
||||
|
||||
{1}{W}, {T}: You may put an Equipment card from your hand onto the battlefield.
|
||||
*/
|
||||
private static final String stoneforgeMystic = "Stoneforge Mystic";
|
||||
/*
|
||||
Noble Hierarch
|
||||
{G}
|
||||
Creature — Human Druid
|
||||
|
||||
Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.)
|
||||
|
||||
{T}: Add {G}, {W}, or {U}.
|
||||
*/
|
||||
private static final String nobleHierarch = "Noble Hierarch";
|
||||
|
||||
@Test
|
||||
public void testExperimentKraj() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
Zone.ALL,
|
||||
new UntapAllControllerEffect(StaticFilters.FILTER_CONTROLLED_A_CREATURE),
|
||||
new ManaCostsImpl<>("")
|
||||
);
|
||||
addCustomCardWithAbility("Untap creatures", playerA, ability);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, experimentKraj);
|
||||
addCard(Zone.BATTLEFIELD, playerA, stoneforgeMystic);
|
||||
addCard(Zone.BATTLEFIELD, playerB, nobleHierarch);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Put a +1/+1", stoneforgeMystic);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "untap all");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Put a +1/+1", nobleHierarch);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertEquals("Kraj should have 5 activated abilities", 5, getPermanent(experimentKraj).getAbilities(currentGame)
|
||||
.stream()
|
||||
.filter(Ability::isActivatedAbility)
|
||||
.count());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package org.mage.test.cards.single.fic;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.UntapAllControllerEffect;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
|
||||
public class UriangerAugureltTest extends CardTestPlayerBase {
|
||||
|
||||
private static final String urianger = "Urianger Augurelt";
|
||||
private static final String arcaneSignet = "Arcane Signet";
|
||||
private static final String howlingMine = "Howling Mine";
|
||||
private static final String thoughtVessel = "Thought Vessel";
|
||||
private static final String benalishKnight = "Benalish Knight";
|
||||
|
||||
@Test
|
||||
public void uriangerAugureltTest() {
|
||||
setStrictChooseMode(true);
|
||||
skipInitShuffling();
|
||||
removeAllCardsFromLibrary(playerA);
|
||||
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
Zone.ALL,
|
||||
new UntapAllControllerEffect(StaticFilters.FILTER_CONTROLLED_A_CREATURE),
|
||||
new ManaCostsImpl<>("")
|
||||
);
|
||||
addCustomCardWithAbility("Untap creatures", playerA, ability);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, urianger);
|
||||
addCard(Zone.LIBRARY, playerA, "Plains", 3);
|
||||
addCard(Zone.LIBRARY, playerA, arcaneSignet);
|
||||
addCard(Zone.LIBRARY, playerA, howlingMine);
|
||||
addCard(Zone.LIBRARY, playerA, thoughtVessel);
|
||||
addCard(Zone.LIBRARY, playerA, benalishKnight);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "<i>Draw Arcanum</i>");
|
||||
setChoice(playerA, true, 4);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "untap all");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "<i>Draw Arcanum</i>");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "untap all");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "<i>Draw Arcanum</i>");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "untap all");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "<i>Draw Arcanum</i>");
|
||||
|
||||
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "<i>Play Arcanum</i>");
|
||||
waitStackResolved(3, PhaseStep.PRECOMBAT_MAIN);
|
||||
playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains");
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, benalishKnight, true);
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, arcaneSignet, true);
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, howlingMine, true);
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, thoughtVessel, true);
|
||||
|
||||
setStopAt(3, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, benalishKnight, 1);
|
||||
assertPermanentCount(playerA, arcaneSignet, 1);
|
||||
assertPermanentCount(playerA, howlingMine, 1);
|
||||
assertPermanentCount(playerA, thoughtVessel, 1);
|
||||
assertLife(playerA, 20 + 2 * 4);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package org.mage.test.cards.single.fin;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.permanent.Permanent;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class AettirAndPriwenTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Aettir and Priwen
|
||||
{6}
|
||||
Legendary Artifact — Equipment
|
||||
Equipped creature has base power and toughness X/X, where X is your life total.
|
||||
Equip {5}
|
||||
*/
|
||||
private static final String aettir = "Aettir and Priwen";
|
||||
/*
|
||||
Bear Cub
|
||||
{1}{G}
|
||||
Creature — Bear
|
||||
2/2
|
||||
*/
|
||||
private static final String cub = "Bear Cub";
|
||||
/*
|
||||
Lightning Bolt
|
||||
{R}
|
||||
Instant
|
||||
Lightning Bolt deals 3 damage to any target.
|
||||
*/
|
||||
public static final String bolt = "Lightning Bolt";
|
||||
|
||||
@Test
|
||||
public void testAettirAndPriwen() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, aettir);
|
||||
addCard(Zone.BATTLEFIELD, playerA, cub);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 7);
|
||||
addCard(Zone.HAND, playerA, bolt, 2);
|
||||
|
||||
checkPowerToughness(2, cub, 1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{5}: Equip");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPowerToughness(20, cub, 1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bolt, playerA);
|
||||
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
checkPowerToughness(20 - 3, cub, 1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bolt, playerA);
|
||||
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
checkPowerToughness(20 - 3 * 2, cub, 1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
|
||||
checkPowerToughness(20 - 3 * 2, cub, 2, PhaseStep.PRECOMBAT_MAIN);
|
||||
}
|
||||
|
||||
void checkPowerToughness(int xValue, String name, int turnNum, PhaseStep phaseStep) {
|
||||
runCode("Checking P/T is " + xValue, turnNum, phaseStep, playerA, (info, player, game) -> {
|
||||
Permanent permanent = getPermanent(name, player);
|
||||
Assert.assertEquals(xValue, permanent.getPower().getModifiedBaseValue());
|
||||
Assert.assertEquals(xValue, permanent.getToughness().getModifiedBaseValue());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package org.mage.test.cards.single.lci;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class AbuelosAwakeningTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Abuelo's Awakening
|
||||
{X}{3}{W}
|
||||
Sorcery
|
||||
Return target artifact or non-Aura enchantment card from your graveyard to the battlefield with X additional +1/+1 counters on it.
|
||||
It’s a 1/1 Spirit creature with flying in addition to its other types.
|
||||
*/
|
||||
public static final String abuelosAwakening = "Abuelo's Awakening";
|
||||
/*
|
||||
Talisman of Progress
|
||||
{2}
|
||||
Artifact
|
||||
{T}: Add {C}.
|
||||
{T}: Add {W} or {U}. This artifact deals 1 damage to you.
|
||||
*/
|
||||
public static final String talisman = "Talisman of Progress";
|
||||
/*
|
||||
Lightning Bolt
|
||||
{R}
|
||||
Instant
|
||||
Lightning Bolt deals 3 damage to any target.
|
||||
*/
|
||||
public static final String bolt = "Lightning Bolt";
|
||||
|
||||
@Test
|
||||
public void testAbuelosAwakening() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.GRAVEYARD, playerA, talisman);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
|
||||
addCard(Zone.HAND, playerA, abuelosAwakening);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, abuelosAwakening, talisman);
|
||||
setChoiceAmount(playerA, 2);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertCounterCount(playerA, talisman, CounterType.P1P1, 2);
|
||||
assertType(talisman, CardType.CREATURE, true);
|
||||
assertSubtype(talisman, SubType.SPIRIT);
|
||||
assertBasePowerToughness(playerA, talisman, 1, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbuelosAwakeningDies() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.GRAVEYARD, playerA, talisman);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
|
||||
addCard(Zone.HAND, playerA, abuelosAwakening);
|
||||
addCard(Zone.HAND, playerB, bolt);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, abuelosAwakening, talisman);
|
||||
setChoiceAmount(playerA, 2);
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, bolt, talisman);
|
||||
|
||||
setStopAt(2, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, talisman, 0);
|
||||
assertGraveyardCount(playerA, talisman, 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package org.mage.test.cards.single.lci;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
|
||||
public class DireBlunderbussTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Dire Blunderbuss
|
||||
Color Indicator: RedArtifact — Equipment
|
||||
|
||||
Equipped creature gets +3/+0 and has “Whenever this creature attacks, you may sacrifice an artifact other than Dire Blunderbuss. When you do, this creature deals damage equal to its power to target creature.”
|
||||
|
||||
Equip {1}
|
||||
*/
|
||||
private static final String direBlunderBuss = "Dire Blunderbuss";
|
||||
|
||||
@Test
|
||||
public void DireBlunderbussTest() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest");
|
||||
addCard(Zone.BATTLEFIELD, playerA, direBlunderBuss);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Balduvian Bears@bearsB");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tormod's Crypt");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Balduvian Bears");
|
||||
|
||||
attack(1, playerA, "Balduvian Bears");
|
||||
setChoice(playerA, true);
|
||||
setChoice(playerA, "Tormod's Crypt");
|
||||
addTarget(playerA, "@bearsB");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerB, "Balduvian Bears", 1);
|
||||
assertLife(playerB, 20 - 2 - 3);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package org.mage.test.cards.single.lci;
|
||||
|
||||
import mage.ObjectColor;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
|
||||
public class EatenByPiranhasTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Eaten by Piranhas
|
||||
{1}{U}
|
||||
Enchantment — Aura
|
||||
|
||||
Flash (You may cast this spell any time you could cast an instant.)
|
||||
|
||||
Enchant creature
|
||||
|
||||
Enchanted creature loses all abilities and is a black Skeleton creature with base power and toughness 1/1. (It loses all other colors, card types, and creature types.)
|
||||
*/
|
||||
private static final String eatenByPiranhas = "Eaten by Piranhas";
|
||||
|
||||
@Test
|
||||
public void testEatenByPiranhas() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.HAND, playerB, eatenByPiranhas);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, eatenByPiranhas);
|
||||
addTarget(playerB, "Balduvian Bears");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertType("Balduvian Bears", CardType.CREATURE, SubType.SKELETON);
|
||||
assertPowerToughness(playerA, "Balduvian Bears", 1, 1);
|
||||
assertColor(playerA, "Balduvian Bears", ObjectColor.BLACK, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package org.mage.test.cards.single.m19;
|
||||
|
||||
import mage.abilities.mana.AnyColorManaAbility;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class AlpineMoonTest extends CardTestPlayerBase {
|
||||
/*
|
||||
Alpine Moon
|
||||
{R}
|
||||
Enchantment
|
||||
As this enchantment enters, choose a nonbasic land card name.
|
||||
Lands your opponents control with the chosen name lose all land types and abilities, and they gain “{T}: Add one mana of any color.”
|
||||
*/
|
||||
private static final String alpine = "Alpine Moon";
|
||||
/*
|
||||
Urborg, Tomb of Yawgmoth
|
||||
Legendary Land
|
||||
Each land is a Swamp in addition to its other land types.
|
||||
*/
|
||||
private static final String urborg = "Urborg, Tomb of Yawgmoth";
|
||||
|
||||
@Test
|
||||
public void testAlpineMoonAfterUrborg() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, urborg);
|
||||
addCard(Zone.BATTLEFIELD, playerB, alpine);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island");
|
||||
|
||||
setChoice(playerB, urborg);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertNotSubtype(urborg, SubType.SWAMP);
|
||||
assertSubtype("Mountain", SubType.SWAMP);
|
||||
assertSubtype("Island", SubType.SWAMP);
|
||||
assertAbility(playerA, urborg, new AnyColorManaAbility(), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlpineMoonBeforeUrborg() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerB, urborg);
|
||||
addCard(Zone.BATTLEFIELD, playerA, alpine);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island");
|
||||
|
||||
setChoice(playerA, urborg);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertNotSubtype(urborg, SubType.SWAMP);
|
||||
assertSubtype("Mountain", SubType.SWAMP);
|
||||
assertSubtype("Island", SubType.SWAMP);
|
||||
assertAbility(playerB, urborg, new AnyColorManaAbility(), true);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package org.mage.test.cards.single.mh2;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class AeveProgenitorOozeTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Aeve, Progenitor Ooze
|
||||
{2}{G}{G}{G}
|
||||
Legendary Creature — Ooze
|
||||
Storm (When you cast this spell, copy it for each spell cast before it this turn. Copies become tokens.)
|
||||
Aeve isn’t legendary if it’s a token.
|
||||
Aeve enters with a +1/+1 counter on it for each other Ooze you control.
|
||||
2/2
|
||||
*/
|
||||
private static final String aeve = "Aeve, Progenitor Ooze";
|
||||
/*
|
||||
Lightning Bolt
|
||||
{R}
|
||||
Instant
|
||||
Lightning Bolt deals 3 damage to any target.
|
||||
*/
|
||||
public static final String bolt = "Lightning Bolt";
|
||||
|
||||
@Test
|
||||
public void testAeve() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.HAND, playerA, aeve);
|
||||
addCard(Zone.HAND, playerA, bolt);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, playerB);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aeve);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, aeve, 2);
|
||||
assertTokenCount(playerA, aeve, 1);
|
||||
for (Permanent permanent : currentGame.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, playerA.getId(), currentGame)) {
|
||||
if (permanent.getName().equals(aeve)) {
|
||||
if (permanent instanceof PermanentToken) {
|
||||
Assert.assertEquals(0, permanent.getCounters(currentGame).getCount(CounterType.P1P1));
|
||||
} else {
|
||||
Assert.assertEquals(1, permanent.getCounters(currentGame).getCount(CounterType.P1P1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package org.mage.test.cards.single.mir;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.player.TestPlayer;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class PhyrexianDreadnoughtTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Phyrexian Dreadnought
|
||||
{1}
|
||||
Artifact Creature — Phyrexian Dreadnought
|
||||
|
||||
Trample
|
||||
|
||||
When this creature enters, sacrifice it unless you sacrifice any number of creatures with total power 12 or greater.
|
||||
|
||||
12/12
|
||||
*/
|
||||
private static final String phyrexianDreadnought = "Phyrexian Dreadnought";
|
||||
|
||||
@Test
|
||||
public void testPhyrexianDreadnoughtCanPay() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.HAND, playerA, phyrexianDreadnought);
|
||||
addCard(Zone.BATTLEFIELD, playerA, phyrexianDreadnought + "@sacTarget");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, phyrexianDreadnought);
|
||||
setChoice(playerA, true);
|
||||
setChoice(playerA, "@sacTarget");
|
||||
setChoice(playerA, TestPlayer.CHOICE_SKIP);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, phyrexianDreadnought, 1);
|
||||
assertGraveyardCount(playerA, phyrexianDreadnought, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPhyrexianDreadnoughtCantPay() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.HAND, playerA, phyrexianDreadnought);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, phyrexianDreadnought);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
setChoice(playerA, false);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, phyrexianDreadnought, 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package org.mage.test.cards.single.neo;
|
||||
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.abilities.keyword.LifelinkAbility;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
public class EaterOfVirtueTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Eater of Virtue
|
||||
{1}
|
||||
Legendary Artifact — Equipment
|
||||
|
||||
Whenever equipped creature dies, exile it.
|
||||
|
||||
Equipped creature gets +2/+0.
|
||||
|
||||
As long as a card exiled with Eater of Virtue has flying, equipped creature has flying.
|
||||
The same is true for first strike, double strike, deathtouch, haste, hexproof, indestructible, lifelink, menace, protection, reach, trample, and vigilance.
|
||||
|
||||
Equip {1}
|
||||
*/
|
||||
public static final String eaterOfVirtue = "Eater of Virtue";
|
||||
|
||||
@Test
|
||||
public void testEaterOfVirtue() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, eaterOfVirtue);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Adult Gold Dragon"); // Flying, Lifelink, Haste
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears");
|
||||
addCard(Zone.HAND, playerB, "Doom Blade");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Adult Gold Dragon");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Doom Blade", "Adult Gold Dragon");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1);
|
||||
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Equip", "Balduvian Bears");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertAbilities(playerA, "Balduvian Bears", Arrays.asList(FlyingAbility.getInstance(), LifelinkAbility.getInstance(), HasteAbility.getInstance()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package org.mage.test.cards.single.one;
|
||||
|
||||
import mage.cards.Card;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestCommanderDuelBase;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
public class EncroachingMycosynthTest extends CardTestCommanderDuelBase {
|
||||
|
||||
/*
|
||||
Encroaching Mycosynth
|
||||
{3}{U}
|
||||
Artifact
|
||||
|
||||
Nonland permanents you control are artifacts in addition to their other types.
|
||||
The same is true for permanent spells you control and nonland permanent cards you own that aren’t on the battlefield.
|
||||
*/
|
||||
private static final String encroachingMycosynth = "Encroaching Mycosynth";
|
||||
private static final String balduvianBears = "Balduvian Bears";
|
||||
@Test
|
||||
public void testEncroachingMycosynth() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.GRAVEYARD, playerA, balduvianBears);
|
||||
addCard(Zone.HAND, playerA, balduvianBears, 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, balduvianBears);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, encroachingMycosynth);
|
||||
addCard(Zone.EXILED, playerA, balduvianBears);
|
||||
addCard(Zone.LIBRARY, playerA, balduvianBears);
|
||||
addCard(Zone.COMMAND, playerA, balduvianBears);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, balduvianBears);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertType(balduvianBears, CardType.ARTIFACT, true);
|
||||
List<Card> cards = getHandCards(playerA);
|
||||
cards.addAll(getLibraryCards(playerA));
|
||||
cards.addAll(getCommandCards(playerA));
|
||||
cards.addAll(getExiledCards(playerA));
|
||||
cards.addAll(getLibraryCards(playerA));
|
||||
for (Card card : cards) {
|
||||
if (!card.isLand(currentGame)) {
|
||||
assertTrue(card.getCardType(currentGame).contains(CardType.ARTIFACT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package org.mage.test.cards.single.one;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
|
||||
public class NahirisSacrificeTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Nahiri's Sacrifice
|
||||
{1}{R}
|
||||
Sorcery
|
||||
|
||||
As an additional cost to cast this spell, sacrifice an artifact or creature with mana value X.
|
||||
|
||||
Nahiri’s Sacrifice deals X damage divided as you choose among any number of target creatures.
|
||||
*/
|
||||
private static final String nahirisSacrifice = "Nahiri's Sacrifice";
|
||||
private static final String balduvianBears = "Balduvian Bears";
|
||||
@Test
|
||||
public void testNahirisSacrifice() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.HAND, playerA, nahirisSacrifice);
|
||||
addCard(Zone.BATTLEFIELD, playerA, balduvianBears);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, balduvianBears + "@bearsB");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, nahirisSacrifice, "@bearsB");
|
||||
setChoice(playerA, "X=2");
|
||||
setChoice(playerA, balduvianBears);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerB, balduvianBears, 1);
|
||||
assertGraveyardCount(playerA, nahirisSacrifice, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // Enable after merging #13916
|
||||
public void testNahirisSacrificePrevented() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.HAND, playerA, nahirisSacrifice);
|
||||
addCard(Zone.BATTLEFIELD, playerA, balduvianBears);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, balduvianBears + "@bearsB");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Yasharn, Implacable Earth");
|
||||
|
||||
checkPlayableAbility("Can't cast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + nahirisSacrifice, false);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package org.mage.test.cards.single.shm;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
|
||||
public class ElsewhereFlaskTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Elsewhere Flask
|
||||
{2}
|
||||
Artifact
|
||||
|
||||
When this artifact enters, draw a card.
|
||||
|
||||
Sacrifice this artifact: Choose a basic land type. Each land you control becomes that type until end of turn.
|
||||
*/
|
||||
private static final String elsewhereFlask = "Elsewhere Flask";
|
||||
|
||||
@Test
|
||||
public void testElsewhereFlask() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, elsewhereFlask);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice");
|
||||
setChoice(playerA, "Swamp");
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertType("Island", CardType.LAND, SubType.SWAMP);
|
||||
assertType("Forest", CardType.LAND, SubType.SWAMP);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testElsewhereFlask2() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, elsewhereFlask);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice");
|
||||
setChoice(playerA, "Swamp");
|
||||
|
||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertType("Island", CardType.LAND, SubType.ISLAND);
|
||||
assertType("Forest", CardType.LAND, SubType.FOREST);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package org.mage.test.cards.single.tdm;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class StalwartSuccessorTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Stalwart Successor
|
||||
{1}{B}{G}
|
||||
Creature — Human Warrior
|
||||
|
||||
Menace (This creature can’t be blocked except by two or more creatures.)
|
||||
|
||||
Whenever one or more counters are put on a creature you control, if it’s the first time counters have been put on that creature this turn, put a +1/+1 counter on that creature.
|
||||
|
||||
3/2
|
||||
*/
|
||||
private static final String stalwartSuccessor = "Stalwart Successor";
|
||||
/*
|
||||
Purestrain Genestealer
|
||||
{2}{G}
|
||||
Creature — Tyranid
|
||||
|
||||
This creature enters with two +1/+1 counters on it.
|
||||
|
||||
Vanguard Species — Whenever this creature attacks, you may remove a +1/+1 counter from it. If you do, search your library for a basic land card, put it onto the battlefield tapped, then shuffle.
|
||||
|
||||
1/1
|
||||
*/
|
||||
private static final String purestrainGenestealer = "Purestrain Genestealer";
|
||||
@Test
|
||||
public void testStalwartSuccessor() {
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, stalwartSuccessor);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||
addCard(Zone.HAND, playerA, purestrainGenestealer);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, purestrainGenestealer);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertCounterCount(playerA, purestrainGenestealer, CounterType.P1P1, 2 + 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package org.mage.test.cards.single.tmp;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class AlurenTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Aluren
|
||||
{2}{G}{G}
|
||||
Enchantment
|
||||
Any player may cast creature spells with mana value 3 or less without paying their mana costs and as though they had flash.
|
||||
*/
|
||||
private static final String aluren = "Aluren";
|
||||
|
||||
/*
|
||||
Bear Cub
|
||||
{1}{G}
|
||||
Creature — Bear
|
||||
2/2
|
||||
*/
|
||||
private static final String cub = "Bear Cub";
|
||||
|
||||
@Test
|
||||
public void testAluren() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, aluren);
|
||||
addCard(Zone.HAND, playerA, cub);
|
||||
addCard(Zone.HAND, playerB, cub);
|
||||
|
||||
castSpell(1, PhaseStep.UPKEEP, playerA, cub);
|
||||
setChoice(playerA, "Cast without paying its mana cost");
|
||||
|
||||
castSpell(1, PhaseStep.END_TURN, playerB, cub);
|
||||
setChoice(playerB, "Cast without paying its mana cost");
|
||||
|
||||
setStopAt(2, PhaseStep.UPKEEP);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, cub, 1);
|
||||
assertPermanentCount(playerB, cub, 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package org.mage.test.cards.single.tmp;
|
||||
|
||||
import mage.abilities.keyword.LandwalkAbility;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class ExcavatorTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Excavator
|
||||
{2}
|
||||
Artifact
|
||||
|
||||
{T}, Sacrifice a basic land: Target creature gains landwalk of each of the land types of the sacrificed land until end of turn.
|
||||
(It can’t be blocked as long as defending player controls a land of any of those types.)
|
||||
*/
|
||||
public static final String excavator = "Excavator";
|
||||
|
||||
/*
|
||||
Leyline of the Guildpact
|
||||
{G/W}{G/U}{B/G}{R/G}
|
||||
Enchantment
|
||||
|
||||
If this card is in your opening hand, you may begin the game with it on the battlefield.
|
||||
|
||||
Each nonland permanent you control is all colors.
|
||||
|
||||
Lands you control are every basic land type in addition to their other types.
|
||||
*/
|
||||
public static final String leylineOfTheGuildpact = "Leyline of the Guildpact";
|
||||
|
||||
@Test
|
||||
@Ignore("Failing because permanent LKI does not save MageObjectAttribute values")
|
||||
public void testExcavator() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, excavator);
|
||||
addCard(Zone.BATTLEFIELD, playerA, leylineOfTheGuildpact);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}");
|
||||
setChoice(playerA, "Island");
|
||||
addTarget(playerA, "Balduvian Bears");
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertAbilityCount(playerA, "Balduvian Bears", LandwalkAbility.class, 5);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
package org.mage.test.cards.single.who;
|
||||
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.LoseGameSourceControllerEffect;
|
||||
import mage.abilities.effects.common.LoseLifeAllPlayersEffect;
|
||||
import mage.abilities.effects.common.WinGameSourceControllerEffect;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestCommander4Players;
|
||||
|
||||
public class EverybodyLivesTest extends CardTestCommander4Players {
|
||||
|
||||
/*
|
||||
Everybody Lives!
|
||||
{1}{W}
|
||||
Instant
|
||||
|
||||
All creatures gain hexproof and indestructible until end of turn. Players gain hexproof until end of turn.
|
||||
Players can’t lose life this turn and players can’t lose the game or win the game this turn.
|
||||
*/
|
||||
private static final String everybodyLives = "Everybody Lives!";
|
||||
|
||||
@Test
|
||||
public void testEverybodyLivesCantLoseLifeAndHexproof() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCustomCardWithAbility("lose life effect", playerA, new SimpleActivatedAbility(
|
||||
new LoseLifeAllPlayersEffect(20),
|
||||
new ManaCostsImpl<>(""))
|
||||
);
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||
addCard(Zone.HAND, playerA, everybodyLives);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, everybodyLives, true);
|
||||
checkPlayableAbility("Can't cast lightning bolt", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", false);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "each player");
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
assertLife(playerC, 20);
|
||||
assertLife(playerD, 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEverybodyLivesCantLoseGame() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCustomCardWithAbility("lose game effect", playerA, new SimpleActivatedAbility(
|
||||
new LoseGameSourceControllerEffect(),
|
||||
new ManaCostsImpl<>(""))
|
||||
);
|
||||
addCard(Zone.HAND, playerA, everybodyLives);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, everybodyLives, true);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "you lose");
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertHasNotLostTheGame(playerA);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEverybodyLivesCantWinGame() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCustomCardWithAbility("win game effect", playerA, new SimpleActivatedAbility(
|
||||
new WinGameSourceControllerEffect(),
|
||||
new ManaCostsImpl<>(""))
|
||||
);
|
||||
addCard(Zone.HAND, playerA, everybodyLives);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, everybodyLives, true);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "you win");
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertHasNotWonTheGame(playerA);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2079,6 +2079,7 @@ public class VerifyCardDataTest {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSubtypes(Card card, MtgJsonCard ref) {
|
||||
if (skipListHaveName(SKIP_LIST_SUBTYPE, card.getExpansionSetCode(), card.getName())) {
|
||||
return;
|
||||
|
|
@ -2343,7 +2344,11 @@ public class VerifyCardDataTest {
|
|||
|
||||
|
||||
// search and check dies related abilities
|
||||
String rules = triggeredAbility.getRule();
|
||||
// remove reminder text
|
||||
String rules = triggeredAbility
|
||||
.getRule()
|
||||
.replaceAll("(?i) <i>\\(.+\\)</i>", "")
|
||||
.replaceAll("(?i) \\(.+\\)", "");
|
||||
if (ignoredAbilities.stream().anyMatch(rules::contains)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ import mage.abilities.dynamicvalue.DynamicValue;
|
|||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
|
|
@ -47,12 +49,12 @@ public class DamageWithExcessEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
int damage = amount.calculate(game, source, this);
|
||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
||||
lethal = Math.min(lethal, damage);
|
||||
permanent.damage(lethal, source.getSourceId(), source, game);
|
||||
Player player = game.getPlayer(permanent.getControllerId());
|
||||
if (player != null && lethal < damage) {
|
||||
player.damage(damage - lethal, source.getSourceId(), source, game);
|
||||
int excess = permanent.damageWithExcess(damage, source, game);
|
||||
if (excess > 0) {
|
||||
Optional.ofNullable(permanent)
|
||||
.map(Controllable::getControllerId)
|
||||
.map(game::getPlayer)
|
||||
.ifPresent(player -> player.damage(excess, source, game));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import mage.constants.Zone;
|
|||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameState;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
|
@ -177,6 +178,23 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
int getLethalDamage(UUID attackerId, Game game);
|
||||
|
||||
/**
|
||||
* Same arguments as regular damage method, but returns the amount of excess damage dealt instead
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
default int damageWithExcess(int damage, Ability source, Game game) {
|
||||
return this.damageWithExcess(damage, source.getSourceId(), source, game);
|
||||
}
|
||||
|
||||
default int damageWithExcess(int damage, UUID attackerId, Ability source, Game game) {
|
||||
int lethal = getLethalDamage(attackerId, game);
|
||||
int excess = Math.max(CardUtil.overflowDec(damage, lethal), 0);
|
||||
int dealt = Math.min(lethal, damage);
|
||||
this.damage(dealt, attackerId, source, game);
|
||||
return excess;
|
||||
}
|
||||
|
||||
void removeAllDamage(Game game);
|
||||
|
||||
void reset(Game game);
|
||||
|
|
|
|||
|
|
@ -38,14 +38,6 @@ public class TargetCardAndOrCardInLibrary extends TargetCardInLibrary {
|
|||
|
||||
private final PredicateCardAssignment assignment;
|
||||
|
||||
/**
|
||||
* a [firstType] card and/or a [secondType] card
|
||||
*/
|
||||
protected TargetCardAndOrCardInLibrary(Predicate<? super Card> firstPredicate, Predicate<? super Card> secondPredicate, String filterText) {
|
||||
super(0, 2, makeFilter(firstPredicate, secondPredicate, filterText));
|
||||
this.assignment = new PredicateCardAssignment(firstPredicate, secondPredicate);
|
||||
}
|
||||
|
||||
public TargetCardAndOrCardInLibrary(CardType firstType, CardType secondType) {
|
||||
this(firstType.getPredicate(), secondType.getPredicate(), makeFilterText(
|
||||
CardUtil.getTextWithFirstCharLowerCase(firstType.toString()),
|
||||
|
|
@ -60,6 +52,14 @@ public class TargetCardAndOrCardInLibrary extends TargetCardInLibrary {
|
|||
this(firstType.getPredicate(), secondType.getPredicate(), makeFilterText(firstType.getDescription(), secondType.getDescription()));
|
||||
}
|
||||
|
||||
/**
|
||||
* a [firstType] card and/or a [secondType] card
|
||||
*/
|
||||
public TargetCardAndOrCardInLibrary(Predicate<? super Card> firstPredicate, Predicate<? super Card> secondPredicate, String filterText) {
|
||||
super(0, 2, makeFilter(firstPredicate, secondPredicate, filterText));
|
||||
this.assignment = new PredicateCardAssignment(firstPredicate, secondPredicate);
|
||||
}
|
||||
|
||||
protected TargetCardAndOrCardInLibrary(final TargetCardAndOrCardInLibrary target) {
|
||||
super(target);
|
||||
this.assignment = target.assignment;
|
||||
|
|
|
|||
|
|
@ -59737,7 +59737,7 @@ Flexible Waterbender|Avatar: The Last Airbender|50|C|{3}{U}|Creature - Human War
|
|||
Geyser Leaper|Avatar: The Last Airbender|52|C|{4}{U}|Creature - Human Warrior Ally|4|3|Flying$Waterbend {4}: Draw a card, then discard a card.|
|
||||
Giant Koi|Avatar: The Last Airbender|53|C|{4}{U}{U}|Creature - Fish|5|7|Waterbend {3}: This creature can't be blocked this turn.$Islandcycling {2}|
|
||||
Iguana Parrot|Avatar: The Last Airbender|56|C|{2}{U}|Creature - Lizard Bird Pirate|2|2|Flying, vigilance$Prowess|
|
||||
It'll Quench Ya!|Avatar: The Last Airbender|58|C|{1}{U}|Instant - Lesson|||Counter target spell unless its controller pays 2.|
|
||||
It'll Quench Ya!|Avatar: The Last Airbender|58|C|{1}{U}|Instant - Lesson|||Counter target spell unless its controller pays {2}.|
|
||||
Katara, Bending Prodigy|Avatar: The Last Airbender|59|U|{2}{U}|Legendary Creature - Human Warrior Ally|2|3|At the beginning of your end step, if Katara is tapped, put a +1/+1 counter on her.$Waterbend {6}: Draw a card.|
|
||||
Master Pakku|Avatar: The Last Airbender|63|U|{1}{U}|Legendary Creature - Human Advisor Ally|1|3|Prowess$Whenever Master Pakku becomes tapped, target player mills X cards, where X is the number of Lesson cards in your graveyard.|
|
||||
Otter-Penguin|Avatar: The Last Airbender|67|C|{1}{U}|Creature - Otter Bird|2|1|Whenever you draw your second card each turn, this creature gets +1/+2 until end of turn and can't be blocked this turn.|
|
||||
|
|
@ -59804,6 +59804,11 @@ Toph, the First Metalbender|Avatar: The Last Airbender|247|R|{1}{R}{G}{W}|Legend
|
|||
Vindictive Warden|Avatar: The Last Airbender|249|C|{2}{B/R}|Creature - Human Soldier|2|3|Menace$Firebending 1${3}: This creature deals 1 damage to each opponent.|
|
||||
Barrels of Blasting Jelly|Avatar: The Last Airbender|254|C|{1}|Artifact|||{1}: Add one mana of any color. Activate only once each turn.${5}, {T}, Sacrifice this artifact: It deals 5 damage to target creature.|
|
||||
Bender's Waterskin|Avatar: The Last Airbender|255|C|{3}|Artifact|||Untap this artifact during each other player's untap step.${T}: Add one mana of any color.|
|
||||
Plains|Avatar: The Last Airbender|282|C||Basic Land - Plains|||({T}: Add {W}.)|
|
||||
Island|Avatar: The Last Airbender|283|C||Basic Land - Island|||({T}: Add {U}.)|
|
||||
Swamp|Avatar: The Last Airbender|284|C||Basic Land - Swamp|||({T}: Add {B}.)|
|
||||
Mountain|Avatar: The Last Airbender|285|C||Basic Land - Mountain|||({T}: Add {R}.)|
|
||||
Forest|Avatar: The Last Airbender|286|C||Basic Land - Forest|||({T}: Add {G}.)|
|
||||
Plains|Avatar: The Last Airbender|287|C||Basic Land - Plains|||({T}: Add {W}.)|
|
||||
Island|Avatar: The Last Airbender|288|C||Basic Land - Island|||({T}: Add {U}.)|
|
||||
Swamp|Avatar: The Last Airbender|289|C||Basic Land - Swamp|||({T}: Add {B}.)|
|
||||
|
|
@ -59825,6 +59830,7 @@ Katara, the Fearless|Avatar: The Last Airbender|361|R|{G}{W}{U}|Legendary Creatu
|
|||
Toph, the First Metalbender|Avatar: The Last Airbender|362|R|{1}{R}{G}{W}|Legendary Creature - Human Warrior Ally|3|3|Nontoken artifacts you control are lands in addition to their other types.$At the beginning of your end step, earthbend 2.|
|
||||
Avatar Aang|Avatar: The Last Airbender|363|M|{R}{G}{W}{U}|Legendary Creature - Human Avatar Ally|4|4|Flying, firebending 2$Whenever you waterbend, earthbend, firebend, or airbend, draw a card. Then if you've done all four this turn, transform Avatar Aang.|
|
||||
Aang, Master of Elements|Avatar: The Last Airbender|363|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.|
|
||||
Hakoda, Selfless Commander|Avatar: The Last Airbender|366|R|{3}{W}|Legendary Creature - Human Warrior Ally|3|5|Vigilance$You may look at the top card of your library any time.$You may cast Ally spells from the top of your library.$Sacrifice Hakoda: Creatures you control get +0/+5 and gain indestructible until end of turn.|
|
||||
Sokka, Bold Boomeranger|Avatar: The Last Airbender|383|R|{U}{R}|Legendary Creature - Human Warrior Ally|1|1|When Sokka enters, discard up to two cards, then draw that many cards.$Whenever you cast an artifact or Lesson spell, put a +1/+1 counter on Sokka.|
|
||||
Anti-Venom, Horrifying Healer|Marvel's Spider-Man|1|M|{W}{W}{W}{W}{W}|Legendary Creature - Symbiote Hero|5|5|When Anti-Venom enters, if he was cast, return target creature card from your graveyard to the battlefield.$If damage would be dealt to Anti-Venom, prevent that damage and put that many +1/+1 counters on him.|
|
||||
Aunt May|Marvel's Spider-Man|3|U|{W}|Legendary Creature - Human Citizen|0|2|Whenever another creature you control enters, you gain 1 life. If it's a Spider, put a +1/+1 counter on it.|
|
||||
|
|
@ -59940,7 +59946,7 @@ Aang, Air Nomad|Avatar: The Last Airbender Eternal|210|R|{3}{W}{W}|Legendary Cre
|
|||
Aang's Defense|Avatar: The Last Airbender Eternal|211|C|{W}|Instant|||Target blocking creature you control gets +2/+2 until end of turn.$Draw a card.|
|
||||
Aardvark Sloth|Avatar: The Last Airbender Eternal|212|C|{3}{W}|Creature - Sloth Beast|3|3|Lifelink|
|
||||
Allied Teamwork|Avatar: The Last Airbender Eternal|213|R|{2}{W}|Enchantment|||When this enchantment enters, create a 1/1 white Ally creature token.$Allies you control get +1/+1.|
|
||||
Appa, Aang's Companion|Avatar: The Last Airbender Eternal|214|U|{3}{W}|Legendary Creature - Bison Ally|2|4|Flying$Whenever Appa attacks, another target attacking creature without flying gains flying until until end of turn.|
|
||||
Appa, Aang's Companion|Avatar: The Last Airbender Eternal|214|U|{3}{W}|Legendary Creature - Bison Ally|2|4|Flying$Whenever Appa attacks, another target attacking creature without flying gains flying until end of turn.|
|
||||
Katara, Heroic Healer|Avatar: The Last Airbender Eternal|215|U|{4}{W}|Legendary Creature - Human Warrior Ally|2|3|Lifelink$When Katara enters, put a +1/+1 counter on each other creature you control.|
|
||||
Kyoshi Warrior Guard|Avatar: The Last Airbender Eternal|216|C|{1}{W}|Creature - Human Warrior Ally|2|3||
|
||||
Momo, Rambunctious Rascal|Avatar: The Last Airbender Eternal|217|U|{2}{W}|Legendary Creature - Lemur Bat Ally|1|1|Flying$When Momo enters, he deals 4 damage to target tapped creature an opponent controls.|
|
||||
|
|
@ -59991,3 +59997,43 @@ Thriving Grove|Avatar: The Last Airbender Eternal|261|C||Land|||This land enters
|
|||
Thriving Heath|Avatar: The Last Airbender Eternal|262|C||Land|||This land enters tapped. As it enters, choose a color other than white.${T}: Add {W} or one mana of the chosen color.|
|
||||
Thriving Isle|Avatar: The Last Airbender Eternal|263|C||Land|||This land enters tapped. As it enters, choose a color other than blue.${T}: Add {U} or one mana of the chosen color.|
|
||||
Thriving Moor|Avatar: The Last Airbender Eternal|264|C||Land|||This land enters tapped. As it enters, choose a color other than black.${T}: Add {B} or one mana of the chosen color.|
|
||||
Aang, Air Nomad|Avatar: The Last Airbender Eternal|265|R|{3}{W}{W}|Legendary Creature - Human Avatar Ally|5|4|Flying$Vigilance$Other creatures you control have vigilance.|
|
||||
Aang's Defense|Avatar: The Last Airbender Eternal|266|C|{W}|Instant|||Target blocking creature you control gets +2/+2 until end of turn.$Draw a card.|
|
||||
Aardvark Sloth|Avatar: The Last Airbender Eternal|267|C|{3}{W}|Creature - Sloth Beast|3|3|Lifelink|
|
||||
Appa, Aang's Companion|Avatar: The Last Airbender Eternal|268|U|{3}{W}|Legendary Creature - Bison Ally|2|4|Flying$Whenever Appa attacks, another target attacking creature without flying gains flying until end of turn.|
|
||||
Katara, Heroic Healer|Avatar: The Last Airbender Eternal|269|U|{4}{W}|Legendary Creature - Human Warrior Ally|2|3|Lifelink$When Katara enters, put a +1/+1 counter on each other creature you control.|
|
||||
Momo, Rambunctious Rascal|Avatar: The Last Airbender Eternal|270|U|{2}{W}|Legendary Creature - Lemur Bat Ally|1|1|Flying$When Momo enters, he deals 4 damage to target tapped creature an opponent controls.|
|
||||
Path to Redemption|Avatar: The Last Airbender Eternal|271|C|{1}{W}|Enchantment - Aura|||Enchant creature$Enchanted creature can't attack or block.${5}, Sacrifice this Aura: Exile enchanted creature. Create a 1/1 white Ally creature token. Activate only during your turn.|
|
||||
Razor Rings|Avatar: The Last Airbender Eternal|272|C|{1}{W}|Instant|||Razor Rings deals 4 damage to target attacking or blocking creature. You gain life equal to the excess damage dealt this way.|
|
||||
Sledding Otter-Penguin|Avatar: The Last Airbender Eternal|273|C|{2}{W}|Creature - Otter Bird|2|3|{3}: Put a +1/+1 counter on this creature.|
|
||||
Sokka, Wolf Cove's Protector|Avatar: The Last Airbender Eternal|274|U|{2}{W}|Legendary Creature - Human Warrior Ally|3|3|Vigilance|
|
||||
Tundra Wall|Avatar: The Last Airbender Eternal|275|C|{1}{W}|Creature - Wall|0|4|Defender|
|
||||
Wolf Cove Villager|Avatar: The Last Airbender Eternal|276|C|{W}|Creature - Human Peasant|2|2|This creature enters tapped.|
|
||||
Capital Guard|Avatar: The Last Airbender Eternal|277|C|{1}{R}|Creature - Human Soldier|2|2||
|
||||
Dragon Moose|Avatar: The Last Airbender Eternal|278|C|{3}{R}|Creature - Dragon Elk|3|3|Haste|
|
||||
Explosive Shot|Avatar: The Last Airbender Eternal|279|C|{1}{R}|Sorcery|||Explosive Shot deals 4 damage to target creature.|
|
||||
Fire Nation Soldier|Avatar: The Last Airbender Eternal|280|C|{2}{R}|Creature - Human Soldier|3|2|Haste|
|
||||
Fire Nation's Conquest|Avatar: The Last Airbender Eternal|281|U|{2}{R}|Enchantment|||Creatures you control get +1/+0.|
|
||||
Iroh, Firebending Instructor|Avatar: The Last Airbender Eternal|282|U|{2}{R}|Legendary Creature - Human Noble Ally|2|2|Whenever Iroh attacks, attacking creatures get +1/+1 until end of turn.|
|
||||
Komodo Rhino|Avatar: The Last Airbender Eternal|283|C|{3}{R}|Creature - Lizard Rhino|5|2|Trample|
|
||||
Run Amok|Avatar: The Last Airbender Eternal|284|C|{1}{R}|Instant|||Target attacking creature gets +3/+3 and gains trample until end of turn.|
|
||||
Warship Scout|Avatar: The Last Airbender Eternal|285|C|{R}|Creature - Human Scout|2|1||
|
||||
Zhao, the Seething Flame|Avatar: The Last Airbender Eternal|286|U|{4}{R}|Legendary Creature - Human Soldier|5|5|Menace|
|
||||
Zuko, Avatar Hunter|Avatar: The Last Airbender Eternal|287|R|{3}{R}{R}|Legendary Creature - Human Noble|4|5|Reach$Whenever you cast a red spell, create a 2/2 red Soldier creature token.|
|
||||
Zuko's Offense|Avatar: The Last Airbender Eternal|288|C|{R}|Sorcery|||Zuko's Offense deals 2 damage to any target.|
|
||||
Mountain|Avatar: The Last Airbender Eternal|289|C||Basic Land - Mountain|||({T}: Add {R}.)|
|
||||
Mountain|Avatar: The Last Airbender Eternal|290|C||Basic Land - Mountain|||({T}: Add {R}.)|
|
||||
Mountain|Avatar: The Last Airbender Eternal|291|C||Basic Land - Mountain|||({T}: Add {R}.)|
|
||||
Mountain|Avatar: The Last Airbender Eternal|292|C||Basic Land - Mountain|||({T}: Add {R}.)|
|
||||
Mountain|Avatar: The Last Airbender Eternal|293|C||Basic Land - Mountain|||({T}: Add {R}.)|
|
||||
Mountain|Avatar: The Last Airbender Eternal|294|C||Basic Land - Mountain|||({T}: Add {R}.)|
|
||||
Mountain|Avatar: The Last Airbender Eternal|295|C||Basic Land - Mountain|||({T}: Add {R}.)|
|
||||
Mountain|Avatar: The Last Airbender Eternal|296|C||Basic Land - Mountain|||({T}: Add {R}.)|
|
||||
Plains|Avatar: The Last Airbender Eternal|297|C||Basic Land - Plains|||({T}: Add {W}.)|
|
||||
Plains|Avatar: The Last Airbender Eternal|298|C||Basic Land - Plains|||({T}: Add {W}.)|
|
||||
Plains|Avatar: The Last Airbender Eternal|299|C||Basic Land - Plains|||({T}: Add {W}.)|
|
||||
Plains|Avatar: The Last Airbender Eternal|300|C||Basic Land - Plains|||({T}: Add {W}.)|
|
||||
Plains|Avatar: The Last Airbender Eternal|301|C||Basic Land - Plains|||({T}: Add {W}.)|
|
||||
Plains|Avatar: The Last Airbender Eternal|302|C||Basic Land - Plains|||({T}: Add {W}.)|
|
||||
Plains|Avatar: The Last Airbender Eternal|303|C||Basic Land - Plains|||({T}: Add {W}.)|
|
||||
Plains|Avatar: The Last Airbender Eternal|304|C||Basic Land - Plains|||({T}: Add {W}.)|
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue