From cec8c544017920670619dcbe99a8a8b46be140a0 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 24 Apr 2022 17:20:57 -0400 Subject: [PATCH] [SNC] Implemented Ziatora's Envoy --- Mage.Sets/src/mage/cards/z/ZiatorasEnvoy.java | 138 ++++++++++++++++++ .../src/mage/sets/StreetsOfNewCapenna.java | 1 + ...CombatDamageToAPlayerTriggeredAbility.java | 2 +- .../main/java/mage/players/PlayerImpl.java | 6 +- 4 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/z/ZiatorasEnvoy.java diff --git a/Mage.Sets/src/mage/cards/z/ZiatorasEnvoy.java b/Mage.Sets/src/mage/cards/z/ZiatorasEnvoy.java new file mode 100644 index 00000000000..e146c3b6426 --- /dev/null +++ b/Mage.Sets/src/mage/cards/z/ZiatorasEnvoy.java @@ -0,0 +1,138 @@ +package mage.cards.z; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.BlitzAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.*; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.ManaValuePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; +import mage.util.RandomUtil; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ZiatorasEnvoy extends CardImpl { + + public ZiatorasEnvoy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{R}{G}"); + + this.subtype.add(SubType.VIASHINO); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Whenever Ziatora's Envoy deals combat damage to a player, look at the top card of your library. You may play a land from the top of your library or cast a spell with mana value less than or equal to the damage dealt from the top of your library without paying its mana cost. If you don't, put that card into your hand. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ZiatorasEnvoyEffect(), false)); + + // Blitz {2}{B}{R}{G} + this.addAbility(new BlitzAbility(this, "{2}{B}{R}{G}")); + } + + private ZiatorasEnvoy(final ZiatorasEnvoy card) { + super(card); + } + + @Override + public ZiatorasEnvoy copy() { + return new ZiatorasEnvoy(this); + } +} + +class ZiatorasEnvoyEffect extends OneShotEffect { + + ZiatorasEnvoyEffect() { + super(Outcome.Benefit); + staticText = "look at the top card of your library. You may play a land from the top of your library " + + "or cast a spell with mana value less than or equal to the damage dealt from the top of your " + + "library without paying its mana cost. If you don't, put that card into your hand"; + } + + private ZiatorasEnvoyEffect(final ZiatorasEnvoyEffect effect) { + super(effect); + } + + @Override + public ZiatorasEnvoyEffect copy() { + return new ZiatorasEnvoyEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Card card = player.getLibrary().getFromTop(game); + if (card == null) { + return false; + } + player.lookAtCards("Top of your library", card, game); + Cards cards = new CardsImpl(card); + // TODO: factor this out and reuse for other cards + if (player.canPlayLand()) { + Set landSet = new HashSet<>(); + if (card instanceof ModalDoubleFacesCard) { + ModalDoubleFacesCard mdfc = (ModalDoubleFacesCard) card; + if (mdfc.getLeftHalfCard().isLand(game)) { + landSet.add(mdfc.getLeftHalfCard()); + } + if (mdfc.getRightHalfCard().isLand(game)) { + landSet.add(mdfc.getRightHalfCard()); + } + } else if (card.isLand(game)) { + landSet.add(card); + } + Card land; + if (!landSet.isEmpty() && player.chooseUse( + Outcome.PutLandInPlay, "Play " + card.getName() + " as a land?", source, game + )) { + switch (landSet.size()) { + case 1: + land = RandomUtil.randomFromCollection(landSet); + break; + case 2: + Iterator iterator = landSet.iterator(); + Card land1 = iterator.next(); + Card land2 = iterator.next(); + land = player.chooseUse( + outcome, "Choose which land to play ", null, + land1.getName(), land2.getName(), source, game + ) ? land1 : land2; + break; + default: + land = null; + } + } else { + land = null; + } + if (land != null) { + player.playLand(land, game, true); + } + } + cards.retainZone(Zone.LIBRARY, game); + if (cards.isEmpty()) { + return true; + } + int damage = (Integer) this.getValue("damage"); + FilterCard filter = new FilterCard(); + filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, damage + 1)); + CardUtil.castSpellWithAttributesForFree(player, source, game, cards, filter); + cards.retainZone(Zone.LIBRARY, game); + return cards.isEmpty() || player.moveCards(cards, Zone.HAND, source, game); + } +} diff --git a/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java b/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java index 2c4a4fcaea0..8d8035a1a1b 100644 --- a/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java +++ b/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java @@ -282,6 +282,7 @@ public final class StreetsOfNewCapenna extends ExpansionSet { cards.add(new SetCardInfo("Workshop Warchief", 165, Rarity.RARE, mage.cards.w.WorkshopWarchief.class)); cards.add(new SetCardInfo("Wrecking Crew", 132, Rarity.COMMON, mage.cards.w.WreckingCrew.class)); cards.add(new SetCardInfo("Xander's Lounge", 260, Rarity.RARE, mage.cards.x.XandersLounge.class)); + cards.add(new SetCardInfo("Ziatora's Envoy", 232, Rarity.RARE, mage.cards.z.ZiatorasEnvoy.class)); cards.add(new SetCardInfo("Ziatora's Proving Ground", 261, Rarity.RARE, mage.cards.z.ZiatorasProvingGround.class)); cards.add(new SetCardInfo("Ziatora, the Incinerator", 231, Rarity.MYTHIC, mage.cards.z.ZiatoraTheIncinerator.class)); } diff --git a/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java index f62306e734a..1d0bfcc6565 100644 --- a/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java @@ -83,9 +83,9 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility return false; } } + getAllEffects().setValue("damage", event.getAmount()); if (setTargetPointer) { getAllEffects().setTargetPointer(new FixedTarget(event.getPlayerId())); - getAllEffects().setValue("damage", event.getAmount()); } return true; } diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index d07e39ccf39..a03d9521f46 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1288,8 +1288,10 @@ public abstract class PlayerImpl implements Player, Serializable { //20091005 - 114.2a ActivationStatus activationStatus = playLandAbility.canActivate(this.playerId, game); if (ignoreTiming) { - if (!canPlayLand()) { - return false; // ignore timing does not mean that more lands than normal can be played + if (!canPlayLand() || !isActivePlayer(game)) { + // ignore timing does not mean that more lands than normal can be played + // it also has to be your turn + return false; } } else { if (!activationStatus.canActivate()) {