[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}"));
// 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(
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)));
// {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.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.hint.ConditionHint;
import mage.abilities.hint.Hint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.StaticFilters;
import mage.game.Controllable;
import mage.game.Game;
import mage.game.permanent.token.FishNoAbilityToken;
import mage.game.permanent.token.TreasureToken;
import mage.players.Player;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
/**
@ -28,6 +33,13 @@ import java.util.UUID;
*/
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) {
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.
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(
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(
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(
new DrawCardSourceControllerEffect(1), BezaOpponentHasMoreCardsInHandThanYouCondition.instance));
this.addAbility(ability);
new DrawCardSourceControllerEffect(1),
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) {
@ -61,22 +82,23 @@ public final class BezaTheBoundingSpring extends CardImpl {
//Based on MoreCardsInHandThanOpponentsCondition
enum BezaOpponentHasMoreCardsInHandThanYouCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
int cardsInHand = player.getHand().size();
for (UUID playerId : game.getOpponents(source.getControllerId())) {
Player opponent = game.getPlayer(playerId);
if (opponent != null && opponent.getHand().size() > cardsInHand) {
return true;
}
}
}
return false;
int cardsInHand = Optional
.ofNullable(source)
.map(Controllable::getControllerId)
.map(game::getPlayer)
.map(Player::getHand)
.map(Set::size)
.orElse(0);
return game.getOpponents(source.getControllerId())
.stream()
.map(game::getPlayer)
.map(Player::getHand)
.mapToInt(Set::size)
.anyMatch(x -> x > cardsInHand);
}
@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.
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
*/
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 {
filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, 4));

View file

@ -118,7 +118,7 @@ class ElugeTheShorelessSeaEffect extends BecomesBasicLandTargetEffect {
ElugeTheShorelessSeaEffect() {
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) {

View file

@ -16,9 +16,7 @@ import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import mage.target.targetpointer.FirstTargetPointer;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
@ -53,7 +51,7 @@ class FabledPassageSearchForLandEffect extends OneShotEffect {
FabledPassageSearchForLandEffect() {
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) {

View file

@ -1,7 +1,5 @@
package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
@ -11,24 +9,27 @@ import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.hint.common.LandsYouControlHint;
import mage.cards.Card;
import mage.constants.*;
import mage.abilities.keyword.ReachAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.ToughnessGreaterThanPowerPredicate;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
* @author Cguy7777
*/
public final class FecundGreenshell extends CardImpl {
private static final FilterCreaturePermanent filter
= new FilterCreaturePermanent("creature you control with toughness greater than its power");
private static final FilterPermanent filter
= new FilterControlledCreaturePermanent("creature you control with toughness greater than its power");
static {
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,
// 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(
new FecundGreenshellEffect(), filter, false, true));
new FecundGreenshellEffect(), filter, false, false));
}
private FecundGreenshell(final FecundGreenshell card) {

View file

@ -50,7 +50,7 @@ public final class ForTheCommonGood extends CardImpl {
IndestructibleAbility.getInstance(),
Duration.UntilYourNextTurn, StaticFilters.FILTER_PERMANENT_TOKENS
).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);
}

View file

@ -1,7 +1,10 @@
package mage.cards.g;
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.combat.CantBeBlockedTargetEffect;
import mage.abilities.effects.common.continuous.GainClassAbilitySourceEffect;
@ -10,7 +13,10 @@ import mage.abilities.keyword.ClassLevelAbility;
import mage.abilities.keyword.ClassReminderAbility;
import mage.cards.CardImpl;
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.StaticFilters;
import mage.filter.common.FilterAttackingCreature;
@ -24,7 +30,7 @@ import java.util.UUID;
*/
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 {
filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 4));
@ -59,7 +65,7 @@ public final class GossipsTalent extends CardImpl {
new DealsDamageToAPlayerAllTriggeredAbility(
new ExileThenReturnTargetEffect(false, false)
.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
)));
}

View file

@ -2,7 +2,7 @@ package mage.cards.h;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility;
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.TargetObjectMatchesFilterCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
@ -35,7 +35,7 @@ public final class HazardrootHerbalist extends CardImpl {
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.
Ability ability = new AttacksCreatureYouControlTriggeredAbility(new BoostTargetEffect(1, 0));
Ability ability = new AttacksWithCreaturesTriggeredAbility(new BoostTargetEffect(1, 0), 1);
ability.addEffect(new ConditionalOneShotEffect(
new AddContinuousEffectToGame(new GainAbilityTargetEffect(DeathtouchAbility.getInstance())),
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.
Ability ability = new SimpleActivatedAbility(new DiscardHandControllerEffect(), new ManaCostsImpl<>("{1}{R}"));
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);
}

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.
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"));
this.getSpellAbility().addTarget(new TargetPermanent(playableFilter));
this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(GiftWasPromisedCondition.TRUE,

View file

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

View file

@ -36,6 +36,7 @@ import java.util.stream.Collectors;
public final class PartingGust extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature");
static {
filter.add(TokenPredicate.FALSE);
}
@ -52,7 +53,7 @@ public final class PartingGust extends CardImpl {
new ExileTargetEffect(),
new PartingGustExileReturnEffect(),
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."
));
}

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.
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"));
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_PERMANENT));
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().addEffect(new ConditionalOneShotEffect(
new SurveilEffect(2), condition,
"then if you control a Rat, surveil 2"
"Then if you control a Rat, surveil 2"
));
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.
this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0));
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));
}

View file

@ -71,7 +71,7 @@ class RottenmouthViperEffect extends OneShotEffect{
RottenmouthViperEffect(DynamicValue blightCounterAmount) {
super(Outcome.LoseLife);
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) {

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.
this.addAbility(new AttacksTriggeredAbility(
new BoostSourceEffect(2, 0, Duration.EndOfTurn)
).withTriggerCondition(condition).addHint(hint));
).withRuleTextReplacement(false).withTriggerCondition(condition).addHint(hint));
}
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.addEffect(new ConditionalOneShotEffect(
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));
}

View file

@ -25,7 +25,7 @@ public final class Spellgyre extends CardImpl {
this.getSpellAbility().addTarget(new TargetSpell());
// * 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")));
}

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?"
)
), 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.addWatcher(new PlayerGainedLifeWatcher());

View file

@ -42,7 +42,7 @@ public final class ThornplateIntimidator extends CardImpl {
new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_NON_LAND), new DiscardCardCost()
),
"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());
this.addAbility(ability);
}

View file

@ -2,15 +2,16 @@ package mage.cards.v;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.replacement.CreaturesAreExiledOnDeathReplacementEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.WardAbility;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@ -31,6 +32,10 @@ import java.util.UUID;
*/
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) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{B}");
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
// other Rat you control," where X is the number of creatures your opponents controlled that were exiled this turn.
this.addAbility(new BeginningOfEndStepTriggeredAbility(
TargetController.ANY, new CreateTokenEffect(new VrenRatToken(), VrenTheRelentlessCount.instance)
.setText("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"),
false
).addHint(new ValueHint("Creatures exiled under opponents' control this turn", VrenTheRelentlessCount.instance)), new VrenTheRelentlessWatcher());
TargetController.ANY, new CreateTokenEffect(new VrenRatToken(), VrenTheRelentlessCount.instance), false
).addHint(hint), new VrenTheRelentlessWatcher());
}
private VrenTheRelentless(final VrenTheRelentless card) {
@ -72,7 +74,7 @@ enum VrenTheRelentlessCount implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
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
@ -80,9 +82,14 @@ enum VrenTheRelentlessCount implements DynamicValue {
return instance;
}
@Override
public String toString() {
return "X";
}
@Override
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;
}
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);
}
}
@ -111,10 +120,11 @@ class VrenTheRelentlessWatcher extends Watcher {
super.reset();
}
int getCount(UUID playerId) {
return playerMap.entrySet().stream()
.filter(entry -> !entry.getKey().equals(playerId))
.mapToInt(Map.Entry::getValue)
int getCount(UUID playerId, Game game) {
return game
.getOpponents(playerId)
.stream()
.mapToInt(uuid -> playerMap.getOrDefault(uuid, 0))
.sum();
}
}

View file

@ -75,7 +75,7 @@ public class VerifyCardDataTest {
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_COPYABLE_FIELDS = true; // disable for better verify test performance

View file

@ -51,7 +51,7 @@ public class LoseAllAbilitiesTargetEffect extends ContinuousEffectImpl {
return staticText;
}
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.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
@ -16,26 +17,23 @@ import mage.filter.predicate.mageobject.AnotherPredicate;
*/
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 {
filter.add(SubType.RAT.getPredicate());
filter.add(AnotherPredicate.instance);
}
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
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);
color.setBlack(true);
subtype.add(SubType.RAT);
power = new MageInt(1);
toughness = new MageInt(1);
this.addAbility(new SimpleStaticAbility(
new BoostSourceEffect(new PermanentsOnBattlefieldCount(filter),
new PermanentsOnBattlefieldCount(filter), Duration.WhileOnBattlefield
)
));
this.addAbility(new SimpleStaticAbility(new BoostSourceEffect(xValue, xValue, Duration.WhileOnBattlefield)));
}
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");
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"