refactored some instances of Player::moveCardToExileWithInfo

This commit is contained in:
Evan Kranzler 2022-03-14 21:14:12 -04:00
parent 8198322ba5
commit 83c94322c6
18 changed files with 183 additions and 213 deletions

View file

@ -1,7 +1,5 @@
package mage.abilities.costs.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
@ -10,8 +8,9 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
*
* @author magenoxx_at_gmail.com
*/
public class ExileSourceFromGraveCost extends CostImpl {
@ -20,36 +19,36 @@ public class ExileSourceFromGraveCost extends CostImpl {
this.text = "exile {this} from your graveyard";
}
public ExileSourceFromGraveCost(ExileSourceFromGraveCost cost) {
private ExileSourceFromGraveCost(final ExileSourceFromGraveCost cost) {
super(cost);
}
@Override
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
Card card = game.getCard(source.getSourceId());
if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) {
controller.moveCardToExileWithInfo(card, null, "", source, game, Zone.GRAVEYARD, true);
// 117.11. The actions performed when paying a cost may be modified by effects.
// Even if they are, meaning the actions that are performed don't match the actions
// that are called for, the cost has still been paid.
// so return state here is not important because the user indended to exile the target anyway
paid = true;
}
if (controller == null) {
return paid;
}
Card card = game.getCard(source.getSourceId());
if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) {
controller.moveCards(card, Zone.EXILED, source, game);
// 117.11. The actions performed when paying a cost may be modified by effects.
// Even if they are, meaning the actions that are performed don't match the actions
// that are called for, the cost has still been paid.
// so return state here is not important because the user indended to exile the target anyway
paid = true;
}
return paid;
}
@Override
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
Card card = game.getCard(source.getSourceId());
return card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD;
return game.getCard(source.getSourceId()) != null
&& game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD;
}
@Override
public ExileSourceFromGraveCost copy() {
return new ExileSourceFromGraveCost(this);
}
}

View file

@ -1,6 +1,5 @@
package mage.abilities.costs.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
@ -9,45 +8,40 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public class ExileTopCardOfGraveyardCost extends CostImpl {
private final int amount;
public ExileTopCardOfGraveyardCost(int amount) {
this.amount = amount;
public ExileTopCardOfGraveyardCost() {
this.text = "Exile the top card of your graveyard";
}
public ExileTopCardOfGraveyardCost(ExileTopCardOfGraveyardCost cost) {
private ExileTopCardOfGraveyardCost(final ExileTopCardOfGraveyardCost cost) {
super(cost);
this.amount = cost.amount;
}
@Override
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
Player controller = game.getPlayer(controllerId);
if(controller == null) {
if (controller == null) {
return false;
}
return controller.getGraveyard().size() >= amount;
return !controller.getGraveyard().isEmpty();
}
@Override
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
Player controller = game.getPlayer(controllerId);
if(controller != null) {
Card topCard = null;
for (Card card :controller.getGraveyard().getCards(game)) {
topCard = card;
}
if (topCard != null) {
controller.moveCardToExileWithInfo(topCard, null, "", source, game, Zone.GRAVEYARD, true);
paid = true;
}
if (controller == null) {
return paid;
}
Card topCard = controller.getGraveyard().getTopCard(game);
if (topCard != null) {
controller.moveCards(topCard, Zone.EXILED, source, game);
paid = true;
}
return paid;
}
@ -56,4 +50,4 @@ public class ExileTopCardOfGraveyardCost extends CostImpl {
public ExileTopCardOfGraveyardCost copy() {
return new ExileTopCardOfGraveyardCost(this);
}
}
}

View file

@ -1,6 +1,5 @@
package mage.abilities.costs.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
@ -9,8 +8,9 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public class ExileTopCreatureCardOfGraveyardCost extends CostImpl {
@ -30,7 +30,7 @@ public class ExileTopCreatureCardOfGraveyardCost extends CostImpl {
@Override
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
Player controller = game.getPlayer(controllerId);
if(controller == null) {
if (controller == null) {
return false;
}
return controller.getGraveyard().size() >= amount;
@ -39,17 +39,19 @@ public class ExileTopCreatureCardOfGraveyardCost extends CostImpl {
@Override
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
Player controller = game.getPlayer(controllerId);
if(controller != null) {
Card topCard = null;
for (Card card :controller.getGraveyard().getCards(game)) {
if (card.isCreature(game)) {
topCard = card;
}
}
if (topCard != null) {
controller.moveCardToExileWithInfo(topCard, null, "", source, game, Zone.GRAVEYARD, true);
paid = true;
}
if (controller == null) {
return paid;
}
Card topCard = controller
.getGraveyard()
.getCards(game)
.stream()
.filter(card -> card.isCreature(game))
.findFirst()
.orElse(null);
if (topCard != null) {
controller.moveCards(topCard, Zone.EXILED, source, game);
paid = true;
}
return paid;
}

View file

@ -1,4 +1,3 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
@ -12,25 +11,20 @@ import mage.players.Player;
import mage.target.TargetCard;
/**
*
* @author LevelX2
*/
public class ExileCardYouChooseTargetOpponentEffect extends OneShotEffect {
private FilterCard filter;
public ExileCardYouChooseTargetOpponentEffect() {
this(new FilterCard("a card"));
}
private final FilterCard filter;
public ExileCardYouChooseTargetOpponentEffect(FilterCard filter) {
super(Outcome.Discard);
staticText = new StringBuilder("Target opponent reveals their hand. You choose ")
.append(filter.getMessage()).append(" from it and exile that card").toString();
this.staticText = "Target opponent reveals their hand. You choose "
+ filter.getMessage() + " from it and exile that card";
this.filter = filter;
}
public ExileCardYouChooseTargetOpponentEffect(final ExileCardYouChooseTargetOpponentEffect effect) {
private ExileCardYouChooseTargetOpponentEffect(final ExileCardYouChooseTargetOpponentEffect effect) {
super(effect);
this.filter = effect.filter;
}
@ -39,26 +33,22 @@ public class ExileCardYouChooseTargetOpponentEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player opponent = game.getPlayer(source.getFirstTarget());
Card sourceCard = game.getCard(source.getSourceId());
if (controller != null && opponent != null) {
if (!opponent.getHand().isEmpty()) {
opponent.revealCards(sourceCard != null ? sourceCard.getIdName() + " (" + sourceCard.getZoneChangeCounter(game) + ')' : "Exile", opponent.getHand(), game);
TargetCard target = new TargetCard(Zone.HAND, filter);
if (controller.choose(Outcome.Exile, opponent.getHand(), target, game)) {
Card card = opponent.getHand().get(target.getFirstTarget(), game);
if (card != null) {
controller.moveCardToExileWithInfo(card, null, "", source, game, Zone.HAND, true);
}
}
}
return true;
if (controller == null || opponent == null
|| opponent.getHand().count(filter, game) < 1) {
return false;
}
return false;
opponent.revealCards(source, opponent.getHand(), game);
TargetCard target = new TargetCard(Zone.HAND, filter);
controller.choose(Outcome.Exile, opponent.getHand(), target, game);
Card card = opponent.getHand().get(target.getFirstTarget(), game);
if (card != null) {
controller.moveCards(card, Zone.EXILED, source, game);
}
return true;
}
@Override
public ExileCardYouChooseTargetOpponentEffect copy() {
return new ExileCardYouChooseTargetOpponentEffect(this);
}
}

View file

@ -1,4 +1,3 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
@ -9,69 +8,55 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author LevelX2
*/
public class ExileReturnBattlefieldOwnerNextEndStepSourceEffect extends OneShotEffect {
private boolean returnAlways;
private boolean returnTapped;
private final boolean returnTapped;
public ExileReturnBattlefieldOwnerNextEndStepSourceEffect() {
this(false);
}
public ExileReturnBattlefieldOwnerNextEndStepSourceEffect(boolean returnAlways) {
this(returnAlways, false);
}
/**
*
* @param returnAlways Return the permanent also if it does not go to exile
* but is moved to another zone (e.g. command zone by commander replacement
* effect)
* @param returnTapped Does the source return tapped to the battlefield
*/
public ExileReturnBattlefieldOwnerNextEndStepSourceEffect(boolean returnAlways, boolean returnTapped) {
public ExileReturnBattlefieldOwnerNextEndStepSourceEffect(boolean returnTapped) {
super(Outcome.Benefit);
this.returnTapped = returnTapped;
this.returnAlways = returnAlways;
staticText = "exile {this}. Return it to the battlefield "
+ (returnTapped ? "tapped " : "")
+ "under its owner's control at the beginning of the next end step";
staticText = "exile {this}. Return it to the battlefield " + (returnTapped ? "tapped " : "") +
"under its owner's control at the beginning of the next end step";
}
public ExileReturnBattlefieldOwnerNextEndStepSourceEffect(ExileReturnBattlefieldOwnerNextEndStepSourceEffect effect) {
super(effect);
this.returnAlways = effect.returnAlways;
this.returnTapped = effect.returnTapped;
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
int zcc = game.getState().getZoneChangeCounter(permanent.getId());
boolean exiled = controller.moveCardToExileWithInfo(permanent, source.getSourceId(), permanent.getIdName(), source, game, Zone.BATTLEFIELD, true);
if (exiled || (returnAlways && (zcc == game.getState().getZoneChangeCounter(permanent.getId()) - 1))) {
//create delayed triggered ability and return it from every public zone it was next moved to
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
new ReturnToBattlefieldUnderOwnerControlSourceEffect(returnTapped, zcc + 1));
game.addDelayedTriggeredAbility(delayedAbility, source);
}
}
if (controller == null) {
return false;
}
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
if (permanent == null) {
return true;
}
return false;
controller.moveCards(permanent, Zone.EXILED, source, game);
//create delayed triggered ability and return it from every public zone it was next moved to
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
new ReturnToBattlefieldUnderOwnerControlTargetEffect(returnTapped, true)
.setTargetPointer(new FixedTarget(permanent.getId(), game))
), source);
return true;
}
@Override
public ExileReturnBattlefieldOwnerNextEndStepSourceEffect copy() {
return new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(this);
}
}

View file

@ -1,7 +1,11 @@
package mage.abilities.keyword;
import mage.ApprovingObject;
import mage.MageObject;
import mage.abilities.*;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.StaticAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.condition.Condition;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.costs.mana.ManaCost;
@ -18,7 +22,6 @@ import mage.game.stack.Spell;
import mage.players.Player;
import java.util.UUID;
import mage.ApprovingObject;
/**
* 702.33. Madness
@ -124,13 +127,17 @@ class MadnessReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) { return false; }
if (controller == null) {
return false;
}
Card card = game.getCard(event.getTargetId());
if (card == null) { return false; }
if (card == null) {
return false;
}
// TODO, deal with deprecated call
if (controller.moveCardToExileWithInfo(card, source.getSourceId(), "Madness", source, game, ((ZoneChangeEvent) event).getFromZone(), true)) {
if (controller.moveCards(card, Zone.EXILED, source, game)) {
game.applyEffects(); // needed to add Madness ability to cards (e.g. by Falkenrath Gorger)
GameEvent gameEvent = new MadnessCardExiledEvent(card.getId(), source, controller.getId());
game.fireEvent(gameEvent);
@ -190,13 +197,19 @@ class MadnessTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean resolve(Game game) {
if (super.resolve(game)) { return true; }
if (super.resolve(game)) {
return true;
}
Card card = game.getCard(getSourceId());
if (card == null) { return false; }
if (card == null) {
return false;
}
Player owner = game.getPlayer(card.getOwnerId());
if (owner == null) { return false; }
if (owner == null) {
return false;
}
// if cast was not successfull, the card is moved to graveyard
owner.moveCards(card, Zone.GRAVEYARD, this, game);
@ -205,7 +218,7 @@ class MadnessTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getTriggerPhrase() {
return "When this card is exiled this way, " ;
return "When this card is exiled this way, ";
}
}
@ -237,15 +250,21 @@ class MadnessCastEffect extends OneShotEffect {
}
@Override
public MadnessCastEffect copy() { return new MadnessCastEffect(this); }
public MadnessCastEffect copy() {
return new MadnessCastEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Card card = game.getCard(source.getSourceId());
if (card == null) { return false; }
if (card == null) {
return false;
}
Player owner = game.getPlayer(card.getOwnerId());
if (owner == null) { return false; }
if (owner == null) {
return false;
}
// Replace with the new cost
SpellAbility castByMadness = card.getSpellAbility().copy();
@ -268,9 +287,13 @@ enum MadnessCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
MageObject madnessSpell = game.getLastKnownInformation(source.getSourceId(), Zone.STACK, source.getSourceObjectZoneChangeCounter() - 1);
if (!(madnessSpell instanceof Spell)) { return false; }
if (!(madnessSpell instanceof Spell)) {
return false;
}
if (((Spell) madnessSpell).getSpellAbility() == null) { return false; }
if (((Spell) madnessSpell).getSpellAbility() == null) {
return false;
}
return ((Spell) madnessSpell).getSpellAbility().getSpellAbilityCastMode() == SpellAbilityCastMode.MADNESS;
}

View file

@ -3,22 +3,21 @@ package mage.abilities.keyword;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MyTurnCondition;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.Card;
import mage.cards.CardsImpl;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.ExileZone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.stack.Spell;
import mage.players.Player;
import java.util.UUID;
import mage.ApprovingObject;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
/**
* This ability has no effect by default and will always return false on the
@ -49,7 +48,7 @@ public class ReboundAbility extends SimpleStaticAbility {
super(Zone.STACK, new ReboundCastFromHandReplacementEffect());
}
public ReboundAbility(ReboundAbility ability) {
public ReboundAbility(final ReboundAbility ability) {
super(ability);
}
@ -57,18 +56,22 @@ public class ReboundAbility extends SimpleStaticAbility {
public ReboundAbility copy() {
return new ReboundAbility(this);
}
@Override
public String getRule() {
return "Rebound <i>(If you cast this spell from your hand, "
+ "exile it as it resolves. At the beginning of your next upkeep, "
+ "you may cast this card from exile without paying its mana cost.)</i>";
}
}
class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl {
ReboundCastFromHandReplacementEffect() {
super(Duration.WhileOnStack, Outcome.Benefit);
this.staticText = "Rebound <i>(If you cast this spell from your hand, "
+ "exile it as it resolves. At the beginning of your next upkeep, "
+ "you may cast this card from exile without paying its mana cost.)</i>";
}
ReboundCastFromHandReplacementEffect(ReboundCastFromHandReplacementEffect effect) {
private ReboundCastFromHandReplacementEffect(final ReboundCastFromHandReplacementEffect effect) {
super(effect);
}
@ -84,17 +87,14 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl {
// by a spell like Cancel, or because all of its targets are illegal), rebound has no effect.
// The spell is simply put into your graveyard. You wont get to cast it again next turn.
// (2010-06-15)
if (((ZoneChangeEvent) event).getFromZone() == Zone.STACK
&& ((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD
&& event.getSourceId() != null
&& event.getSourceId().equals(source.getSourceId())) { // if countered the source.sourceId is different or null if it fizzles
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell != null
&& spell.getFromZone() == Zone.HAND) {
return true;
}
}
return false;
if (((ZoneChangeEvent) event).getFromZone() != Zone.STACK
|| ((ZoneChangeEvent) event).getToZone() != Zone.GRAVEYARD
|| event.getSourceId() == null
|| !event.getSourceId().equals(source.getSourceId())) {
return false;
} // if countered the source.sourceId is different or null if it fizzles
Spell spell = game.getStack().getSpell(event.getTargetId());
return spell != null && spell.getFromZone() == Zone.HAND;
}
@Override
@ -102,23 +102,19 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl {
Spell sourceSpell = game.getStack().getSpell(source.getSourceId());
if (sourceSpell != null && sourceSpell.isCopy()) {
return false;
} else {
Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard != null) {
Player player = game.getPlayer(sourceCard.getOwnerId());
if (player != null) {
// Add the delayed triggered effect
ReboundEffectCastFromExileDelayedTrigger trigger
= new ReboundEffectCastFromExileDelayedTrigger(source.getSourceId(), source.getSourceId());
game.addDelayedTriggeredAbility(trigger, source);
player.moveCardToExileWithInfo(sourceCard, sourceCard.getId(),
player.getName() + " Rebound", source, game, Zone.STACK, true);
return true;
}
}
}
return false;
Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard == null) {
return false;
}
Player player = game.getPlayer(sourceCard.getOwnerId());
if (player == null) {
return false;
}
// Add the delayed triggered effect
player.moveCardsToExile(sourceCard, source, game, true, null, "Rebound");
game.addDelayedTriggeredAbility(new ReboundEffectCastFromExileDelayedTrigger(sourceCard, game), source);
return true;
}
@Override
@ -130,13 +126,11 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl {
class ReboundEffectCastFromExileDelayedTrigger extends DelayedTriggeredAbility {
ReboundEffectCastFromExileDelayedTrigger(UUID cardId, UUID sourceId) {
super(new ReboundCastSpellFromExileEffect());
setSourceId(sourceId); // TODO: WTF?!
this.optional = true;
ReboundEffectCastFromExileDelayedTrigger(Card card, Game game) {
super(new ReboundCastSpellFromExileEffect().setTargetPointer(new FixedTarget(card, game)), Duration.Custom, true, true);
}
ReboundEffectCastFromExileDelayedTrigger(ReboundEffectCastFromExileDelayedTrigger ability) {
private ReboundEffectCastFromExileDelayedTrigger(final ReboundEffectCastFromExileDelayedTrigger ability) {
super(ability);
}
@ -152,7 +146,7 @@ class ReboundEffectCastFromExileDelayedTrigger extends DelayedTriggeredAbility {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return MyTurnCondition.instance.apply(game, this);
return game.isActivePlayer(getControllerId());
}
@Override
@ -169,41 +163,25 @@ class ReboundEffectCastFromExileDelayedTrigger extends DelayedTriggeredAbility {
*/
class ReboundCastSpellFromExileEffect extends OneShotEffect {
private static String castFromExileText = "Rebound - You may cast {this} "
+ "from exile without paying its mana cost";
ReboundCastSpellFromExileEffect() {
super(Outcome.PlayForFree);
staticText = castFromExileText;
}
ReboundCastSpellFromExileEffect(ReboundCastSpellFromExileEffect effect) {
private ReboundCastSpellFromExileEffect(final ReboundCastSpellFromExileEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
ExileZone zone = game.getExile().getExileZone(source.getSourceId());
if (zone == null
|| zone.isEmpty()) {
return false;
}
Card reboundCard = zone.get(source.getSourceId(), game);
Player player = game.getPlayer(source.getControllerId());
if (player != null
&& reboundCard != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + reboundCard.getId(), Boolean.TRUE);
Boolean cardWasCast = player.cast(player.chooseAbilityForCast(reboundCard, game, true),
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + reboundCard.getId(), null);
return cardWasCast;
}
return false;
Card reboundCard = game.getCard(getTargetPointer().getFirst(game, source));
return player != null && reboundCard != null && CardUtil.castSpellWithAttributesForFree(
player, source, game, new CardsImpl(reboundCard), StaticFilters.FILTER_CARD
);
}
@Override
public ReboundCastSpellFromExileEffect copy() {
return new ReboundCastSpellFromExileEffect(this);
}
}