diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java index 2a1811e8b8e..e670880fba1 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java @@ -404,7 +404,7 @@ public class ScryfallImageSupportCards { add("XANA"); // Arena New Player Experience Extras add("OANA"); // Arena New Player Experience Cards add("PS18"); // San Diego Comic-Con 2018 - //add("HTR17"); // Heroes of the Realm 2017 + add("PH17"); // Heroes of the Realm 2017 add("C18"); // Commander 2018 add("PGRN"); // Guilds of Ravnica Promos add("PRWK"); // GRN Ravnica Weekend diff --git a/Mage.Sets/src/mage/cards/i/InzervaMasterOfInsights.java b/Mage.Sets/src/mage/cards/i/InzervaMasterOfInsights.java new file mode 100644 index 00000000000..7a02e65e87e --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InzervaMasterOfInsights.java @@ -0,0 +1,100 @@ +package mage.cards.i; + +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.*; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.game.command.emblems.InzervaMasterOfInsightsEmblem; +import mage.players.Player; +import mage.target.TargetCard; + +import java.util.UUID; + +/** + * @author PurpleCrowbar + */ +public final class InzervaMasterOfInsights extends CardImpl { + + public InzervaMasterOfInsights(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{2/U}{2/R}"); + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.INZERVA); + this.setStartingLoyalty(4); + + // +2: Draw two cards, then discard a card. + this.addAbility(new LoyaltyAbility(new DrawDiscardControllerEffect(2, 1), 2)); + + // −2: Look at the top two cards of each other player's library, then put any number of them on the bottom of that library and the rest on top in any order. Scry 2. + LoyaltyAbility ability = new LoyaltyAbility(new InzervaMasterOfInsightsEffect(), -2); + ability.addEffect(new ScryEffect(2, false)); + this.addAbility(ability); + + // −4: You get an emblem with "Your opponents play with their hands revealed" and "Whenever an opponent draws a card, this emblem deals 1 damage to them." + this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new InzervaMasterOfInsightsEmblem()), -4)); + } + + private InzervaMasterOfInsights(final InzervaMasterOfInsights card) { + super(card); + } + + @Override + public InzervaMasterOfInsights copy() { + return new InzervaMasterOfInsights(this); + } +} + +class InzervaMasterOfInsightsEffect extends OneShotEffect { + + InzervaMasterOfInsightsEffect() { + super(Outcome.Benefit); + staticText = "Look at the top two cards of each other player's library, then put any number of them on the bottom of that library and the rest on top in any order"; + } + + private InzervaMasterOfInsightsEffect(final InzervaMasterOfInsightsEffect effect) { + super(effect); + } + + @Override + public InzervaMasterOfInsightsEffect copy() { + return new InzervaMasterOfInsightsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player opponent = game.getPlayer(playerId); + if (playerId.equals(controller.getId()) || opponent == null) { + continue; + } + Cards cards = new CardsImpl(); + int count = Math.min(2, opponent.getLibrary().size()); + if (count == 0) { + continue; + } + for (int i = 0; i < count; i++) { + Card card = opponent.getLibrary().removeFromTop(game); + cards.add(card); + } + TargetCard targets = new TargetCard(0, cards.size(), Zone.LIBRARY, new FilterCard("cards to PUT on the BOTTOM of " + opponent.getName() + "'s library")); + controller.chooseTarget(Outcome.Neutral, cards, targets, source, game); + if (!controller.canRespond() || !opponent.canRespond()) { + continue; + } + controller.putCardsOnBottomOfLibrary(new CardsImpl(targets.getTargets()), game, source, true); + cards.removeIf(targets.getTargets()::contains); + + controller.putCardsOnTopOfLibrary(cards, game, source, true); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/HeroesOfTheRealm2017.java b/Mage.Sets/src/mage/sets/HeroesOfTheRealm2017.java new file mode 100644 index 00000000000..a712e7615aa --- /dev/null +++ b/Mage.Sets/src/mage/sets/HeroesOfTheRealm2017.java @@ -0,0 +1,26 @@ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * https://scryfall.com/sets/ph17 + * @author PurpleCrowbar + */ +public class HeroesOfTheRealm2017 extends ExpansionSet { + + private static final HeroesOfTheRealm2017 instance = new HeroesOfTheRealm2017(); + + public static HeroesOfTheRealm2017 getInstance() { + return instance; + } + + private HeroesOfTheRealm2017() { + super("Heroes of the Realm 2017", "PH17", ExpansionSet.buildDate(2018, 8, 1), SetType.JOKESET); + this.hasBoosters = false; + this.hasBasicLands = false; + + cards.add(new SetCardInfo("Inzerva, Master of Insights", 2, Rarity.MYTHIC, mage.cards.i.InzervaMasterOfInsights.class)); + } +} diff --git a/Mage/src/main/java/mage/abilities/common/DrawCardOpponentTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DrawCardOpponentTriggeredAbility.java index a4e79936fe9..42f5f4dae2d 100644 --- a/Mage/src/main/java/mage/abilities/common/DrawCardOpponentTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DrawCardOpponentTriggeredAbility.java @@ -15,7 +15,11 @@ public class DrawCardOpponentTriggeredAbility extends TriggeredAbilityImpl { private final boolean setTargetPointer; public DrawCardOpponentTriggeredAbility(Effect effect, boolean optional, boolean setTargetPointer) { - super(Zone.BATTLEFIELD, effect, optional); + this(Zone.BATTLEFIELD, effect, optional, setTargetPointer); + } + + public DrawCardOpponentTriggeredAbility(Zone zone, Effect effect, boolean optional, boolean setTargetPointer) { + super(zone, effect, optional); this.setTargetPointer = setTargetPointer; setTriggerPhrase("Whenever an opponent draws a card, "); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayWithHandRevealedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayWithHandRevealedEffect.java index 220470f6cb1..824dd5d6765 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayWithHandRevealedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayWithHandRevealedEffect.java @@ -57,7 +57,7 @@ public class PlayWithHandRevealedEffect extends ContinuousEffectImpl { for (UUID playerID : affectedPlayers) { Player player = game.getPlayer(playerID); if (player != null) { - player.revealCards(player.getName() + "'s hand cards", player.getHand(), game, false); + player.revealCards("Cards in " + player.getName() + "'s hand", player.getHand(), game, false); } } return true; diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/FatesealEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/FatesealEffect.java index 81332c811ac..a8fffd829a5 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/FatesealEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/FatesealEffect.java @@ -48,8 +48,6 @@ public class FatesealEffect extends OneShotEffect { if (opponent == null) { return false; } - boolean revealed = opponent.isTopCardRevealed(); // by looking at the cards with fateseal you have not to reveal the next card - opponent.setTopCardRevealed(false); Cards cards = new CardsImpl(); int count = Math.min(fatesealNumber, opponent.getLibrary().size()); if (count == 0) { @@ -76,7 +74,6 @@ public class FatesealEffect extends OneShotEffect { // move cards to the top of the library controller.putCardsOnTopOfLibrary(cards, game, source, true); game.fireEvent(new GameEvent(GameEvent.EventType.FATESEALED, opponent.getId(), source, source.getControllerId())); - controller.setTopCardRevealed(revealed); return true; } diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index f1ff16e0d66..9408d21e0b5 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -464,6 +464,7 @@ public enum SubType { GRIST("Grist", SubTypeSet.PlaneswalkerType), GUFF("Guff", SubTypeSet.PlaneswalkerType), HUATLI("Huatli", SubTypeSet.PlaneswalkerType), + INZERVA("Inzerva", SubTypeSet.PlaneswalkerType), JACE("Jace", SubTypeSet.PlaneswalkerType), JARED("Jared", SubTypeSet.PlaneswalkerType), JESKA("Jeska", SubTypeSet.PlaneswalkerType), diff --git a/Mage/src/main/java/mage/game/command/emblems/InzervaMasterOfInsightsEmblem.java b/Mage/src/main/java/mage/game/command/emblems/InzervaMasterOfInsightsEmblem.java new file mode 100644 index 00000000000..cf3f474532d --- /dev/null +++ b/Mage/src/main/java/mage/game/command/emblems/InzervaMasterOfInsightsEmblem.java @@ -0,0 +1,39 @@ +package mage.game.command.emblems; + +import mage.abilities.common.DrawCardOpponentTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.PlayWithHandRevealedEffect; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.command.Emblem; + +/** + * @author PurpleCrowbar + */ +public final class InzervaMasterOfInsightsEmblem extends Emblem { + + // You get an emblem with "Your opponents play with their hands revealed" and "Whenever an opponent draws a card, this emblem deals 1 damage to them." + public InzervaMasterOfInsightsEmblem() { + super("Emblem Inzerva"); + // Your opponents play with their hands revealed + this.getAbilities().add(new SimpleStaticAbility( + Zone.COMMAND, + new PlayWithHandRevealedEffect(TargetController.OPPONENT) + )); + // Whenever an opponent draws a card, this emblem deals 1 damage to them + this.getAbilities().add(new DrawCardOpponentTriggeredAbility( + Zone.COMMAND, new DamageTargetEffect(1, true, "them") + .setText("this emblem deals 1 damage to them"), false, true + )); + } + + private InzervaMasterOfInsightsEmblem(final InzervaMasterOfInsightsEmblem card) { + super(card); + } + + @Override + public InzervaMasterOfInsightsEmblem copy() { + return new InzervaMasterOfInsightsEmblem(this); + } +} diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index b1698c4f49f..1fc300ac559 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -985,8 +985,11 @@ public abstract class PlayerImpl implements Player, Serializable { } } else { // user defined order + UUID cardOwner = cards.getRandom(game).getOwnerId(); TargetCard target = new TargetCard(Zone.ALL, - new FilterCard("card ORDER to put on the BOTTOM of your library (last one chosen will be bottommost)")); + new FilterCard("card ORDER to put on the BOTTOM of " + + (cardOwner.equals(playerId) ? "your" : game.getPlayer(cardOwner).getName() + "'s") + + " library (last one chosen will be bottommost)")); target.setRequired(true); while (cards.size() > 1 && this.canRespond() && this.choose(Outcome.Neutral, cards, target, source, game)) { @@ -1078,8 +1081,11 @@ public abstract class PlayerImpl implements Player, Serializable { } } else { // user defined order + UUID cardOwner = cards.getRandom(game).getOwnerId(); TargetCard target = new TargetCard(Zone.ALL, - new FilterCard("card ORDER to put on the TOP of your library (last one chosen will be topmost)")); + new FilterCard("card ORDER to put on the TOP of " + + (cardOwner.equals(playerId) ? "your" : game.getPlayer(cardOwner).getName() + "'s") + + " library (last one chosen will be topmost)")); target.setRequired(true); while (cards.size() > 1 && this.canRespond() diff --git a/Mage/src/main/resources/tokens-database.txt b/Mage/src/main/resources/tokens-database.txt index 17ac4ae9ff9..fea5905a58f 100644 --- a/Mage/src/main/resources/tokens-database.txt +++ b/Mage/src/main/resources/tokens-database.txt @@ -126,6 +126,7 @@ |Generate|EMBLEM:CMM|Emblem Narset|||NarsetOfTheAncientWayEmblem| |Generate|EMBLEM:CMM|Emblem Nixilis|||ObNixilisOfTheBlackOathEmblem| |Generate|EMBLEM:CMM|Emblem Teferi|||TeferiTemporalArchmageEmblem| +|Generate|EMBLEM:PH17|Emblem Inzerva|||InzervaMasterOfInsightsEmblem| |Generate|EMBLEM:LCC|Emblem Sorin|||SorinLordOfInnistradEmblem| |Generate|EMBLEM:RVR|Emblem Domri|||DomriRadeEmblem|