diff --git a/Mage.Sets/src/mage/cards/f/FrogkinKidnapper.java b/Mage.Sets/src/mage/cards/f/FrogkinKidnapper.java new file mode 100644 index 00000000000..6cd928951b5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FrogkinKidnapper.java @@ -0,0 +1,164 @@ + +package mage.cards.f; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.SpecialAction; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.CreateSpecialActionEffect; +import mage.abilities.effects.common.RemoveSpecialActionEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.*; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetOpponent; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class FrogkinKidnapper extends CardImpl { + + public FrogkinKidnapper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + this.subtype.add(SubType.FROG); + this.subtype.add(SubType.ROGUE); + + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // When Frogkin Kidnapper enters the battlefield, target opponent reveals their hand. Choose a nonland card from it. Ransom that card. (Exile it. Its owner may pay {3} at any time to return it to their hand.) + Ability ability = new EntersBattlefieldTriggeredAbility( + new FrogkinKidnapperEffect() + ); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + private FrogkinKidnapper(final FrogkinKidnapper card) { + super(card); + } + + @Override + public FrogkinKidnapper copy() { + return new FrogkinKidnapper(this); + } +} + +class FrogkinKidnapperEffect extends OneShotEffect { + + FrogkinKidnapperEffect() { + super(Outcome.Exile); + this.staticText = "target opponent reveals their hand. Choose a nonland card from it. " + + "Ransom that card. (Exile it. Its owner may pay {3} at any time to return it to their hand.)"; + } + + private FrogkinKidnapperEffect(final FrogkinKidnapperEffect effect) { + super(effect); + } + + @Override + public FrogkinKidnapperEffect copy() { + return new FrogkinKidnapperEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player opponent = game.getPlayer(source.getFirstTarget()); + Player controller = game.getPlayer(source.getControllerId()); + if (opponent == null || controller == null) { + return false; + } + opponent.revealCards(source, opponent.getHand(), game); + TargetCard target = new TargetCard(1, Zone.HAND, StaticFilters.FILTER_CARD_A_NON_LAND); + Cards toRansom = new CardsImpl(); + if (controller.chooseTarget(outcome, opponent.getHand(), target, source, game)) { + toRansom.addAll(target.getTargets()); + + String exileName = "Ransomed (owned by " + opponent.getName() + ")"; + UUID exileId = CardUtil.getExileZoneId("Ransom|" + opponent.getId(), game); + + for (Card card : toRansom.getCards(game)) { + card.moveToExile(exileId, exileName, source, game); + + MageObjectReference mor = new MageObjectReference(card, game); + SpecialAction specialAction = new FrogkinKidnapperSpecialAction(card.getIdName()); + specialAction.getEffects().setTargetPointer(new FixedTarget(mor)); + new CreateSpecialActionEffect(specialAction, opponent.getId()).apply(game, source); + + // Create a hidden delayed triggered ability to remove the special action when the card leaves the zone. + new CreateDelayedTriggeredAbilityEffect( + new FrogkinKidnapperTriggeredAbility(mor, specialAction.getId()), + false + ).apply(game, source); + } + } + return true; + } +} + +class FrogkinKidnapperSpecialAction extends SpecialAction { + + FrogkinKidnapperSpecialAction(String idName) { + super(); + this.addCost(new GenericManaCost(3)); + this.addEffect(new ReturnToHandTargetEffect().setText("return " + idName + " to your hand. (Ransomed)")); + } + + private FrogkinKidnapperSpecialAction(final FrogkinKidnapperSpecialAction ability) { + super(ability); + } + + @Override + public FrogkinKidnapperSpecialAction copy() { + return new FrogkinKidnapperSpecialAction(this); + } + +} + +class FrogkinKidnapperTriggeredAbility extends DelayedTriggeredAbility { + + private final MageObjectReference mor; + + FrogkinKidnapperTriggeredAbility(MageObjectReference mor, UUID specialActionId) { + super(new RemoveSpecialActionEffect(specialActionId), Duration.OneUse); + this.usesStack = false; + this.setRuleVisible(false); + this.mor = mor; + } + + private FrogkinKidnapperTriggeredAbility(final FrogkinKidnapperTriggeredAbility ability) { + super(ability); + this.mor = ability.mor; + } + + @Override + public FrogkinKidnapperTriggeredAbility copy() { + return new FrogkinKidnapperTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + return zEvent.getFromZone() == Zone.EXILED + && zEvent.getTargetId().equals(mor.getSourceId()); + } +} diff --git a/Mage.Sets/src/mage/sets/MysteryBoosterPlaytest.java b/Mage.Sets/src/mage/sets/MysteryBoosterPlaytest.java index ea3e81ea6df..0c7558bb656 100644 --- a/Mage.Sets/src/mage/sets/MysteryBoosterPlaytest.java +++ b/Mage.Sets/src/mage/sets/MysteryBoosterPlaytest.java @@ -24,6 +24,7 @@ public class MysteryBoosterPlaytest extends ExpansionSet { this.hasBasicLands = false; cards.add(new SetCardInfo("Banding Sliver", 2, Rarity.RARE, mage.cards.b.BandingSliver.class)); + cards.add(new SetCardInfo("Frogkin Kidnapper", 42, Rarity.RARE, mage.cards.f.FrogkinKidnapper.class)); cards.add(new SetCardInfo("How to Keep an Izzet Mage Busy", 93, Rarity.RARE, mage.cards.h.HowToKeepAnIzzetMageBusy.class)); cards.add(new SetCardInfo("Recycla-bird", 28, Rarity.RARE, mage.cards.r.RecyclaBird.class)); cards.add(new SetCardInfo("Slivdrazi Monstrosity", 102, Rarity.RARE, mage.cards.s.SlivdraziMonstrosity.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateSpecialActionEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateSpecialActionEffect.java index d8c1fc8a517..5766aba546a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateSpecialActionEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateSpecialActionEffect.java @@ -6,21 +6,30 @@ import mage.abilities.SpecialAction; import mage.abilities.effects.OneShotEffect; import mage.game.Game; +import java.util.UUID; + /** * @author BetaSteward_at_googlemail.com */ public class CreateSpecialActionEffect extends OneShotEffect { - protected SpecialAction action; + private final SpecialAction action; + private final UUID playerId; // If set, that player can activate the special action. If null, use the source controller instead. public CreateSpecialActionEffect(SpecialAction action) { + this(action, null); + } + + public CreateSpecialActionEffect(SpecialAction action, UUID playerId) { super(action.getEffects().getOutcome(action)); this.action = action; + this.playerId = playerId; } protected CreateSpecialActionEffect(final CreateSpecialActionEffect effect) { super(effect); this.action = (SpecialAction) effect.action.copy(); + this.playerId = effect.playerId; } @Override @@ -32,7 +41,7 @@ public class CreateSpecialActionEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { SpecialAction newAction = (SpecialAction) action.copy(); newAction.setSourceId(source.getSourceId()); - newAction.setControllerId(source.getControllerId()); + newAction.setControllerId(playerId == null ? source.getControllerId() : playerId); newAction.getTargets().addAll(source.getTargets()); game.getState().getSpecialActions().add(newAction); return true;