From b8858a881ee194001d5dce8bfcc2180dfaf8bbf7 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sun, 23 Apr 2023 16:15:40 -0400 Subject: [PATCH] [MOC] Implement Pain Distributor --- .../src/mage/cards/p/PainDistributor.java | 115 ++++++++++++++++++ .../mage/sets/MarchOfTheMachineCommander.java | 1 + ...aveFromBattlefieldAllTriggeredAbility.java | 22 ++-- 3 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/p/PainDistributor.java diff --git a/Mage.Sets/src/mage/cards/p/PainDistributor.java b/Mage.Sets/src/mage/cards/p/PainDistributor.java new file mode 100644 index 0000000000..768d5d219c --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PainDistributor.java @@ -0,0 +1,115 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; +import mage.abilities.common.SpellCastAllTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenTargetEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.FilterSpell; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.predicate.Predicate; +import mage.game.Controllable; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.TreasureToken; +import mage.game.stack.StackObject; +import mage.watchers.common.SpellsCastWatcher; + +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PainDistributor extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("their first spell each turn"); + private static final FilterPermanent filter2 = new FilterArtifactPermanent("an artifact an opponent controls"); + + static { + filter.add(PainDistributorPredicate.instance); + filter.add(TargetController.OPPONENT.getControllerPredicate()); + } + + public PainDistributor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.DEVIL); + this.subtype.add(SubType.CITIZEN); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Menace + this.addAbility(new MenaceAbility()); + + // Whenever a player casts their first spell each turn, they create a Treasure token. + this.addAbility(new SpellCastAllTriggeredAbility( + new CreateTokenTargetEffect(new TreasureToken()) + .setText("they create a Treasure token"), + filter, false, SetTargetPointer.PLAYER + ), new SpellsCastWatcher()); + + // Whenever an artifact an opponent controls is put into a graveyard from the battlefield, Pain Distributor deals 1 damage to that player. + this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility( + new PainDistributorEffect(), false, filter2, false + )); + } + + private PainDistributor(final PainDistributor card) { + super(card); + } + + @Override + public PainDistributor copy() { + return new PainDistributor(this); + } +} + +enum PainDistributorPredicate implements Predicate { + instance; + + @Override + public boolean apply(StackObject input, Game game) { + return game.getState() + .getWatcher(SpellsCastWatcher.class) + .getSpellsCastThisTurn(input.getControllerId()) + .size() == 1; + } +} + +class PainDistributorEffect extends OneShotEffect { + + PainDistributorEffect() { + super(Outcome.Benefit); + staticText = "{this} deals 1 damage to that player"; + } + + private PainDistributorEffect(final PainDistributorEffect effect) { + super(effect); + } + + @Override + public PainDistributorEffect copy() { + return new PainDistributorEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return Optional + .ofNullable(getValue("permanentDied")) + .filter(Objects::nonNull) + .map(Permanent.class::cast) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .filter(Objects::nonNull) + .map(player -> player.damage(1, source, game) > 0) + .orElse(false); + } +} diff --git a/Mage.Sets/src/mage/sets/MarchOfTheMachineCommander.java b/Mage.Sets/src/mage/sets/MarchOfTheMachineCommander.java index 22328f6320..317a708f49 100644 --- a/Mage.Sets/src/mage/sets/MarchOfTheMachineCommander.java +++ b/Mage.Sets/src/mage/sets/MarchOfTheMachineCommander.java @@ -228,6 +228,7 @@ public final class MarchOfTheMachineCommander extends ExpansionSet { cards.add(new SetCardInfo("Order of Midnight", 261, Rarity.UNCOMMON, mage.cards.o.OrderOfMidnight.class)); cards.add(new SetCardInfo("Orzhov Locket", 368, Rarity.COMMON, mage.cards.o.OrzhovLocket.class)); cards.add(new SetCardInfo("Orzhov Signet", 369, Rarity.COMMON, mage.cards.o.OrzhovSignet.class)); + cards.add(new SetCardInfo("Pain Distributor", 33, Rarity.RARE, mage.cards.p.PainDistributor.class)); cards.add(new SetCardInfo("Painful Truths", 262, Rarity.RARE, mage.cards.p.PainfulTruths.class)); cards.add(new SetCardInfo("Path of Ancestry", 418, Rarity.COMMON, mage.cards.p.PathOfAncestry.class)); cards.add(new SetCardInfo("Path to Exile", 198, Rarity.UNCOMMON, mage.cards.p.PathToExile.class)); diff --git a/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java index 07dcf7aa16..20b4139208 100644 --- a/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java @@ -11,7 +11,6 @@ import mage.game.events.ZoneChangeEvent; import mage.target.targetpointer.FixedTarget; /** - * * @author LevelX2 */ public class PutIntoGraveFromBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl { @@ -49,20 +48,15 @@ public class PutIntoGraveFromBattlefieldAllTriggeredAbility extends TriggeredAbi @Override public boolean checkTrigger(GameEvent event, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.isDiesEvent()) { - if (filter.match(zEvent.getTarget(), this.getControllerId(), this, game)) { - if (onlyToControllerGraveyard && !this.isControlledBy(game.getOwnerId(zEvent.getTargetId()))) { - return false; - } - if (setTargetPointer) { - for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getTargetId(), game.getObject(event.getTargetId()).getZoneChangeCounter(game))); - } - } - return true; - } + if (!zEvent.isDiesEvent() || !filter.match(zEvent.getTarget(), this.getControllerId(), this, game) + || onlyToControllerGraveyard && !this.isControlledBy(game.getOwnerId(zEvent.getTargetId()))) { + return false; } - return false; + this.getEffects().setValue("permanentDied", zEvent.getTarget()); + if (setTargetPointer) { + this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game.getObject(event.getTargetId()).getZoneChangeCounter(game))); + } + return true; } @Override