* Blazing Shoal, Banisher Priest, Colossal Whale - Fixed that target was wrongly also exiled if source permanent was no more on the battlefield as the exile effect resolves.

This commit is contained in:
LevelX2 2014-02-23 13:05:32 +01:00
parent 6f5d789057
commit 22fccea168
3 changed files with 109 additions and 61 deletions

View file

@ -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<BlazingShoal> {
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<BlazingShoal> {
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<BlazingShoal> {
public BlazingShoal copy() {
return new BlazingShoal(this);
}
}
}
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;
}
}

View file

@ -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<BanisherPriest> {
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<BanisherPriest> {
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<BanisherPriest> {
}
}
class BanisherPriestTriggeredAbility extends TriggeredAbilityImpl<BanisherPriestTriggeredAbility> {
class BanisherPriestExileEffect extends OneShotEffect<BanisherPriestExileEffect> {
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. <i>(That creature returns under its owner's control.)</i>";
}
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<BanisherPriestWatcher> {
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<UUID> cards = new LinkedList<UUID>(exile);
ExileZone exile = game.getExile().getExileZone(this.getSourceId());
Card sourceCard = game.getCard(this.getSourceId());
if (exile != null && sourceCard != null) {
LinkedList<UUID> 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();
}

View file

@ -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<ColossalWhale> {
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<ColossalWhale> {
// 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<ColossalWhale> {
class ColossalWhaleAbility extends TriggeredAbilityImpl<ColossalWhaleAbility> {
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<ColossalWhaleAbility> {
@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<ColossalWhaleAbility> {
}
}
class ColossalWhaleExileEffect extends OneShotEffect<ColossalWhaleExileEffect> {
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<ColossalWhaleWatcher> {
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<UUID> cards = new LinkedList<UUID>(exile);
ExileZone exile = game.getExile().getExileZone(this.getSourceId());
Card sourceCard = game.getCard(this.getSourceId());
if (exile != null && sourceCard != null) {
LinkedList<UUID> 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();
}