From 34c4eebd445e07f02b5fb5c7f46748a1b7310cd3 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 14 May 2025 21:59:11 -0400 Subject: [PATCH] [FIN] Implement Sahagin --- .../mage/cards/b/BoromirWardenOfTheTower.java | 19 ++++---- .../mage/cards/l/LaviniaAzoriusRenegade.java | 13 ++--- .../src/mage/cards/m/MarchOfTheWorldOoze.java | 35 +++++++------- .../mage/cards/r/RaggadraggaGoregutsBoss.java | 20 ++------ Mage.Sets/src/mage/cards/s/Sahagin.java | 48 +++++++++++++++++++ Mage.Sets/src/mage/cards/v/VexingBauble.java | 18 +++---- Mage.Sets/src/mage/sets/FinalFantasy.java | 1 + ...stOpponentNoManaSpentTriggeredAbility.java | 48 ------------------- .../main/java/mage/filter/StaticFilters.java | 20 ++++++-- .../mageobject/ManaSpentToCastPredicate.java | 25 ++++++++++ 10 files changed, 138 insertions(+), 109 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/s/Sahagin.java delete mode 100644 Mage/src/main/java/mage/abilities/common/SpellCastOpponentNoManaSpentTriggeredAbility.java create mode 100644 Mage/src/main/java/mage/filter/predicate/mageobject/ManaSpentToCastPredicate.java diff --git a/Mage.Sets/src/mage/cards/b/BoromirWardenOfTheTower.java b/Mage.Sets/src/mage/cards/b/BoromirWardenOfTheTower.java index f902918bb4d..d76f59ad088 100644 --- a/Mage.Sets/src/mage/cards/b/BoromirWardenOfTheTower.java +++ b/Mage.Sets/src/mage/cards/b/BoromirWardenOfTheTower.java @@ -3,7 +3,7 @@ package mage.cards.b; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.common.SpellCastOpponentNoManaSpentTriggeredAbility; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.effects.common.CounterTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; @@ -12,23 +12,19 @@ import mage.abilities.keyword.IndestructibleAbility; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.SubType; -import mage.constants.SuperType; +import mage.constants.*; import mage.filter.StaticFilters; import java.util.UUID; /** - * * @author Susucr */ public final class BoromirWardenOfTheTower extends CardImpl { public BoromirWardenOfTheTower(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); @@ -39,12 +35,15 @@ public final class BoromirWardenOfTheTower extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // Whenever an opponent casts a spell, if no mana was spent to cast it, counter that spell. - this.addAbility(new SpellCastOpponentNoManaSpentTriggeredAbility(new CounterTargetEffect().setText("counter that spell"))); + this.addAbility(new SpellCastOpponentTriggeredAbility( + Zone.BATTLEFIELD, new CounterTargetEffect(), + StaticFilters.FILTER_SPELL_NO_MANA_SPENT, false, true + )); // Sacrifice Boromir, Warden of the Tower: Creatures you control gain indestructible until end of turn. The Ring tempts you. Ability ability = new SimpleActivatedAbility(new GainAbilityAllEffect( - IndestructibleAbility.getInstance(), Duration.EndOfTurn, - StaticFilters.FILTER_CONTROLLED_CREATURES, false + IndestructibleAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_CONTROLLED_CREATURES, false ), new SacrificeSourceCost()); ability.addEffect(new TheRingTemptsYouEffect()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/l/LaviniaAzoriusRenegade.java b/Mage.Sets/src/mage/cards/l/LaviniaAzoriusRenegade.java index 5820d24f257..5dd5ac6e8d5 100644 --- a/Mage.Sets/src/mage/cards/l/LaviniaAzoriusRenegade.java +++ b/Mage.Sets/src/mage/cards/l/LaviniaAzoriusRenegade.java @@ -1,11 +1,10 @@ - package mage.cards.l; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.common.SpellCastOpponentNoManaSpentTriggeredAbility; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.common.CounterTargetEffect; import mage.cards.Card; @@ -24,13 +23,12 @@ import java.util.List; import java.util.UUID; /** - * * @author NinthWorld */ public final class LaviniaAzoriusRenegade extends CardImpl { public LaviniaAzoriusRenegade(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{U}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); this.supertype.add(SuperType.LEGENDARY); @@ -42,7 +40,10 @@ public final class LaviniaAzoriusRenegade extends CardImpl { this.addAbility(new SimpleStaticAbility(new LaviniaAzoriusRenegadeReplacementEffect())); // Whenever an opponent casts a spell, if no mana was spent to cast it, counter that spell. - this.addAbility(new SpellCastOpponentNoManaSpentTriggeredAbility(new CounterTargetEffect().setText("counter that spell"))); + this.addAbility(new SpellCastOpponentTriggeredAbility( + Zone.BATTLEFIELD, new CounterTargetEffect(), + StaticFilters.FILTER_SPELL_NO_MANA_SPENT, false, true + )); } private LaviniaAzoriusRenegade(final LaviniaAzoriusRenegade card) { @@ -96,7 +97,7 @@ class LaviniaAzoriusRenegadeReplacementEffect extends ContinuousRuleModifyingEff private int getLandCount(Ability source, GameEvent event, Game game) { int landCount = 0; UUID playerId = event.getPlayerId(); - if(playerId != null) { + if (playerId != null) { List permanents = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LAND, playerId, source, game); for (Permanent permanent : permanents) { if (permanent.isControlledBy(playerId)) { diff --git a/Mage.Sets/src/mage/cards/m/MarchOfTheWorldOoze.java b/Mage.Sets/src/mage/cards/m/MarchOfTheWorldOoze.java index 7cb1ae1f446..44328e1b21f 100644 --- a/Mage.Sets/src/mage/cards/m/MarchOfTheWorldOoze.java +++ b/Mage.Sets/src/mage/cards/m/MarchOfTheWorldOoze.java @@ -1,49 +1,52 @@ package mage.cards.m; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.common.SpellCastOpponentNoManaSpentTriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.OnOpponentsTurnCondition; -import mage.abilities.effects.common.CastSourceTriggeredAbility; -import mage.abilities.effects.common.CreateTokenAllEffect; -import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.AddCardSubtypeAllEffect; import mage.abilities.effects.common.continuous.SetBasePowerToughnessAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.TargetController; import mage.filter.FilterSpell; import mage.filter.StaticFilters; import mage.game.permanent.token.ElephantToken; +import java.util.UUID; + /** - * * @author Jmlundeen */ public final class MarchOfTheWorldOoze extends CardImpl { + public static final FilterSpell filter = new FilterSpell("a spell, if it's not their turn"); static { filter.add(TargetController.INACTIVE.getControllerPredicate()); } + public MarchOfTheWorldOoze(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}{G}{G}"); - // Creatures you control have base power and toughness 6/6 and are Oozes in addition to their other types. Ability ability = new SimpleStaticAbility(new SetBasePowerToughnessAllEffect( - 6, 6, Duration.WhileOnBattlefield, StaticFilters.FILTER_CONTROLLED_CREATURE)); - ability.addEffect(new AddCardSubtypeAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE, SubType.OOZE, null) - .concatBy("and")); + 6, 6, Duration.WhileOnBattlefield, StaticFilters.FILTER_CONTROLLED_CREATURE + )); + ability.addEffect(new AddCardSubtypeAllEffect( + StaticFilters.FILTER_CONTROLLED_CREATURE, SubType.OOZE, null + ).concatBy("and")); this.addAbility(ability); + // Whenever an opponent casts a spell, if it's not their turn, you create a 3/3 green Elephant creature token. - Ability ability2 = new SpellCastOpponentTriggeredAbility(new CreateTokenEffect(new ElephantToken()) - .setText("you create a 3/3 green Elephant creature token"), - filter, false); + Ability ability2 = new SpellCastOpponentTriggeredAbility( + new CreateTokenEffect(new ElephantToken()) + .setText("you create a 3/3 green Elephant creature token"), + filter, false + ); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/r/RaggadraggaGoregutsBoss.java b/Mage.Sets/src/mage/cards/r/RaggadraggaGoregutsBoss.java index fc6afae7fc0..8f6d8d56b4c 100644 --- a/Mage.Sets/src/mage/cards/r/RaggadraggaGoregutsBoss.java +++ b/Mage.Sets/src/mage/cards/r/RaggadraggaGoregutsBoss.java @@ -17,11 +17,10 @@ import mage.constants.*; import mage.filter.FilterSpell; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicate; +import mage.filter.predicate.mageobject.ManaSpentToCastPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.stack.StackObject; import mage.target.common.TargetCreaturePermanent; -import mage.watchers.common.ManaPaidSourceWatcher; import java.util.UUID; @@ -32,12 +31,12 @@ public final class RaggadraggaGoregutsBoss extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you control with a mana ability"); - private static final FilterSpell filter2 = new FilterSpell(); + private static final FilterSpell filter2 = new FilterSpell("a spell, if at least seven mana was spent to cast it"); static { filter.add(TargetController.YOU.getOwnerPredicate()); filter.add(RaggadraggaGoregutsBossCreaturePredicate.instance); - filter2.add(RaggadraggaGoregutsBossSpellPredicate.instance); + filter2.add(new ManaSpentToCastPredicate(ComparisonType.MORE_THAN, 6)); } public RaggadraggaGoregutsBoss(UUID ownerId, CardSetInfo setInfo) { @@ -61,9 +60,7 @@ public final class RaggadraggaGoregutsBoss extends CardImpl { )); // Whenever you cast a spell, if at least seven mana was spent to cast it, untap target creature. It gets +7/+7 and gains trample until end of turn. - Ability ability = new SpellCastControllerTriggeredAbility( - new UntapTargetEffect(), filter2, false - ).setTriggerPhrase("Whenever you cast a spell, if at least seven mana was spent to cast it, "); + Ability ability = new SpellCastControllerTriggeredAbility(new UntapTargetEffect(), filter2, false); ability.addEffect(new BoostTargetEffect(7, 7).setText("It gets +7/+7")); ability.addEffect(new GainAbilityTargetEffect( TrampleAbility.getInstance(), Duration.EndOfTurn @@ -90,12 +87,3 @@ enum RaggadraggaGoregutsBossCreaturePredicate implements Predicate { return input.getAbilities(game).stream().anyMatch(ManaAbility.class::isInstance); } } - -enum RaggadraggaGoregutsBossSpellPredicate implements Predicate { - instance; - - @Override - public boolean apply(StackObject input, Game game) { - return ManaPaidSourceWatcher.getTotalPaid(input.getId(), game) >= 7; - } -} diff --git a/Mage.Sets/src/mage/cards/s/Sahagin.java b/Mage.Sets/src/mage/cards/s/Sahagin.java new file mode 100644 index 00000000000..95f145ce811 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/Sahagin.java @@ -0,0 +1,48 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Sahagin extends CardImpl { + + public Sahagin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.MERFOLK); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Whenever you cast a noncreature spell, if at least four mana was spent to cast it, put a +1/+1 counter on this creature and it can't be blocked this turn. + Ability ability = new SpellCastControllerTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), + StaticFilters.FILTER_NONCREATURE_SPELL_FOUR_MANA_SPENT, false + ); + ability.addEffect(new CantBeBlockedSourceEffect(Duration.EndOfTurn).setText("and it can't be blocked this turn")); + this.addAbility(ability); + } + + private Sahagin(final Sahagin card) { + super(card); + } + + @Override + public Sahagin copy() { + return new Sahagin(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VexingBauble.java b/Mage.Sets/src/mage/cards/v/VexingBauble.java index 276328d321d..bfa2e028493 100644 --- a/Mage.Sets/src/mage/cards/v/VexingBauble.java +++ b/Mage.Sets/src/mage/cards/v/VexingBauble.java @@ -1,10 +1,8 @@ package mage.cards.v; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.common.SpellCastNoManaSpentTriggeredAbility; +import mage.abilities.common.SpellCastAllTriggeredAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; @@ -13,20 +11,23 @@ import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.SetTargetPointer; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author grimreap124 */ public final class VexingBauble extends CardImpl { public VexingBauble(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[] { CardType.ARTIFACT }, "{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); // Whenever a player casts a spell, if no mana was spent to cast it, counter that spell. - this.addAbility(new SpellCastNoManaSpentTriggeredAbility( - new CounterTargetEffect().setText("counter that spell"))); + this.addAbility(new SpellCastAllTriggeredAbility( + new CounterTargetEffect(), StaticFilters.FILTER_SPELL_NO_MANA_SPENT, false, SetTargetPointer.SPELL + )); // {1}, {T}, Sacrifice Vexing Bauble: Draw a card. Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), @@ -34,7 +35,6 @@ public final class VexingBauble extends CardImpl { ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); - ; } private VexingBauble(final VexingBauble card) { diff --git a/Mage.Sets/src/mage/sets/FinalFantasy.java b/Mage.Sets/src/mage/sets/FinalFantasy.java index caa70bf10ea..b8b48586f99 100644 --- a/Mage.Sets/src/mage/sets/FinalFantasy.java +++ b/Mage.Sets/src/mage/sets/FinalFantasy.java @@ -180,6 +180,7 @@ public final class FinalFantasy extends ExpansionSet { cards.add(new SetCardInfo("Rosa, Resolute White Mage", 555, Rarity.RARE, mage.cards.r.RosaResoluteWhiteMage.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sage's Nouliths", 582, Rarity.COMMON, mage.cards.s.SagesNouliths.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sage's Nouliths", 70, Rarity.COMMON, mage.cards.s.SagesNouliths.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sahagin", 71, Rarity.COMMON, mage.cards.s.Sahagin.class)); cards.add(new SetCardInfo("Samurai's Katana", 154, Rarity.UNCOMMON, mage.cards.s.SamuraisKatana.class)); cards.add(new SetCardInfo("Sazh's Chocobo", 200, Rarity.UNCOMMON, mage.cards.s.SazhsChocobo.class)); cards.add(new SetCardInfo("Sephiroth's Intervention", 116, Rarity.COMMON, mage.cards.s.SephirothsIntervention.class)); diff --git a/Mage/src/main/java/mage/abilities/common/SpellCastOpponentNoManaSpentTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/SpellCastOpponentNoManaSpentTriggeredAbility.java deleted file mode 100644 index 46bf4418db4..00000000000 --- a/Mage/src/main/java/mage/abilities/common/SpellCastOpponentNoManaSpentTriggeredAbility.java +++ /dev/null @@ -1,48 +0,0 @@ -package mage.abilities.common; - -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.stack.Spell; -import mage.target.targetpointer.FixedTarget; - -/** - * @author Susucr - */ -public class SpellCastOpponentNoManaSpentTriggeredAbility extends TriggeredAbilityImpl { - - public SpellCastOpponentNoManaSpentTriggeredAbility(Effect effect) { - super(Zone.BATTLEFIELD, effect, false); - this.setTriggerPhrase("Whenever an opponent casts a spell, if no mana was spent to cast it, "); - } - - protected SpellCastOpponentNoManaSpentTriggeredAbility(final SpellCastOpponentNoManaSpentTriggeredAbility ability) { - super(ability); - } - - @Override - public SpellCastOpponentNoManaSpentTriggeredAbility copy() { - return new SpellCastOpponentNoManaSpentTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (game.getPlayer(this.getControllerId()).hasOpponent(event.getPlayerId(), game)) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.getStackAbility().getManaCostsToPay().getUsedManaToPay().count() == 0) { - for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getTargetId())); - } - return true; - } - } - return false; - } -} \ No newline at end of file diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 6e74bbf8c94..31d2277e82c 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -1,10 +1,7 @@ package mage.filter; import mage.ObjectColor; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.constants.TargetController; +import mage.constants.*; import mage.counters.CounterType; import mage.filter.common.*; import mage.filter.predicate.Predicates; @@ -1045,6 +1042,21 @@ public final class StaticFilters { FILTER_SPELL_KICKED_A.setLockedFilter(true); } + public static final FilterSpell FILTER_SPELL_NO_MANA_SPENT = new FilterSpell("a spell, if no mana was spent to cast it"); + + static { + FILTER_SPELL_NO_MANA_SPENT.add(new ManaSpentToCastPredicate(ComparisonType.EQUAL_TO, 0)); + FILTER_SPELL_NO_MANA_SPENT.setLockedFilter(true); + } + + public static final FilterSpell FILTER_NONCREATURE_SPELL_FOUR_MANA_SPENT = new FilterSpell("a noncreature spell, if at least four mana was spent to cast it"); + + static { + FILTER_NONCREATURE_SPELL_FOUR_MANA_SPENT.add(Predicates.not(CardType.CREATURE.getPredicate())); + FILTER_NONCREATURE_SPELL_FOUR_MANA_SPENT.add(new ManaSpentToCastPredicate(ComparisonType.MORE_THAN, 3)); + FILTER_NONCREATURE_SPELL_FOUR_MANA_SPENT.setLockedFilter(true); + } + public static final FilterPermanent FILTER_PERMANENT_TOKEN = new FilterPermanent("token"); static { diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/ManaSpentToCastPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/ManaSpentToCastPredicate.java new file mode 100644 index 00000000000..c9f44076895 --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/ManaSpentToCastPredicate.java @@ -0,0 +1,25 @@ +package mage.filter.predicate.mageobject; + +import mage.constants.ComparisonType; +import mage.filter.predicate.IntComparePredicate; +import mage.game.stack.StackObject; + +/** + * @author TheElk801 + */ +public class ManaSpentToCastPredicate extends IntComparePredicate { + + public ManaSpentToCastPredicate(ComparisonType type, int value) { + super(type, value); + } + + @Override + protected int getInputValue(StackObject input) { + return input.getStackAbility().getManaCostsToPay().getUsedManaToPay().count(); + } + + @Override + public String toString() { + return "ManaSpent" + super.toString(); + } +}