mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 13:19:18 -08:00
refactor: PlayFromGraveyardControllerEffect (#13032)
* refactor PlayFromGraveyardControllerEffect for broader usage * AbandonedSarcophagus to common class * refactor Player::canPlayCardsFromGraveyard to AsThough common class * a few more refactors
This commit is contained in:
parent
0d63750a81
commit
001f9e866f
21 changed files with 125 additions and 354 deletions
|
|
@ -20,6 +20,7 @@ public class PlayFromNotOwnHandZoneAllEffect extends AsThoughEffectImpl {
|
|||
private final boolean onlyOwnedCards;
|
||||
private final TargetController allowedCaster;
|
||||
|
||||
@Deprecated // Only used in some tests - should be refactored and removed
|
||||
public PlayFromNotOwnHandZoneAllEffect(FilterCard filter, Zone fromZone, boolean onlyOwnedCards, TargetController allowedCaster, Duration duration) {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, duration, Outcome.Benefit);
|
||||
this.filter = filter;
|
||||
|
|
|
|||
|
|
@ -15,23 +15,58 @@ import mage.players.Player;
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
* @author JayDi85, xenohedron
|
||||
*/
|
||||
public class PlayLandsFromGraveyardControllerEffect extends AsThoughEffectImpl {
|
||||
public class PlayFromGraveyardControllerEffect extends AsThoughEffectImpl {
|
||||
|
||||
private static final FilterCard filterPlayLands = new FilterLandCard("lands");
|
||||
private static final FilterCard filterPlayCast = new FilterCard("play lands and cast spells");
|
||||
|
||||
private final FilterCard filter;
|
||||
|
||||
public PlayLandsFromGraveyardControllerEffect() {
|
||||
this(new FilterLandCard("lands"));
|
||||
/**
|
||||
* You may play lands from your graveyard.
|
||||
*/
|
||||
public static PlayFromGraveyardControllerEffect playLands() {
|
||||
return new PlayFromGraveyardControllerEffect(filterPlayLands);
|
||||
}
|
||||
|
||||
public PlayLandsFromGraveyardControllerEffect(FilterCard filter) {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||
/**
|
||||
* You may play lands and cast spells from your graveyard.
|
||||
*/
|
||||
public static PlayFromGraveyardControllerEffect playLandsAndCastSpells(Duration duration) {
|
||||
return new PlayFromGraveyardControllerEffect(filterPlayCast, duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* You may [play/cast xxx] from your graveyard.
|
||||
*/
|
||||
public PlayFromGraveyardControllerEffect(FilterCard filter) {
|
||||
this(filter, Duration.WhileOnBattlefield);
|
||||
}
|
||||
|
||||
/**
|
||||
* [Until duration,] you may [play/cast xxx] from your graveyard.
|
||||
*/
|
||||
public PlayFromGraveyardControllerEffect(FilterCard filter, Duration duration) {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, duration, Outcome.Benefit);
|
||||
this.filter = filter;
|
||||
this.staticText = "You may play " + filter.getMessage() + " from your graveyard";
|
||||
String filterMessage = filter.getMessage();
|
||||
if (!filterMessage.startsWith("play ") && !filterMessage.startsWith("cast")) {
|
||||
if (filterMessage.contains("lands")) {
|
||||
filterMessage = "play " + filterMessage;
|
||||
} else {
|
||||
filterMessage = "cast " + filterMessage;
|
||||
}
|
||||
}
|
||||
String durationString = duration.toString();
|
||||
if (!durationString.isEmpty()) {
|
||||
durationString += ", ";
|
||||
}
|
||||
this.staticText = durationString + "you may " + filterMessage + " from your graveyard";
|
||||
}
|
||||
|
||||
protected PlayLandsFromGraveyardControllerEffect(final PlayLandsFromGraveyardControllerEffect effect) {
|
||||
protected PlayFromGraveyardControllerEffect(final PlayFromGraveyardControllerEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter;
|
||||
}
|
||||
|
|
@ -41,16 +76,16 @@ public class PlayLandsFromGraveyardControllerEffect extends AsThoughEffectImpl {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PlayLandsFromGraveyardControllerEffect copy() {
|
||||
return new PlayLandsFromGraveyardControllerEffect(this);
|
||||
public PlayFromGraveyardControllerEffect copy() {
|
||||
return new PlayFromGraveyardControllerEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
throw new IllegalArgumentException("Wrong code usage: can't call applies method on empty affectedAbility");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID playerId) {
|
||||
// current card's part
|
||||
|
|
@ -80,7 +115,7 @@ public class PlayLandsFromGraveyardControllerEffect extends AsThoughEffectImpl {
|
|||
if (!cardToCheck.isLand(game) && cardToCheck.getManaCost().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (affectedAbility instanceof SpellAbility){
|
||||
if (affectedAbility instanceof SpellAbility) {
|
||||
cardToCheck = ((SpellAbility) affectedAbility).getCharacteristics(game);
|
||||
}
|
||||
// must be correct card
|
||||
|
|
@ -1,27 +1,22 @@
|
|||
package mage.game.command.emblems;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.abilities.effects.common.ruleModifying.PlayFromGraveyardControllerEffect;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.filter.common.FilterPermanentCard;
|
||||
import mage.game.command.Emblem;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class WrennAndRealmbreakerEmblem extends Emblem {
|
||||
|
||||
private static final FilterPermanentCard filter = new FilterPermanentCard("play lands and cast permanent spells");
|
||||
|
||||
// -7: You get an emblem with "You may play lands and cast permanent spells from your graveyard."
|
||||
public WrennAndRealmbreakerEmblem() {
|
||||
super("Emblem Wrenn");
|
||||
this.getAbilities().add(new SimpleStaticAbility(Zone.COMMAND, new WrennAndRealmbreakerEmblemEffect()));
|
||||
this.getAbilities().add(new SimpleStaticAbility(Zone.COMMAND, new PlayFromGraveyardControllerEffect(filter)));
|
||||
}
|
||||
|
||||
private WrennAndRealmbreakerEmblem(final WrennAndRealmbreakerEmblem card) {
|
||||
|
|
@ -33,37 +28,3 @@ public final class WrennAndRealmbreakerEmblem extends Emblem {
|
|||
return new WrennAndRealmbreakerEmblem(this);
|
||||
}
|
||||
}
|
||||
|
||||
class WrennAndRealmbreakerEmblemEffect extends AsThoughEffectImpl {
|
||||
|
||||
public WrennAndRealmbreakerEmblemEffect() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||
staticText = "you may play lands and cast permanent spells from your graveyard";
|
||||
}
|
||||
|
||||
protected WrennAndRealmbreakerEmblemEffect(final WrennAndRealmbreakerEmblemEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrennAndRealmbreakerEmblemEffect copy() {
|
||||
return new WrennAndRealmbreakerEmblemEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (!source.isControlledBy(affectedControllerId)) {
|
||||
return false;
|
||||
}
|
||||
Card card = game.getCard(objectId);
|
||||
return card != null
|
||||
&& card.isPermanent(game)
|
||||
&& card.isOwnedBy(source.getControllerId())
|
||||
&& game.getState().getZone(objectId) == Zone.GRAVEYARD;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,10 +196,6 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
|
||||
boolean canLoseByZeroOrLessLife();
|
||||
|
||||
void setPlayCardsFromGraveyard(boolean playCardsFromGraveyard);
|
||||
|
||||
boolean canPlayCardsFromGraveyard();
|
||||
|
||||
void setPlotFromTopOfLibrary(boolean canPlotFromTopOfLibrary);
|
||||
|
||||
boolean canPlotFromTopOfLibrary();
|
||||
|
|
|
|||
|
|
@ -152,7 +152,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
protected boolean canLoseLife = true;
|
||||
protected PayLifeCostLevel payLifeCostLevel = PayLifeCostLevel.allAbilities;
|
||||
protected boolean loseByZeroOrLessLife = true;
|
||||
protected boolean canPlayCardsFromGraveyard = true;
|
||||
protected boolean canPlotFromTopOfLibrary = false;
|
||||
protected boolean drawsFromBottom = false;
|
||||
protected boolean drawsOnOpponentsTurn = false;
|
||||
|
|
@ -252,7 +251,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
this.canGainLife = player.canGainLife;
|
||||
this.canLoseLife = player.canLoseLife;
|
||||
this.loseByZeroOrLessLife = player.loseByZeroOrLessLife;
|
||||
this.canPlayCardsFromGraveyard = player.canPlayCardsFromGraveyard;
|
||||
this.canPlotFromTopOfLibrary = player.canPlotFromTopOfLibrary;
|
||||
this.drawsFromBottom = player.drawsFromBottom;
|
||||
this.drawsOnOpponentsTurn = player.drawsOnOpponentsTurn;
|
||||
|
|
@ -367,7 +365,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
this.sacrificeCostFilter = player.getSacrificeCostFilter() != null
|
||||
? player.getSacrificeCostFilter().copy() : null;
|
||||
this.loseByZeroOrLessLife = player.canLoseByZeroOrLessLife();
|
||||
this.canPlayCardsFromGraveyard = player.canPlayCardsFromGraveyard();
|
||||
this.canPlotFromTopOfLibrary = player.canPlotFromTopOfLibrary();
|
||||
this.drawsFromBottom = player.isDrawsFromBottom();
|
||||
this.drawsOnOpponentsTurn = player.isDrawsOnOpponentsTurn();
|
||||
|
|
@ -482,7 +479,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
this.canLoseLife = true;
|
||||
this.payLifeCostLevel = PayLifeCostLevel.allAbilities;
|
||||
this.loseByZeroOrLessLife = true;
|
||||
this.canPlayCardsFromGraveyard = true;
|
||||
this.canPlotFromTopOfLibrary = false;
|
||||
this.drawsFromBottom = false;
|
||||
this.drawsOnOpponentsTurn = false;
|
||||
|
|
@ -526,7 +522,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
this.payLifeCostLevel = PayLifeCostLevel.allAbilities;
|
||||
this.sacrificeCostFilter = null;
|
||||
this.loseByZeroOrLessLife = true;
|
||||
this.canPlayCardsFromGraveyard = false;
|
||||
this.canPlotFromTopOfLibrary = false;
|
||||
this.drawsFromBottom = false;
|
||||
this.drawsOnOpponentsTurn = false;
|
||||
|
|
@ -4138,9 +4133,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
approvingObjects = new HashSet<>();
|
||||
}
|
||||
|
||||
boolean canActivateAsHandZone = !approvingObjects.isEmpty()
|
||||
|| (fromZone == Zone.GRAVEYARD && canPlayCardsFromGraveyard());
|
||||
boolean possibleToPlay = canActivateAsHandZone
|
||||
boolean possibleToPlay = !approvingObjects.isEmpty()
|
||||
&& ability.getZone().match(Zone.HAND)
|
||||
&& (isPlaySpell || isPlayLand);
|
||||
|
||||
|
|
@ -4164,7 +4157,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
// from non hand mode (with affected controller)
|
||||
if (canActivateAsHandZone && ability.getControllerId() != this.getId()) {
|
||||
if (!approvingObjects.isEmpty() && ability.getControllerId() != this.getId()) {
|
||||
UUID savedControllerId = ability.getControllerId();
|
||||
ability.setControllerId(this.getId());
|
||||
try {
|
||||
|
|
@ -4646,16 +4639,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
this.loseByZeroOrLessLife = loseByZeroOrLessLife;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayCardsFromGraveyard() {
|
||||
return canPlayCardsFromGraveyard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayCardsFromGraveyard(boolean playCardsFromGraveyard) {
|
||||
this.canPlayCardsFromGraveyard = playCardsFromGraveyard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlotFromTopOfLibrary() {
|
||||
return canPlotFromTopOfLibrary;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue