From c28a6780806fbc1082f1ed41a2c2edeed7009533 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 24 Jul 2025 13:30:26 -0400 Subject: [PATCH] [SPM] Implement Unstable Experiment --- Mage.Sets/src/mage/cards/c/ChangeOfPlans.java | 8 ++-- .../src/mage/cards/k/KamizObscuraOculus.java | 31 ++----------- .../src/mage/cards/o/ObscuraConfluence.java | 29 +----------- .../mage/cards/s/ScorpionSeethingStriker.java | 31 +------------ .../src/mage/cards/u/UnstableExperiment.java | 37 ++++++++++++++++ Mage.Sets/src/mage/sets/MarvelsSpiderMan.java | 1 + .../effects/keyword/ConniveTargetEffect.java | 44 +++++++++++++++++++ 7 files changed, 93 insertions(+), 88 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/u/UnstableExperiment.java create mode 100644 Mage/src/main/java/mage/abilities/effects/keyword/ConniveTargetEffect.java diff --git a/Mage.Sets/src/mage/cards/c/ChangeOfPlans.java b/Mage.Sets/src/mage/cards/c/ChangeOfPlans.java index 0d0b27b6f5b..e4b236b1c97 100644 --- a/Mage.Sets/src/mage/cards/c/ChangeOfPlans.java +++ b/Mage.Sets/src/mage/cards/c/ChangeOfPlans.java @@ -2,7 +2,7 @@ package mage.cards.c; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.keyword.ConniveSourceEffect; +import mage.abilities.effects.keyword.ConniveTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -30,6 +30,7 @@ public final class ChangeOfPlans extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{1}{U}"); // Each of X target creatures you control connive. You may have any number of them phase out. + this.getSpellAbility().addEffect(new ConniveTargetEffect().setText("each of X target creatures you control connive")); this.getSpellAbility().addEffect(new ChangeOfPlansEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); this.getSpellAbility().setTargetAdjuster(new XTargetsCountAdjuster()); @@ -49,7 +50,7 @@ class ChangeOfPlansEffect extends OneShotEffect { ChangeOfPlansEffect() { super(Outcome.Benefit); - staticText = "each of X target creatures you control connive. You may have any number of them phase out"; + staticText = "You may have any number of them phase out"; } private ChangeOfPlansEffect(final ChangeOfPlansEffect effect) { @@ -73,9 +74,6 @@ class ChangeOfPlansEffect extends OneShotEffect { if (permanents.isEmpty()) { return false; } - for (Permanent permanent : permanents) { - ConniveSourceEffect.connive(permanent, 1, source, game); - } Player player = game.getPlayer(source.getControllerId()); if (player == null) { return true; diff --git a/Mage.Sets/src/mage/cards/k/KamizObscuraOculus.java b/Mage.Sets/src/mage/cards/k/KamizObscuraOculus.java index 592a648f543..b08245c145f 100644 --- a/Mage.Sets/src/mage/cards/k/KamizObscuraOculus.java +++ b/Mage.Sets/src/mage/cards/k/KamizObscuraOculus.java @@ -6,7 +6,7 @@ import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; -import mage.abilities.effects.keyword.ConniveSourceEffect; +import mage.abilities.effects.keyword.ConniveTargetEffect; import mage.abilities.keyword.DoubleStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -39,7 +39,7 @@ public final class KamizObscuraOculus extends CardImpl { // Whenever you attack, target attacking creature can't be blocked this turn. It connives. Then choose another attacking creature with lesser power. That creature gains double strike until end of turn. Ability ability = new AttacksWithCreaturesTriggeredAbility(new CantBeBlockedTargetEffect(), 1); - ability.addEffect(new KamizConniveEffect()); + ability.addEffect(new ConniveTargetEffect().setText("it connives")); ability.addEffect(new KamizDoubleStrikeEffect().concatBy("Then")); ability.addTarget(new TargetAttackingCreature()); this.addAbility(ability); @@ -55,29 +55,6 @@ public final class KamizObscuraOculus extends CardImpl { } } -class KamizConniveEffect extends OneShotEffect { - - KamizConniveEffect() { - super(Outcome.Benefit); - staticText = "it connives"; - } - - private KamizConniveEffect(final KamizConniveEffect effect) { - super(effect); - } - - @Override - public KamizConniveEffect copy() { - return new KamizConniveEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); - return ConniveSourceEffect.connive(permanent, 1, source, game); - } -} - class KamizDoubleStrikeEffect extends OneShotEffect { KamizDoubleStrikeEffect() { @@ -109,8 +86,8 @@ class KamizDoubleStrikeEffect extends OneShotEffect { if (target.choose(outcome, source.getControllerId(), source.getSourceId(), source, game)) { game.addEffect( new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance()) - .setTargetPointer(new FixedTarget(target.getFirstTarget(), game)) - , source); + .setTargetPointer(new FixedTarget(target.getFirstTarget(), game)), source + ); } return true; } diff --git a/Mage.Sets/src/mage/cards/o/ObscuraConfluence.java b/Mage.Sets/src/mage/cards/o/ObscuraConfluence.java index 663747f9a98..4d053ef18a8 100644 --- a/Mage.Sets/src/mage/cards/o/ObscuraConfluence.java +++ b/Mage.Sets/src/mage/cards/o/ObscuraConfluence.java @@ -5,7 +5,7 @@ import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.LoseAllAbilitiesTargetEffect; import mage.abilities.effects.common.continuous.SetBasePowerToughnessTargetEffect; -import mage.abilities.effects.keyword.ConniveSourceEffect; +import mage.abilities.effects.keyword.ConniveTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -14,7 +14,6 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetCard; import mage.target.TargetPlayer; @@ -44,7 +43,7 @@ public final class ObscuraConfluence extends CardImpl { this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // • Target creature connives. - this.getSpellAbility().addMode(new Mode(new ObscuraConfluenceConniveEffect()).addTarget(new TargetCreaturePermanent())); + this.getSpellAbility().addMode(new Mode(new ConniveTargetEffect()).addTarget(new TargetCreaturePermanent())); // • Target player returns a creature card from their graveyard to their hand. this.getSpellAbility().addMode(new Mode(new ObscuraConfluenceReturnEffect()).addTarget(new TargetPlayer())); @@ -60,30 +59,6 @@ public final class ObscuraConfluence extends CardImpl { } } -class ObscuraConfluenceConniveEffect extends OneShotEffect { - - ObscuraConfluenceConniveEffect() { - super(Outcome.Benefit); - staticText = "target creature connives. (Draw a card, then discard a card. " + - "If you discarded a nonland card, put a +1/+1 counter on that creature.)"; - } - - private ObscuraConfluenceConniveEffect(final ObscuraConfluenceConniveEffect effect) { - super(effect); - } - - @Override - public ObscuraConfluenceConniveEffect copy() { - return new ObscuraConfluenceConniveEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); - return ConniveSourceEffect.connive(permanent, 1, source, game); - } -} - class ObscuraConfluenceReturnEffect extends OneShotEffect { ObscuraConfluenceReturnEffect() { diff --git a/Mage.Sets/src/mage/cards/s/ScorpionSeethingStriker.java b/Mage.Sets/src/mage/cards/s/ScorpionSeethingStriker.java index ae85ab0fa00..61699b8f551 100644 --- a/Mage.Sets/src/mage/cards/s/ScorpionSeethingStriker.java +++ b/Mage.Sets/src/mage/cards/s/ScorpionSeethingStriker.java @@ -2,17 +2,14 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.keyword.ConniveSourceEffect; +import mage.abilities.effects.keyword.ConniveTargetEffect; import mage.abilities.keyword.DeathtouchAbility; import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.SuperType; -import mage.game.Game; import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -36,7 +33,7 @@ public final class ScorpionSeethingStriker extends CardImpl { this.addAbility(DeathtouchAbility.getInstance()); // At the beginning of your end step, if a creature died this turn, target creature you control connives. - Ability ability = new BeginningOfEndStepTriggeredAbility(new ScorpionSeethingStrikerEffect()); + Ability ability = new BeginningOfEndStepTriggeredAbility(new ConniveTargetEffect()); ability.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(ability); } @@ -50,27 +47,3 @@ public final class ScorpionSeethingStriker extends CardImpl { return new ScorpionSeethingStriker(this); } } - -class ScorpionSeethingStrikerEffect extends OneShotEffect { - - ScorpionSeethingStrikerEffect() { - super(Outcome.Benefit); - staticText = "target creature you control connives"; - } - - private ScorpionSeethingStrikerEffect(final ScorpionSeethingStrikerEffect effect) { - super(effect); - } - - @Override - public ScorpionSeethingStrikerEffect copy() { - return new ScorpionSeethingStrikerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return ConniveSourceEffect.connive( - game.getPermanent(getTargetPointer().getFirst(game, source)), 1, source, game - ); - } -} diff --git a/Mage.Sets/src/mage/cards/u/UnstableExperiment.java b/Mage.Sets/src/mage/cards/u/UnstableExperiment.java new file mode 100644 index 00000000000..45e47307181 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UnstableExperiment.java @@ -0,0 +1,37 @@ +package mage.cards.u; + +import mage.abilities.effects.common.DrawCardTargetEffect; +import mage.abilities.effects.keyword.ConniveTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.TargetPlayer; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class UnstableExperiment extends CardImpl { + + public UnstableExperiment(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); + + // Target player draws a card, then up to one target creature you control connives. + this.getSpellAbility().addEffect(new DrawCardTargetEffect(1)); + this.getSpellAbility().addTarget(new TargetPlayer()); + this.getSpellAbility().addEffect(new ConniveTargetEffect().setTargetPointer(new SecondTargetPointer()).concatBy(", then")); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 1)); + } + + private UnstableExperiment(final UnstableExperiment card) { + super(card); + } + + @Override + public UnstableExperiment copy() { + return new UnstableExperiment(this); + } +} diff --git a/Mage.Sets/src/mage/sets/MarvelsSpiderMan.java b/Mage.Sets/src/mage/sets/MarvelsSpiderMan.java index 2f412dd33f1..72bf67a3015 100644 --- a/Mage.Sets/src/mage/sets/MarvelsSpiderMan.java +++ b/Mage.Sets/src/mage/sets/MarvelsSpiderMan.java @@ -62,6 +62,7 @@ public final class MarvelsSpiderMan extends ExpansionSet { cards.add(new SetCardInfo("Taxi Driver", 97, Rarity.COMMON, mage.cards.t.TaxiDriver.class)); cards.add(new SetCardInfo("Thwip!", 20, Rarity.COMMON, mage.cards.t.Thwip.class)); cards.add(new SetCardInfo("Tombstone, Career Criminal", 70, Rarity.UNCOMMON, mage.cards.t.TombstoneCareerCriminal.class)); + cards.add(new SetCardInfo("Unstable Experiment", 47, Rarity.COMMON, mage.cards.u.UnstableExperiment.class)); cards.add(new SetCardInfo("Venom's Hunger", 73, Rarity.COMMON, mage.cards.v.VenomsHunger.class)); cards.add(new SetCardInfo("Venom, Evil Unleashed", 71, Rarity.COMMON, mage.cards.v.VenomEvilUnleashed.class)); cards.add(new SetCardInfo("Web Up", 21, Rarity.COMMON, mage.cards.w.WebUp.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/ConniveTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/ConniveTargetEffect.java new file mode 100644 index 00000000000..cf2edfe58c1 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/keyword/ConniveTargetEffect.java @@ -0,0 +1,44 @@ +package mage.abilities.effects.keyword; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public class ConniveTargetEffect extends OneShotEffect { + + public ConniveTargetEffect() { + super(Outcome.Benefit); + } + + private ConniveTargetEffect(final ConniveTargetEffect effect) { + super(effect); + } + + @Override + public ConniveTargetEffect copy() { + return new ConniveTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID targetId : getTargetPointer().getTargets(game, source)) { + ConniveSourceEffect.connive(game.getPermanent(targetId), 1, source, game); + } + return true; + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + return this.getTargetPointer().describeTargets(mode.getTargets(), "it") + " connives"; + } +}