From 18097e12483a8896035aabf32ab50fb7d10f2eac Mon Sep 17 00:00:00 2001 From: Colin Redman Date: Fri, 3 Aug 2018 00:29:44 -0600 Subject: [PATCH] Implemented Emissary of Grudges Moved Leonin Stalker ability and cost to common classes --- .../src/mage/cards/e/EmissaryOfGrudges.java | 116 +++++++++++++++++ .../src/mage/cards/s/StalkingLeonin.java | 120 +----------------- Mage.Sets/src/mage/sets/Commander2018.java | 1 + .../common/RevealSecretOpponentCost.java | 68 ++++++++++ .../common/ChooseSecretOpponentEffect.java | 68 ++++++++++ 5 files changed, 260 insertions(+), 113 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/e/EmissaryOfGrudges.java create mode 100644 Mage/src/main/java/mage/abilities/costs/common/RevealSecretOpponentCost.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/ChooseSecretOpponentEffect.java diff --git a/Mage.Sets/src/mage/cards/e/EmissaryOfGrudges.java b/Mage.Sets/src/mage/cards/e/EmissaryOfGrudges.java new file mode 100644 index 0000000000..9bd4c2fa1f --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EmissaryOfGrudges.java @@ -0,0 +1,116 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.RevealSecretOpponentCost; +import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseSecretOpponentEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetStackObject; + +import java.util.UUID; + +/** + * + * @author credman0 + */ +public class EmissaryOfGrudges extends CardImpl { + + public EmissaryOfGrudges(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}"); + + this.subtype.add(SubType.EFREET); + this.power = new MageInt(6); + this.toughness = new MageInt(5); + + // flying + this.addAbility(FlyingAbility.getInstance()); + // haste + this.addAbility(HasteAbility.getInstance()); + + // As Emissary of Grudges enters the battlefield, secretly choose an opponent. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new EntersBattlefieldEffect(new ChooseSecretOpponentEffect(),"As {this} enters the battlefield, secretly choose an opponent."))); + // Choose new targets for target spell or ability if it’s controlled by the chosen player and if it targets you + // or a permanent you control. Activate this ability only once. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new EmissaryOfGrudgesEffect(), new RevealSecretOpponentCost()); + ability.addTarget(new TargetStackObject()); + this.addAbility(ability); + } + + public EmissaryOfGrudges(final EmissaryOfGrudges card) { + super(card); + } + + @Override + public EmissaryOfGrudges copy() { + return new EmissaryOfGrudges(this); + } +} + +class EmissaryOfGrudgesEffect extends OneShotEffect { + + public EmissaryOfGrudgesEffect() { + super(Outcome.Neutral); + this.staticText = "Choose new targets for target spell or ability if it’s controlled by the chosen player and" + + " if it targets you or a permanent you control. Activate this ability only once."; + } + + public EmissaryOfGrudgesEffect(final EmissaryOfGrudgesEffect effect) { + super(effect); + } + + @Override + public EmissaryOfGrudgesEffect copy() { + return new EmissaryOfGrudgesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget()); + if (stackObject != null) { + UUID opponentId = (UUID) game.getState().getValue(source.getSourceId() + ChooseSecretOpponentEffect.SECRET_OPPONENT); + if (opponentId != null && opponentId.equals(stackObject.getControllerId())) { + // find if it targets you or a permanent you control + boolean targetsYouOrAPermanentYouControl = false; + for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) { + Mode mode = stackObject.getStackAbility().getModes().get(modeId); + for (Target target : mode.getTargets()) { + for (UUID targetId : target.getTargets()) { + if (source.getControllerId().equals(targetId)) { + targetsYouOrAPermanentYouControl = true; + } + Permanent permanent = game.getPermanent(targetId); + if (permanent != null && source.getControllerId().equals(permanent.getControllerId())) { + targetsYouOrAPermanentYouControl = true; + } + } + } + } + if (targetsYouOrAPermanentYouControl){ + return stackObject.chooseNewTargets(game, source.getControllerId(), false, false, null); + } + } + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/StalkingLeonin.java b/Mage.Sets/src/mage/cards/s/StalkingLeonin.java index c07650cbe7..851483b435 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingLeonin.java +++ b/Mage.Sets/src/mage/cards/s/StalkingLeonin.java @@ -1,19 +1,15 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.Cost; -import mage.abilities.costs.CostImpl; +import mage.abilities.costs.common.RevealSecretOpponentCost; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseSecretOpponentEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import static mage.cards.s.StalkingLeonin.SECRET_OPPONENT; -import static mage.cards.s.StalkingLeonin.SECRET_OWNER; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; @@ -23,8 +19,8 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.FilterCreatureAttackingYou; import mage.target.common.TargetCreaturePermanent; -import mage.target.common.TargetOpponent; -import mage.util.CardUtil; + +import java.util.UUID; /** * @@ -32,9 +28,6 @@ import mage.util.CardUtil; */ public final class StalkingLeonin extends CardImpl { - static final String SECRET_OPPONENT = "_secOpp"; - static final String SECRET_OWNER = "_secOwn"; - public StalkingLeonin(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); @@ -43,9 +36,9 @@ public final class StalkingLeonin extends CardImpl { this.toughness = new MageInt(3); // When Stalking Leonin enters the battlefield, secretly choose an opponent. - this.addAbility(new EntersBattlefieldTriggeredAbility(new StalkingLeoninChooseOpponent(), false)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new ChooseSecretOpponentEffect(), false)); // Reveal the player you chose: Exile target creature that's attacking you if it's controlled by the chosen player. Activate this ability only once. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new StalkingLeoninEffect(), new StalkingLeoninRevealOpponentCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new StalkingLeoninEffect(), new RevealSecretOpponentCost()); ability.addTarget(new TargetCreaturePermanent(new FilterCreatureAttackingYou())); this.addAbility(ability); } @@ -60,105 +53,6 @@ public final class StalkingLeonin extends CardImpl { } } -class StalkingLeoninChooseOpponent extends OneShotEffect { - - public StalkingLeoninChooseOpponent() { - super(Outcome.Neutral); - staticText = "secretly choose an opponent"; - } - - public StalkingLeoninChooseOpponent(final StalkingLeoninChooseOpponent effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject mageObject = game.getPermanentEntering(source.getSourceId()); - if (mageObject == null) { - mageObject = game.getObject(source.getSourceId()); - } - if (controller != null && mageObject != null) { - TargetOpponent targetOpponent = new TargetOpponent(); - targetOpponent.setTargetName("opponent (secretly)"); - while (!controller.choose(outcome, targetOpponent, source.getSourceId(), game)) { - if (!controller.canRespond()) { - return false; - } - } - if (targetOpponent.getTargets().isEmpty()) { - return false; - } - if (!game.isSimulation()) { - game.informPlayers(mageObject.getName() + ": " + controller.getLogName() + " has secretly chosen an opponent."); - } - game.getState().setValue(mageObject.getId() + SECRET_OPPONENT, targetOpponent.getTargets().get(0)); - game.getState().setValue(mageObject.getId() + SECRET_OWNER, controller.getId()); - if (mageObject instanceof Permanent) { - ((Permanent) mageObject).addInfo(SECRET_OPPONENT, - CardUtil.addToolTipMarkTags(controller.getLogName() + " has secretly chosen an opponent."), game); - } - } - return false; - } - - @Override - public StalkingLeoninChooseOpponent copy() { - return new StalkingLeoninChooseOpponent(this); - } - -} - -class StalkingLeoninRevealOpponentCost extends CostImpl { - - public StalkingLeoninRevealOpponentCost() { - this.text = "Reveal the player you chose"; - } - - public StalkingLeoninRevealOpponentCost(final StalkingLeoninRevealOpponentCost cost) { - super(cost); - } - - @Override - public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { - UUID playerThatChoseId = (UUID) game.getState().getValue(sourceId + SECRET_OWNER); - if (playerThatChoseId == null || !playerThatChoseId.equals(controllerId)) { - return false; - } - UUID opponentId = (UUID) game.getState().getValue(sourceId + SECRET_OPPONENT); - return opponentId != null; - } - - @Override - public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { - UUID playerThatChoseId = (UUID) game.getState().getValue(sourceId + SECRET_OWNER); - if (playerThatChoseId == null || !playerThatChoseId.equals(controllerId)) { - return false; - } - UUID opponentId = (UUID) game.getState().getValue(sourceId + SECRET_OPPONENT); - if (opponentId != null) { - game.getState().setValue(sourceId + SECRET_OWNER, null); // because only once, the vale is set to null - Player controller = game.getPlayer(controllerId); - Player opponent = game.getPlayer(opponentId); - MageObject sourceObject = game.getObject(sourceId); - if (controller != null && opponent != null && sourceObject != null) { - if (sourceObject instanceof Permanent) { - ((Permanent) sourceObject).addInfo(SECRET_OPPONENT, null, game); - } - game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " reveals the secretly chosen opponent " + opponent.getLogName()); - } - paid = true; - } - return paid; - } - - @Override - public StalkingLeoninRevealOpponentCost copy() { - return new StalkingLeoninRevealOpponentCost(this); - } - -} - class StalkingLeoninEffect extends OneShotEffect { public StalkingLeoninEffect() { @@ -181,7 +75,7 @@ class StalkingLeoninEffect extends OneShotEffect { if (controller != null) { Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); if (targetCreature != null) { - UUID opponentId = (UUID) game.getState().getValue(source.getSourceId() + SECRET_OPPONENT); + UUID opponentId = (UUID) game.getState().getValue(source.getSourceId() + ChooseSecretOpponentEffect.SECRET_OPPONENT); if (opponentId != null && opponentId.equals(targetCreature.getControllerId())) { controller.moveCards(targetCreature, Zone.EXILED, source, game); } diff --git a/Mage.Sets/src/mage/sets/Commander2018.java b/Mage.Sets/src/mage/sets/Commander2018.java index 7f1aeea8b0..2bdecbe2fe 100644 --- a/Mage.Sets/src/mage/sets/Commander2018.java +++ b/Mage.Sets/src/mage/sets/Commander2018.java @@ -98,6 +98,7 @@ public final class Commander2018 extends ExpansionSet { cards.add(new SetCardInfo("Eel Umbra", 89, Rarity.COMMON, mage.cards.e.EelUmbra.class)); cards.add(new SetCardInfo("Eidolon of Blossoms", 140, Rarity.RARE, mage.cards.e.EidolonOfBlossoms.class)); cards.add(new SetCardInfo("Elderwood Scion", 177, Rarity.RARE, mage.cards.e.ElderwoodScion.class)); + cards.add(new SetCardInfo("Emissary of Grudges", 20, Rarity.RARE, mage.cards.e.EmissaryOfGrudges.class)); cards.add(new SetCardInfo("Empyrial Storm", 2, Rarity.RARE, mage.cards.e.EmpyrialStorm.class)); cards.add(new SetCardInfo("Enchanter's Bane", 21, Rarity.RARE, mage.cards.e.EnchantersBane.class)); cards.add(new SetCardInfo("Enchantress's Presence", 141, Rarity.RARE, mage.cards.e.EnchantresssPresence.class)); diff --git a/Mage/src/main/java/mage/abilities/costs/common/RevealSecretOpponentCost.java b/Mage/src/main/java/mage/abilities/costs/common/RevealSecretOpponentCost.java new file mode 100644 index 0000000000..daf8d54be5 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/costs/common/RevealSecretOpponentCost.java @@ -0,0 +1,68 @@ +package mage.abilities.costs.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.effects.common.ChooseSecretOpponentEffect; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * + * @author LevelX2 + * @author credman0 + */ +public class RevealSecretOpponentCost extends CostImpl { + + public RevealSecretOpponentCost() { + this.text = "Reveal the player you chose"; + } + + public RevealSecretOpponentCost(final RevealSecretOpponentCost cost) { + super(cost); + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + UUID playerThatChoseId = (UUID) game.getState().getValue(sourceId + ChooseSecretOpponentEffect.SECRET_OWNER); + if (playerThatChoseId == null || !playerThatChoseId.equals(controllerId)) { + return false; + } + UUID opponentId = (UUID) game.getState().getValue(sourceId + ChooseSecretOpponentEffect.SECRET_OPPONENT); + return opponentId != null; + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { + UUID playerThatChoseId = (UUID) game.getState().getValue(sourceId + ChooseSecretOpponentEffect.SECRET_OWNER); + if (playerThatChoseId == null || !playerThatChoseId.equals(controllerId)) { + return false; + } + UUID opponentId = (UUID) game.getState().getValue(sourceId + ChooseSecretOpponentEffect.SECRET_OPPONENT); + if (opponentId != null) { + game.getState().setValue(sourceId + ChooseSecretOpponentEffect.SECRET_OWNER, null); // because only once, the vale is set to null + Player controller = game.getPlayer(controllerId); + Player opponent = game.getPlayer(opponentId); + MageObject sourceObject = game.getObject(sourceId); + if (controller != null && opponent != null && sourceObject != null) { + if (sourceObject instanceof Permanent) { + ((Permanent) sourceObject).addInfo(ChooseSecretOpponentEffect.SECRET_OPPONENT, null, game); + } + game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " reveals the secretly chosen opponent " + opponent.getLogName()); + } + paid = true; + } + return paid; + } + + @Override + public RevealSecretOpponentCost copy() { + return new RevealSecretOpponentCost(this); + } + + +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/ChooseSecretOpponentEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ChooseSecretOpponentEffect.java new file mode 100644 index 0000000000..6c1a8ba5c6 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/ChooseSecretOpponentEffect.java @@ -0,0 +1,68 @@ +package mage.abilities.effects.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetOpponent; +import mage.util.CardUtil; +/** + * + * @author LevelX2 + * @author credman0 + */ +public class ChooseSecretOpponentEffect extends OneShotEffect { + + public static final String SECRET_OPPONENT = "_secOpp"; + public static final String SECRET_OWNER = "_secOwn"; + + public ChooseSecretOpponentEffect() { + super(Outcome.Neutral); + staticText = "secretly choose an opponent"; + } + + public ChooseSecretOpponentEffect(final ChooseSecretOpponentEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject mageObject = game.getPermanentEntering(source.getSourceId()); + if (mageObject == null) { + mageObject = game.getObject(source.getSourceId()); + } + if (controller != null && mageObject != null) { + TargetOpponent targetOpponent = new TargetOpponent(); + targetOpponent.setTargetName("opponent (secretly)"); + while (!controller.choose(outcome, targetOpponent, source.getSourceId(), game)) { + if (!controller.canRespond()) { + return false; + } + } + if (targetOpponent.getTargets().isEmpty()) { + return false; + } + if (!game.isSimulation()) { + game.informPlayers(mageObject.getName() + ": " + controller.getLogName() + " has secretly chosen an opponent."); + } + game.getState().setValue(mageObject.getId() + SECRET_OPPONENT, targetOpponent.getTargets().get(0)); + game.getState().setValue(mageObject.getId() + SECRET_OWNER, controller.getId()); + if (mageObject instanceof Permanent) { + ((Permanent) mageObject).addInfo(SECRET_OPPONENT, + CardUtil.addToolTipMarkTags(controller.getLogName() + " has secretly chosen an opponent."), game); + } + } + return false; + } + + @Override + public ChooseSecretOpponentEffect copy() { + return new ChooseSecretOpponentEffect(this); + } + + +}