From 1d9cc2a87f093e38aa999d57365c289cc9247b8a Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 6 Jul 2024 14:56:15 -0400 Subject: [PATCH] [DSK] Implement Chainsaw --- .../mage/cards/b/BloodSpatterAnalysis.java | 66 ++++--------------- Mage.Sets/src/mage/cards/c/Chainsaw.java | 58 ++++++++++++++++ .../src/mage/sets/DuskmournHouseOfHorror.java | 1 + ...iesOneOrMoreCreaturesTriggeredAbility.java | 53 +++++++++++++++ .../main/java/mage/counters/CounterType.java | 1 + 5 files changed, 126 insertions(+), 53 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/c/Chainsaw.java create mode 100644 Mage/src/main/java/mage/abilities/common/DiesOneOrMoreCreaturesTriggeredAbility.java diff --git a/Mage.Sets/src/mage/cards/b/BloodSpatterAnalysis.java b/Mage.Sets/src/mage/cards/b/BloodSpatterAnalysis.java index 592cb644a0c..6957e645a74 100644 --- a/Mage.Sets/src/mage/cards/b/BloodSpatterAnalysis.java +++ b/Mage.Sets/src/mage/cards/b/BloodSpatterAnalysis.java @@ -1,9 +1,10 @@ package mage.cards.b; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DiesOneOrMoreCreaturesTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.delayed.ReflexiveTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.decorator.ConditionalOneShotEffect; @@ -15,14 +16,8 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeBatchEvent; -import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetOpponentsCreaturePermanent; @@ -33,6 +28,8 @@ import java.util.UUID; */ public final class BloodSpatterAnalysis extends CardImpl { + private static final Condition condition = new SourceHasCounterCondition(CounterType.BLOODSTAIN, 5); + public BloodSpatterAnalysis(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}{R}"); @@ -44,7 +41,15 @@ public final class BloodSpatterAnalysis extends CardImpl { // Whenever one or more creatures die, mill a card and put a bloodstain counter on Blood Spatter Analysis. // Then sacrifice it if it has five or more bloodstain counters on it. // When you do, return target creature card from your graveyard to your hand. - this.addAbility(new BloodSpatterAnalysisTriggeredAbility()); + ability = new DiesOneOrMoreCreaturesTriggeredAbility(new MillCardsControllerEffect(1)); + ability.addEffect(new AddCountersSourceEffect(CounterType.BLOODSTAIN.createInstance()).concatBy("and")); + ReflexiveTriggeredAbility returnAbility = new ReflexiveTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect(), false); + returnAbility.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); + ability.addEffect(new ConditionalOneShotEffect(new DoWhenCostPaid( + returnAbility, new SacrificeSourceCost(), null, false + ), condition).setText("Then sacrifice it if it has five or more bloodstain counters on it. " + + "When you do, return target creature card from your graveyard to your hand")); + this.addAbility(ability); } private BloodSpatterAnalysis(final BloodSpatterAnalysis card) { @@ -56,48 +61,3 @@ public final class BloodSpatterAnalysis extends CardImpl { return new BloodSpatterAnalysis(this); } } - -class BloodSpatterAnalysisTriggeredAbility extends TriggeredAbilityImpl { - - BloodSpatterAnalysisTriggeredAbility() { - super(Zone.BATTLEFIELD, new MillCardsControllerEffect(1)); - this.addEffect(new AddCountersSourceEffect(CounterType.BLOODSTAIN.createInstance()).concatBy("and")); - - ReflexiveTriggeredAbility returnAbility = new ReflexiveTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect(), false); - returnAbility.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); - - this.addEffect(new ConditionalOneShotEffect( - new DoWhenCostPaid(returnAbility, new SacrificeSourceCost(), null, false), - new SourceHasCounterCondition(CounterType.BLOODSTAIN, 5)) - .setText("Then sacrifice it if it has five or more bloodstain counters on it. When you do, return target creature card from your graveyard to your hand")); - - setTriggerPhrase("Whenever one or more creatures die, "); - } - - private BloodSpatterAnalysisTriggeredAbility(final BloodSpatterAnalysisTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - for (ZoneChangeEvent zEvent : ((ZoneChangeBatchEvent) event).getEvents()) { - if (zEvent.isDiesEvent()) { - Permanent permanent = game.getPermanentOrLKIBattlefield(zEvent.getTargetId()); - if (permanent != null && permanent.isCreature(game)) { - return true; - } - } - } - return false; - } - - @Override - public BloodSpatterAnalysisTriggeredAbility copy() { - return new BloodSpatterAnalysisTriggeredAbility(this); - } -} diff --git a/Mage.Sets/src/mage/cards/c/Chainsaw.java b/Mage.Sets/src/mage/cards/c/Chainsaw.java new file mode 100644 index 00000000000..52331f290e1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/Chainsaw.java @@ -0,0 +1,58 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.common.DiesOneOrMoreCreaturesTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Chainsaw extends CardImpl { + + private static final DynamicValue xValue = new CountersSourceCount(CounterType.REV); + + public Chainsaw(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{R}"); + + this.subtype.add(SubType.EQUIPMENT); + + // When Chainsaw enters, it deals 3 damage to up to one target creature. + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3, "it")); + ability.addTarget(new TargetCreaturePermanent(0, 1)); + this.addAbility(ability); + + // Whenever one or more creatures die, put a rev counter on Chainsaw. + this.addAbility(new DiesOneOrMoreCreaturesTriggeredAbility(new AddCountersSourceEffect(CounterType.REV.createInstance()))); + + // Equipped creature gets +X/+0, where X is the number of rev counters on Chainsaw. + this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(xValue, StaticValue.get(0)))); + + // Equip {3} + this.addAbility(new EquipAbility(3)); + } + + private Chainsaw(final Chainsaw card) { + super(card); + } + + @Override + public Chainsaw copy() { + return new Chainsaw(this); + } +} diff --git a/Mage.Sets/src/mage/sets/DuskmournHouseOfHorror.java b/Mage.Sets/src/mage/sets/DuskmournHouseOfHorror.java index 7ccd43cc8a6..c620eae53ce 100644 --- a/Mage.Sets/src/mage/sets/DuskmournHouseOfHorror.java +++ b/Mage.Sets/src/mage/sets/DuskmournHouseOfHorror.java @@ -21,6 +21,7 @@ public final class DuskmournHouseOfHorror extends ExpansionSet { this.hasBasicLands = true; this.hasBoosters = false; // temporary + cards.add(new SetCardInfo("Chainsaw", 128, Rarity.RARE, mage.cards.c.Chainsaw.class)); cards.add(new SetCardInfo("Cursed Recording", 131, Rarity.RARE, mage.cards.c.CursedRecording.class)); cards.add(new SetCardInfo("Doomsday Excruciator", 94, Rarity.RARE, mage.cards.d.DoomsdayExcruciator.class)); cards.add(new SetCardInfo("Enduring Tenacity", 95, Rarity.RARE, mage.cards.e.EnduringTenacity.class)); diff --git a/Mage/src/main/java/mage/abilities/common/DiesOneOrMoreCreaturesTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DiesOneOrMoreCreaturesTriggeredAbility.java new file mode 100644 index 00000000000..debd9ca43da --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/DiesOneOrMoreCreaturesTriggeredAbility.java @@ -0,0 +1,53 @@ +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.events.ZoneChangeBatchEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; + +/** + * @author Cguy7777 + */ +public class DiesOneOrMoreCreaturesTriggeredAbility extends TriggeredAbilityImpl { + + public DiesOneOrMoreCreaturesTriggeredAbility(Effect effect) { + this(effect, false); + } + + public DiesOneOrMoreCreaturesTriggeredAbility(Effect effect, boolean optional) { + super(Zone.BATTLEFIELD, effect, optional); + setTriggerPhrase("Whenever one or more creatures die, "); + } + + private DiesOneOrMoreCreaturesTriggeredAbility(final DiesOneOrMoreCreaturesTriggeredAbility ability) { + super(ability); + } + + @Override + public DiesOneOrMoreCreaturesTriggeredAbility copy() { + return new DiesOneOrMoreCreaturesTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + for (ZoneChangeEvent zEvent : ((ZoneChangeBatchEvent) event).getEvents()) { + if (!zEvent.isDiesEvent()) { + continue; + } + Permanent permanent = game.getPermanentOrLKIBattlefield(zEvent.getTargetId()); + if (permanent != null && permanent.isCreature(game)) { + return true; + } + } + return false; + } +} diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index 6aeec2fcef9..54ae1be784e 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -180,6 +180,7 @@ public enum CounterType { REJECTION("rejection"), REPAIR("repair"), REPRIEVE("reprieve"), + REV("rev"), RIBBON("ribbon"), RITUAL("ritual"), ROPE("rope"),