mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
Fixed NullPointerException when Accursed Witch transforms (#5571)
* Fixed NullPointerException when Accursed Witch transforms Feedback issue: #5529 Aura replacement code tried to remove the second face from the original zone which had ownerId == null. Now, we remember the first face (the original card) and remove it from the old zone before creating a permanent out of the second face. * Accursed Witch's death trigger now requires targetting opponent instead of using aura replacement effects Feedback issue: #5529 Previously you could attach Infectious Curse to either player and get around hexproof The ability text has also been updated to match the Oracle text of Accursed Witch.
This commit is contained in:
parent
b36465e5c9
commit
fce93c66e1
3 changed files with 22 additions and 7 deletions
|
@ -18,6 +18,7 @@ import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
|
import mage.target.common.TargetOpponent;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -41,7 +42,9 @@ public final class AccursedWitch extends CardImpl {
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AccursedWitchSpellsCostReductionEffect()));
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AccursedWitchSpellsCostReductionEffect()));
|
||||||
// When Accursed Witch dies, return it to the battlefield transformed under your control attached to target opponent.
|
// When Accursed Witch dies, return it to the battlefield transformed under your control attached to target opponent.
|
||||||
this.addAbility(new TransformAbility());
|
this.addAbility(new TransformAbility());
|
||||||
this.addAbility(new DiesTriggeredAbility(new AccursedWitchReturnTransformedEffect()));
|
Ability ability = new DiesTriggeredAbility(new AccursedWitchReturnTransformedEffect());
|
||||||
|
ability.addTarget(new TargetOpponent());
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccursedWitch(final AccursedWitch card) {
|
private AccursedWitch(final AccursedWitch card) {
|
||||||
|
@ -58,7 +61,7 @@ class AccursedWitchReturnTransformedEffect extends OneShotEffect {
|
||||||
|
|
||||||
AccursedWitchReturnTransformedEffect() {
|
AccursedWitchReturnTransformedEffect() {
|
||||||
super(Outcome.PutCardInPlay);
|
super(Outcome.PutCardInPlay);
|
||||||
this.staticText = "Put {this} from your graveyard onto the battlefield transformed";
|
this.staticText = "Put {this} from your graveyard onto the battlefield transformed under your control attached to target opponent";
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccursedWitchReturnTransformedEffect(final AccursedWitchReturnTransformedEffect effect) {
|
private AccursedWitchReturnTransformedEffect(final AccursedWitchReturnTransformedEffect effect) {
|
||||||
|
@ -73,14 +76,19 @@ class AccursedWitchReturnTransformedEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller == null || !(game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD)) {
|
Player attachTo = game.getPlayer(targetPointer.getFirst(game, source));
|
||||||
|
if (controller == null || !(game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) || attachTo == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
|
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
|
||||||
|
UUID secondFaceId = game.getCard(source.getSourceId()).getSecondCardFace().getId();
|
||||||
|
game.getState().setValue("attachTo:" + secondFaceId, attachTo.getId());
|
||||||
//note: should check for null after game.getCard
|
//note: should check for null after game.getCard
|
||||||
Card card = game.getCard(source.getSourceId());
|
Card card = game.getCard(source.getSourceId());
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
|
if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) {
|
||||||
|
attachTo.addAttachment(card.getId(), game);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,9 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Card firstCardFace = null;
|
||||||
if (game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()) != null) {
|
if (game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()) != null) {
|
||||||
|
firstCardFace = card;
|
||||||
card = card.getSecondCardFace();
|
card = card.getSecondCardFace();
|
||||||
if (!card.isEnchantment() || !card.hasSubtype(SubType.AURA, game)) {
|
if (!card.isEnchantment() || !card.hasSubtype(SubType.AURA, game)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -129,7 +131,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
||||||
enchantCardInGraveyard = target instanceof TargetCardInGraveyard;
|
enchantCardInGraveyard = target instanceof TargetCardInGraveyard;
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
target.setNotTarget(true); // always not target because this way it's not handled targeted
|
target.setNotTarget(true); // always not target because this way it's not handled targeted
|
||||||
target.clearChosen(); // neccessary if e.g. aura is blinked multiple times
|
target.clearChosen(); // necessary if e.g. aura is blinked multiple times
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.getPlayerId() != null) {
|
if (event.getPlayerId() != null) {
|
||||||
|
@ -152,7 +154,12 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
||||||
}
|
}
|
||||||
Player targetPlayer = game.getPlayer(targetId);
|
Player targetPlayer = game.getPlayer(targetId);
|
||||||
if (targetCard != null || targetPermanent != null || targetPlayer != null) {
|
if (targetCard != null || targetPermanent != null || targetPlayer != null) {
|
||||||
card.removeFromZone(game, fromZone, sourceId);
|
if (firstCardFace != null) {
|
||||||
|
// transforming card. remove first face (original card) from old zone
|
||||||
|
firstCardFace.removeFromZone(game, fromZone, sourceId);
|
||||||
|
} else {
|
||||||
|
card.removeFromZone(game, fromZone, sourceId);
|
||||||
|
}
|
||||||
PermanentCard permanent = new PermanentCard(card, (controllingPlayer == null ? card.getOwnerId() : controllingPlayer.getId()), game);
|
PermanentCard permanent = new PermanentCard(card, (controllingPlayer == null ? card.getOwnerId() : controllingPlayer.getId()), game);
|
||||||
ZoneChangeEvent zoneChangeEvent = new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD);
|
ZoneChangeEvent zoneChangeEvent = new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD);
|
||||||
permanent.updateZoneChangeCounter(game, zoneChangeEvent);
|
permanent.updateZoneChangeCounter(game, zoneChangeEvent);
|
||||||
|
|
|
@ -18,7 +18,7 @@ public class TransformAbility extends SimpleStaticAbility {
|
||||||
public static final String NO_SPELLS_TRANSFORM_RULE = "At the beginning of each upkeep, if no spells were cast last turn, transform {this}.";
|
public static final String NO_SPELLS_TRANSFORM_RULE = "At the beginning of each upkeep, if no spells were cast last turn, transform {this}.";
|
||||||
public static final String TWO_OR_MORE_SPELLS_TRANSFORM_RULE = "At the beginning of each upkeep, if a player cast two or more spells last turn, transform {this}.";
|
public static final String TWO_OR_MORE_SPELLS_TRANSFORM_RULE = "At the beginning of each upkeep, if a player cast two or more spells last turn, transform {this}.";
|
||||||
|
|
||||||
// this state value controlls if a permanent enters the battlefield already transformed
|
// this state value controls if a permanent enters the battlefield already transformed
|
||||||
public static final String VALUE_KEY_ENTER_TRANSFORMED = "EnterTransformed";
|
public static final String VALUE_KEY_ENTER_TRANSFORMED = "EnterTransformed";
|
||||||
|
|
||||||
public TransformAbility() {
|
public TransformAbility() {
|
||||||
|
|
Loading…
Reference in a new issue