diff --git a/Mage.Sets/src/mage/cards/h/HidetsuguConsumesAll.java b/Mage.Sets/src/mage/cards/h/HidetsuguConsumesAll.java new file mode 100644 index 0000000000..16e6ba35dc --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HidetsuguConsumesAll.java @@ -0,0 +1,62 @@ +package mage.cards.h; + +import mage.abilities.common.SagaAbility; +import mage.abilities.effects.common.DestroyAllEffect; +import mage.abilities.effects.common.ExileGraveyardAllPlayersEffect; +import mage.abilities.effects.common.ExileSagaAndReturnTransformedEffect; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SagaChapter; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.mageobject.ManaValuePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class HidetsuguConsumesAll extends CardImpl { + + private static final FilterPermanent filter = new FilterNonlandPermanent(); + + static { + filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 2)); + } + + public HidetsuguConsumesAll(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{R}"); + + this.subtype.add(SubType.SAGA); + this.secondSideCardClazz = mage.cards.v.VesselOfTheAllConsuming.class; + + // (As this Saga enters and after your draw step, add a lore counter.) + SagaAbility sagaAbility = new SagaAbility(this); + + // I — Destroy each nonland permanent with mana value 1 or less. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, new DestroyAllEffect(filter) + .setText("destroy each nonland permanent with mana value 1 or less")); + + // II — Exile all graveyards. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_II, new ExileGraveyardAllPlayersEffect()); + + // III — Exile this Saga, then return it to the battlefield transformed under your control. + this.addAbility(new TransformAbility()); + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, new ExileSagaAndReturnTransformedEffect()); + + this.addAbility(sagaAbility, mage.cards.v.VesselOfTheAllConsuming.makeWatcher()); + } + + private HidetsuguConsumesAll(final HidetsuguConsumesAll card) { + super(card); + } + + @Override + public HidetsuguConsumesAll copy() { + return new HidetsuguConsumesAll(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MindlinkMech.java b/Mage.Sets/src/mage/cards/m/MindlinkMech.java index 31d24eb697..38bd095507 100644 --- a/Mage.Sets/src/mage/cards/m/MindlinkMech.java +++ b/Mage.Sets/src/mage/cards/m/MindlinkMech.java @@ -131,7 +131,7 @@ class MindlinkMechWatcher extends Watcher { return; } if (crewer == null) { - crewCount.compute(new MageObjectReference(vehicle, game), (m, i) -> Integer.sum(i, 1)); + crewCount.compute(new MageObjectReference(vehicle, game), (m, i) -> i == null ? 1 : Integer.sum(i, 1)); return; } crewMap.computeIfAbsent(new MageObjectReference(vehicle, game), x -> new HashSet<>()).add(new MageObjectReference(crewer, game)); diff --git a/Mage.Sets/src/mage/cards/v/VesselOfTheAllConsuming.java b/Mage.Sets/src/mage/cards/v/VesselOfTheAllConsuming.java new file mode 100644 index 0000000000..c032a42e8e --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VesselOfTheAllConsuming.java @@ -0,0 +1,139 @@ +package mage.cards.v; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.LoseGameTargetPlayerEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.DamagedEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.watchers.Watcher; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class VesselOfTheAllConsuming extends CardImpl { + + public VesselOfTheAllConsuming(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, ""); + + this.subtype.add(SubType.OGRE); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + this.color.setBlack(true); + this.color.setRed(true); + this.nightCard = true; + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Whenever Vessel of the All-Consuming deals damage, put a +1/+1 counter on it. + this.addAbility(new VesselOfTheAllConsumingTriggeredAbility()); + + // Whenever Vessel of the All-Consuming deals damage to a player, if it has dealt 10 or more damage to that player this turn, they lose the game. + this.addAbility(new ConditionalInterveningIfTriggeredAbility( + new DealsDamageToAPlayerTriggeredAbility( + new LoseGameTargetPlayerEffect(), false, true + ), VesselOfTheAllConsumingWatcher::checkPermanent, "Whenever {this} deals damage to a player, " + + "if it has dealt 10 or more damage to that player this turn, they lose the game." + )); + } + + private VesselOfTheAllConsuming(final VesselOfTheAllConsuming card) { + super(card); + } + + @Override + public VesselOfTheAllConsuming copy() { + return new VesselOfTheAllConsuming(this); + } + + public static Watcher makeWatcher() { + return new VesselOfTheAllConsumingWatcher(); + } +} + +class VesselOfTheAllConsumingTriggeredAbility extends TriggeredAbilityImpl { + + VesselOfTheAllConsumingTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance())); + } + + private VesselOfTheAllConsumingTriggeredAbility(final VesselOfTheAllConsumingTriggeredAbility ability) { + super(ability); + } + + @Override + public VesselOfTheAllConsumingTriggeredAbility copy() { + return new VesselOfTheAllConsumingTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event instanceof DamagedEvent; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getSourceId().equals(getSourceId()); + } + + @Override + public String getRule() { + return "Whenever {this} deals damage, put a +1/+1 counter on it."; + } +} + +class VesselOfTheAllConsumingWatcher extends Watcher { + + private final Map> morMap = new HashMap<>(); + private static final Map emptyMap = new HashMap<>(); + + VesselOfTheAllConsumingWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() != GameEvent.EventType.DAMAGED_PLAYER) { + return; + } + Permanent permanent = game.getPermanent(event.getSourceId()); + if (permanent != null) { + morMap.computeIfAbsent(new MageObjectReference(permanent, game), x -> new HashMap<>()) + .compute(event.getTargetId(), (u, i) -> i == null ? 1 : Integer.sum(i, 1)); + } + } + + @Override + public void reset() { + super.reset(); + morMap.clear(); + } + + static boolean checkPermanent(Game game, Ability source) { + return game.getState() + .getWatcher(VesselOfTheAllConsumingWatcher.class) + .morMap + .getOrDefault(new MageObjectReference(source), emptyMap) + .getOrDefault(source.getEffects().get(0).getTargetPointer().getFirst(game, source), 0) >= 10; + } +} diff --git a/Mage.Sets/src/mage/sets/KamigawaNeonDynasty.java b/Mage.Sets/src/mage/sets/KamigawaNeonDynasty.java index 82b9fafac5..37e8301c1e 100644 --- a/Mage.Sets/src/mage/sets/KamigawaNeonDynasty.java +++ b/Mage.Sets/src/mage/sets/KamigawaNeonDynasty.java @@ -120,6 +120,7 @@ public final class KamigawaNeonDynasty extends ExpansionSet { cards.add(new SetCardInfo("Harmonious Emergence", 190, Rarity.COMMON, mage.cards.h.HarmoniousEmergence.class)); cards.add(new SetCardInfo("Heiko Yamazaki, the General", 146, Rarity.UNCOMMON, mage.cards.h.HeikoYamazakiTheGeneral.class)); cards.add(new SetCardInfo("Heir of the Ancient Fang", 191, Rarity.COMMON, mage.cards.h.HeirOfTheAncientFang.class)); + cards.add(new SetCardInfo("Hidetsugu Consumes All", 221, Rarity.MYTHIC, mage.cards.h.HidetsuguConsumesAll.class)); cards.add(new SetCardInfo("Hidetsugu, Devouring Chaos", 99, Rarity.RARE, mage.cards.h.HidetsuguDevouringChaos.class)); cards.add(new SetCardInfo("High-Speed Hoverbike", 247, Rarity.UNCOMMON, mage.cards.h.HighSpeedHoverbike.class)); cards.add(new SetCardInfo("Hinata, Dawn-Crowned", 222, Rarity.RARE, mage.cards.h.HinataDawnCrowned.class)); @@ -300,6 +301,7 @@ public final class KamigawaNeonDynasty extends ExpansionSet { cards.add(new SetCardInfo("Unstoppable Ogre", 169, Rarity.COMMON, mage.cards.u.UnstoppableOgre.class)); cards.add(new SetCardInfo("Upriser Renegade", 170, Rarity.UNCOMMON, mage.cards.u.UpriserRenegade.class)); cards.add(new SetCardInfo("Vector Glider", 66, Rarity.COMMON, mage.cards.v.VectorGlider.class)); + cards.add(new SetCardInfo("Vessel of the All-Consuming", 221, Rarity.MYTHIC, mage.cards.v.VesselOfTheAllConsuming.class)); cards.add(new SetCardInfo("Virus Beetle", 128, Rarity.COMMON, mage.cards.v.VirusBeetle.class)); cards.add(new SetCardInfo("Vision of the Unspeakable", 48, Rarity.UNCOMMON, mage.cards.v.VisionOfTheUnspeakable.class)); cards.add(new SetCardInfo("Voltage Surge", 171, Rarity.COMMON, mage.cards.v.VoltageSurge.class));