From eaf412590a9d876c2e5d2053ff4d03b138f8e7f3 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sat, 18 Apr 2020 12:44:23 -0400 Subject: [PATCH 1/2] Implemented Lavabrink Floodgates --- .../src/mage/cards/l/LavabrinkFloodgates.java | 137 ++++++++++++++++++ .../src/mage/sets/Commander2020Edition.java | 1 + 2 files changed, 138 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LavabrinkFloodgates.java diff --git a/Mage.Sets/src/mage/cards/l/LavabrinkFloodgates.java b/Mage.Sets/src/mage/cards/l/LavabrinkFloodgates.java new file mode 100644 index 00000000000..f08023b8d19 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LavabrinkFloodgates.java @@ -0,0 +1,137 @@ +package mage.cards.l; + +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageAllEffect; +import mage.abilities.effects.common.SendOptionUsedEventEffect; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class LavabrinkFloodgates extends CardImpl { + + public LavabrinkFloodgates(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}{R}"); + + // {T}: Add {R}{R}. + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.RedMana(2), new TapSourceCost())); + + // At the beginning of each player's upkeep, that player may put a doom counter on Lavabrink Floodgates or remove a doom counter from it. Then if it has three or more doom counters on it, sacrifice it. When you do, it deals 6 damage to each creature. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new LavabrinkFloodgatesEffect(), TargetController.ACTIVE, false + )); + } + + private LavabrinkFloodgates(final LavabrinkFloodgates card) { + super(card); + } + + @Override + public LavabrinkFloodgates copy() { + return new LavabrinkFloodgates(this); + } +} + +class LavabrinkFloodgatesEffect extends OneShotEffect { + + LavabrinkFloodgatesEffect() { + super(Outcome.Benefit); + staticText = "that player may put a doom counter on {this} or remove a doom counter from it. " + + "Then if it has three or more doom counters on it, sacrifice it. " + + "When you do, it deals 6 damage to each creature."; + } + + private LavabrinkFloodgatesEffect(final LavabrinkFloodgatesEffect effect) { + super(effect); + } + + @Override + public LavabrinkFloodgatesEffect copy() { + return new LavabrinkFloodgatesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(game.getActivePlayerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (player == null || permanent == null) { + return false; + } + Choice choice = new ChoiceImpl(); + choice.setChoices(new HashSet(Arrays.asList( + "Add a doom counter", + "Remove a doom counter", + "Do nothing" + ))); + player.choose(outcome, choice, game); + switch (choice.getChoice()) { + case "Add a doom counter": + permanent.addCounters(CounterType.DOOM.createInstance(), source, game); + break; + case "Remove a doom counter": + permanent.removeCounters(CounterType.DOOM.createInstance(), game); + break; + case "Do nothing": + default: + return false; + } + if (permanent.getCounters(game).getCount(CounterType.DOOM) < 3 + || !permanent.sacrifice(source.getSourceId(), game)) { + return true; + } + game.addDelayedTriggeredAbility(new LavabrinkFloodgatesReflexiveTriggeredAbility(), source); + return new SendOptionUsedEventEffect().apply(game, source); + } +} + +class LavabrinkFloodgatesReflexiveTriggeredAbility extends DelayedTriggeredAbility { + + LavabrinkFloodgatesReflexiveTriggeredAbility() { + super(new DamageAllEffect(6, StaticFilters.FILTER_PERMANENT_CREATURE), Duration.OneUse, true); + } + + private LavabrinkFloodgatesReflexiveTriggeredAbility(final LavabrinkFloodgatesReflexiveTriggeredAbility ability) { + super(ability); + } + + @Override + public LavabrinkFloodgatesReflexiveTriggeredAbility copy() { + return new LavabrinkFloodgatesReflexiveTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.OPTION_USED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(this.getControllerId()) + && event.getSourceId().equals(this.getSourceId()); + } + + @Override + public String getRule() { + return "It deals 6 damage to each creature."; + } +} diff --git a/Mage.Sets/src/mage/sets/Commander2020Edition.java b/Mage.Sets/src/mage/sets/Commander2020Edition.java index 28e2011b8d0..67585324c86 100644 --- a/Mage.Sets/src/mage/sets/Commander2020Edition.java +++ b/Mage.Sets/src/mage/sets/Commander2020Edition.java @@ -175,6 +175,7 @@ public final class Commander2020Edition extends ExpansionSet { cards.add(new SetCardInfo("Kodama's Reach", 180, Rarity.COMMON, mage.cards.k.KodamasReach.class)); cards.add(new SetCardInfo("Krosan Grip", 181, Rarity.UNCOMMON, mage.cards.k.KrosanGrip.class)); cards.add(new SetCardInfo("Krosan Verge", 285, Rarity.UNCOMMON, mage.cards.k.KrosanVerge.class)); + cards.add(new SetCardInfo("Lavabrink Floodgates", 53, Rarity.RARE, mage.cards.l.LavabrinkFloodgates.class)); cards.add(new SetCardInfo("Lifecrafter's Bestiary", 244, Rarity.RARE, mage.cards.l.LifecraftersBestiary.class)); cards.add(new SetCardInfo("Lightning Greaves", 245, Rarity.UNCOMMON, mage.cards.l.LightningGreaves.class)); cards.add(new SetCardInfo("Lightning Rift", 155, Rarity.UNCOMMON, mage.cards.l.LightningRift.class)); From e37438caf6463963ad424a45abd3bd886fb12392 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sat, 18 Apr 2020 13:11:27 -0400 Subject: [PATCH 2/2] Implemented Agitator Ant --- Mage.Sets/src/mage/cards/a/AgitatorAnt.java | 98 +++++++++++++++++++ .../src/mage/sets/Commander2020Edition.java | 1 + 2 files changed, 99 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AgitatorAnt.java diff --git a/Mage.Sets/src/mage/cards/a/AgitatorAnt.java b/Mage.Sets/src/mage/cards/a/AgitatorAnt.java new file mode 100644 index 00000000000..e33d7a1a230 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AgitatorAnt.java @@ -0,0 +1,98 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.combat.GoadTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public final class AgitatorAnt extends CardImpl { + + public AgitatorAnt(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.INSECT); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // At the beginning of your end step, each player may put two +1/+1 counters on a creature they control. Goad each creature that had counters put on it this way. + this.addAbility(new BeginningOfEndStepTriggeredAbility( + new AgitatorAntEffect(), TargetController.YOU, false + )); + } + + private AgitatorAnt(final AgitatorAnt card) { + super(card); + } + + @Override + public AgitatorAnt copy() { + return new AgitatorAnt(this); + } +} + +class AgitatorAntEffect extends OneShotEffect { + + AgitatorAntEffect() { + super(Outcome.Benefit); + staticText = "each player may put two +1/+1 counters on a creature they control. " + + "Goad each creature that had counters put on it this way."; + } + + private AgitatorAntEffect(final AgitatorAntEffect effect) { + super(effect); + } + + @Override + public AgitatorAntEffect copy() { + return new AgitatorAntEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Player player : game + .getState() + .getPlayersInRange(source.getControllerId(), game) + .stream() + .map(game::getPlayer) + .filter(Objects::nonNull).collect(Collectors.toList())) { + if (game.getBattlefield().countAll( + StaticFilters.FILTER_PERMANENT_CREATURE, player.getId(), game + ) < 1 || !player.chooseUse( + Outcome.BoostCreature, "Put two +1/+1 counters on a creature you control?", source, game + )) { + continue; + } + TargetPermanent targetPermanent = new TargetControlledCreaturePermanent(0, 1); + targetPermanent.setNotTarget(true); + player.choose(Outcome.BoostCreature, targetPermanent, source.getSourceId(), game); + Permanent permanent = game.getPermanent(targetPermanent.getFirstTarget()); + if (permanent == null || !permanent.addCounters(CounterType.P1P1.createInstance(2), source, game)) { + continue; + } + new GoadTargetEffect().setTargetPointer(new FixedTarget(permanent, game)).apply(game, source); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/Commander2020Edition.java b/Mage.Sets/src/mage/sets/Commander2020Edition.java index 67585324c86..e6b0138c5c9 100644 --- a/Mage.Sets/src/mage/sets/Commander2020Edition.java +++ b/Mage.Sets/src/mage/sets/Commander2020Edition.java @@ -36,6 +36,7 @@ public final class Commander2020Edition extends ExpansionSet { cards.add(new SetCardInfo("Acidic Slime", 165, Rarity.UNCOMMON, mage.cards.a.AcidicSlime.class)); cards.add(new SetCardInfo("Adriana, Captain of the Guard", 200, Rarity.RARE, mage.cards.a.AdrianaCaptainOfTheGuard.class)); cards.add(new SetCardInfo("Aerial Responder", 72, Rarity.UNCOMMON, mage.cards.a.AerialResponder.class)); + cards.add(new SetCardInfo("Agitator Ant", 49, Rarity.RARE, mage.cards.a.AgitatorAnt.class)); cards.add(new SetCardInfo("Ajani Unyielding", 201, Rarity.MYTHIC, mage.cards.a.AjaniUnyielding.class)); cards.add(new SetCardInfo("Akroma's Vengeance", 74, Rarity.RARE, mage.cards.a.AkromasVengeance.class)); cards.add(new SetCardInfo("Akroma, Angel of Wrath", 73, Rarity.MYTHIC, mage.cards.a.AkromaAngelOfWrath.class));