diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/BlazingShoal.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/BlazingShoal.java index 914f12f7039..66e1ea6f09b 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/BlazingShoal.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/BlazingShoal.java @@ -32,8 +32,11 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Rarity; import mage.ObjectColor; -import mage.abilities.costs.AlternativeCostImpl; +import mage.abilities.Ability; +import mage.abilities.costs.AlternativeCostSourceAbility; +import mage.abilities.costs.Cost; import mage.abilities.costs.common.ExileFromHandCost; +import mage.abilities.costs.common.PayLifeCost; import mage.abilities.dynamicvalue.common.ExileFromHandCostCardConvertedMana; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.continious.BoostTargetEffect; @@ -42,6 +45,7 @@ import mage.filter.common.FilterOwnedCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardIdPredicate; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; import mage.target.common.TargetCardInHand; import mage.target.common.TargetCreaturePermanent; @@ -51,8 +55,6 @@ import mage.target.common.TargetCreaturePermanent; */ public class BlazingShoal extends CardImpl { - private static final String ALTERNATIVE_COST_DESCRIPTION = "You may exile a red card with converted mana cost X from your hand rather than pay Blazing Shoal's mana cost"; - public BlazingShoal(UUID ownerId) { super(ownerId, 96, "Blazing Shoal", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{X}{R}{R}"); this.expansionSetCode = "BOK"; @@ -63,7 +65,10 @@ public class BlazingShoal extends CardImpl { FilterOwnedCard filter = new FilterOwnedCard("red card from your hand"); filter.add(new ColorPredicate(ObjectColor.RED)); filter.add(Predicates.not(new CardIdPredicate(this.getId()))); // the exile cost can never be paid with the card itself - this.getSpellAbility().addAlternativeCost(new AlternativeCostImpl(ALTERNATIVE_COST_DESCRIPTION, new ExileFromHandCost(new TargetCardInHand(filter)))); + + AlternativeCostSourceAbility ability = new BlazingShoalAlternativeCostAbility(new PayLifeCost(1)); + ability.addCost(new ExileFromHandCost(new TargetCardInHand(filter))); + this.addAbility(ability); // Target creature gets +X/+0 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(new ExileFromHandCostCardConvertedMana(), new StaticValue(0), Duration.EndOfTurn)); @@ -78,4 +83,20 @@ public class BlazingShoal extends CardImpl { public BlazingShoal copy() { return new BlazingShoal(this); } -} \ No newline at end of file +} + +class BlazingShoalAlternativeCostAbility extends AlternativeCostSourceAbility { + + public BlazingShoalAlternativeCostAbility(Cost cost) { + super(cost, null, null); + } + + @Override + public boolean askToActivateAlternativeCosts(Ability ability, Game game) { + if (super.askToActivateAlternativeCosts(ability, game)) { + + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/magic2014/BanisherPriest.java b/Mage.Sets/src/mage/sets/magic2014/BanisherPriest.java index 5c2184b2040..92ab38a8784 100644 --- a/Mage.Sets/src/mage/sets/magic2014/BanisherPriest.java +++ b/Mage.Sets/src/mage/sets/magic2014/BanisherPriest.java @@ -30,21 +30,25 @@ package mage.sets.magic2014; import java.util.LinkedList; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.Rarity; +import mage.constants.TargetController; import mage.constants.WatcherScope; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.WatcherImpl; @@ -54,7 +58,10 @@ import mage.watchers.WatcherImpl; */ public class BanisherPriest extends CardImpl { - private UUID exileId = UUID.randomUUID(); + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls"); + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + } public BanisherPriest(UUID ownerId) { super(ownerId, 7, "Banisher Priest", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); @@ -67,8 +74,10 @@ public class BanisherPriest extends CardImpl { this.toughness = new MageInt(2); // When Banisher Priest enters the battlefield, exile target creature an opponent controls until Banisher Priest leaves the battlefield. - this.addAbility(new BanisherPriestTriggeredAbility(exileId)); - this.addWatcher(new BanisherPriestWatcher(exileId)); + Ability ability = new EntersBattlefieldTriggeredAbility(new BanisherPriestExileEffect()); + ability.addTarget(new TargetCreaturePermanent(filter, true)); + this.addAbility(ability); + this.addWatcher(new BanisherPriestWatcher()); } @@ -82,67 +91,57 @@ public class BanisherPriest extends CardImpl { } } -class BanisherPriestTriggeredAbility extends TriggeredAbilityImpl { +class BanisherPriestExileEffect extends OneShotEffect { - public BanisherPriestTriggeredAbility(UUID exileId) { - super(Zone.BATTLEFIELD, null, false); - this.addEffect(new ExileTargetEffect(exileId, "Banisher Priest")); + public BanisherPriestExileEffect() { + super(Outcome.Benefit); + this.staticText = "exile target creature an opponent controls until {this} leaves the battlefield. (That creature returns under its owner's control.)"; } - public BanisherPriestTriggeredAbility(final BanisherPriestTriggeredAbility ability) { - super(ability); + public BanisherPriestExileEffect(final BanisherPriestExileEffect effect) { + super(effect); } @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && event.getTargetId().equals(this.getSourceId())) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls"); - filter.add(Predicates.not(new ControllerIdPredicate(controllerId))); - this.getTargets().clear(); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - target.setRequired(true); - this.addTarget(target); - return true; + public BanisherPriestExileEffect copy() { + return new BanisherPriestExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + // If Banisher Priest leaves the battlefield before its triggered ability resolves, + // the target creature won't be exiled. + if (permanent != null) { + new ExileTargetEffect(source.getSourceId(), permanent.getName()).apply(game, source); } return false; } - - @Override - public String getRule() { - return "Whenever {this} enters the battlefield, exile target creature an opponent controls until Banisher Priest leaves the battlefield."; - } - - @Override - public BanisherPriestTriggeredAbility copy() { - return new BanisherPriestTriggeredAbility(this); - } } class BanisherPriestWatcher extends WatcherImpl { - UUID exileId; - - BanisherPriestWatcher(UUID exileId) { + BanisherPriestWatcher() { super("BattlefieldLeft", WatcherScope.CARD); - this.exileId = exileId; } BanisherPriestWatcher(final BanisherPriestWatcher watcher) { super(watcher); - this.exileId = watcher.exileId; } @Override public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(sourceId)) { + if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - ExileZone exile = game.getExile().getExileZone(exileId); - if (exile != null) { - LinkedList cards = new LinkedList(exile); + ExileZone exile = game.getExile().getExileZone(this.getSourceId()); + Card sourceCard = game.getCard(this.getSourceId()); + if (exile != null && sourceCard != null) { + LinkedList cards = new LinkedList<>(exile); for (UUID cardId : cards) { Card card = game.getCard(cardId); card.moveToZone(Zone.BATTLEFIELD, this.getSourceId(), game, false); + game.informPlayers(new StringBuilder(sourceCard.getName()).append(": ").append(card.getName()).append(" was returned to battlefield from exile").toString()); } exile.clear(); } diff --git a/Mage.Sets/src/mage/sets/magic2014/ColossalWhale.java b/Mage.Sets/src/mage/sets/magic2014/ColossalWhale.java index 70bb858a311..362b8e90512 100644 --- a/Mage.Sets/src/mage/sets/magic2014/ColossalWhale.java +++ b/Mage.Sets/src/mage/sets/magic2014/ColossalWhale.java @@ -30,12 +30,15 @@ package mage.sets.magic2014; import java.util.LinkedList; import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.IslandwalkAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.WatcherScope; import mage.constants.Zone; @@ -45,6 +48,7 @@ import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.WatcherImpl; @@ -54,8 +58,6 @@ import mage.watchers.WatcherImpl; */ public class ColossalWhale extends CardImpl { - private UUID exileId = UUID.randomUUID(); - public ColossalWhale(UUID ownerId) { super(ownerId, 48, "Colossal Whale", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{U}{U}"); this.expansionSetCode = "M14"; @@ -68,8 +70,8 @@ public class ColossalWhale extends CardImpl { // Islandwalk this.addAbility(new IslandwalkAbility()); // Whenever Colossal Whale attacks, you may exile target creature defending player controls until Colossal Whale leaves the battlefield. - this.addAbility(new ColossalWhaleAbility(exileId)); - this.addWatcher(new ColossalWhaleWatcher(exileId)); + this.addAbility(new ColossalWhaleAbility()); + this.addWatcher(new ColossalWhaleWatcher()); } @@ -86,9 +88,9 @@ public class ColossalWhale extends CardImpl { class ColossalWhaleAbility extends TriggeredAbilityImpl { - public ColossalWhaleAbility(UUID exileId) { + public ColossalWhaleAbility() { super(Zone.BATTLEFIELD, null); - this.addEffect(new ExileTargetEffect(exileId,"Colossal Whale")); + this.addEffect(new ColossalWhaleExileEffect()); } public ColossalWhaleAbility(final ColossalWhaleAbility ability) { @@ -113,7 +115,7 @@ class ColossalWhaleAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever {this} attacks, you may exile target creature defending player controls until {this} leaves the battlefield."; + return new StringBuilder("Whenever {this} attacks, ").append(super.getRule()).toString(); } @Override @@ -122,31 +124,57 @@ class ColossalWhaleAbility extends TriggeredAbilityImpl { } } +class ColossalWhaleExileEffect extends OneShotEffect { + + public ColossalWhaleExileEffect() { + super(Outcome.Benefit); + this.staticText = "you may exile target creature defending player controls until {this} leaves the battlefield"; + } + + public ColossalWhaleExileEffect(final ColossalWhaleExileEffect effect) { + super(effect); + } + + @Override + public ColossalWhaleExileEffect copy() { + return new ColossalWhaleExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + // If Chained to the Rocks leaves the battlefield before its triggered ability resolves, + // the target creature won't be exiled. + if (permanent != null) { + new ExileTargetEffect(source.getSourceId(), permanent.getName()).apply(game, source); + } + return false; + } +} + class ColossalWhaleWatcher extends WatcherImpl { - private UUID exileId; - - ColossalWhaleWatcher (UUID exileId) { + ColossalWhaleWatcher () { super("BattlefieldLeft", WatcherScope.CARD); - this.exileId = exileId; } ColossalWhaleWatcher(final ColossalWhaleWatcher watcher) { super(watcher); - this.exileId = watcher.exileId; } @Override public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(sourceId)) { + if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { ZoneChangeEvent zEvent = (ZoneChangeEvent)event; if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - ExileZone exile = game.getExile().getExileZone(exileId); - if (exile != null) { - LinkedList cards = new LinkedList(exile); + ExileZone exile = game.getExile().getExileZone(this.getSourceId()); + Card sourceCard = game.getCard(this.getSourceId()); + if (exile != null && sourceCard != null) { + LinkedList cards = new LinkedList<>(exile); for (UUID cardId: cards) { Card card = game.getCard(cardId); card.moveToZone(Zone.BATTLEFIELD, this.getSourceId(), game, false); + game.informPlayers(new StringBuilder(sourceCard.getName()).append(": ").append(card.getName()).append(" was returned to battlefield from exile").toString()); } exile.clear(); }