This commit is contained in:
Jeff 2022-06-03 20:26:55 -05:00
commit 36fdebef7f
43 changed files with 475 additions and 64 deletions

View file

@ -30,7 +30,7 @@ public final class AltarOfBhaal extends AdventureCard {
new ReturnFromGraveyardToBattlefieldTargetEffect(), new ManaCostsImpl<>("{2}{B}") new ReturnFromGraveyardToBattlefieldTargetEffect(), new ManaCostsImpl<>("{2}{B}")
); );
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
ability.addCost(new ExileTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_CREATURE))); ability.addCost(new ExileTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_A_CREATURE)));
ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD));
this.addAbility(ability); this.addAbility(ability);

View file

@ -1,11 +1,11 @@
package mage.cards.a; package mage.cards.a;
import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.TargetController; import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
@ -16,7 +16,7 @@ import java.util.UUID;
*/ */
public final class ArmsOfHadar extends CardImpl { public final class ArmsOfHadar extends CardImpl {
private static final FilterPermanent filter = new FilterCreaturePermanent("creatures target player controls"); private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures target player controls");
static { static {
filter.add(TargetController.SOURCE_TARGETS.getControllerPredicate()); filter.add(TargetController.SOURCE_TARGETS.getControllerPredicate());
@ -26,7 +26,9 @@ public final class ArmsOfHadar extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}");
// Creatures target player controls get -2/-2 until end of turn. // Creatures target player controls get -2/-2 until end of turn.
this.getSpellAbility().addEffect(new BoostTargetEffect(-2, -2)); this.getSpellAbility().addEffect(new BoostAllEffect(
-2, -2, Duration.EndOfTurn, filter, false
));
this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetPlayer());
} }

View file

@ -47,7 +47,8 @@ public final class BaldursGate extends CardImpl {
// {2}, {T}: Add X mana of any one color, where X is the number of other Gates you control. // {2}, {T}: Add X mana of any one color, where X is the number of other Gates you control.
Ability ability = new DynamicManaAbility( Ability ability = new DynamicManaAbility(
Mana.AnyMana(1), xValue, new GenericManaCost(2), null, true Mana.AnyMana(1), xValue, new GenericManaCost(2), "Add X mana of any one color, " +
"where X is the number of other Gates you control.", true
); );
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
this.addAbility(ability.addHint(hint)); this.addAbility(ability.addHint(hint));

View file

@ -32,7 +32,7 @@ public final class DungeoneersPack extends CardImpl {
Ability ability = new ActivateAsSorceryActivatedAbility(new TakeTheInitiativeEffect(), new GenericManaCost(2)); Ability ability = new ActivateAsSorceryActivatedAbility(new TakeTheInitiativeEffect(), new GenericManaCost(2));
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeSourceCost()); ability.addCost(new SacrificeSourceCost());
ability.addEffect(new GainLifeEffect(3).concatBy(", you")); ability.addEffect(new GainLifeEffect(3).setText("gain 3 life"));
ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy(",")); ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy(","));
ability.addEffect(new CreateTokenEffect(new TreasureToken()).concatBy(", and")); ability.addEffect(new CreateTokenEffect(new TreasureToken()).concatBy(", and"));
this.addAbility(ability); this.addAbility(ability);

View file

@ -30,7 +30,7 @@ public final class FlamingFist extends CardImpl {
this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect( this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect(
new AttacksTriggeredAbility(new GainAbilitySourceEffect( new AttacksTriggeredAbility(new GainAbilitySourceEffect(
DoubleStrikeAbility.getInstance(), Duration.EndOfTurn DoubleStrikeAbility.getInstance(), Duration.EndOfTurn
).setText("it gains double strike until end of turn")), ).setText("it gains double strike until end of turn")).setTriggerPhrase("Whenever this creature attacks, "),
Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURES_OWNED_COMMANDER Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURES_OWNED_COMMANDER
))); )));
} }

View file

@ -8,7 +8,9 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.filter.StaticFilters; import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import java.util.UUID; import java.util.UUID;
@ -17,6 +19,13 @@ import java.util.UUID;
*/ */
public final class FlamingFistOfficer extends CardImpl { public final class FlamingFistOfficer extends CardImpl {
private static final FilterPermanent filter
= new FilterControlledCreaturePermanent("another creature you control");
static {
filter.add(AnotherPredicate.instance);
}
public FlamingFistOfficer(UUID ownerId, CardSetInfo setInfo) { public FlamingFistOfficer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
@ -27,8 +36,7 @@ public final class FlamingFistOfficer extends CardImpl {
// Whenever another creature you control leaves the battlefield, put a +1/+1 counter on Flaming Fist Officer. // Whenever another creature you control leaves the battlefield, put a +1/+1 counter on Flaming Fist Officer.
this.addAbility(new LeavesBattlefieldAllTriggeredAbility( this.addAbility(new LeavesBattlefieldAllTriggeredAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter
StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE
)); ));
} }

View file

@ -45,7 +45,7 @@ public final class FrayingLine extends CardImpl {
// At the beginning of each player's upkeep, that player may pay {2}. If they do, they put a rope counter on a creature they control. Otherwise, exile Fraying Line and each creature without a rope counter on it, then remove all rope counters from all creatures. // At the beginning of each player's upkeep, that player may pay {2}. If they do, they put a rope counter on a creature they control. Otherwise, exile Fraying Line and each creature without a rope counter on it, then remove all rope counters from all creatures.
this.addAbility(new BeginningOfUpkeepTriggeredAbility( this.addAbility(new BeginningOfUpkeepTriggeredAbility(
new FrayingLineEffect(), TargetController.ACTIVE, true new FrayingLineEffect(), TargetController.ACTIVE, false
)); ));
} }

View file

@ -2,7 +2,7 @@ package mage.cards.g;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.GateYouControlCount; import mage.abilities.dynamicvalue.common.GateYouControlCount;
import mage.abilities.effects.common.PutOnLibrarySourceEffect; import mage.abilities.effects.common.PutOnLibrarySourceEffect;
@ -41,7 +41,7 @@ public final class GateColossus extends CardImpl {
this.addAbility(new DauntAbility()); this.addAbility(new DauntAbility());
// Whenever a Gate enters the battlefield under your control, you may put Gate Colossus from your graveyard on top of your library. // Whenever a Gate enters the battlefield under your control, you may put Gate Colossus from your graveyard on top of your library.
this.addAbility(new EntersBattlefieldAllTriggeredAbility( this.addAbility(new EntersBattlefieldControlledTriggeredAbility(
Zone.GRAVEYARD, Zone.GRAVEYARD,
new PutOnLibrarySourceEffect( new PutOnLibrarySourceEffect(
true, "put {this} from your graveyard on top of your library" true, "put {this} from your graveyard on top of your library"

View file

@ -43,7 +43,7 @@ public final class GiantAnkheg extends CardImpl {
ability.addEffect(new GainAbilityControlledEffect( ability.addEffect(new GainAbilityControlledEffect(
new WardAbility(new GenericManaCost(2), false), Duration.WhileOnBattlefield, new WardAbility(new GenericManaCost(2), false), Duration.WhileOnBattlefield,
StaticFilters.FILTER_PERMANENT_CREATURES, true StaticFilters.FILTER_PERMANENT_CREATURES, true
)); ).setText("and ward {2}"));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -40,7 +40,7 @@ public final class GorionWiseMentor extends CardImpl {
// Whenever you cast an Adventure spell, you may copy it. You may choose new targets for the copy. // Whenever you cast an Adventure spell, you may copy it. You may choose new targets for the copy.
this.addAbility(new SpellCastControllerTriggeredAbility( this.addAbility(new SpellCastControllerTriggeredAbility(
new CopyTargetSpellEffect(true).withSpellName("it"), new CopyTargetSpellEffect(true).withSpellName("it"),
filter, false, true filter, true, true
)); ));
} }

View file

@ -43,6 +43,7 @@ public final class GraySlaad extends AdventureCard {
ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect( ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect(
DeathtouchAbility.getInstance(), Duration.WhileOnBattlefield DeathtouchAbility.getInstance(), Duration.WhileOnBattlefield
), condition, "and deathtouch")); ), condition, "and deathtouch"));
this.addAbility(ability);
// Entropic Decay // Entropic Decay
// Mill four cards. // Mill four cards.

View file

@ -17,8 +17,6 @@ import mage.constants.SubType;
import mage.filter.FilterObject; import mage.filter.FilterObject;
import mage.filter.FilterStackObject; import mage.filter.FilterStackObject;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledArtifactPermanent;
import mage.filter.predicate.Predicates;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -33,12 +31,10 @@ import java.util.UUID;
public final class GuardianBeast extends CardImpl { public final class GuardianBeast extends CardImpl {
private static final FilterObject filterAura = new FilterStackObject("auras"); private static final FilterObject filterAura = new FilterStackObject("auras");
private static final FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent("Noncreature artifacts");
static { static {
filterAura.add(CardType.ENCHANTMENT.getPredicate()); filterAura.add(CardType.ENCHANTMENT.getPredicate());
filterAura.add(SubType.AURA.getPredicate()); filterAura.add(SubType.AURA.getPredicate());
filter.add(Predicates.not(CardType.CREATURE.getPredicate()));
} }
public GuardianBeast(UUID ownerId, CardSetInfo setInfo) { public GuardianBeast(UUID ownerId, CardSetInfo setInfo) {
@ -51,7 +47,8 @@ public final class GuardianBeast extends CardImpl {
// This effect doesn't remove Auras already attached to those artifacts. // This effect doesn't remove Auras already attached to those artifacts.
Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect( Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect(
new GainAbilityControlledEffect( new GainAbilityControlledEffect(
IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield, filter IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield,
StaticFilters.FILTER_ARTIFACT_NON_CREATURE
), SourceTappedCondition.UNTAPPED, "As long as {this} is untapped, " + ), SourceTappedCondition.UNTAPPED, "As long as {this} is untapped, " +
"noncreature artifacts you control can't be enchanted, they're indestructible" "noncreature artifacts you control can't be enchanted, they're indestructible"
)); ));
@ -113,7 +110,7 @@ class GuardianBeastConditionalEffect extends ContinuousRuleModifyingEffectImpl {
|| ((event.getType() == GameEvent.EventType.ATTACH || ((event.getType() == GameEvent.EventType.ATTACH
|| event.getType() == GameEvent.EventType.TARGET) || event.getType() == GameEvent.EventType.TARGET)
&& spell != null && spell.isEnchantment(game) && spell.hasSubtype(SubType.AURA, game))) { && spell != null && spell.isEnchantment(game) && spell.hasSubtype(SubType.AURA, game))) {
for (Permanent perm : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_ARTIFACTS_NON_CREATURE, source.getControllerId(), game)) { for (Permanent perm : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_ARTIFACT_NON_CREATURE, source.getControllerId(), game)) {
if (perm != null && Objects.equals(perm.getId(), targetPermanent.getId()) && !perm.isCreature(game)) { if (perm != null && Objects.equals(perm.getId(), targetPermanent.getId()) && !perm.isCreature(game)) {
return true; return true;
} }

View file

@ -30,7 +30,7 @@ public final class InspiringLeader extends CardImpl {
2, 2, Duration.WhileOnBattlefield, 2, 2, Duration.WhileOnBattlefield,
StaticFilters.FILTER_CREATURE_TOKENS StaticFilters.FILTER_CREATURE_TOKENS
)), Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURES_OWNED_COMMANDER )), Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURES_OWNED_COMMANDER
))); ).withForceQuotes()));
} }
private InspiringLeader(final InspiringLeader card) { private InspiringLeader(final InspiringLeader card) {

View file

@ -41,7 +41,7 @@ public final class JavelinOfLightning extends CardImpl {
"as long as it's your turn, equipped creature gets +2/+0")); "as long as it's your turn, equipped creature gets +2/+0"));
ability.addEffect(new ConditionalContinuousEffect(new GainAbilityAttachedEffect( ability.addEffect(new ConditionalContinuousEffect(new GainAbilityAttachedEffect(
FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT
), MyTurnCondition.instance, "and first strike")); ), MyTurnCondition.instance, "and has first strike"));
this.addAbility(ability.addHint(MyTurnHint.instance)); this.addAbility(ability.addHint(MyTurnHint.instance));
// Equip {4} // Equip {4}

View file

@ -50,7 +50,7 @@ public final class KenkuArtificer extends CardImpl {
.withAbility(FlyingAbility.getInstance()), .withAbility(FlyingAbility.getInstance()),
false, false, Duration.EndOfTurn false, false, Duration.EndOfTurn
).setText("That artifact becomes a 0/0 Homunculus artifact creature with flying")); ).setText("That artifact becomes a 0/0 Homunculus artifact creature with flying"));
ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_ARTIFACTS_NON_CREATURE)); ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_ARTIFACT_NON_CREATURE));
this.addAbility(ability.withFlavorWord("Homunculus Servant")); this.addAbility(ability.withFlavorWord("Homunculus Servant"));
} }

View file

@ -34,7 +34,7 @@ public final class MahadiEmporiumMaster extends CardImpl {
this.addAbility(new BeginningOfEndStepTriggeredAbility( this.addAbility(new BeginningOfEndStepTriggeredAbility(
new CreateTokenEffect( new CreateTokenEffect(
new TreasureToken(), CreaturesDiedThisTurnCount.instance new TreasureToken(), CreaturesDiedThisTurnCount.instance
), TargetController.YOU, false ).setText("create a Treasure token for each creature that died this turn"), TargetController.YOU, false
).addHint(CreaturesDiedThisTurnHint.instance), new CreaturesDiedWatcher()); ).addHint(CreaturesDiedThisTurnHint.instance), new CreaturesDiedWatcher());
} }

View file

@ -15,10 +15,11 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.WatcherScope; import mage.constants.WatcherScope;
import mage.filter.StaticFilters;
import mage.game.Game; import mage.game.Game;
import mage.game.events.DamagedEvent; import mage.game.events.DamagedEvent;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.target.common.TargetCreaturePermanent; import mage.target.TargetPermanent;
import mage.watchers.Watcher; import mage.watchers.Watcher;
import java.util.HashSet; import java.util.HashSet;
@ -51,7 +52,9 @@ public final class MoonshaePixie extends AdventureCard {
// Pixie Dust // Pixie Dust
// Up to three target creatures gain flying until end of turn. // Up to three target creatures gain flying until end of turn.
this.getSpellCard().getSpellAbility().addEffect(new GainAbilityTargetEffect(FlyingAbility.getInstance())); this.getSpellCard().getSpellAbility().addEffect(new GainAbilityTargetEffect(FlyingAbility.getInstance()));
this.getSpellCard().getSpellAbility().addTarget(new TargetCreaturePermanent(0, 3)); this.getSpellCard().getSpellAbility().addTarget(new TargetPermanent(
0, 3, StaticFilters.FILTER_PERMANENT_CREATURES
));
} }
private MoonshaePixie(final MoonshaePixie card) { private MoonshaePixie(final MoonshaePixie card) {

View file

@ -38,7 +38,7 @@ public final class MyrkulsInvoker extends CardImpl {
ability.addEffect(new GainAbilityControlledEffect( ability.addEffect(new GainAbilityControlledEffect(
new MenaceAbility(false), Duration.EndOfTurn, new MenaceAbility(false), Duration.EndOfTurn,
StaticFilters.FILTER_CONTROLLED_CREATURE StaticFilters.FILTER_CONTROLLED_CREATURE
).setText("and gain menace until end of turn " + ).setText("and gain menace until end of turn. " +
"<i>(A creature with menace can't be blocked except by two or more creatures.)</i>")); "<i>(A creature with menace can't be blocked except by two or more creatures.)</i>"));
this.addAbility(ability.withFlavorWord("Psychic Blades")); this.addAbility(ability.withFlavorWord("Psychic Blades"));
} }

View file

@ -28,7 +28,7 @@ public final class MysteryKey extends CardImpl {
new DrawCardSourceControllerEffect(3), new DrawCardSourceControllerEffect(3),
new SacrificeSourceCost(), null, false new SacrificeSourceCost(), null, false
), "equipped", false ), "equipped", false
)); ).setTriggerPhrase("When equipped creature deals combat damage to a player, "));
// Equip {1} // Equip {1}
this.addAbility(new EquipAbility(1)); this.addAbility(new EquipAbility(1));

View file

@ -37,7 +37,8 @@ public final class NemesisPhoenix extends CardImpl {
// {2}{R}: Return Nemesis Phoenix from your graveyard to the battlefield tapped and attacking. Activate only during the declare attackers step and only if you're attacking two or more opponents. // {2}{R}: Return Nemesis Phoenix from your graveyard to the battlefield tapped and attacking. Activate only during the declare attackers step and only if you're attacking two or more opponents.
this.addAbility(new ActivateIfConditionActivatedAbility( this.addAbility(new ActivateIfConditionActivatedAbility(
Zone.GRAVEYARD, Zone.GRAVEYARD,
new ReturnToBattlefieldUnderOwnerControlSourceEffect(true, true, -1), new ReturnToBattlefieldUnderOwnerControlSourceEffect(true, true, -1)
.setText("return {this} from your graveyard to the battlefield tapped and attacking"),
new ManaCostsImpl<>("{2}{R}"), NemesisPhoenixCondition.instance new ManaCostsImpl<>("{2}{R}"), NemesisPhoenixCondition.instance
)); ));
} }

View file

@ -33,7 +33,7 @@ public final class OjiTheExquisiteBlade extends CardImpl {
// When Oji, the Exquisite Blade enters the battlefield, you gain 2 life and scry 2. // When Oji, the Exquisite Blade enters the battlefield, you gain 2 life and scry 2.
Ability ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(2)); Ability ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(2));
ability.addEffect(new ScryEffect(2, false)); ability.addEffect(new ScryEffect(2, false).concatBy("and"));
this.addAbility(ability); this.addAbility(ability);
// Whenever you cast your second spell each turn, exile up to one target creature you control, then return it to the battlefield under its owner's control. // Whenever you cast your second spell each turn, exile up to one target creature you control, then return it to the battlefield under its owner's control.

View file

@ -39,7 +39,7 @@ public final class RasaadYnBashir extends CardImpl {
// Each creature you control assigns combat damage equal to its toughness rather than its power. // Each creature you control assigns combat damage equal to its toughness rather than its power.
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessEffect( this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessEffect(
StaticFilters.FILTER_PERMANENT_CREATURE, false StaticFilters.FILTER_PERMANENT_CREATURE, true
))); )));
// Whenever Rasaad yn Bashir attacks, if you have the initiative, double the toughness of each creature you control until end of turn. // Whenever Rasaad yn Bashir attacks, if you have the initiative, double the toughness of each creature you control until end of turn.

View file

@ -5,8 +5,8 @@ import mage.abilities.effects.common.RollDieWithResultTableEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.game.permanent.token.KnightToken;
import mage.game.permanent.token.SoldierToken; import mage.game.permanent.token.SoldierToken;
import mage.game.permanent.token.WaylayToken;
import java.util.UUID; import java.util.UUID;
@ -25,10 +25,10 @@ public final class RecruitmentDrive extends CardImpl {
effect.addTableEntry(1, 9, new CreateTokenEffect(new SoldierToken(), 2)); effect.addTableEntry(1, 9, new CreateTokenEffect(new SoldierToken(), 2));
// 10-19 | Create two 2/2 white Knight creature tokens. // 10-19 | Create two 2/2 white Knight creature tokens.
effect.addTableEntry(10, 19, new CreateTokenEffect(new KnightToken(), 2)); effect.addTableEntry(10, 19, new CreateTokenEffect(new WaylayToken(), 2));
// 20 | Create three 2/2 white Knight creature tokens. // 20 | Create three 2/2 white Knight creature tokens.
effect.addTableEntry(20, 20, new CreateTokenEffect(new KnightToken(), 3)); effect.addTableEntry(20, 20, new CreateTokenEffect(new WaylayToken(), 3));
this.getSpellAbility().addEffect(effect); this.getSpellAbility().addEffect(effect);
} }

View file

@ -0,0 +1,111 @@
package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class SculptedSunburst extends CardImpl {
public SculptedSunburst(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{W}{W}");
// Choose a creature you control, then each opponent chooses a creature they control with equal or lesser power. If you chose a creature this way, exile each creature not chosen by any player this way.
this.getSpellAbility().addEffect(new SculptedSunburstEffect());
}
private SculptedSunburst(final SculptedSunburst card) {
super(card);
}
@Override
public SculptedSunburst copy() {
return new SculptedSunburst(this);
}
}
class SculptedSunburstEffect extends OneShotEffect {
SculptedSunburstEffect() {
super(Outcome.Benefit);
staticText = "choose a creature you control, then each opponent chooses " +
"a creature they control with equal or lesser power. If you chose a creature this way, " +
"exile each creature not chosen by any player this way";
}
private SculptedSunburstEffect(final SculptedSunburstEffect effect) {
super(effect);
}
@Override
public SculptedSunburstEffect copy() {
return new SculptedSunburstEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (!game.getBattlefield().contains(StaticFilters.FILTER_CONTROLLED_CREATURE, source, game, 1)) {
return false;
}
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
TargetPermanent target = new TargetControlledCreaturePermanent();
target.setNotTarget(true);
player.choose(outcome, target, source, game);
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent == null) {
return false;
}
Set<UUID> set = new HashSet<>();
set.add(permanent.getId());
int power = permanent.getPower().getValue();
FilterPermanent filter = new FilterControlledCreaturePermanent(
"creature you control with power " + power + " or less"
);
filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, power + 1));
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
if (!game.getBattlefield().contains(filter, source, game, 1)) {
continue;
}
Player opponent = game.getPlayer(opponentId);
if (opponent == null) {
continue;
}
TargetPermanent targetPermanent = new TargetPermanent(filter);
targetPermanent.setNotTarget(true);
opponent.choose(outcome, targetPermanent, source, game);
set.add(targetPermanent.getFirstTarget());
}
Cards cards = new CardsImpl(game.getBattlefield().getActivePermanents(
StaticFilters.FILTER_PERMANENT_CREATURE,
source.getControllerId(), source, game
));
cards.removeIf(set::contains);
player.moveCards(cards, Zone.EXILED, source, game);
return true;
}
}

View file

@ -59,6 +59,7 @@ public final class SharpshooterElf extends CardImpl {
new DamageTargetEffect(xValue, "it"), true new DamageTargetEffect(xValue, "it"), true
); );
ability.addTarget(new TargetPermanent(filter)); ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
} }
private SharpshooterElf(final SharpshooterElf card) { private SharpshooterElf(final SharpshooterElf card) {

View file

@ -46,7 +46,8 @@ public final class SkanosDragonheart extends CardImpl {
// Whenever Skanos Dragonheart attacks, it gets +X/+X until end of turn, where X is the greatest power among Dragon cards in your graveyard or other Dragons you control. // Whenever Skanos Dragonheart attacks, it gets +X/+X until end of turn, where X is the greatest power among Dragon cards in your graveyard or other Dragons you control.
this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect( this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(
SkanosDragonheartValue.instance, SkanosDragonheartValue.instance, Duration.EndOfTurn SkanosDragonheartValue.instance, SkanosDragonheartValue.instance,
Duration.EndOfTurn, true, "it"
)).addHint(hint)); )).addHint(hint));
// Choose a Background // Choose a Background

View file

@ -14,6 +14,7 @@ import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.target.common.TargetAnyTarget;
import java.util.UUID; import java.util.UUID;
@ -33,6 +34,7 @@ public final class StreetUrchin extends CardImpl {
new DamageTargetEffect(1, "this creature"), new GenericManaCost(1) new DamageTargetEffect(1, "this creature"), new GenericManaCost(1)
); );
ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_ARTIFACT_OR_OTHER_CREATURE)); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_ARTIFACT_OR_OTHER_CREATURE));
ability.addTarget(new TargetAnyTarget());
this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect( this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect(
ability, Duration.WhileOnBattlefield, ability, Duration.WhileOnBattlefield,
StaticFilters.FILTER_CREATURES_OWNED_COMMANDER StaticFilters.FILTER_CREATURES_OWNED_COMMANDER

View file

@ -0,0 +1,106 @@
package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.AttachedToMatchesFilterCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.FlashAbility;
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.FilterPermanent;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class StunningStrike extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent();
static {
filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate()));
}
private static final Condition condition = new AttachedToMatchesFilterCondition(filter);
public StunningStrike(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
this.subtype.add(SubType.AURA);
// Flash
this.addAbility(FlashAbility.getInstance());
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// When Stunning Strike enters the battlefield, tap enchanted creature and remove it from combat.
this.addAbility(new EntersBattlefieldTriggeredAbility(new StunningStrikeEffect()));
// As long as enchanted creature isn't legendary, it doesn't untap during its controller's untap step.
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
new DontUntapInControllersUntapStepEnchantedEffect(), condition, "as long as " +
"enchanted creature isn't legendary, it doesn't untap during its controller's untap step"
)));
}
private StunningStrike(final StunningStrike card) {
super(card);
}
@Override
public StunningStrike copy() {
return new StunningStrike(this);
}
}
class StunningStrikeEffect extends OneShotEffect {
StunningStrikeEffect() {
super(Outcome.Benefit);
staticText = "tap enchanted creature and remove it from combat";
}
private StunningStrikeEffect(final StunningStrikeEffect effect) {
super(effect);
}
@Override
public StunningStrikeEffect copy() {
return new StunningStrikeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Optional.of(source.getSourcePermanentOrLKI(game))
.filter(Objects::nonNull)
.map(Permanent::getAttachedTo)
.map(game::getPermanent)
.ifPresent(permanent -> {
permanent.tap(source, game);
permanent.removeFromCombat(game);
});
return true;
}
}

View file

@ -36,6 +36,8 @@ public final class Thunderwave extends CardImpl {
// 20 | Thunderwave deals 6 damage to each creature your opponents control. // 20 | Thunderwave deals 6 damage to each creature your opponents control.
effect.addTableEntry(20, 20, new DamageAllEffect(6, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); effect.addTableEntry(20, 20, new DamageAllEffect(6, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE));
this.getSpellAbility().addEffect(effect);
} }
private Thunderwave(final Thunderwave card) { private Thunderwave(final Thunderwave card) {

View file

@ -0,0 +1,65 @@
package mage.cards.u;
import mage.abilities.Ability;
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.TakeTheInitiativeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.game.Game;
import mage.game.permanent.token.SoldierToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class UndercellarSweep extends CardImpl {
public UndercellarSweep(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}");
// When Undercellar Sweep enters the battlefield, you take the initiative.
this.addAbility(new EntersBattlefieldTriggeredAbility(new TakeTheInitiativeEffect()));
// Whenever you attack, if you or a player you're attacking has the initiative, you create two 1/1 white Soldier creature token that are tapped and attacking.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new AttacksWithCreaturesTriggeredAbility(
new CreateTokenEffect(new SoldierToken(), 2, true, true), 1
), UndercellarSweepCondition.instance, "Whenever you attack, if you or a player you're attacking " +
"has the initiative, you create two 1/1 white Soldier creature token that are tapped and attacking."
));
}
private UndercellarSweep(final UndercellarSweep card) {
super(card);
}
@Override
public UndercellarSweep copy() {
return new UndercellarSweep(this);
}
}
enum UndercellarSweepCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
if (game.getInitiativeId() == null) {
return false;
}
return source.isControlledBy(game.getInitiativeId())
|| game
.getCombat()
.getAttackers()
.stream()
.filter(uuid -> source.isControlledBy(game.getControllerId(uuid)))
.map(game.getCombat()::getDefenderId)
.anyMatch(game.getInitiativeId()::equals);
}
}

View file

@ -0,0 +1,86 @@
package mage.cards.v;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSpellEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.SuspendAbility;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class VentureForth extends CardImpl {
public VentureForth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}");
// Exile cards from the top of your library until you exile a land card. Put that onto the battlefield and the rest on the bottom of your library in a random order. Exile Venture Forth with three time counters on it.
this.getSpellAbility().addEffect(new VentureForthEffect());
this.getSpellAbility().addEffect(new ExileSpellEffect());
this.getSpellAbility().addEffect(new AddCountersSourceEffect(
CounterType.TIME.createInstance(), StaticValue.get(3), false, true
).setText("with three time counters on it"));
this.getSpellAbility().addTarget(new TargetPermanent());
// Suspend 3{1}{G}
this.addAbility(new SuspendAbility(3, new ManaCostsImpl<>("{1}{G}"), this));
}
private VentureForth(final VentureForth card) {
super(card);
}
@Override
public VentureForth copy() {
return new VentureForth(this);
}
}
class VentureForthEffect extends OneShotEffect {
VentureForthEffect() {
super(Outcome.Benefit);
staticText = "exile cards from the top of your library until you exile a land card. Put that card " +
"onto the battlefield and the rest on the bottom of your library in a random order";
}
private VentureForthEffect(final VentureForthEffect effect) {
super(effect);
}
@Override
public VentureForthEffect copy() {
return new VentureForthEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Cards cards = new CardsImpl();
for (Card card : player.getLibrary().getCards(game)) {
player.moveCards(card, Zone.EXILED, source, game);
if (card.isLand(game)) {
player.moveCards(card, Zone.BATTLEFIELD, source, game);
break;
}
cards.add(card);
}
player.putCardsOnBottomOfLibrary(cards, game, source, false);
return true;
}
}

View file

@ -10,6 +10,7 @@ import mage.abilities.effects.common.ExileTopXMayPlayUntilEndOfTurnEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
@ -40,7 +41,7 @@ public final class WarehouseThief extends CardImpl {
// {2}, {T}, Sacrifice an artifact or creature: Exile the top card of your library. Until the end of your next turn, you may play that card. // {2}, {T}, Sacrifice an artifact or creature: Exile the top card of your library. Until the end of your next turn, you may play that card.
Ability ability = new SimpleActivatedAbility( Ability ability = new SimpleActivatedAbility(
new ExileTopXMayPlayUntilEndOfTurnEffect(1), new GenericManaCost(2) new ExileTopXMayPlayUntilEndOfTurnEffect(1, false, Duration.UntilEndOfYourNextTurn), new GenericManaCost(2)
); );
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeTargetCost(filter)); ability.addCost(new SacrificeTargetCost(filter));

View file

@ -3,7 +3,7 @@ package mage.cards.y;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.Mode; import mage.abilities.Mode;
import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.RequirementEffect;
import mage.abilities.effects.common.PreventAllNonCombatDamageToAllEffect; import mage.abilities.effects.common.PreventAllDamageToAllEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.IndestructibleAbility; import mage.abilities.keyword.IndestructibleAbility;
@ -11,7 +11,10 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.TargetController;
import mage.filter.FilterPlayer;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.common.FilterPermanentOrPlayer;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
@ -23,14 +26,21 @@ import java.util.UUID;
*/ */
public final class YouLookUponTheTarrasque extends CardImpl { public final class YouLookUponTheTarrasque extends CardImpl {
private static final FilterPermanentOrPlayer filter = new FilterPermanentOrPlayer(
"you and creatures you control",
StaticFilters.FILTER_CONTROLLED_CREATURES, new FilterPlayer()
);
static {
filter.getPlayerFilter().add(TargetController.YOU.getPlayerPredicate());
}
public YouLookUponTheTarrasque(UUID ownerId, CardSetInfo setInfo) { public YouLookUponTheTarrasque(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{G}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{G}");
// Choose one // Choose one
// Run and Hide Prevent all combat damage that would be dealt to you and creatures you control this turn. // Run and Hide Prevent all combat damage that would be dealt to you and creatures you control this turn.
this.getSpellAbility().addEffect(new PreventAllNonCombatDamageToAllEffect( this.getSpellAbility().addEffect(new PreventAllDamageToAllEffect(Duration.EndOfTurn, filter, true));
Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES, true
));
this.getSpellAbility().withFirstModeFlavorWord("Run and Hide"); this.getSpellAbility().withFirstModeFlavorWord("Run and Hide");
// Gather Your Courage Target creature gets +5/+5 and gains indestructible until end of turn. All creatures your opponents control able to block that creature this turn do so. // Gather Your Courage Target creature gets +5/+5 and gains indestructible until end of turn. All creatures your opponents control able to block that creature this turn do so.

View file

@ -33,7 +33,7 @@ public final class YouveBeenCaughtStealing extends CardImpl {
// Bribe the Guards You create a Treasure token for each opponent who was dealt damage this turn. // Bribe the Guards You create a Treasure token for each opponent who was dealt damage this turn.
this.getSpellAbility().addMode(new Mode(new CreateTokenEffect( this.getSpellAbility().addMode(new Mode(new CreateTokenEffect(
new TreasureToken(), YouveBeenCaughtStealingValue.instance new TreasureToken(), YouveBeenCaughtStealingValue.instance
)).withFlavorWord("Bribe the Guards")); ).setText("you create a Treasure token for each opponent who was dealt damage this turn")).withFlavorWord("Bribe the Guards"));
} }
private YouveBeenCaughtStealing(final YouveBeenCaughtStealing card) { private YouveBeenCaughtStealing(final YouveBeenCaughtStealing card) {

View file

@ -123,7 +123,7 @@ class ZevlorElturelExileTriggeredAbility extends DelayedTriggeredAbility {
@Override @Override
public String getRule() { public String getRule() {
return "When you next cast an instant or sorcery spell that targets only a single opponent or a single permanent an opponent controls this turn, for each other opponent, choose that player or a permanent they control, copy that spell, and the copy targets the chosen permanent."; return "When you next cast an instant or sorcery spell that targets only a single opponent or a single permanent an opponent controls this turn, for each other opponent, choose that player or a permanent they control, copy that spell, and the copy targets the chosen player or permanent.";
} }
} }

View file

@ -465,6 +465,7 @@ public final class CommanderLegendsBattleForBaldursGate extends ExpansionSet {
cards.add(new SetCardInfo("Sarevok, Deathbringer", 144, Rarity.UNCOMMON, mage.cards.s.SarevokDeathbringer.class)); cards.add(new SetCardInfo("Sarevok, Deathbringer", 144, Rarity.UNCOMMON, mage.cards.s.SarevokDeathbringer.class));
cards.add(new SetCardInfo("Scaled Nurturer", 252, Rarity.COMMON, mage.cards.s.ScaledNurturer.class)); cards.add(new SetCardInfo("Scaled Nurturer", 252, Rarity.COMMON, mage.cards.s.ScaledNurturer.class));
cards.add(new SetCardInfo("Scouting Hawk", 41, Rarity.COMMON, mage.cards.s.ScoutingHawk.class)); cards.add(new SetCardInfo("Scouting Hawk", 41, Rarity.COMMON, mage.cards.s.ScoutingHawk.class));
cards.add(new SetCardInfo("Sculpted Sunburst", 42, Rarity.RARE, mage.cards.s.SculptedSunburst.class));
cards.add(new SetCardInfo("Sea Gate", 359, Rarity.COMMON, mage.cards.s.SeaGate.class)); cards.add(new SetCardInfo("Sea Gate", 359, Rarity.COMMON, mage.cards.s.SeaGate.class));
cards.add(new SetCardInfo("Sea Hag", 95, Rarity.COMMON, mage.cards.s.SeaHag.class)); cards.add(new SetCardInfo("Sea Hag", 95, Rarity.COMMON, mage.cards.s.SeaHag.class));
cards.add(new SetCardInfo("Sea of Clouds", 360, Rarity.RARE, mage.cards.s.SeaOfClouds.class)); cards.add(new SetCardInfo("Sea of Clouds", 360, Rarity.RARE, mage.cards.s.SeaOfClouds.class));
@ -511,6 +512,7 @@ public final class CommanderLegendsBattleForBaldursGate extends ExpansionSet {
cards.add(new SetCardInfo("Stonespeaker Crystal", 338, Rarity.UNCOMMON, mage.cards.s.StonespeakerCrystal.class)); cards.add(new SetCardInfo("Stonespeaker Crystal", 338, Rarity.UNCOMMON, mage.cards.s.StonespeakerCrystal.class));
cards.add(new SetCardInfo("Street Urchin", 197, Rarity.UNCOMMON, mage.cards.s.StreetUrchin.class)); cards.add(new SetCardInfo("Street Urchin", 197, Rarity.UNCOMMON, mage.cards.s.StreetUrchin.class));
cards.add(new SetCardInfo("Stuffy Doll", 875, Rarity.RARE, mage.cards.s.StuffyDoll.class)); cards.add(new SetCardInfo("Stuffy Doll", 875, Rarity.RARE, mage.cards.s.StuffyDoll.class));
cards.add(new SetCardInfo("Stunning Strike", 97, Rarity.COMMON, mage.cards.s.StunningStrike.class));
cards.add(new SetCardInfo("Summon Undead", 151, Rarity.COMMON, mage.cards.s.SummonUndead.class)); cards.add(new SetCardInfo("Summon Undead", 151, Rarity.COMMON, mage.cards.s.SummonUndead.class));
cards.add(new SetCardInfo("Sunken Hollow", 918, Rarity.RARE, mage.cards.s.SunkenHollow.class)); cards.add(new SetCardInfo("Sunken Hollow", 918, Rarity.RARE, mage.cards.s.SunkenHollow.class));
cards.add(new SetCardInfo("Swamp", 459, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Swamp", 459, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
@ -557,6 +559,7 @@ public final class CommanderLegendsBattleForBaldursGate extends ExpansionSet {
cards.add(new SetCardInfo("Uchuulon", 673, Rarity.RARE, mage.cards.u.Uchuulon.class)); cards.add(new SetCardInfo("Uchuulon", 673, Rarity.RARE, mage.cards.u.Uchuulon.class));
cards.add(new SetCardInfo("Unbreakable Formation", 710, Rarity.RARE, mage.cards.u.UnbreakableFormation.class)); cards.add(new SetCardInfo("Unbreakable Formation", 710, Rarity.RARE, mage.cards.u.UnbreakableFormation.class));
cards.add(new SetCardInfo("Undercellar Myconid", 259, Rarity.COMMON, mage.cards.u.UndercellarMyconid.class)); cards.add(new SetCardInfo("Undercellar Myconid", 259, Rarity.COMMON, mage.cards.u.UndercellarMyconid.class));
cards.add(new SetCardInfo("Undercellar Sweep", 47, Rarity.UNCOMMON, mage.cards.u.UndercellarSweep.class));
cards.add(new SetCardInfo("Underdark Explorer", 154, Rarity.COMMON, mage.cards.u.UnderdarkExplorer.class)); cards.add(new SetCardInfo("Underdark Explorer", 154, Rarity.COMMON, mage.cards.u.UnderdarkExplorer.class));
cards.add(new SetCardInfo("Undermountain Adventurer", 260, Rarity.RARE, mage.cards.u.UndermountainAdventurer.class)); cards.add(new SetCardInfo("Undermountain Adventurer", 260, Rarity.RARE, mage.cards.u.UndermountainAdventurer.class));
cards.add(new SetCardInfo("Universal Solvent", 342, Rarity.COMMON, mage.cards.u.UniversalSolvent.class)); cards.add(new SetCardInfo("Universal Solvent", 342, Rarity.COMMON, mage.cards.u.UniversalSolvent.class));
@ -564,6 +567,7 @@ public final class CommanderLegendsBattleForBaldursGate extends ExpansionSet {
cards.add(new SetCardInfo("Valiant Changeling", 711, Rarity.UNCOMMON, mage.cards.v.ValiantChangeling.class)); cards.add(new SetCardInfo("Valiant Changeling", 711, Rarity.UNCOMMON, mage.cards.v.ValiantChangeling.class));
cards.add(new SetCardInfo("Vault of the Archangel", 927, Rarity.RARE, mage.cards.v.VaultOfTheArchangel.class)); cards.add(new SetCardInfo("Vault of the Archangel", 927, Rarity.RARE, mage.cards.v.VaultOfTheArchangel.class));
cards.add(new SetCardInfo("Vengeful Ancestor", 812, Rarity.RARE, mage.cards.v.VengefulAncestor.class)); cards.add(new SetCardInfo("Vengeful Ancestor", 812, Rarity.RARE, mage.cards.v.VengefulAncestor.class));
cards.add(new SetCardInfo("Venture Forth", 683, Rarity.RARE, mage.cards.v.VentureForth.class));
cards.add(new SetCardInfo("Veteran Soldier", 48, Rarity.UNCOMMON, mage.cards.v.VeteranSoldier.class)); cards.add(new SetCardInfo("Veteran Soldier", 48, Rarity.UNCOMMON, mage.cards.v.VeteranSoldier.class));
cards.add(new SetCardInfo("Vexing Puzzlebox", 343, Rarity.MYTHIC, mage.cards.v.VexingPuzzlebox.class)); cards.add(new SetCardInfo("Vexing Puzzlebox", 343, Rarity.MYTHIC, mage.cards.v.VexingPuzzlebox.class));
cards.add(new SetCardInfo("Vicious Battlerager", 155, Rarity.COMMON, mage.cards.v.ViciousBattlerager.class)); cards.add(new SetCardInfo("Vicious Battlerager", 155, Rarity.COMMON, mage.cards.v.ViciousBattlerager.class));

View file

@ -60,7 +60,7 @@ public class VerifyCardDataTest {
private static final Logger logger = Logger.getLogger(VerifyCardDataTest.class); private static final Logger logger = Logger.getLogger(VerifyCardDataTest.class);
private static final String FULL_ABILITIES_CHECK_SET_CODE = "ELD"; // check all abilities and output cards with wrong abilities texts; private static final String FULL_ABILITIES_CHECK_SET_CODE = "CLB"; // check all abilities and output cards with wrong abilities texts;
private static final boolean AUTO_FIX_SAMPLE_DECKS = false; // debug only: auto-fix sample decks by test_checkSampleDecks test run private static final boolean AUTO_FIX_SAMPLE_DECKS = false; // debug only: auto-fix sample decks by test_checkSampleDecks test run
private static final boolean ONLY_TEXT = false; // use when checking text locally, suppresses unnecessary checks and output messages private static final boolean ONLY_TEXT = false; // use when checking text locally, suppresses unnecessary checks and output messages
@ -83,7 +83,7 @@ public class VerifyCardDataTest {
private static final List<String> evergreenKeywords = Arrays.asList( private static final List<String> evergreenKeywords = Arrays.asList(
"flying", "lifelink", "menace", "trample", "haste", "first strike", "hexproof", "fear", "flying", "lifelink", "menace", "trample", "haste", "first strike", "hexproof", "fear",
"deathtouch", "double strike", "indestructible", "reach", "flash", "defender", "vigilance", "deathtouch", "double strike", "indestructible", "reach", "flash", "defender", "vigilance",
"plainswalk", "islandwalk", "swampwalk", "mountainwalk", "forestwalk" "plainswalk", "islandwalk", "swampwalk", "mountainwalk", "forestwalk", "myriad"
); );
static { static {

View file

@ -1,5 +1,6 @@
package mage.abilities.effects.common; package mage.abilities.effects.common;
import mage.MageItem;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.PreventionEffectImpl; import mage.abilities.effects.PreventionEffectImpl;
import mage.constants.Duration; import mage.constants.Duration;
@ -10,10 +11,9 @@ import mage.filter.predicate.other.PlayerIdPredicate;
import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.filter.predicate.permanent.PermanentIdPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import java.util.UUID; import java.util.UUID;
import mage.MageItem;
import mage.game.events.GameEvent.EventType;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
@ -41,7 +41,8 @@ public class PreventAllDamageToAllEffect extends PreventionEffectImpl {
+ (onlyCombat ? "combat " : "") + (onlyCombat ? "combat " : "")
+ "damage that would be dealt to " + "damage that would be dealt to "
+ filter.getMessage() + filter.getMessage()
+ (duration.toString().isEmpty() ? "" : ' ' + duration.toString()); + (duration.toString().isEmpty() ? "" : ' ')
+ (duration == Duration.EndOfTurn ? "this turn" : duration.toString());
} }
public PreventAllDamageToAllEffect(final PreventAllDamageToAllEffect effect) { public PreventAllDamageToAllEffect(final PreventAllDamageToAllEffect effect) {

View file

@ -68,7 +68,10 @@ public class UntapTargetEffect extends OneShotEffect {
if (target.getMaxNumberOfTargets() > 1 || target.getNumberOfTargets() == 0) { if (target.getMaxNumberOfTargets() > 1 || target.getNumberOfTargets() == 0) {
sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets())); sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets()));
sb.append(haveTargetWord ? " " : " target "); sb.append(haveTargetWord ? " " : " target ");
sb.append(target.getTargetName()).append('s'); sb.append(target.getTargetName());
if (!target.getTargetName().endsWith("s")) {
sb.append('s');
}
} else { } else {
sb.append(haveTargetWord ? "" : "target "); sb.append(haveTargetWord ? "" : "target ");
sb.append(target.getTargetName()); sb.append(target.getTargetName());

View file

@ -7,10 +7,14 @@ import mage.abilities.TriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.constants.*; import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.util.CardUtil;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale; import java.util.Locale;
@ -150,10 +154,10 @@ public class GainAbilityAllEffect extends ContinuousEffectImpl {
} }
if (quotes) { if (quotes) {
sb.append('"'); sb.append('"');
} sb.append(CardUtil.getTextWithFirstCharUpperCase(ability.getRule()));
sb.append(ability.getRule());
if (quotes) {
sb.append('"'); sb.append('"');
} else {
sb.append(ability.getRule());
} }
if (!duration.toString().isEmpty()) { if (!duration.toString().isEmpty()) {
sb.append(' ').append(duration.toString()); sb.append(' ').append(duration.toString());

View file

@ -9,6 +9,7 @@ import mage.constants.*;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.Target; import mage.target.Target;
import mage.util.CardUtil;
import java.util.*; import java.util.*;
@ -218,7 +219,7 @@ public class GainAbilityTargetEffect extends ContinuousEffectImpl {
if (target.getNumberOfTargets() < target.getMaxNumberOfTargets()) { if (target.getNumberOfTargets() < target.getMaxNumberOfTargets()) {
sb.append("up to "); sb.append("up to ");
} }
sb.append(target.getMaxNumberOfTargets()).append(" target ").append(target.getTargetName()).append(" gain "); sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(" target ").append(target.getTargetName()).append(" gain ");
} else { } else {
if (!target.getTargetName().toLowerCase(Locale.ENGLISH).startsWith("another")) { if (!target.getTargetName().toLowerCase(Locale.ENGLISH).startsWith("another")) {
sb.append("target "); sb.append("target ");

View file

@ -23,7 +23,7 @@ public class MyriadAbility extends AttacksTriggeredAbility {
public MyriadAbility() { public MyriadAbility() {
super(new MyriadEffect(), false, super(new MyriadEffect(), false,
"Myriad <i>(Whenever this creature attacks, for each opponent other than the defending player, " "myriad <i>(Whenever this creature attacks, for each opponent other than the defending player, "
+ "put a token that's a copy of this creature onto the battlefield tapped and attacking " + "put a token that's a copy of this creature onto the battlefield tapped and attacking "
+ "that player or a planeswalker they control. Exile those tokens at the end of combat.)</i>", + "that player or a planeswalker they control. Exile those tokens at the end of combat.)</i>",
SetTargetPointer.PLAYER SetTargetPointer.PLAYER

View file

@ -301,11 +301,11 @@ public final class StaticFilters {
FILTER_PERMANENTS_ARTIFACT_CREATURE.setLockedFilter(true); FILTER_PERMANENTS_ARTIFACT_CREATURE.setLockedFilter(true);
} }
public static final FilterControlledArtifactPermanent FILTER_ARTIFACTS_NON_CREATURE = new FilterControlledArtifactPermanent("Noncreature artifacts"); public static final FilterControlledArtifactPermanent FILTER_ARTIFACT_NON_CREATURE = new FilterControlledArtifactPermanent("noncreature artifact");
static { static {
FILTER_ARTIFACTS_NON_CREATURE.add(Predicates.not(CardType.CREATURE.getPredicate())); FILTER_ARTIFACT_NON_CREATURE.add(Predicates.not(CardType.CREATURE.getPredicate()));
FILTER_ARTIFACTS_NON_CREATURE.setLockedFilter(true); FILTER_ARTIFACT_NON_CREATURE.setLockedFilter(true);
} }
public static final FilterPermanent FILTER_PERMANENT_ARTIFACT_OR_CREATURE = new FilterPermanent("artifact or creature"); public static final FilterPermanent FILTER_PERMANENT_ARTIFACT_OR_CREATURE = new FilterPermanent("artifact or creature");