mirror of
https://github.com/magefree/mage.git
synced 2025-12-26 21:42:07 -08:00
* Exile card and return it from exile - fixed rollback error on commander creature exile (#7250);
[CMR] fixed PromiseOfTomorrow - not working ability;
This commit is contained in:
parent
a6f79580d7
commit
3f44d9eef3
19 changed files with 232 additions and 116 deletions
|
|
@ -3,6 +3,7 @@ package mage.abilities.effects.common;
|
|||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
|
|
@ -10,15 +11,19 @@ import mage.game.Game;
|
|||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.targetpointer.FirstTargetPointer;
|
||||
import mage.util.CardUtil;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.target.targetpointer.TargetPointer;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Use it for combo with ReturnFromExileForSourceEffect (exile and return exiled later)
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class ExileTargetForSourceEffect extends OneShotEffect {
|
||||
|
|
@ -45,46 +50,50 @@ public class ExileTargetForSourceEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller == null || sourceObject == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (controller != null
|
||||
&& sourceObject != null) {
|
||||
Set<Card> cards = new LinkedHashSet<>();
|
||||
if (source.getTargets().size() > 1
|
||||
&& targetPointer instanceof FirstTargetPointer) {
|
||||
for (Target target : source.getTargets()) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
MageObject mageObject = game.getObject(targetId);
|
||||
if (mageObject instanceof Card) {
|
||||
cards.add((Card) mageObject);
|
||||
}
|
||||
Set<UUID> objectsToMove = new LinkedHashSet<>();
|
||||
if (this.targetPointer instanceof FirstTargetPointer
|
||||
&& source.getTargets().size() > 1) {
|
||||
for (Target target : source.getTargets()) {
|
||||
objectsToMove.addAll(target.getTargets());
|
||||
}
|
||||
} else {
|
||||
if (this.targetPointer != null && !this.targetPointer.getTargets(game, source).isEmpty()) {
|
||||
objectsToMove.addAll(this.targetPointer.getTargets(game, source));
|
||||
} else {
|
||||
// issue with Madness keyword #6889
|
||||
UUID fixedTargetId = null;
|
||||
for (Effect effect : source.getEffects()) {
|
||||
TargetPointer targetPointerId = effect.getTargetPointer();
|
||||
if (targetPointerId instanceof FixedTarget) {
|
||||
fixedTargetId = (((FixedTarget) targetPointerId).getTarget());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!targetPointer.getTargets(game, source).isEmpty()) {
|
||||
for (UUID targetId : targetPointer.getTargets(game, source)) {
|
||||
MageObject mageObject = game.getObject(targetId);
|
||||
if (mageObject != null) {
|
||||
cards.add((Card) mageObject);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// issue with Madness keyword #6889
|
||||
UUID fixedTargetId = null;
|
||||
for (Effect effect : source.getEffects()) {
|
||||
TargetPointer targetPointerId = effect.getTargetPointer();
|
||||
if (targetPointerId instanceof FixedTarget) {
|
||||
fixedTargetId = (((FixedTarget) targetPointerId).getTarget());
|
||||
}
|
||||
}
|
||||
if (fixedTargetId != null) {
|
||||
cards.add((Card) game.getObject(fixedTargetId));
|
||||
}
|
||||
if (fixedTargetId != null) {
|
||||
objectsToMove.add(fixedTargetId);
|
||||
}
|
||||
}
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
return controller.moveCardsToExile(cards, source, game, true, exileId, sourceObject.getIdName());
|
||||
}
|
||||
return false;
|
||||
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
|
||||
// it can target permanents on battlefield, so use objects first
|
||||
Set<Card> cardsToMove = objectsToMove.stream()
|
||||
.map(game::getObject)
|
||||
.filter(Objects::nonNull)
|
||||
.map(object -> {
|
||||
if (object instanceof Card) {
|
||||
return (Card) object;
|
||||
} else {
|
||||
return game.getCard(object.getId());
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
return controller.moveCardsToExile(cardsToMove, source, game, true, exileId, sourceObject.getIdName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
|
|
@ -10,16 +9,19 @@ import mage.game.Game;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Use it for combo with ExileTargetForSourceEffect (exile and return exiled later)
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class ReturnFromExileForSourceEffect extends OneShotEffect {
|
||||
|
||||
private Zone returnToZone;
|
||||
private boolean tapped;
|
||||
private boolean previousZone;
|
||||
private final Zone returnToZone;
|
||||
private final boolean tapped;
|
||||
private final boolean previousZone;
|
||||
private String returnName = "cards";
|
||||
private String returnControlName;
|
||||
|
||||
|
|
@ -78,24 +80,32 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (sourceObject != null && controller != null) {
|
||||
Permanent permanentLeftBattlefield = (Permanent) getValue("permanentLeftBattlefield");
|
||||
if (permanentLeftBattlefield == null) {
|
||||
Logger.getLogger(ReturnFromExileForSourceEffect.class).error("Permanent not found: " + sourceObject.getName());
|
||||
return false;
|
||||
}
|
||||
ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), permanentLeftBattlefield.getZoneChangeCounter(game)));
|
||||
if (exile != null) { // null is valid if source left battlefield before enters the battlefield effect resolved
|
||||
if (returnToZone == Zone.BATTLEFIELD) {
|
||||
controller.moveCards(exile.getCards(game), returnToZone, source, game, false, false, true, null);
|
||||
} else {
|
||||
controller.moveCards(exile, returnToZone, source, game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
// effect uses in two use cases:
|
||||
// * on battlefield
|
||||
// * after leaves the battlefield
|
||||
// so ZCC must be different in different use cases
|
||||
|
||||
UUID exileId;
|
||||
Permanent permanentLeftBattlefield = (Permanent) getValue("permanentLeftBattlefield");
|
||||
if (permanentLeftBattlefield != null) {
|
||||
exileId = CardUtil.getExileZoneId(game, source.getSourceId(), permanentLeftBattlefield.getZoneChangeCounter(game));
|
||||
} else {
|
||||
exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
}
|
||||
|
||||
ExileZone exile = game.getExile().getExileZone(exileId);
|
||||
if (exile != null) { // null is valid if source left battlefield before enters the battlefield effect resolved
|
||||
if (returnToZone == Zone.BATTLEFIELD) {
|
||||
controller.moveCards(exile.getCards(game), returnToZone, source, game, false, false, true, null);
|
||||
} else {
|
||||
controller.moveCards(exile, returnToZone, source, game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateText() {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public class SkipNextPlayerUntapStepEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player player = null;
|
||||
if (targetPointer != null) {
|
||||
if (!targetPointer.getTargets(game, source).isEmpty()) {
|
||||
if (!this.targetPointer.getTargets(game, source).isEmpty()) {
|
||||
player = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
} else {
|
||||
player = game.getPlayer(source.getControllerId());
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ class ChampionExileCost extends CostImpl {
|
|||
MageObject sourceObject = ability.getSourceObject(game);
|
||||
if (controller != null && sourceObject != null) {
|
||||
if (targets.choose(Outcome.Exile, controllerId, source.getSourceId(), game)) {
|
||||
UUID exileId = CardUtil.getExileZoneId(game, ability.getSourceId(), ability.getSourceObjectZoneChangeCounter());
|
||||
UUID exileId = CardUtil.getExileZoneId(game, ability.getSourceId(), ability.getSourceObjectZoneChangeCounter()); // exileId important for return effect
|
||||
for (UUID targetId : targets.get(0).getTargets()) {
|
||||
Permanent permanent = game.getPermanent(targetId);
|
||||
if (permanent == null) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue