[BLB] various text fixes

This commit is contained in:
theelk801 2025-06-02 16:30:11 -04:00
parent ca1145c967
commit fe4d6d3197
29 changed files with 120 additions and 83 deletions

View file

@ -54,7 +54,7 @@ public final class BanditsTalent extends CardImpl {
this.addAbility(new ClassLevelAbility(2, "{B}")); this.addAbility(new ClassLevelAbility(2, "{B}"));
// At the beginning of each opponent's upkeep, if that player has one or fewer cards in hand, they lose 2 life. // At the beginning of each opponent's upkeep, if that player has one or fewer cards in hand, they lose 2 life.
this.addAbility(new SimpleStaticAbility(new GainClassAbilitySourceEffect(new BeginningOfUpkeepTriggeredAbility( this.addAbility(new SimpleStaticAbility(new GainClassAbilitySourceEffect(new BeginningOfUpkeepTriggeredAbility(
TargetController.OPPONENT, new ConditionalOneShotEffect(new LoseLifeTargetEffect(2), new CardsInHandCondition(ComparisonType.OR_LESS, 1, TargetController.ACTIVE)), TargetController.OPPONENT, new ConditionalOneShotEffect(new LoseLifeTargetEffect(2).setText("they lose 2 life"), new CardsInHandCondition(ComparisonType.OR_LESS, 1, TargetController.ACTIVE)),
false), 2))); false), 2)));
// {3}{B}: Level 3 // {3}{B}: Level 3

View file

@ -10,17 +10,22 @@ import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.hint.ConditionHint;
import mage.abilities.hint.Hint;
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.SubType; import mage.constants.SubType;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.game.Controllable;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.token.FishNoAbilityToken; import mage.game.permanent.token.FishNoAbilityToken;
import mage.game.permanent.token.TreasureToken; import mage.game.permanent.token.TreasureToken;
import mage.players.Player; import mage.players.Player;
import java.util.Optional;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
/** /**
@ -28,6 +33,13 @@ import java.util.UUID;
*/ */
public final class BezaTheBoundingSpring extends CardImpl { public final class BezaTheBoundingSpring extends CardImpl {
private static final Condition condition = new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS);
private static final Condition condition2 = new OpponentControlsMoreCondition(StaticFilters.FILTER_PERMANENT_CREATURES);
private static final Hint hint = new ConditionHint(condition);
private static final Hint hint2 = new ConditionHint(condition2);
private static final Hint hint3 = new ConditionHint(OpponentHasMoreLifeCondition.instance);
private static final Hint hint4 = new ConditionHint(BezaOpponentHasMoreCardsInHandThanYouCondition.instance);
public BezaTheBoundingSpring(UUID ownerId, CardSetInfo setInfo) { public BezaTheBoundingSpring(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}");
@ -39,14 +51,23 @@ public final class BezaTheBoundingSpring extends CardImpl {
// When Beza, the Bounding Spring enters, create a Treasure token if an opponent controls more lands than you. You gain 4 life if an opponent has more life than you. Create two 1/1 blue Fish creature tokens if an opponent controls more creatures than you. Draw a card if an opponent has more cards in hand than you. // When Beza, the Bounding Spring enters, create a Treasure token if an opponent controls more lands than you. You gain 4 life if an opponent has more life than you. Create two 1/1 blue Fish creature tokens if an opponent controls more creatures than you. Draw a card if an opponent has more cards in hand than you.
Ability ability = new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect( Ability ability = new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(
new CreateTokenEffect(new TreasureToken()), new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS))); new CreateTokenEffect(new TreasureToken()), condition,
"create a Treasure token if an opponent controls more lands than you"
));
ability.addEffect(new ConditionalOneShotEffect( ability.addEffect(new ConditionalOneShotEffect(
new GainLifeEffect(4), OpponentHasMoreLifeCondition.instance)); new GainLifeEffect(4), OpponentHasMoreLifeCondition.instance,
"you gain 4 life if an opponent has more life than you"
));
ability.addEffect(new ConditionalOneShotEffect( ability.addEffect(new ConditionalOneShotEffect(
new CreateTokenEffect(new FishNoAbilityToken(), 2), new OpponentControlsMoreCondition(StaticFilters.FILTER_PERMANENT_CREATURES))); new CreateTokenEffect(new FishNoAbilityToken(), 2), condition2,
"Create two 1/1 blue Fish creature tokens if an opponent controls more creatures than you"
));
ability.addEffect(new ConditionalOneShotEffect( ability.addEffect(new ConditionalOneShotEffect(
new DrawCardSourceControllerEffect(1), BezaOpponentHasMoreCardsInHandThanYouCondition.instance)); new DrawCardSourceControllerEffect(1),
this.addAbility(ability); BezaOpponentHasMoreCardsInHandThanYouCondition.instance,
"draw a card if an opponent has more cards in hand than you"
));
this.addAbility(ability.addHint(hint).addHint(hint2).addHint(hint3).addHint(hint4));
} }
private BezaTheBoundingSpring(final BezaTheBoundingSpring card) { private BezaTheBoundingSpring(final BezaTheBoundingSpring card) {
@ -61,22 +82,23 @@ public final class BezaTheBoundingSpring extends CardImpl {
//Based on MoreCardsInHandThanOpponentsCondition //Based on MoreCardsInHandThanOpponentsCondition
enum BezaOpponentHasMoreCardsInHandThanYouCondition implements Condition { enum BezaOpponentHasMoreCardsInHandThanYouCondition implements Condition {
instance; instance;
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); int cardsInHand = Optional
if (player != null) { .ofNullable(source)
int cardsInHand = player.getHand().size(); .map(Controllable::getControllerId)
for (UUID playerId : game.getOpponents(source.getControllerId())) { .map(game::getPlayer)
Player opponent = game.getPlayer(playerId); .map(Player::getHand)
if (opponent != null && opponent.getHand().size() > cardsInHand) { .map(Set::size)
return true; .orElse(0);
} return game.getOpponents(source.getControllerId())
} .stream()
} .map(game::getPlayer)
return false; .map(Player::getHand)
.mapToInt(Set::size)
.anyMatch(x -> x > cardsInHand);
} }
@Override @Override

View file

@ -32,7 +32,7 @@ public final class BushyBodyguard extends CardImpl {
// When this creature enters, you may forage. If you do, put two +1/+1 counters on it. // When this creature enters, you may forage. If you do, put two +1/+1 counters on it.
this.addAbility(new EntersBattlefieldTriggeredAbility(new DoIfCostPaid( this.addAbility(new EntersBattlefieldTriggeredAbility(new DoIfCostPaid(
new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), new ForageCost() new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)).setText("put two +1/+1 counters on it"), new ForageCost()
))); )));
} }

View file

@ -21,7 +21,7 @@ import java.util.UUID;
* @author notgreat * @author notgreat
*/ */
public final class DaringWaverider extends CardImpl { public final class DaringWaverider extends CardImpl {
private static final FilterCard filter = new FilterInstantOrSorceryCard("instant or sorcery card with mana value 4 or less"); private static final FilterCard filter = new FilterInstantOrSorceryCard("instant or sorcery card with mana value 4 or less from your graveyard");
static { static {
filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, 4)); filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, 4));

View file

@ -118,7 +118,7 @@ class ElugeTheShorelessSeaEffect extends BecomesBasicLandTargetEffect {
ElugeTheShorelessSeaEffect() { ElugeTheShorelessSeaEffect() {
super(Duration.Custom, false, false, SubType.ISLAND); super(Duration.Custom, false, false, SubType.ISLAND);
staticText = "It's an land is an Island in addition to its other types for as long as it has a flood counter on it"; staticText = "It's an Island in addition to its other types for as long as it has a flood counter on it";
} }
private ElugeTheShorelessSeaEffect(final ElugeTheShorelessSeaEffect effect) { private ElugeTheShorelessSeaEffect(final ElugeTheShorelessSeaEffect effect) {

View file

@ -16,9 +16,7 @@ import mage.filter.StaticFilters;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInLibrary;
import mage.target.targetpointer.FirstTargetPointer;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import java.util.UUID; import java.util.UUID;
@ -53,7 +51,7 @@ class FabledPassageSearchForLandEffect extends OneShotEffect {
FabledPassageSearchForLandEffect() { FabledPassageSearchForLandEffect() {
super(Outcome.PutCardInPlay); super(Outcome.PutCardInPlay);
staticText = "Search your library for a basic land card, put it onto the battlefield tapped, then shuffle "; staticText = "Search your library for a basic land card, put it onto the battlefield tapped, then shuffle";
} }
private FabledPassageSearchForLandEffect(final FabledPassageSearchForLandEffect effect) { private FabledPassageSearchForLandEffect(final FabledPassageSearchForLandEffect effect) {

View file

@ -1,7 +1,5 @@
package mage.cards.f; package mage.cards.f;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility; import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
@ -11,24 +9,27 @@ import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.hint.common.LandsYouControlHint; import mage.abilities.hint.common.LandsYouControlHint;
import mage.cards.Card;
import mage.constants.*;
import mage.abilities.keyword.ReachAbility; import mage.abilities.keyword.ReachAbility;
import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.ToughnessGreaterThanPowerPredicate; import mage.filter.predicate.mageobject.ToughnessGreaterThanPowerPredicate;
import mage.game.Game; import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import java.util.UUID;
/** /**
* @author Cguy7777 * @author Cguy7777
*/ */
public final class FecundGreenshell extends CardImpl { public final class FecundGreenshell extends CardImpl {
private static final FilterCreaturePermanent filter private static final FilterPermanent filter
= new FilterCreaturePermanent("creature you control with toughness greater than its power"); = new FilterControlledCreaturePermanent("creature you control with toughness greater than its power");
static { static {
filter.add(ToughnessGreaterThanPowerPredicate.instance); filter.add(ToughnessGreaterThanPowerPredicate.instance);
@ -59,7 +60,7 @@ public final class FecundGreenshell extends CardImpl {
// Whenever Fecund Greenshell or another creature you control with toughness greater than its power enters, // Whenever Fecund Greenshell or another creature you control with toughness greater than its power enters,
// look at the top card of your library. If it's a land card, you may put it onto the battlefield tapped. Otherwise, put it into your hand. // look at the top card of your library. If it's a land card, you may put it onto the battlefield tapped. Otherwise, put it into your hand.
this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility( this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
new FecundGreenshellEffect(), filter, false, true)); new FecundGreenshellEffect(), filter, false, false));
} }
private FecundGreenshell(final FecundGreenshell card) { private FecundGreenshell(final FecundGreenshell card) {

View file

@ -50,7 +50,7 @@ public final class ForTheCommonGood extends CardImpl {
IndestructibleAbility.getInstance(), IndestructibleAbility.getInstance(),
Duration.UntilYourNextTurn, StaticFilters.FILTER_PERMANENT_TOKENS Duration.UntilYourNextTurn, StaticFilters.FILTER_PERMANENT_TOKENS
).concatBy("Then")); ).concatBy("Then"));
this.getSpellAbility().addEffect(new GainLifeEffect(xValue)); this.getSpellAbility().addEffect(new GainLifeEffect(xValue).setText("You gain 1 life for each token you control"));
this.getSpellAbility().addHint(hint); this.getSpellAbility().addHint(hint);
} }

View file

@ -1,7 +1,10 @@
package mage.cards.g; package mage.cards.g;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.*; import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.ExileThenReturnTargetEffect; import mage.abilities.effects.common.ExileThenReturnTargetEffect;
import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect;
import mage.abilities.effects.common.continuous.GainClassAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainClassAbilitySourceEffect;
@ -10,7 +13,10 @@ import mage.abilities.keyword.ClassLevelAbility;
import mage.abilities.keyword.ClassReminderAbility; import mage.abilities.keyword.ClassReminderAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.common.FilterAttackingCreature; import mage.filter.common.FilterAttackingCreature;
@ -24,7 +30,7 @@ import java.util.UUID;
*/ */
public final class GossipsTalent extends CardImpl { public final class GossipsTalent extends CardImpl {
private static final FilterPermanent filter = new FilterAttackingCreature("attacking creature with power 3 or less can't be blocked this turn"); private static final FilterPermanent filter = new FilterAttackingCreature("attacking creature with power 3 or less");
static { static {
filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 4)); filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 4));
@ -59,7 +65,7 @@ public final class GossipsTalent extends CardImpl {
new DealsDamageToAPlayerAllTriggeredAbility( new DealsDamageToAPlayerAllTriggeredAbility(
new ExileThenReturnTargetEffect(false, false) new ExileThenReturnTargetEffect(false, false)
.setText("exile it, then return it to the battlefield under its owner's control"), .setText("exile it, then return it to the battlefield under its owner's control"),
StaticFilters.FILTER_PERMANENT_CREATURE, true, SetTargetPointer.PERMANENT, true StaticFilters.FILTER_CONTROLLED_CREATURE, true, SetTargetPointer.PERMANENT, true
), 3 ), 3
))); )));
} }

View file

@ -2,7 +2,7 @@ package mage.cards.h;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility; import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
import mage.abilities.condition.Condition; import mage.abilities.condition.Condition;
import mage.abilities.condition.common.TargetObjectMatchesFilterCondition; import mage.abilities.condition.common.TargetObjectMatchesFilterCondition;
import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.decorator.ConditionalOneShotEffect;
@ -35,7 +35,7 @@ public final class HazardrootHerbalist extends CardImpl {
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
// Whenever you attack, target creature you control gets +1/+0 until end of turn. If that creature is a token, it also gains deathtouch until end of turn. // Whenever you attack, target creature you control gets +1/+0 until end of turn. If that creature is a token, it also gains deathtouch until end of turn.
Ability ability = new AttacksCreatureYouControlTriggeredAbility(new BoostTargetEffect(1, 0)); Ability ability = new AttacksWithCreaturesTriggeredAbility(new BoostTargetEffect(1, 0), 1);
ability.addEffect(new ConditionalOneShotEffect( ability.addEffect(new ConditionalOneShotEffect(
new AddContinuousEffectToGame(new GainAbilityTargetEffect(DeathtouchAbility.getInstance())), new AddContinuousEffectToGame(new GainAbilityTargetEffect(DeathtouchAbility.getInstance())),
condition, "if that creature is a token, it also gains deathtouch until end of turn" condition, "if that creature is a token, it also gains deathtouch until end of turn"

View file

@ -37,7 +37,7 @@ public final class HoardersOverflow extends CardImpl {
// {1}{R}, Sacrifice Hoarder's Overflow: Discard your hand, then draw cards equal to the number of stash counters on Hoarder's Overflow. // {1}{R}, Sacrifice Hoarder's Overflow: Discard your hand, then draw cards equal to the number of stash counters on Hoarder's Overflow.
Ability ability = new SimpleActivatedAbility(new DiscardHandControllerEffect(), new ManaCostsImpl<>("{1}{R}")); Ability ability = new SimpleActivatedAbility(new DiscardHandControllerEffect(), new ManaCostsImpl<>("{1}{R}"));
ability.addCost(new SacrificeSourceCost()); ability.addCost(new SacrificeSourceCost());
ability.addEffect(new DrawCardSourceControllerEffect(new CountersSourceCount(CounterType.STASH)).concatBy(", then")); ability.addEffect(new DrawCardSourceControllerEffect(new CountersSourceCount(CounterType.STASH)).setText(", then draw cards equal to the number of stash counters on {this}"));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -39,7 +39,7 @@ public final class IntoTheFloodMaw extends CardImpl {
// Return target creature an opponent controls to its owner's hand. If the gift was promise, instead return target nonland permanent an opponent controls to its owner's hand. // Return target creature an opponent controls to its owner's hand. If the gift was promise, instead return target nonland permanent an opponent controls to its owner's hand.
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect() this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()
.setText("return target creature an opponent controls to its owner's hand. If the gift was promise, " + .setText("return target creature an opponent controls to its owner's hand. If the gift was promised, " +
"instead return target nonland permanent an opponent controls to its owner's hand")); "instead return target nonland permanent an opponent controls to its owner's hand"));
this.getSpellAbility().addTarget(new TargetPermanent(playableFilter)); this.getSpellAbility().addTarget(new TargetPermanent(playableFilter));
this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(GiftWasPromisedCondition.TRUE, this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(GiftWasPromisedCondition.TRUE,

View file

@ -1,7 +1,7 @@
package mage.cards.k; package mage.cards.k;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -9,6 +9,8 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.filter.predicate.permanent.TokenPredicate; import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.permanent.token.FishNoAbilityToken; import mage.game.permanent.token.FishNoAbilityToken;
@ -19,9 +21,10 @@ import java.util.UUID;
*/ */
public final class Knightfisher extends CardImpl { public final class Knightfisher extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent(SubType.BIRD, "nontoken Bird"); private static final FilterPermanent filter = new FilterControlledPermanent(SubType.BIRD, "another nontoken Bird you control");
static { static {
filter.add(AnotherPredicate.instance);
filter.add(TokenPredicate.FALSE); filter.add(TokenPredicate.FALSE);
} }
@ -37,9 +40,7 @@ public final class Knightfisher extends CardImpl {
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// Whenever another nontoken Bird you control enters, create a 1/1 blue Fish creature token. // Whenever another nontoken Bird you control enters, create a 1/1 blue Fish creature token.
this.addAbility(new EntersBattlefieldControlledTriggeredAbility( this.addAbility(new EntersBattlefieldAllTriggeredAbility(new CreateTokenEffect(new FishNoAbilityToken()), filter));
new CreateTokenEffect(new FishNoAbilityToken()), filter
));
} }
private Knightfisher(final Knightfisher card) { private Knightfisher(final Knightfisher card) {

View file

@ -33,7 +33,7 @@ public final class LongstalkBrawl extends CardImpl {
GiftWasPromisedCondition.TRUE, "choose target creature you control and target creature " + GiftWasPromisedCondition.TRUE, "choose target creature you control and target creature " +
"you don't control. Put a +1/+1 counter on the creature you control if the gift was promised" "you don't control. Put a +1/+1 counter on the creature you control if the gift was promised"
)); ));
this.getSpellAbility().addEffect(new FightTargetsEffect().setText("then those creatures fight each other")); this.getSpellAbility().addEffect(new FightTargetsEffect().setText("Then those creatures fight each other"));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL));
} }

View file

@ -36,6 +36,7 @@ import java.util.stream.Collectors;
public final class PartingGust extends CardImpl { public final class PartingGust extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature");
static { static {
filter.add(TokenPredicate.FALSE); filter.add(TokenPredicate.FALSE);
} }
@ -52,7 +53,7 @@ public final class PartingGust extends CardImpl {
new ExileTargetEffect(), new ExileTargetEffect(),
new PartingGustExileReturnEffect(), new PartingGustExileReturnEffect(),
GiftWasPromisedCondition.TRUE, GiftWasPromisedCondition.TRUE,
"Exile target nontoken creature. If the gift wasn't promised, return that creature to the " + "Exile target nontoken creature. If the gift wasn't promised, return that card to the " +
"battlefield under its owner's control with a +1/+1 counter on it at the beginning of the next end step." "battlefield under its owner's control with a +1/+1 counter on it at the beginning of the next end step."
)); ));
} }

View file

@ -26,7 +26,7 @@ public final class PeerlessRecycling extends CardImpl {
// Return target permanent from your graveyard to your hand. If the gift was promised, instead return two target permanent cards from your graveyard to your hand. // Return target permanent from your graveyard to your hand. If the gift was promised, instead return two target permanent cards from your graveyard to your hand.
this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect() this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect()
.setText("return target permanent from your graveyard to your hand. If the gift was promised, " + .setText("return target permanent card from your graveyard to your hand. If the gift was promised, " +
"instead return two target permanent cards from your graveyard to your hand")); "instead return two target permanent cards from your graveyard to your hand"));
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_PERMANENT)); this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_PERMANENT));
this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(GiftWasPromisedCondition.TRUE, this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(GiftWasPromisedCondition.TRUE,

View file

@ -32,7 +32,7 @@ public final class PsychicWhorl extends CardImpl {
this.getSpellAbility().addTarget(new TargetOpponent()); this.getSpellAbility().addTarget(new TargetOpponent());
this.getSpellAbility().addEffect(new ConditionalOneShotEffect( this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new SurveilEffect(2), condition, new SurveilEffect(2), condition,
"then if you control a Rat, surveil 2" "Then if you control a Rat, surveil 2"
)); ));
this.getSpellAbility().addHint(hint); this.getSpellAbility().addHint(hint);
} }

View file

@ -22,7 +22,7 @@ public final class RabidGnaw extends CardImpl {
// Target creature you control gets +1/+0 until end of turn. Then it deals damage equal to its power to target creature you don't control. // Target creature you control gets +1/+0 until end of turn. Then it deals damage equal to its power to target creature you don't control.
this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0)); this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("then it")); this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("Then it"));
this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL));
} }

View file

@ -71,7 +71,7 @@ class RottenmouthViperEffect extends OneShotEffect{
RottenmouthViperEffect(DynamicValue blightCounterAmount) { RottenmouthViperEffect(DynamicValue blightCounterAmount) {
super(Outcome.LoseLife); super(Outcome.LoseLife);
this.blightCounterAmount = blightCounterAmount; this.blightCounterAmount = blightCounterAmount;
this.staticText = "Then for each blight counter on it, each opponent loses 4 life unless that player sacrifices a nonland permanent or discards a card."; this.staticText = "Then for each blight counter on it, each opponent loses 4 life unless that player sacrifices a nonland permanent of their choice or discards a card.";
} }
private RottenmouthViperEffect(final RottenmouthViperEffect effect) { private RottenmouthViperEffect(final RottenmouthViperEffect effect) {

View file

@ -43,7 +43,7 @@ public final class SeasonedWarrenguard extends CardImpl {
// Whenever Seasoned Warrenguard attacks while you control a token, Seasoned Warrenguard gets +2/+0 until end of turn. // Whenever Seasoned Warrenguard attacks while you control a token, Seasoned Warrenguard gets +2/+0 until end of turn.
this.addAbility(new AttacksTriggeredAbility( this.addAbility(new AttacksTriggeredAbility(
new BoostSourceEffect(2, 0, Duration.EndOfTurn) new BoostSourceEffect(2, 0, Duration.EndOfTurn)
).withTriggerCondition(condition).addHint(hint)); ).withRuleTextReplacement(false).withTriggerCondition(condition).addHint(hint));
} }
private SeasonedWarrenguard(final SeasonedWarrenguard card) { private SeasonedWarrenguard(final SeasonedWarrenguard card) {

View file

@ -40,7 +40,7 @@ public final class ShorelineLooter extends CardImpl {
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1)); Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1));
ability.addEffect(new ConditionalOneShotEffect( ability.addEffect(new ConditionalOneShotEffect(
new DiscardControllerEffect(1), condition, new DiscardControllerEffect(1), condition,
"then discard a card unless seven or more cards are in your graveyard" "Then discard a card unless seven or more cards are in your graveyard"
)); ));
this.addAbility(ability.setAbilityWord(AbilityWord.THRESHOLD)); this.addAbility(ability.setAbilityWord(AbilityWord.THRESHOLD));
} }

View file

@ -25,7 +25,7 @@ public final class Spellgyre extends CardImpl {
this.getSpellAbility().addTarget(new TargetSpell()); this.getSpellAbility().addTarget(new TargetSpell());
// * Surveil 2, then draw two cards. // * Surveil 2, then draw two cards.
this.getSpellAbility().addMode(new Mode(new SurveilEffect(2)) this.getSpellAbility().addMode(new Mode(new SurveilEffect(2, false))
.addEffect(new DrawCardSourceControllerEffect(2).concatBy(", then"))); .addEffect(new DrawCardSourceControllerEffect(2).concatBy(", then")));
} }

View file

@ -54,7 +54,7 @@ public final class StarseerMentor extends CardImpl {
"Sacrifice a nonland permanent or discard a card to prevent losing 3 life?" "Sacrifice a nonland permanent or discard a card to prevent losing 3 life?"
) )
), YouGainedOrLostLifeCondition.instance, "At the beginning of your end step, if you gained or lost life this turn, " ), YouGainedOrLostLifeCondition.instance, "At the beginning of your end step, if you gained or lost life this turn, "
+ "target opponent loses 3 life unless they sacrifice a nonland permanent or discard a card." + "target opponent loses 3 life unless they sacrifice a nonland permanent of their choice or discard a card."
); );
ability.addTarget(new TargetOpponent()); ability.addTarget(new TargetOpponent());
ability.addWatcher(new PlayerGainedLifeWatcher()); ability.addWatcher(new PlayerGainedLifeWatcher());

View file

@ -42,7 +42,7 @@ public final class ThornplateIntimidator extends CardImpl {
new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_NON_LAND), new DiscardCardCost() new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_NON_LAND), new DiscardCardCost()
), ),
"Sacrifice a nonland permanent or discard a card to prevent losing 3 life?" "Sacrifice a nonland permanent or discard a card to prevent losing 3 life?"
)); ).setText("target opponent loses 3 life unless they sacrifice a nonland permanent of their choice or discard a card"));
ability.addTarget(new TargetOpponent()); ability.addTarget(new TargetOpponent());
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -2,15 +2,16 @@ package mage.cards.v;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.replacement.CreaturesAreExiledOnDeathReplacementEffect; import mage.abilities.effects.common.replacement.CreaturesAreExiledOnDeathReplacementEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint; import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.WardAbility; import mage.abilities.keyword.WardAbility;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
@ -31,6 +32,10 @@ import java.util.UUID;
*/ */
public final class VrenTheRelentless extends CardImpl { public final class VrenTheRelentless extends CardImpl {
private static final Hint hint = new ValueHint(
"Creatures exiled under opponents' control this turn", VrenTheRelentlessCount.instance
);
public VrenTheRelentless(UUID ownerId, CardSetInfo setInfo) { public VrenTheRelentless(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{B}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{B}");
this.supertype.add(SuperType.LEGENDARY); this.supertype.add(SuperType.LEGENDARY);
@ -49,11 +54,8 @@ public final class VrenTheRelentless extends CardImpl {
// At the beginning of each end step, create X 1/1 black Rat creature tokens with "This creature gets +1/+1 for each // At the beginning of each end step, create X 1/1 black Rat creature tokens with "This creature gets +1/+1 for each
// other Rat you control," where X is the number of creatures your opponents controlled that were exiled this turn. // other Rat you control," where X is the number of creatures your opponents controlled that were exiled this turn.
this.addAbility(new BeginningOfEndStepTriggeredAbility( this.addAbility(new BeginningOfEndStepTriggeredAbility(
TargetController.ANY, new CreateTokenEffect(new VrenRatToken(), VrenTheRelentlessCount.instance) TargetController.ANY, new CreateTokenEffect(new VrenRatToken(), VrenTheRelentlessCount.instance), false
.setText("create X 1/1 black Rat creature tokens with \"This creature gets +1/+1 for each other Rat you " + ).addHint(hint), new VrenTheRelentlessWatcher());
"control,\" where X is the number of creatures your opponents controlled that were exiled this turn"),
false
).addHint(new ValueHint("Creatures exiled under opponents' control this turn", VrenTheRelentlessCount.instance)), new VrenTheRelentlessWatcher());
} }
private VrenTheRelentless(final VrenTheRelentless card) { private VrenTheRelentless(final VrenTheRelentless card) {
@ -72,7 +74,7 @@ enum VrenTheRelentlessCount implements DynamicValue {
@Override @Override
public int calculate(Game game, Ability sourceAbility, Effect effect) { public int calculate(Game game, Ability sourceAbility, Effect effect) {
VrenTheRelentlessWatcher watcher = game.getState().getWatcher(VrenTheRelentlessWatcher.class); VrenTheRelentlessWatcher watcher = game.getState().getWatcher(VrenTheRelentlessWatcher.class);
return watcher == null ? 0 : watcher.getCount(sourceAbility.getControllerId()); return watcher == null ? 0 : watcher.getCount(sourceAbility.getControllerId(), game);
} }
@Override @Override
@ -80,9 +82,14 @@ enum VrenTheRelentlessCount implements DynamicValue {
return instance; return instance;
} }
@Override
public String toString() {
return "X";
}
@Override @Override
public String getMessage() { public String getMessage() {
return ""; return "the number of creatures that were exiled under your opponents' control this turn";
} }
} }
@ -100,7 +107,9 @@ class VrenTheRelentlessWatcher extends Watcher {
return; return;
} }
ZoneChangeEvent zEvent = (ZoneChangeEvent) event; ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if ((zEvent.getToZone() == Zone.EXILED && zEvent.getFromZone() == Zone.BATTLEFIELD) && zEvent.getTarget().isCreature(game)) { if (zEvent.getToZone() == Zone.EXILED
&& zEvent.getFromZone() == Zone.BATTLEFIELD
&& zEvent.getTarget().isCreature(game)) {
playerMap.compute(zEvent.getTarget().getControllerId(), CardUtil::setOrIncrementValue); playerMap.compute(zEvent.getTarget().getControllerId(), CardUtil::setOrIncrementValue);
} }
} }
@ -111,10 +120,11 @@ class VrenTheRelentlessWatcher extends Watcher {
super.reset(); super.reset();
} }
int getCount(UUID playerId) { int getCount(UUID playerId, Game game) {
return playerMap.entrySet().stream() return game
.filter(entry -> !entry.getKey().equals(playerId)) .getOpponents(playerId)
.mapToInt(Map.Entry::getValue) .stream()
.mapToInt(uuid -> playerMap.getOrDefault(uuid, 0))
.sum(); .sum();
} }
} }

View file

@ -75,7 +75,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_CODES = "DRC"; // check ability text due mtgjson, can use multiple sets like MAT;CMD or * for all private static final String FULL_ABILITIES_CHECK_SET_CODES = "BLB"; // check ability text due mtgjson, can use multiple sets like MAT;CMD or * for all
private static final boolean CHECK_ONLY_ABILITIES_TEXT = false; // use when checking text locally, suppresses unnecessary checks and output messages private static final boolean CHECK_ONLY_ABILITIES_TEXT = false; // use when checking text locally, suppresses unnecessary checks and output messages
private static final boolean CHECK_COPYABLE_FIELDS = true; // disable for better verify test performance private static final boolean CHECK_COPYABLE_FIELDS = true; // disable for better verify test performance

View file

@ -51,7 +51,7 @@ public class LoseAllAbilitiesTargetEffect extends ContinuousEffectImpl {
return staticText; return staticText;
} }
return getTargetPointer().describeTargets(mode.getTargets(), "it") return getTargetPointer().describeTargets(mode.getTargets(), "it")
+ " loses all abilities " + (duration.toString().isEmpty() ? "" : ' ' + duration.toString()); + " loses all abilities" + (duration.toString().isEmpty() ? "" : ' ' + duration.toString());
} }
} }

View file

@ -2,12 +2,13 @@ package mage.game.permanent.token;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone; import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.mageobject.AnotherPredicate;
@ -16,26 +17,23 @@ import mage.filter.predicate.mageobject.AnotherPredicate;
*/ */
public final class VrenRatToken extends TokenImpl { public final class VrenRatToken extends TokenImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("other Rat you control"); private static final FilterPermanent filter = new FilterControlledPermanent(SubType.RAT, "other Rat you control");
static { static {
filter.add(SubType.RAT.getPredicate());
filter.add(AnotherPredicate.instance); filter.add(AnotherPredicate.instance);
} }
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
public VrenRatToken() { public VrenRatToken() {
super("Rat Token", "1/1 black Rat creature tokens with \"This creature gets +1/+1 for each other Rat you control\""); super("Rat Token", "1/1 black Rat creature token with \"This token gets +1/+1 for each other Rat you control.\"");
cardType.add(CardType.CREATURE); cardType.add(CardType.CREATURE);
color.setBlack(true); color.setBlack(true);
subtype.add(SubType.RAT); subtype.add(SubType.RAT);
power = new MageInt(1); power = new MageInt(1);
toughness = new MageInt(1); toughness = new MageInt(1);
this.addAbility(new SimpleStaticAbility( this.addAbility(new SimpleStaticAbility(new BoostSourceEffect(xValue, xValue, Duration.WhileOnBattlefield)));
new BoostSourceEffect(new PermanentsOnBattlefieldCount(filter),
new PermanentsOnBattlefieldCount(filter), Duration.WhileOnBattlefield
)
));
} }
private VrenRatToken(final VrenRatToken token) { private VrenRatToken(final VrenRatToken token) {

View file

@ -85,7 +85,7 @@ public final class CardUtil {
public static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS"); public static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
private static final List<String> costWords = Arrays.asList( private static final List<String> costWords = Arrays.asList(
"put", "return", "exile", "discard", "sacrifice", "remove", "tap", "reveal", "pay", "collect" "put", "return", "exile", "discard", "sacrifice", "remove", "tap", "reveal", "pay", "collect", "forage"
); );
// search set code in commands like "set_code-card_name" // search set code in commands like "set_code-card_name"