From aa1590a72d9bcbe0daae1bf63e0c4fc7bf7aa83d Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 21 Apr 2020 20:35:49 -0400 Subject: [PATCH] Implemented Valiant Rescuer --- .../src/mage/cards/v/ValiantRescuer.java | 123 ++++++++++++++++++ .../src/mage/sets/IkoriaLairOfBehemoths.java | 1 + 2 files changed, 124 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/v/ValiantRescuer.java diff --git a/Mage.Sets/src/mage/cards/v/ValiantRescuer.java b/Mage.Sets/src/mage/cards/v/ValiantRescuer.java new file mode 100644 index 0000000000..d9c9a255ef --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/ValiantRescuer.java @@ -0,0 +1,123 @@ +package mage.cards.v; + +import mage.MageInt; +import mage.abilities.TriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.CyclingAbility; +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.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.HumanSoldierToken; +import mage.game.stack.StackAbility; +import mage.game.stack.StackObject; +import mage.watchers.Watcher; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ValiantRescuer extends CardImpl { + + public ValiantRescuer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Whenever you cycle another card for the first time each turn, create a 1/1 white Human Soldier creature token. + this.addAbility(new ValiantRescuerTriggeredAbility()); + + // Cycling {2} + this.addAbility(new CyclingAbility(new ManaCostsImpl("{2}"))); + } + + private ValiantRescuer(final ValiantRescuer card) { + super(card); + } + + @Override + public ValiantRescuer copy() { + return new ValiantRescuer(this); + } +} + +class ValiantRescuerTriggeredAbility extends TriggeredAbilityImpl { + + ValiantRescuerTriggeredAbility() { + super(Zone.BATTLEFIELD, new CreateTokenEffect(new HumanSoldierToken())); + this.addWatcher(new ValiantRescuerWatcher()); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + ValiantRescuerWatcher watcher = game.getState().getWatcher(ValiantRescuerWatcher.class); + if (watcher == null + || !watcher.checkSpell(event.getPlayerId(), event.getSourceId()) + || game.getState().getStack().isEmpty() + || !event.getPlayerId().equals(this.getControllerId()) + || event.getSourceId().equals(this.getSourceId())) { + return false; + } + StackObject item = game.getState().getStack().getFirst(); + return item instanceof StackAbility + && item.getStackAbility() instanceof CyclingAbility; + } + + @Override + public TriggeredAbility copy() { + return null; + } +} + +class ValiantRescuerWatcher extends Watcher { + + private final Map> playerMap = new HashMap(); + + ValiantRescuerWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + if (game.getState().getStack().isEmpty()) { + return; + } + StackObject item = game.getState().getStack().getFirst(); + if (item instanceof StackAbility + && item.getStackAbility() instanceof CyclingAbility) { + playerMap.computeIfAbsent(event.getPlayerId(), u -> new HashMap()); + playerMap.get(event.getPlayerId()).compute(event.getSourceId(), (u, i) -> i == null ? 1 : i + 1); + } + } + + @Override + public void reset() { + super.reset(); + playerMap.clear(); + } + + boolean checkSpell(UUID playerId, UUID cardId) { + if (!playerMap.containsKey(playerId)) { + return true; + } + Map cardMap = playerMap.get(playerId); + return cardMap.keySet().stream().filter(uuid -> !uuid.equals(cardId)).mapToInt(cardMap::get).sum() < 2; + } +} diff --git a/Mage.Sets/src/mage/sets/IkoriaLairOfBehemoths.java b/Mage.Sets/src/mage/sets/IkoriaLairOfBehemoths.java index cc311f0466..56e8e82cdb 100644 --- a/Mage.Sets/src/mage/sets/IkoriaLairOfBehemoths.java +++ b/Mage.Sets/src/mage/sets/IkoriaLairOfBehemoths.java @@ -325,6 +325,7 @@ public final class IkoriaLairOfBehemoths extends ExpansionSet { cards.add(new SetCardInfo("Unlikely Aid", 103, Rarity.COMMON, mage.cards.u.UnlikelyAid.class)); cards.add(new SetCardInfo("Unpredictable Cyclone", 139, Rarity.RARE, mage.cards.u.UnpredictableCyclone.class)); cards.add(new SetCardInfo("Vadrok, Apex of Thunder", 214, Rarity.MYTHIC, mage.cards.v.VadrokApexOfThunder.class)); + cards.add(new SetCardInfo("Valiant Rescuer", 36, Rarity.UNCOMMON, mage.cards.v.ValiantRescuer.class)); cards.add(new SetCardInfo("Vivien, Monsters' Advocate", 175, Rarity.MYTHIC, mage.cards.v.VivienMonstersAdvocate.class)); cards.add(new SetCardInfo("Void Beckoner", 104, Rarity.UNCOMMON, mage.cards.v.VoidBeckoner.class)); cards.add(new SetCardInfo("Voracious Greatshark", 70, Rarity.RARE, mage.cards.v.VoraciousGreatshark.class));