Implemented castability check for Word of Command

This commit is contained in:
L_J 2018-06-07 05:37:22 +02:00 committed by GitHub
parent cb7c222eb9
commit d19ca838ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 5 deletions

View file

@ -4,17 +4,23 @@ import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.MageObjectReference; import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.AsThoughEffect;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.RestrictionEffect;
import mage.cards.Card; 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;
import mage.constants.AsThoughEffectType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.stack.Spell; import mage.game.stack.Spell;
import mage.players.ManaPool; import mage.players.ManaPool;
@ -99,10 +105,43 @@ class WordOfCommandEffect extends OneShotEffect {
manaPool.storeMana(); manaPool.storeMana();
int bookmark = game.bookmarkState(); int bookmark = game.bookmarkState();
if ((card.isLand() && (!targetPlayer.canPlayLand() || !game.getActivePlayerId().equals(targetPlayer.getId()))) // check for card playability (Word of Command allows the chosen card to be played "as if it had flash" so we need to invoke such effect to bypass the check)
|| !targetPlayer.playCard(card, game, false, true, new MageObjectReference(source.getSourceObject(game), game))) { boolean canPlay = false;
// TODO: needs an automatic check for whether the card is castable (so it can't be cancelled if that's the case) if (card.isLand()) { // we can't use getPlayableInHand(game) in here because it disallows playing lands outside the main step
game.informPlayers(targetPlayer.getLogName() + " didn't play " + card.getLogName()); if (targetPlayer.canPlayLand()
&& game.getActivePlayerId().equals(targetPlayer.getId())) {
canPlay = true;
for (Ability ability : card.getAbilities(game)) {
if (!game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), ability.getSourceId(), targetPlayer.getId()), ability, game, true)) {
canPlay &= true;
}
}
}
} else {
AsThoughEffectImpl effect2 = new WordOfCommandTestFlashEffect();
game.addEffect(effect2, source);
if (targetPlayer.getPlayableInHand(game).contains(card.getId())) {
canPlay = true;
}
for (AsThoughEffect eff : game.getContinuousEffects().getApplicableAsThoughEffects(AsThoughEffectType.CAST_AS_INSTANT, game)) {
if (eff instanceof WordOfCommandTestFlashEffect) {
eff.discard();
break;
}
}
}
if (canPlay) {
while (!targetPlayer.playCard(card, game, false, true, new MageObjectReference(source.getSourceObject(game), game))) {
SpellAbility spellAbility = card.getSpellAbility();
if (spellAbility != null) {
((ManaCostsImpl) spellAbility.getManaCosts()).forceManaRollback(game, manaPool); // force rollback if card was deemed playable
} else {
break;
}
}
} else {
game.informPlayers(targetPlayer.getLogName() + " didn't play " + card.getLogName() + (canPlay ? "" : " (card can't be played)"));
} }
manaPool.setForcedToPay(false); // duplicate in case of a new mana pool existing - probably not necessary, but just in case manaPool.setForcedToPay(false); // duplicate in case of a new mana pool existing - probably not necessary, but just in case
@ -114,6 +153,7 @@ class WordOfCommandEffect extends OneShotEffect {
for (RestrictionEffect eff : game.getContinuousEffects().getRestrictionEffects()) { for (RestrictionEffect eff : game.getContinuousEffects().getRestrictionEffects()) {
if (eff instanceof WordOfCommandCantActivateEffect) { if (eff instanceof WordOfCommandCantActivateEffect) {
eff.discard(); eff.discard();
break;
} }
} }
game.getContinuousEffects().removeInactiveEffects(game); game.getContinuousEffects().removeInactiveEffects(game);
@ -161,3 +201,29 @@ class WordOfCommandCantActivateEffect extends RestrictionEffect {
return false; return false;
} }
} }
class WordOfCommandTestFlashEffect extends AsThoughEffectImpl {
public WordOfCommandTestFlashEffect() {
super(AsThoughEffectType.CAST_AS_INSTANT, Duration.EndOfTurn, Outcome.Benefit);
}
public WordOfCommandTestFlashEffect(final WordOfCommandTestFlashEffect effect) {
super(effect);
}
@Override
public WordOfCommandTestFlashEffect copy() {
return new WordOfCommandTestFlashEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean applies(UUID affectedSpellId, Ability source, UUID affectedControllerId, Game game) {
return true;
}
}

View file

@ -346,6 +346,11 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
} }
} }
public void forceManaRollback(Game game, ManaPool pool) {
// for Word of Command
handleForcedToPayOnlyForCurrentPayment(game, pool, this);
}
@Override @Override
public final void load(String mana) { public final void load(String mana) {
this.clear(); this.clear();

View file

@ -543,7 +543,7 @@ public class ContinuousEffects implements Serializable {
* @param game * @param game
* @return * @return
*/ */
private List<AsThoughEffect> getApplicableAsThoughEffects(AsThoughEffectType type, Game game) { public List<AsThoughEffect> getApplicableAsThoughEffects(AsThoughEffectType type, Game game) {
List<AsThoughEffect> asThoughEffectsList = new ArrayList<>(); List<AsThoughEffect> asThoughEffectsList = new ArrayList<>();
if (asThoughEffectsMap.containsKey(type)) { if (asThoughEffectsMap.containsKey(type)) {
for (AsThoughEffect effect : asThoughEffectsMap.get(type)) { for (AsThoughEffect effect : asThoughEffectsMap.get(type)) {