From a26d9b2fd0009ad083f9c8778c260a7f94fc96be Mon Sep 17 00:00:00 2001 From: Daniel Bomar Date: Fri, 22 Jan 2021 12:13:20 -0600 Subject: [PATCH] [KHM] Implemented The Raven's Warning (#7425) --- .../src/mage/cards/t/TheRavensWarning.java | 117 ++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + .../common/LookAtTargetPlayerHandEffect.java | 2 +- .../abilities/effects/common/WishEffect.java | 20 ++- 4 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/t/TheRavensWarning.java diff --git a/Mage.Sets/src/mage/cards/t/TheRavensWarning.java b/Mage.Sets/src/mage/cards/t/TheRavensWarning.java new file mode 100644 index 0000000000..832b944f9a --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheRavensWarning.java @@ -0,0 +1,117 @@ +package mage.cards.t; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.SagaAbility; +import mage.abilities.effects.common.*; +import mage.abilities.keyword.FlyingAbility; +import mage.constants.Duration; +import mage.constants.SagaChapter; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.OwlToken; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author weirddan455 + */ +public final class TheRavensWarning extends CardImpl { + + public TheRavensWarning(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{U}"); + + this.subtype.add(SubType.SAGA); + + // (As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.) + SagaAbility sagaAbility = new SagaAbility(this, SagaChapter.CHAPTER_III); + + // I — Create a 1/1 blue Bird creature token with flying. You gain 2 life. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, + new CreateTokenEffect(new OwlToken()), new GainLifeEffect(2) + ); + + // II — Whenever one or more creatures you control with flying deal combat damage to a player this turn, + // look at that player's hand and draw a card. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_II, new CreateDelayedTriggeredAbilityEffect( + new TheRavensWarningTriggeredAbility(), false, false + )); + + // III — You may put a card you own from outside the game on top of your library. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, + new WishEffect(StaticFilters.FILTER_CARD_A, false, false, true) + ); + this.addAbility(sagaAbility); + } + + private TheRavensWarning(final TheRavensWarning card) { + super(card); + } + + @Override + public TheRavensWarning copy() { + return new TheRavensWarning(this); + } +} + +class TheRavensWarningTriggeredAbility extends DelayedTriggeredAbility { + + private final Set damagedPlayerIds = new HashSet<>(); + + public TheRavensWarningTriggeredAbility() { + super(new LookAtTargetPlayerHandEffect(), Duration.EndOfTurn, false); + this.addEffect(new DrawCardSourceControllerEffect(1)); + } + + private TheRavensWarningTriggeredAbility(final TheRavensWarningTriggeredAbility ability) { + super(ability); + } + + @Override + public TheRavensWarningTriggeredAbility copy() { + return new TheRavensWarningTriggeredAbility(this); + } + + // Code based on ControlledCreaturesDealCombatDamagePlayerTriggeredAbility + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER + || event.getType() == GameEvent.EventType.COMBAT_DAMAGE_STEP_PRIORITY + || event.getType() == GameEvent.EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) { + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; + Permanent p = game.getPermanent(event.getSourceId()); + if (damageEvent.isCombatDamage() && p != null && p.isControlledBy(this.getControllerId()) + && !damagedPlayerIds.contains(event.getPlayerId()) && p.hasAbility(FlyingAbility.getInstance(), game)) { + damagedPlayerIds.add(event.getPlayerId()); + this.getEffects().get(0).setTargetPointer(new FixedTarget(event.getPlayerId())); + return true; + } + } + if (event.getType() == GameEvent.EventType.COMBAT_DAMAGE_STEP_PRIORITY || + (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(getSourceId()))) { + damagedPlayerIds.clear(); + } + return false; + } + + @Override + public String getRule() { + return "Whenever one or more creatures you control with flying deal combat damage to a player this turn," + + " look at that player's hand and draw a card."; + } +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index ca1a67fc2c..a1b7a79bc6 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -319,6 +319,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Tergrid, God of Fright", 112, Rarity.RARE, mage.cards.t.TergridGodOfFright.class)); cards.add(new SetCardInfo("The Bears of Littjara", 205, Rarity.RARE, mage.cards.t.TheBearsOfLittjara.class)); cards.add(new SetCardInfo("The Bloodsky Massacre", 207, Rarity.RARE, mage.cards.t.TheBloodskyMassacre.class)); + cards.add(new SetCardInfo("The Raven's Warning", 227, Rarity.RARE, mage.cards.t.TheRavensWarning.class)); cards.add(new SetCardInfo("The Trickster-God's Heist", 232, Rarity.UNCOMMON, mage.cards.t.TheTricksterGodsHeist.class)); cards.add(new SetCardInfo("The World Tree", 275, Rarity.RARE, mage.cards.t.TheWorldTree.class)); cards.add(new SetCardInfo("Thornmantle Striker", 387, Rarity.UNCOMMON, mage.cards.t.ThornmantleStriker.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/LookAtTargetPlayerHandEffect.java b/Mage/src/main/java/mage/abilities/effects/common/LookAtTargetPlayerHandEffect.java index 42a414450d..2425125ea5 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/LookAtTargetPlayerHandEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/LookAtTargetPlayerHandEffect.java @@ -31,7 +31,7 @@ public class LookAtTargetPlayerHandEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player you = game.getPlayer(source.getControllerId()); - Player targetPlayer = game.getPlayer(source.getFirstTarget()); + Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source)); MageObject sourceObject = game.getObject(source.getSourceId()); if (you != null && targetPlayer != null) { you.lookAtCards(sourceObject != null ? sourceObject.getIdName() : null, targetPlayer.getHand(), game); diff --git a/Mage/src/main/java/mage/abilities/effects/common/WishEffect.java b/Mage/src/main/java/mage/abilities/effects/common/WishEffect.java index 92a59226bc..24fda8d7c6 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/WishEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/WishEffect.java @@ -25,6 +25,7 @@ public class WishEffect extends OneShotEffect { private final boolean reveal; private final boolean alsoFromExile; private final String choiceText; + private final boolean topOfLibrary; public WishEffect() { this(new FilterCard()); @@ -39,16 +40,20 @@ public class WishEffect extends OneShotEffect { } public WishEffect(FilterCard filter, boolean reveal, boolean alsoFromExile) { + this(filter, reveal, alsoFromExile, false); + } + + public WishEffect(FilterCard filter, boolean reveal, boolean alsoFromExile, boolean topOfLibrary) { super(Outcome.DrawCard); this.filter = filter; this.alsoFromExile = alsoFromExile; this.reveal = reveal; - choiceText = "Choose " + filter.getMessage() + " you own from outside the game" + this.topOfLibrary = topOfLibrary; + choiceText = (topOfLibrary ? "Put " : "Choose ") + filter.getMessage() + " you own from outside the game" + (alsoFromExile ? " or in exile" : "") + (reveal ? ", reveal that card," : "") - + " and put it into your hand."; - staticText = "You may c" + choiceText.substring(1, choiceText.length() - 1); - + + (topOfLibrary ? " on top of your library." : " and put it into your hand."); + staticText = "You may " + Character.toLowerCase(choiceText.charAt(0)) + choiceText.substring(1, choiceText.length() - 1); } public WishEffect(final WishEffect effect) { @@ -57,6 +62,7 @@ public class WishEffect extends OneShotEffect { this.alsoFromExile = effect.alsoFromExile; this.reveal = effect.reveal; this.choiceText = effect.choiceText; + this.topOfLibrary = effect.topOfLibrary; } @Override @@ -103,7 +109,11 @@ public class WishEffect extends OneShotEffect { card = game.getCard(target.getFirstTarget()); } if (card != null) { - card.moveToZone(Zone.HAND, source, game, false); + if (topOfLibrary) { + controller.putCardsOnTopOfLibrary(card, game, source, true); + } else { + card.moveToZone(Zone.HAND, source, game, false); + } if (reveal) { Cards revealCard = new CardsImpl(); revealCard.add(card);