From 16fe17316e3ded65d5e6a8a658c31da7c006ba2d Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 24 Apr 2023 18:41:52 -0400 Subject: [PATCH] [ONE] Implement Blade of Shared Souls --- .../src/mage/cards/b/BladeOfSharedSouls.java | 144 ++++++++++++++++++ .../src/mage/cards/e/EnormousEnergyBlade.java | 52 +++++-- .../src/mage/sets/PhyrexiaAllWillBeOne.java | 1 + ...achedToCreatureSourceTriggeredAbility.java | 15 +- 4 files changed, 195 insertions(+), 17 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/b/BladeOfSharedSouls.java diff --git a/Mage.Sets/src/mage/cards/b/BladeOfSharedSouls.java b/Mage.Sets/src/mage/cards/b/BladeOfSharedSouls.java new file mode 100644 index 0000000000..1423749cfd --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BladeOfSharedSouls.java @@ -0,0 +1,144 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.common.AttachedToCreatureSourceTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CopyEffect; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.ForMirrodinAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BladeOfSharedSouls extends CardImpl { + + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("another creature you control"); + + static { + filter.add(BladeOfSharedSoulsPredicate.instance); + } + + public BladeOfSharedSouls(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{U}"); + + this.subtype.add(SubType.EQUIPMENT); + + // For Mirrodin! + this.addAbility(new ForMirrodinAbility()); + + // Whenever Blade of Shared Souls becomes attached to a creature, for as long as Blade of Shared Souls remains attached to it, you may have that creature become a copy of another target creature you control. + Ability ability = new AttachedToCreatureSourceTriggeredAbility(new BladeOfSharedSoulsEffect(), false); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + + // Equip {2} + this.addAbility(new EquipAbility(2)); + } + + private BladeOfSharedSouls(final BladeOfSharedSouls card) { + super(card); + } + + @Override + public BladeOfSharedSouls copy() { + return new BladeOfSharedSouls(this); + } +} + +enum BladeOfSharedSoulsPredicate implements ObjectSourcePlayerPredicate { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return input.getSource() + .getEffects() + .stream() + .map(effect -> effect.getValue("attachedPermanent")) + .filter(Permanent.class::isInstance) + .map(Permanent.class::cast) + .noneMatch(permanent -> input.getObject().getId().equals(permanent.getId()) + && input.getObject().getZoneChangeCounter(game) == permanent.getZoneChangeCounter(game)); + } +} + +class BladeOfSharedSoulsEffect extends OneShotEffect { + + BladeOfSharedSoulsEffect() { + super(Outcome.Benefit); + staticText = "for as long as {this} remains attached to it, " + + "you may have that creature become a copy of another target creature you control"; + } + + private BladeOfSharedSoulsEffect(final BladeOfSharedSoulsEffect effect) { + super(effect); + } + + @Override + public BladeOfSharedSoulsEffect copy() { + return new BladeOfSharedSoulsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent attachedPermanent = (Permanent) getValue("attachedPermanent"); + Permanent copyCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); + Permanent equipment = source.getSourcePermanentIfItStillExists(game); + if (attachedPermanent == null + || copyCreature == null + || equipment == null + || !equipment.isAttachedTo(attachedPermanent.getId())) { + return false; + } + Player player = game.getPlayer(source.getControllerId()); + if (player == null || !player.chooseUse(outcome, "Copy the creature?", source, game)) { + return false; + } + game.addEffect(new BladeOfSharedSoulsCopyEffect(copyCreature, attachedPermanent), source); + return true; + } +} + +class BladeOfSharedSoulsCopyEffect extends CopyEffect { + + BladeOfSharedSoulsCopyEffect(Permanent copyCreature, Permanent attachedPermanent) { + super(Duration.Custom, copyCreature, attachedPermanent.getId()); + } + + private BladeOfSharedSoulsCopyEffect(final BladeOfSharedSoulsCopyEffect effect) { + super(effect); + } + + @Override + public BladeOfSharedSoulsCopyEffect copy() { + return new BladeOfSharedSoulsCopyEffect(this); + } + + @Override + public boolean isInactive(Ability source, Game game) { + if (super.isInactive(source, game)) { + return true; + } + Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); + if (sourcePermanent == null || !sourcePermanent.isAttachedTo(this.copyToObjectId)) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/e/EnormousEnergyBlade.java b/Mage.Sets/src/mage/cards/e/EnormousEnergyBlade.java index a1e10103aa..90285619cc 100644 --- a/Mage.Sets/src/mage/cards/e/EnormousEnergyBlade.java +++ b/Mage.Sets/src/mage/cards/e/EnormousEnergyBlade.java @@ -1,38 +1,39 @@ package mage.cards.e; +import mage.abilities.Ability; import mage.abilities.common.AttachedToCreatureSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.TapEnchantedEffect; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.SubType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import java.util.Objects; +import java.util.Optional; import java.util.UUID; /** - * * @author Addictiveme */ public final class EnormousEnergyBlade extends CardImpl { public EnormousEnergyBlade(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{B}"); - + this.subtype.add(SubType.EQUIPMENT); - + // Equipped creature gets +4/+0 this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(4, 0))); - + // Whenever Enormous Energy Blade becomes attached to a creature, tap that creature. - TapEnchantedEffect effect = new TapEnchantedEffect(); - effect.setText("tap that creature"); - AttachedToCreatureSourceTriggeredAbility attachTrigger = new AttachedToCreatureSourceTriggeredAbility(effect, false); - attachTrigger.setTriggerPhrase("Whenever {this} becomes attached to a creature, "); - this.addAbility(attachTrigger); - + this.addAbility(new AttachedToCreatureSourceTriggeredAbility(new EnormousEnergyBladeEffect(), false)); + // Equip {2} this.addAbility(new EquipAbility(2)); } @@ -45,4 +46,31 @@ public final class EnormousEnergyBlade extends CardImpl { public EnormousEnergyBlade copy() { return new EnormousEnergyBlade(this); } -} \ No newline at end of file +} + +class EnormousEnergyBladeEffect extends OneShotEffect { + + EnormousEnergyBladeEffect() { + super(Outcome.Benefit); + staticText = "tap that creature"; + } + + private EnormousEnergyBladeEffect(final EnormousEnergyBladeEffect effect) { + super(effect); + } + + @Override + public EnormousEnergyBladeEffect copy() { + return new EnormousEnergyBladeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return Optional + .ofNullable(getValue("attachedPermanent")) + .map(Permanent.class::cast) + .filter(Objects::nonNull) + .map(permanent -> permanent.tap(source, game)) + .orElse(null); + } +} diff --git a/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOne.java b/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOne.java index dbca6d278d..76e5fe99e4 100644 --- a/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOne.java +++ b/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOne.java @@ -44,6 +44,7 @@ public final class PhyrexiaAllWillBeOne extends ExpansionSet { cards.add(new SetCardInfo("Bilious Skulldweller", 83, Rarity.UNCOMMON, mage.cards.b.BiliousSkulldweller.class)); cards.add(new SetCardInfo("Black Sun's Twilight", 84, Rarity.RARE, mage.cards.b.BlackSunsTwilight.class)); cards.add(new SetCardInfo("Blackcleave Cliffs", 248, Rarity.RARE, mage.cards.b.BlackcleaveCliffs.class)); + cards.add(new SetCardInfo("Blade of Shared Souls", 42, Rarity.RARE, mage.cards.b.BladeOfSharedSouls.class)); cards.add(new SetCardInfo("Bladed Ambassador", 5, Rarity.UNCOMMON, mage.cards.b.BladedAmbassador.class)); cards.add(new SetCardInfo("Bladegraft Aspirant", 122, Rarity.COMMON, mage.cards.b.BladegraftAspirant.class)); cards.add(new SetCardInfo("Bladehold War-Whip", 197, Rarity.UNCOMMON, mage.cards.b.BladeholdWarWhip.class)); diff --git a/Mage/src/main/java/mage/abilities/common/AttachedToCreatureSourceTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AttachedToCreatureSourceTriggeredAbility.java index c7b5508878..0e9a525460 100644 --- a/Mage/src/main/java/mage/abilities/common/AttachedToCreatureSourceTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AttachedToCreatureSourceTriggeredAbility.java @@ -14,7 +14,7 @@ public class AttachedToCreatureSourceTriggeredAbility extends TriggeredAbilityIm public AttachedToCreatureSourceTriggeredAbility(Effect effect, boolean optional) { super(Zone.BATTLEFIELD, effect, optional); - setTriggerPhrase("As {this} becomes attached to a creature, "); + setTriggerPhrase("Whenever {this} becomes attached to a creature, "); } public AttachedToCreatureSourceTriggeredAbility(final AttachedToCreatureSourceTriggeredAbility ability) { @@ -23,15 +23,20 @@ public class AttachedToCreatureSourceTriggeredAbility extends TriggeredAbilityIm @Override public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ATTACHED - && event.getSourceId() != null - && event.getSourceId().equals(this.getSourceId()); + return event.getType() == GameEvent.EventType.ATTACHED; } @Override public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getSourceId().equals(this.getSourceId())) { + return false; + } Permanent attachedPermanent = game.getPermanent(event.getTargetId()); - return attachedPermanent != null && attachedPermanent.isCreature(game); + if (attachedPermanent == null || !attachedPermanent.isCreature(game)) { + return false; + } + this.getEffects().setValue("attachedPermanent", attachedPermanent); + return true; } @Override