From f285d5edba6da2f34f7f45fd46b3e6dd6e01f2ed Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 11 Jul 2025 10:53:24 -0400 Subject: [PATCH] [EOE] Implement Fungal Colossus --- .../mage/cards/a/AudienceWithTrostani.java | 68 ++++-------------- .../src/mage/cards/a/AwakenedAmalgam.java | 53 +++----------- .../src/mage/cards/f/FieldOfTheDead.java | 24 +++---- .../src/mage/cards/f/FungalColossus.java | 45 ++++++++++++ .../mage/cards/g/GimbalGremlinProdigy.java | 42 +++++------ .../src/mage/cards/l/LilianasContract.java | 30 ++++---- .../mage/cards/n/NerivCracklingVanguard.java | 71 ++++++++----------- .../src/mage/cards/s/SandsteppeWarRiders.java | 61 +++------------- Mage.Sets/src/mage/cards/t/TheNecrobloom.java | 28 ++++---- Mage.Sets/src/mage/sets/EdgeOfEternities.java | 1 + .../DifferentlyNamedPermanentCount.java | 61 ++++++++++++++++ 11 files changed, 229 insertions(+), 255 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/f/FungalColossus.java create mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/DifferentlyNamedPermanentCount.java diff --git a/Mage.Sets/src/mage/cards/a/AudienceWithTrostani.java b/Mage.Sets/src/mage/cards/a/AudienceWithTrostani.java index ad9aa3dcaea..39b46b05a0d 100644 --- a/Mage.Sets/src/mage/cards/a/AudienceWithTrostani.java +++ b/Mage.Sets/src/mage/cards/a/AudienceWithTrostani.java @@ -1,19 +1,14 @@ package mage.cards.a; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.DifferentlyNamedPermanentCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.PermanentToken; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.TokenPredicate; import mage.game.permanent.token.PlantToken; import java.util.UUID; @@ -23,14 +18,22 @@ import java.util.UUID; */ public final class AudienceWithTrostani extends CardImpl { + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("creature tokens you control"); + + static { + filter.add(TokenPredicate.TRUE); + } + + private static final DifferentlyNamedPermanentCount xValue = new DifferentlyNamedPermanentCount(filter); + public AudienceWithTrostani(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); // Create a 0/1 green Plant creature token, then draw cards equal to the number of differently named creature tokens you control. this.getSpellAbility().addEffect(new CreateTokenEffect(new PlantToken())); - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(AudienceWithTrostaniValue.instance) + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(xValue) .setText(", then draw cards equal to the number of differently named creature tokens you control")); - this.getSpellAbility().addHint(AudienceWithTrostaniValue.getHint()); + this.getSpellAbility().addHint(xValue.getHint()); } private AudienceWithTrostani(final AudienceWithTrostani card) { @@ -42,46 +45,3 @@ public final class AudienceWithTrostani extends CardImpl { return new AudienceWithTrostani(this); } } - -enum AudienceWithTrostaniValue implements DynamicValue { - instance; - private static final Hint hint = new ValueHint( - "Different names among creature tokens you control", instance - ); - - public static Hint getHint() { - return hint; - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents( - StaticFilters.FILTER_CONTROLLED_CREATURE, - sourceAbility.getControllerId(), sourceAbility, game - ) - .stream() - .filter(PermanentToken.class::isInstance) - .map(MageObject::getName) - .filter(s -> !s.isEmpty()) - .distinct() - .mapToInt(x -> 1) - .sum(); - } - - @Override - public AudienceWithTrostaniValue copy() { - return this; - } - - @Override - public String getMessage() { - return ""; - } - - @Override - public String toString() { - return "1"; - } -} diff --git a/Mage.Sets/src/mage/cards/a/AwakenedAmalgam.java b/Mage.Sets/src/mage/cards/a/AwakenedAmalgam.java index 9a2accffcf6..e96bc37e198 100644 --- a/Mage.Sets/src/mage/cards/a/AwakenedAmalgam.java +++ b/Mage.Sets/src/mage/cards/a/AwakenedAmalgam.java @@ -1,29 +1,25 @@ - package mage.cards.a; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.DifferentlyNamedPermanentCount; import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class AwakenedAmalgam extends CardImpl { + private static final DifferentlyNamedPermanentCount xValue = new DifferentlyNamedPermanentCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_LANDS); + public AwakenedAmalgam(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); @@ -32,8 +28,9 @@ public final class AwakenedAmalgam extends CardImpl { this.toughness = new MageInt(0); // Awakened Amalgam's power and toughness are each equal to the number of differently named lands you control. - DynamicValue value = (new AwakenedAmalgamLandNamesCount()); - this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessSourceEffect(value))); + this.addAbility(new SimpleStaticAbility( + Zone.ALL, new SetBasePowerToughnessSourceEffect(xValue) + ).addHint(xValue.getHint())); } private AwakenedAmalgam(final AwakenedAmalgam card) { @@ -45,35 +42,3 @@ public final class AwakenedAmalgam extends CardImpl { return new AwakenedAmalgam(this); } } - -class AwakenedAmalgamLandNamesCount implements DynamicValue { - - public AwakenedAmalgamLandNamesCount() { - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - Set landNames = new HashSet<>(); - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(sourceAbility.getControllerId())) { - if (permanent.isLand(game)) { - landNames.add(permanent.getName()); - } - } - return landNames.size(); - } - - @Override - public AwakenedAmalgamLandNamesCount copy() { - return this; - } - - @Override - public String toString() { - return "1"; - } - - @Override - public String getMessage() { - return "differently named lands you control"; - } -} diff --git a/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java b/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java index 448e161a1ad..652eed8372c 100644 --- a/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java +++ b/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java @@ -4,7 +4,9 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility; import mage.abilities.condition.Condition; +import mage.abilities.dynamicvalue.common.DifferentlyNamedPermanentCount; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.hint.Hint; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -12,7 +14,6 @@ import mage.constants.CardType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.token.ZombieToken; -import mage.players.Player; import java.util.UUID; @@ -33,7 +34,7 @@ public final class FieldOfTheDead extends CardImpl { // Whenever Field of the Dead or another land you control enters, if you control seven or more lands with different names, create a 2/2 black Zombie creature token. this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility( new CreateTokenEffect(new ZombieToken()), StaticFilters.FILTER_LAND, false, true - ).withInterveningIf(FieldOfTheDeadCondition.instance)); + ).withInterveningIf(FieldOfTheDeadCondition.instance).addHint(FieldOfTheDeadCondition.getHint())); } private FieldOfTheDead(final FieldOfTheDead card) { @@ -49,20 +50,15 @@ public final class FieldOfTheDead extends CardImpl { enum FieldOfTheDeadCondition implements Condition { instance; + private static final DifferentlyNamedPermanentCount xValue = new DifferentlyNamedPermanentCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_LANDS); + + static Hint getHint() { + return xValue.getHint(); + } + @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { - return false; - } - return game - .getBattlefield() - .getAllActivePermanents(StaticFilters.FILTER_LAND, source.getControllerId(), game) - .stream() - .map(permanent -> permanent.getName()) - .filter(s -> s.length() > 0) - .distinct() - .count() > 6; + return xValue.calculate(game, source, null) >= 7; } @Override diff --git a/Mage.Sets/src/mage/cards/f/FungalColossus.java b/Mage.Sets/src/mage/cards/f/FungalColossus.java new file mode 100644 index 00000000000..03bce5fa5fe --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FungalColossus.java @@ -0,0 +1,45 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.DifferentlyNamedPermanentCount; +import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FungalColossus extends CardImpl { + + private static final DifferentlyNamedPermanentCount xValue = new DifferentlyNamedPermanentCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_LANDS); + + public FungalColossus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{G}"); + + this.subtype.add(SubType.FUNGUS); + this.subtype.add(SubType.BEAST); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // This spell costs {X} less to cast, where X is the number of differently named lands you control. + this.addAbility(new SimpleStaticAbility( + Zone.ALL, new SpellCostReductionSourceEffect(xValue) + ).addHint(xValue.getHint()).setRuleAtTheTop(true)); + } + + private FungalColossus(final FungalColossus card) { + super(card); + } + + @Override + public FungalColossus copy() { + return new FungalColossus(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GimbalGremlinProdigy.java b/Mage.Sets/src/mage/cards/g/GimbalGremlinProdigy.java index c15322785a5..44deb8cfc66 100644 --- a/Mage.Sets/src/mage/cards/g/GimbalGremlinProdigy.java +++ b/Mage.Sets/src/mage/cards/g/GimbalGremlinProdigy.java @@ -1,25 +1,27 @@ package mage.cards.g; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.DifferentlyNamedPermanentCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.hint.Hint; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentToken; import mage.game.permanent.token.GremlinArtifactToken; import mage.game.permanent.token.Token; -import java.util.Objects; import java.util.UUID; /** @@ -43,9 +45,8 @@ public final class GimbalGremlinProdigy extends CardImpl { ))); // At the beginning of your end step, create a 0/0 red Gremlin artifact creature token. Put X +1/+1 counters on it, where X is the number of differently named artifact tokens you control. - this.addAbility(new BeginningOfEndStepTriggeredAbility( - new GimbalGremlinProdigyEffect() - )); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new GimbalGremlinProdigyEffect()) + .addHint(GimbalGremlinProdigyEffect.getHint())); } private GimbalGremlinProdigy(final GimbalGremlinProdigy card) { @@ -60,6 +61,18 @@ public final class GimbalGremlinProdigy extends CardImpl { class GimbalGremlinProdigyEffect extends OneShotEffect { + private static final FilterPermanent filter = new FilterControlledArtifactPermanent("artifact tokens you control"); + + static { + filter.add(TokenPredicate.TRUE); + } + + private static final DifferentlyNamedPermanentCount xValue = new DifferentlyNamedPermanentCount(filter); + + static final Hint getHint() { + return xValue.getHint(); + } + GimbalGremlinProdigyEffect() { super(Outcome.Benefit); staticText = "create a 0/0 red Gremlin artifact creature token. Put X +1/+1 counters on it, " + @@ -79,20 +92,7 @@ class GimbalGremlinProdigyEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Token token = new GremlinArtifactToken(); token.putOntoBattlefield(1, game, source); - int amount = game - .getBattlefield() - .getActivePermanents( - StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, - source.getControllerId(), source, game - ) - .stream() - .filter(PermanentToken.class::isInstance) - .map(MageObject::getName) - .filter(Objects::nonNull) - .filter(s -> !s.isEmpty()) - .distinct() - .mapToInt(i -> 1) - .sum(); + int amount = xValue.calculate(game, source, this); for (UUID tokenId : token.getLastAddedTokenIds()) { Permanent permanent = game.getPermanent(tokenId); if (permanent != null) { diff --git a/Mage.Sets/src/mage/cards/l/LilianasContract.java b/Mage.Sets/src/mage/cards/l/LilianasContract.java index 77f572540c3..be8b6ba2e5e 100644 --- a/Mage.Sets/src/mage/cards/l/LilianasContract.java +++ b/Mage.Sets/src/mage/cards/l/LilianasContract.java @@ -3,19 +3,19 @@ package mage.cards.l; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; +import mage.abilities.dynamicvalue.common.DifferentlyNamedPermanentCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.abilities.hint.Hint; import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.filter.common.FilterControlledPermanent; import mage.game.Game; -import mage.game.permanent.Permanent; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; /** @@ -33,7 +33,7 @@ public final class LilianasContract extends CardImpl { // At the beginning of your upkeep, if you control four or more Demons with different names, you win the game. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()) - .withInterveningIf(LilianasContractCondition.instance)); + .withInterveningIf(LilianasContractCondition.instance).addHint(LilianasContractCondition.getHint())); } private LilianasContract(final LilianasContract card) { @@ -47,24 +47,18 @@ public final class LilianasContract extends CardImpl { } enum LilianasContractCondition implements Condition { - instance; + private static final DifferentlyNamedPermanentCount xValue = new DifferentlyNamedPermanentCount( + new FilterControlledPermanent(SubType.DEMON, "Demons you control") + ); + + static Hint getHint() { + return xValue.getHint(); + } @Override public boolean apply(Game game, Ability source) { - Set demonNames = new HashSet<>(); - for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { - if (permanent == null - || !permanent.isControlledBy(source.getControllerId()) - || !permanent.hasSubtype(SubType.DEMON, game)) { - continue; - } - demonNames.add(permanent.getName()); - if (demonNames.size() > 3) { - return true; - } - } - return false; + return xValue.calculate(game, source, null) >= 4; } @Override diff --git a/Mage.Sets/src/mage/cards/n/NerivCracklingVanguard.java b/Mage.Sets/src/mage/cards/n/NerivCracklingVanguard.java index 75b317b9e1c..bfcaf621f89 100644 --- a/Mage.Sets/src/mage/cards/n/NerivCracklingVanguard.java +++ b/Mage.Sets/src/mage/cards/n/NerivCracklingVanguard.java @@ -1,45 +1,46 @@ package mage.cards.n; -import java.util.*; -import java.util.stream.Collectors; - import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.decorator.ConditionalAsThoughEffect; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.DifferentlyNamedPermanentCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; -import mage.cards.Card; -import mage.cards.Cards; -import mage.constants.*; -import mage.abilities.keyword.FlyingAbility; +import mage.abilities.hint.Hint; import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; -import mage.game.permanent.PermanentToken; import mage.game.permanent.token.GoblinToken; import mage.players.Player; import mage.target.targetpointer.FixedTargets; import mage.util.CardUtil; import mage.watchers.common.AttackedThisTurnWatcher; +import java.util.Collection; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + /** - * * @author Jmlundeen */ public final class NerivCracklingVanguard extends CardImpl { public NerivCracklingVanguard(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{W}{B}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.SPIRIT); this.subtype.add(SubType.DRAGON); @@ -56,7 +57,7 @@ public final class NerivCracklingVanguard extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new GoblinToken(false), 2))); // Whenever Neriv attacks, exile a number of cards from the top of your library equal to the number of differently named tokens you control. During any turn you attacked with a commander, you may play those cards. - this.addAbility(new AttacksTriggeredAbility(new NerivCracklingVanguardEffect())); + this.addAbility(new AttacksTriggeredAbility(new NerivCracklingVanguardEffect()).addHint(NerivCracklingVanguardEffect.getHint())); } private NerivCracklingVanguard(final NerivCracklingVanguard card) { @@ -71,6 +72,18 @@ public final class NerivCracklingVanguard extends CardImpl { class NerivCracklingVanguardEffect extends OneShotEffect { + private static final FilterPermanent filter = new FilterControlledPermanent("tokens you control"); + + static { + filter.add(TokenPredicate.TRUE); + } + + private static final DifferentlyNamedPermanentCount xValue = new DifferentlyNamedPermanentCount(filter); + + static final Hint getHint() { + return xValue.getHint(); + } + NerivCracklingVanguardEffect() { super(Outcome.Benefit); staticText = "exile a number of cards from the top of your library equal to the number of " + @@ -89,7 +102,7 @@ class NerivCracklingVanguardEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - int tokenNameCount = NerivDynamicValue.instance.calculate(game, source, this); + int tokenNameCount = xValue.calculate(game, source, this); if (controller == null || tokenNameCount == 0) { return false; } @@ -111,30 +124,6 @@ class NerivCracklingVanguardEffect extends OneShotEffect { } } -enum NerivDynamicValue implements DynamicValue { - instance; - - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return (int) game.getBattlefield().getAllActivePermanents(sourceAbility.getControllerId()).stream() - .filter(permanent -> permanent instanceof PermanentToken) - .map(MageObject::getName) - .distinct() - .count(); - } - - @Override - public DynamicValue copy() { - return instance; - } - - @Override - public String getMessage() { - return "X"; - } -} - class CommanderAttackedThisTurnCondition implements Condition { private Ability ability; @@ -177,4 +166,4 @@ class CommanderAttackedThisTurnCondition implements Condition { public String toString() { return "During that turn you attacked with a Commander"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SandsteppeWarRiders.java b/Mage.Sets/src/mage/cards/s/SandsteppeWarRiders.java index 8f18224eb1c..b7ea5a082bd 100644 --- a/Mage.Sets/src/mage/cards/s/SandsteppeWarRiders.java +++ b/Mage.Sets/src/mage/cards/s/SandsteppeWarRiders.java @@ -1,15 +1,10 @@ package mage.cards.s; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.DifferentlyNamedPermanentCount; import mage.abilities.effects.keyword.BolsterEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -17,9 +12,7 @@ import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledArtifactPermanent; import mage.filter.predicate.permanent.TokenPredicate; -import mage.game.Game; -import java.util.Objects; import java.util.UUID; /** @@ -27,6 +20,14 @@ import java.util.UUID; */ public final class SandsteppeWarRiders extends CardImpl { + private static final FilterPermanent filter = new FilterControlledArtifactPermanent("artifact tokens you control"); + + static { + filter.add(TokenPredicate.TRUE); + } + + private static final DifferentlyNamedPermanentCount xValue = new DifferentlyNamedPermanentCount(filter); + public SandsteppeWarRiders(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); @@ -39,7 +40,7 @@ public final class SandsteppeWarRiders extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // At the beginning of combat on your turn, bolster X, where X is the number of differently named artifact tokens you control. - this.addAbility(new BeginningOfCombatTriggeredAbility(new BolsterEffect(SandsteppeWarRidersValue.instance))); + this.addAbility(new BeginningOfCombatTriggeredAbility(new BolsterEffect(xValue)).addHint(xValue.getHint())); } private SandsteppeWarRiders(final SandsteppeWarRiders card) { @@ -51,43 +52,3 @@ public final class SandsteppeWarRiders extends CardImpl { return new SandsteppeWarRiders(this); } } - -enum SandsteppeWarRidersValue implements DynamicValue { - instance; - private static final FilterPermanent filter = new FilterControlledArtifactPermanent(); - - static { - filter.add(TokenPredicate.TRUE); - } - - private static final Hint hint = new ValueHint("Different artifact token names you control", instance); - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents(filter, sourceAbility.getControllerId(), sourceAbility, game) - .stream() - .map(MageObject::getName) - .filter(Objects::nonNull) - .filter(s -> !s.isEmpty()) - .distinct() - .mapToInt(x -> 1) - .sum(); - } - - @Override - public SandsteppeWarRidersValue copy() { - return this; - } - - @Override - public String getMessage() { - return "differently named artifact tokens you control"; - } - - @Override - public String toString() { - return "X"; - } -} diff --git a/Mage.Sets/src/mage/cards/t/TheNecrobloom.java b/Mage.Sets/src/mage/cards/t/TheNecrobloom.java index d281200b1a6..6fc32e607fd 100644 --- a/Mage.Sets/src/mage/cards/t/TheNecrobloom.java +++ b/Mage.Sets/src/mage/cards/t/TheNecrobloom.java @@ -6,8 +6,10 @@ import mage.abilities.common.LandfallAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.DifferentlyNamedPermanentCount; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.hint.Hint; import mage.abilities.keyword.DredgeAbility; import mage.cards.Card; import mage.cards.CardImpl; @@ -42,7 +44,7 @@ public final class TheNecrobloom extends CardImpl { new CreateTokenEffect(new PlantToken()), TheNecrobloomCondition.instance, "create a 0/1 green Plant creature token. If you control " + "seven or more lands with different names, create a 2/2 black Zombie creature token instead" - ))); + )).addHint(TheNecrobloomCondition.getHint())); // Land cards in your graveyard have dredge 2. this.addAbility(new SimpleStaticAbility(new TheNecrobloomDredgeEffect())); @@ -61,20 +63,20 @@ public final class TheNecrobloom extends CardImpl { enum TheNecrobloomCondition implements Condition { instance; + private static final DifferentlyNamedPermanentCount xValue = new DifferentlyNamedPermanentCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_LANDS); + + static Hint getHint() { + return xValue.getHint(); + } + @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { - return false; - } - return game - .getBattlefield() - .getAllActivePermanents(StaticFilters.FILTER_LAND, source.getControllerId(), game) - .stream() - .map(permanent -> permanent.getName()) - .filter(s -> s.length() > 0) - .distinct() - .count() > 6; + return xValue.calculate(game, source, null) >= 7; + } + + @Override + public String toString() { + return "you control seven or more lands with different names"; } } diff --git a/Mage.Sets/src/mage/sets/EdgeOfEternities.java b/Mage.Sets/src/mage/sets/EdgeOfEternities.java index 376cc3854dd..17a9d97f96c 100644 --- a/Mage.Sets/src/mage/sets/EdgeOfEternities.java +++ b/Mage.Sets/src/mage/sets/EdgeOfEternities.java @@ -84,6 +84,7 @@ public final class EdgeOfEternities extends ExpansionSet { cards.add(new SetCardInfo("Forest", 371, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Frenzied Baloth", 183, Rarity.RARE, mage.cards.f.FrenziedBaloth.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Frenzied Baloth", 342, Rarity.RARE, mage.cards.f.FrenziedBaloth.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fungal Colossus", 184, Rarity.COMMON, mage.cards.f.FungalColossus.class)); cards.add(new SetCardInfo("Galactic Wayfarer", 185, Rarity.COMMON, mage.cards.g.GalacticWayfarer.class)); cards.add(new SetCardInfo("Galvanizing Sawship", 136, Rarity.UNCOMMON, mage.cards.g.GalvanizingSawship.class)); cards.add(new SetCardInfo("Genemorph Imago", 217, Rarity.RARE, mage.cards.g.GenemorphImago.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/DifferentlyNamedPermanentCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/DifferentlyNamedPermanentCount.java new file mode 100644 index 00000000000..5d3a5cf4eb1 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/DifferentlyNamedPermanentCount.java @@ -0,0 +1,61 @@ +package mage.abilities.dynamicvalue.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.filter.FilterPermanent; +import mage.game.Game; + +/** + * @author TheElk801 + */ +public class DifferentlyNamedPermanentCount implements DynamicValue { + + private final FilterPermanent filter; + private final Hint hint; + + public DifferentlyNamedPermanentCount(FilterPermanent filter) { + this.filter = filter; + this.hint = new ValueHint("Differently named " + filter.getMessage(), this); + } + + private DifferentlyNamedPermanentCount(final DifferentlyNamedPermanentCount dynamicValue) { + this.filter = dynamicValue.filter; + this.hint = dynamicValue.hint; + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return game + .getBattlefield() + .getActivePermanents(filter, sourceAbility.getControllerId(), sourceAbility, game) + .stream() + .map(MageObject::getName) + .filter(s -> !s.isEmpty()) + .distinct() + .mapToInt(x -> 1) + .sum(); + } + + @Override + public DifferentlyNamedPermanentCount copy() { + return new DifferentlyNamedPermanentCount(this); + } + + @Override + public String getMessage() { + return "differently named " + filter.getMessage(); + } + + @Override + public String toString() { + return "X"; + } + + public Hint getHint() { + return hint; + } +}