mirror of
https://github.com/correl/mage.git
synced 2024-11-28 19:19:55 +00:00
- Workaround for #5437. The delayed triggers work correctly now and the game will no longer freeze. TODO: Cards that are copied and then cast do not retain the correct sourceObject. They instead point to the spell on the stack which fails when delayed triggers are used.
This commit is contained in:
parent
75ad7e73e0
commit
5aaec29361
4 changed files with 43 additions and 15 deletions
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.cards.a;
|
package mage.cards.a;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -11,6 +10,7 @@ import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
import mage.abilities.effects.common.DrawCardTargetEffect;
|
import mage.abilities.effects.common.DrawCardTargetEffect;
|
||||||
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
@ -27,13 +27,16 @@ import mage.target.targetpointer.FixedTarget;
|
||||||
public final class ArcaneDenial extends CardImpl {
|
public final class ArcaneDenial extends CardImpl {
|
||||||
|
|
||||||
public ArcaneDenial(UUID ownerId, CardSetInfo setInfo) {
|
public ArcaneDenial(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
|
||||||
|
|
||||||
// Counter target spell. Its controller may draw up to two cards at the beginning of the next turn's upkeep.
|
// Counter target spell. Its controller may draw up to two cards at
|
||||||
|
// the beginning of the next turn's upkeep.
|
||||||
this.getSpellAbility().addEffect(new ArcaneDenialEffect());
|
this.getSpellAbility().addEffect(new ArcaneDenialEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
// You draw a card at the beginning of the next turn's upkeep.
|
// You draw a card at the beginning of the next turn's upkeep.
|
||||||
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1)), false));
|
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
|
||||||
|
new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(
|
||||||
|
new DrawCardSourceControllerEffect(1)), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArcaneDenial(final ArcaneDenial card) {
|
public ArcaneDenial(final ArcaneDenial card) {
|
||||||
|
@ -50,7 +53,8 @@ class ArcaneDenialEffect extends OneShotEffect {
|
||||||
|
|
||||||
public ArcaneDenialEffect() {
|
public ArcaneDenialEffect() {
|
||||||
super(Outcome.Detriment);
|
super(Outcome.Detriment);
|
||||||
staticText = "Counter target spell. Its controller may draw up to two cards at the beginning of the next turn's upkeep";
|
staticText = "Counter target spell. Its controller may draw up to two cards "
|
||||||
|
+ "at the beginning of the next turn's upkeep";
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArcaneDenialEffect(final ArcaneDenialEffect effect) {
|
public ArcaneDenialEffect(final ArcaneDenialEffect effect) {
|
||||||
|
@ -64,8 +68,22 @@ class ArcaneDenialEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Card originalSourceCard; // needed for copies of Arcane Denial See Bug #5437
|
||||||
Player controller = null;
|
Player controller = null;
|
||||||
boolean countered = false;
|
boolean countered = false;
|
||||||
|
// If the source originates from a copy (Isochron Scepter for example),
|
||||||
|
// then we set the source's sourceId to the original card, otherwise it
|
||||||
|
// uses the spell on the stack as its sourceObject which won't work
|
||||||
|
// correctly with any cards that make use of Delayed Triggers.
|
||||||
|
// see Bug #5437
|
||||||
|
Card cardToCheck = game.getCard(source.getSourceId());
|
||||||
|
if (cardToCheck != null
|
||||||
|
&& cardToCheck.isCopy()) { // Isochron Scepter imprinted card for example
|
||||||
|
originalSourceCard = (Card) game.getState().getValue("RememberSourceObject" + source.getSourceId());
|
||||||
|
if (originalSourceCard != null) {
|
||||||
|
source.setSourceId(originalSourceCard.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
UUID targetId = this.getTargetPointer().getFirst(game, source);
|
UUID targetId = this.getTargetPointer().getFirst(game, source);
|
||||||
if (targetId != null) {
|
if (targetId != null) {
|
||||||
controller = game.getPlayer(game.getControllerId(targetId));
|
controller = game.getPlayer(game.getControllerId(targetId));
|
||||||
|
|
|
@ -88,7 +88,7 @@ class IsochronScepterImprintEffect extends OneShotEffect {
|
||||||
&& controller.choose(Outcome.Benefit, controller.getHand(), target, game)) {
|
&& controller.choose(Outcome.Benefit, controller.getHand(), target, game)) {
|
||||||
Card card = controller.getHand().get(target.getFirstTarget(), game);
|
Card card = controller.getHand().get(target.getFirstTarget(), game);
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
controller.moveCardsToExile(card, source, game, true, source.getSourceId(),
|
controller.moveCardsToExile(card, source, game, true, source.getSourceId(),
|
||||||
sourcePermanent.getIdName() + " (Imprint)");
|
sourcePermanent.getIdName() + " (Imprint)");
|
||||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
|
@ -134,8 +134,8 @@ class IsochronScepterCopyEffect extends OneShotEffect {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
Permanent scepter = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
Permanent scepter = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||||
if (scepter != null
|
if (scepter != null
|
||||||
&& scepter.getImprinted() != null
|
&& scepter.getImprinted() != null
|
||||||
&& !scepter.getImprinted().isEmpty()) {
|
&& !scepter.getImprinted().isEmpty()) {
|
||||||
Card imprintedInstant = game.getCard(scepter.getImprinted().get(0));
|
Card imprintedInstant = game.getCard(scepter.getImprinted().get(0));
|
||||||
if (imprintedInstant != null
|
if (imprintedInstant != null
|
||||||
|
@ -143,6 +143,9 @@ class IsochronScepterCopyEffect extends OneShotEffect {
|
||||||
if (controller.chooseUse(outcome, "Create a copy of " + imprintedInstant.getName() + '?', source, game)) {
|
if (controller.chooseUse(outcome, "Create a copy of " + imprintedInstant.getName() + '?', source, game)) {
|
||||||
Card copiedCard = game.copyCard(imprintedInstant, source, source.getControllerId());
|
Card copiedCard = game.copyCard(imprintedInstant, source, source.getControllerId());
|
||||||
if (copiedCard != null) {
|
if (copiedCard != null) {
|
||||||
|
// Need to record the sourceObject info for the copy (example Arcane Denial)
|
||||||
|
// TODO implement this within the codebase. See Bug #5437
|
||||||
|
game.getState().setValue("RememberSourceObject" + copiedCard.getId(), imprintedInstant);
|
||||||
game.getExile().add(source.getSourceId(), "", copiedCard);
|
game.getExile().add(source.getSourceId(), "", copiedCard);
|
||||||
game.getState().setZone(copiedCard.getId(), Zone.EXILED);
|
game.getState().setZone(copiedCard.getId(), Zone.EXILED);
|
||||||
if (controller.chooseUse(outcome, "Cast the copied card without paying mana cost?", source, game)) {
|
if (controller.chooseUse(outcome, "Cast the copied card without paying mana cost?", source, game)) {
|
||||||
|
|
|
@ -52,7 +52,8 @@ public class DrawCardSourceControllerEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
if (player != null) {
|
if (player != null
|
||||||
|
&& player.isInGame()) {
|
||||||
player.drawCards(amount.calculate(game, source, this), game);
|
player.drawCards(amount.calculate(game, source, this), game);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -61,9 +62,14 @@ public class DrawCardSourceControllerEffect extends OneShotEffect {
|
||||||
|
|
||||||
private void setText() {
|
private void setText() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
boolean oneCard = (amount instanceof StaticValue && amount.calculate(null, null, this) == 1)
|
boolean oneCard = (amount instanceof StaticValue
|
||||||
|| amount instanceof PermanentsOnBattlefieldCount || amount.toString().equals("1") || amount.toString().equals("a");
|
&& amount.calculate(null, null, this) == 1)
|
||||||
sb.append(whoDrawCard.isEmpty() ? "" : whoDrawCard + " ").append("draw ").append(oneCard ? "a" : CardUtil.numberToText(amount.toString())).append(" card");
|
|| amount instanceof PermanentsOnBattlefieldCount
|
||||||
|
|| amount.toString().equals("1")
|
||||||
|
|| amount.toString().equals("a");
|
||||||
|
sb.append(whoDrawCard.isEmpty() ? "" : whoDrawCard
|
||||||
|
+ " ").append("draw ").append(oneCard ? "a"
|
||||||
|
: CardUtil.numberToText(amount.toString())).append(" card");
|
||||||
if (!oneCard) {
|
if (!oneCard) {
|
||||||
sb.append('s');
|
sb.append('s');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.abilities.effects.common;
|
package mage.abilities.effects.common;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -63,12 +62,14 @@ public class DrawCardTargetEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
for (UUID playerId : getTargetPointer().getTargets(game, source)) {
|
for (UUID playerId : getTargetPointer().getTargets(game, source)) {
|
||||||
Player player = game.getPlayer(playerId);
|
Player player = game.getPlayer(playerId);
|
||||||
if (player != null) {
|
if (player != null
|
||||||
|
&& player.isInGame()) {
|
||||||
int cardsToDraw = amount.calculate(game, source, this);
|
int cardsToDraw = amount.calculate(game, source, this);
|
||||||
if (upTo) {
|
if (upTo) {
|
||||||
cardsToDraw = player.getAmount(0, cardsToDraw, "Draw how many cards?", game);
|
cardsToDraw = player.getAmount(0, cardsToDraw, "Draw how many cards?", game);
|
||||||
}
|
}
|
||||||
if (!optional || player.chooseUse(outcome, "Use draw effect?", source, game)) {
|
if (!optional
|
||||||
|
|| player.chooseUse(outcome, "Use draw effect?", source, game)) {
|
||||||
player.drawCards(cardsToDraw, game);
|
player.drawCards(cardsToDraw, game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue