diff --git a/Mage.Sets/src/mage/cards/b/BrilliantUltimatum.java b/Mage.Sets/src/mage/cards/b/BrilliantUltimatum.java index aa914cfbe4..158bfc6d39 100644 --- a/Mage.Sets/src/mage/cards/b/BrilliantUltimatum.java +++ b/Mage.Sets/src/mage/cards/b/BrilliantUltimatum.java @@ -110,8 +110,7 @@ class BrilliantUltimatumEffect extends OneShotEffect { TargetCard targetExiledCard = new TargetCard(Zone.EXILED, new FilterCard()); if (controller.chooseTarget(Outcome.PlayForFree, selectedPile, targetExiledCard, source, game)) { Card card = selectedPile.get(targetExiledCard.getFirstTarget(), game); - controller.canPlayLand(); - if (controller.playCard(card, game, true, true, new ApprovingObject(source, game))) { + if (controller.playCard(card, game, true, new ApprovingObject(source, game))) { selectedPileCards.remove(card); selectedPile.remove(card); } diff --git a/Mage.Sets/src/mage/cards/c/ChandraAblaze.java b/Mage.Sets/src/mage/cards/c/ChandraAblaze.java index 20518c65b7..2e665564df 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraAblaze.java +++ b/Mage.Sets/src/mage/cards/c/ChandraAblaze.java @@ -171,7 +171,10 @@ class ChandraAblazeEffect5 extends OneShotEffect { if (player.choose(outcome, target, source.getSourceId(), game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null) { - player.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); + player.cast(player.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); + cards.remove(card); } } diff --git a/Mage.Sets/src/mage/cards/d/DjinnOfWishes.java b/Mage.Sets/src/mage/cards/d/DjinnOfWishes.java index b51e75ef4d..3269631dec 100644 --- a/Mage.Sets/src/mage/cards/d/DjinnOfWishes.java +++ b/Mage.Sets/src/mage/cards/d/DjinnOfWishes.java @@ -78,7 +78,7 @@ class DjinnOfWishesEffect extends OneShotEffect { Cards cards = new CardsImpl(card); controller.revealCards(sourceObject.getIdName(), cards, game); if (!controller.chooseUse(Outcome.PlayForFree, "Play " + card.getName() + " without paying its mana cost?", source, game) - || !controller.playCard(card, game, true, true, new ApprovingObject(source, game))) { + || !controller.playCard(card, game, true, new ApprovingObject(source, game))) { controller.moveCards(card, Zone.EXILED, source, game); } return true; diff --git a/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java b/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java index b38d643aa1..36273b7f0c 100644 --- a/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java +++ b/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java @@ -154,7 +154,9 @@ class EyeOfTheStormEffect1 extends OneShotEffect { if (cardToCopy != null) { Card copy = game.copyCard(cardToCopy, source, source.getControllerId()); if (spellController.chooseUse(outcome, "Cast " + copy.getIdName() + " without paying mana cost?", source, game)) { - spellController.cast(copy.getSpellAbility(), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + copy.getId(), Boolean.TRUE); + spellController.cast(spellController.chooseAbilityForCast(copy, game, true), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + copy.getId(), null); } } } diff --git a/Mage.Sets/src/mage/cards/g/Guile.java b/Mage.Sets/src/mage/cards/g/Guile.java index d4ddadcd01..057c1cec99 100644 --- a/Mage.Sets/src/mage/cards/g/Guile.java +++ b/Mage.Sets/src/mage/cards/g/Guile.java @@ -86,7 +86,7 @@ class GuileReplacementEffect extends ReplacementEffectImpl { Card spellCard = spell.getCard(); if (spellCard != null && controller.chooseUse(Outcome.PlayForFree, "Play " + spellCard.getIdName() + " for free?", source, game)) { - controller.playCard(spellCard, game, true, true, new ApprovingObject(source, game)); + controller.playCard(spellCard, game, true, new ApprovingObject(source, game)); } return true; } diff --git a/Mage.Sets/src/mage/cards/h/HordeOfNotions.java b/Mage.Sets/src/mage/cards/h/HordeOfNotions.java index 0fbbdfe19b..eaf2125caf 100644 --- a/Mage.Sets/src/mage/cards/h/HordeOfNotions.java +++ b/Mage.Sets/src/mage/cards/h/HordeOfNotions.java @@ -84,7 +84,7 @@ class HordeOfNotionsEffect extends OneShotEffect { if (controller != null) { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (card != null && controller.chooseUse(outcome, "Play " + card.getName() + " from your graveyard for free?", source, game)) { - controller.playCard(card, game, true, true, new ApprovingObject(source, game)); + controller.playCard(card, game, true, new ApprovingObject(source, game)); } return true; } diff --git a/Mage.Sets/src/mage/cards/k/KnowledgePool.java b/Mage.Sets/src/mage/cards/k/KnowledgePool.java index c4af838462..c813eea3cb 100644 --- a/Mage.Sets/src/mage/cards/k/KnowledgePool.java +++ b/Mage.Sets/src/mage/cards/k/KnowledgePool.java @@ -157,7 +157,9 @@ class KnowledgePoolEffect2 extends OneShotEffect { if (player.choose(Outcome.PlayForFree, game.getExile().getExileZone(exileZoneId), target, game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null && !card.getId().equals(spell.getSourceId())) { - player.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); + player.cast(player.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); } } } diff --git a/Mage.Sets/src/mage/cards/l/LeafCrownedElder.java b/Mage.Sets/src/mage/cards/l/LeafCrownedElder.java index 4369e88b39..370a1db735 100644 --- a/Mage.Sets/src/mage/cards/l/LeafCrownedElder.java +++ b/Mage.Sets/src/mage/cards/l/LeafCrownedElder.java @@ -63,7 +63,7 @@ class LeafCrownedElderPlayEffect extends OneShotEffect { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (controller != null && card != null) { if (controller.chooseUse(Outcome.PlayForFree, "Play " + card.getIdName() + " without paying its mana cost?", source, game)) { - controller.playCard(card, game, true, true, new ApprovingObject(source, game)); + controller.playCard(card, game, true, new ApprovingObject(source, game)); } return true; } diff --git a/Mage.Sets/src/mage/cards/o/OmenMachine.java b/Mage.Sets/src/mage/cards/o/OmenMachine.java index b0c7a5bf1d..dc23dc54ae 100644 --- a/Mage.Sets/src/mage/cards/o/OmenMachine.java +++ b/Mage.Sets/src/mage/cards/o/OmenMachine.java @@ -100,7 +100,9 @@ class OmenMachineEffect2 extends OneShotEffect { if (card.isLand(game)) { player.moveCards(card, Zone.BATTLEFIELD, source, game); } else { - player.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); + player.cast(player.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); } } return true; diff --git a/Mage.Sets/src/mage/cards/p/PossibilityStorm.java b/Mage.Sets/src/mage/cards/p/PossibilityStorm.java index 273fff0ad1..10dafb8fea 100644 --- a/Mage.Sets/src/mage/cards/p/PossibilityStorm.java +++ b/Mage.Sets/src/mage/cards/p/PossibilityStorm.java @@ -128,7 +128,9 @@ class PossibilityStormEffect extends OneShotEffect { && !card.isLand(game) && card.getSpellAbility().canChooseTarget(game, spellController.getId())) { if (spellController.chooseUse(Outcome.PlayForFree, "Cast " + card.getLogName() + " without paying cost?", source, game)) { - spellController.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); + spellController.cast(spellController.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); } } diff --git a/Mage.Sets/src/mage/cards/s/SpellQueller.java b/Mage.Sets/src/mage/cards/s/SpellQueller.java index 70a2a9e74a..219a71856f 100644 --- a/Mage.Sets/src/mage/cards/s/SpellQueller.java +++ b/Mage.Sets/src/mage/cards/s/SpellQueller.java @@ -141,7 +141,9 @@ class SpellQuellerLeavesEffect extends OneShotEffect { Player cardOwner = game.getPlayer(card.getOwnerId()); if (cardOwner != null) { if (cardOwner.chooseUse(Outcome.PlayForFree, "Cast " + card.getLogName() + " without paying cost?", source, game)) { - cardOwner.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); + cardOwner.cast(cardOwner.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); } } } diff --git a/Mage.Sets/src/mage/cards/s/Spellshift.java b/Mage.Sets/src/mage/cards/s/Spellshift.java index 274482596d..2d0f562276 100644 --- a/Mage.Sets/src/mage/cards/s/Spellshift.java +++ b/Mage.Sets/src/mage/cards/s/Spellshift.java @@ -78,7 +78,9 @@ class SpellshiftEffect extends OneShotEffect { } spellController.revealCards(source, cardsToReveal, game); if (toCast != null && spellController.chooseUse(outcome, "Cast " + toCast.getLogName() + " without paying its mana cost?", source, game)) { - spellController.cast(toCast.getSpellAbility(), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + toCast.getId(), Boolean.TRUE); + spellController.cast(spellController.chooseAbilityForCast(toCast, game, true), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + toCast.getId(), null); } spellController.shuffleLibrary(source, game); return true; diff --git a/Mage.Sets/src/mage/cards/w/WordOfCommand.java b/Mage.Sets/src/mage/cards/w/WordOfCommand.java index ca70b2d307..0bb6b35bbd 100644 --- a/Mage.Sets/src/mage/cards/w/WordOfCommand.java +++ b/Mage.Sets/src/mage/cards/w/WordOfCommand.java @@ -115,7 +115,7 @@ class WordOfCommandEffect extends OneShotEffect { boolean canPlay = checkPlayability(card, targetPlayer, game, source); while (canPlay && targetPlayer.canRespond() - && !targetPlayer.playCard(card, game, false, true, new ApprovingObject(source, game))) { + && !targetPlayer.playCard(card, game, false, new ApprovingObject(source, game))) { SpellAbility spellAbility = card.getSpellAbility(); if (spellAbility != null) { spellAbility.getManaCostsToPay().clear(); diff --git a/Mage.Sets/src/mage/cards/y/YennettCrypticSovereign.java b/Mage.Sets/src/mage/cards/y/YennettCrypticSovereign.java index 0caca76600..c6e65bb05b 100644 --- a/Mage.Sets/src/mage/cards/y/YennettCrypticSovereign.java +++ b/Mage.Sets/src/mage/cards/y/YennettCrypticSovereign.java @@ -92,7 +92,9 @@ class YennettCrypticSovereignEffect extends OneShotEffect { player.revealCards(source, new CardsImpl(card), game); if (card.getManaValue() % 2 == 1) { if (player.chooseUse(outcome, "Cast " + card.getLogName() + " without paying its mana cost?", source, game)) { - player.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); + player.cast(player.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); } else { /* 7/13/2018 | If the revealed card doesn’t have an odd converted mana cost or if that card does but you diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index d7ff1c66a5..da125caed0 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -3092,8 +3092,8 @@ public class TestPlayer implements Player { } @Override - public boolean playCard(Card card, Game game, boolean noMana, boolean ignoreTiming, ApprovingObject approvingObject) { - return computerPlayer.playCard(card, game, noMana, ignoreTiming, approvingObject); + public boolean playCard(Card card, Game game, boolean noMana, ApprovingObject approvingObject) { + return computerPlayer.playCard(card, game, noMana, approvingObject); } @Override diff --git a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java index 8277b202bc..8a408f0c73 100644 --- a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java +++ b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java @@ -601,7 +601,7 @@ public class PlayerStub implements Player { } @Override - public boolean playCard(Card card, Game game, boolean noMana, boolean checkTiming, ApprovingObject approvingObject) { + public boolean playCard(Card card, Game game, boolean noMana, ApprovingObject approvingObject) { return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/CastCardFromOutsideTheGameEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CastCardFromOutsideTheGameEffect.java index a566afcc6a..4b032cfc69 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CastCardFromOutsideTheGameEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CastCardFromOutsideTheGameEffect.java @@ -72,7 +72,9 @@ public class CastCardFromOutsideTheGameEffect extends OneShotEffect { if (player.choose(Outcome.Benefit, filteredCards, target, game)) { Card card = player.getSideboard().get(target.getFirstTarget(), game); if (card != null) { - player.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); + player.cast(player.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); } } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java b/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java index 63772bab37..ec54ab19a9 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java @@ -67,7 +67,7 @@ public class HideawayPlayEffect extends OneShotEffect { } } - if (!controller.playCard(card, game, true, true, new ApprovingObject(source, game))) { + if (!controller.playCard(card, game, true, new ApprovingObject(source, game))) { if (card.getZoneChangeCounter(game) == zcc) { card.setFaceDown(true, game); } diff --git a/Mage/src/main/java/mage/abilities/keyword/RippleAbility.java b/Mage/src/main/java/mage/abilities/keyword/RippleAbility.java index 35d959a2ee..d1c9ef37cc 100644 --- a/Mage/src/main/java/mage/abilities/keyword/RippleAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/RippleAbility.java @@ -88,7 +88,7 @@ class RippleEffect extends OneShotEffect { if (!player.chooseUse(Outcome.Neutral, "Reveal " + rippleNumber + " cards from the top of your library?", source, game)) { return true; //fizzle } - // reveal to/**/p cards from library + // reveal top cards from library Cards cards = new CardsImpl(); cards.addAll(player.getLibrary().getTopCards(game, rippleNumber)); player.revealCards(sourceObject.getIdName(), cards, game); @@ -104,7 +104,10 @@ class RippleEffect extends OneShotEffect { while (player.canRespond() && cards.count(sameNameFilter, game) > 0 && player.choose(Outcome.PlayForFree, cards, target1, game)) { Card card = cards.get(target1.getFirstTarget(), game); if (card != null) { - player.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); + player.cast(player.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); + cards.remove(card); } target1.clearChosen(); diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index 35adef2c31..abd1239872 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -449,19 +449,15 @@ public interface Player extends MageItem, Copyable { boolean canPlayLand(); /** - * Plays a card if possible + * Plays a card (play land or cast spell). Works from any zones without timing restriction * * @param card the card that can be cast * @param game - * @param noMana if it's a spell i can be cast without paying mana - * @param ignoreTiming if it's cast during the resolution of another - * spell no sorcery or play land timing restriction - * are checked. For a land it has to be the turn of - * the player playing that card. + * @param noMana if it's a spell it can be cast without paying mana * @param approvingObject reference to the ability that allows to play the card * @return */ - boolean playCard(Card card, Game game, boolean noMana, boolean ignoreTiming, ApprovingObject approvingObject); + boolean playCard(Card card, Game game, boolean noMana, ApprovingObject approvingObject); /** * @param card the land card to play diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index d66ad138d0..d5bfc7ef5b 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1128,16 +1128,21 @@ public abstract class PlayerImpl implements Player, Serializable { } @Override - public boolean playCard(Card card, Game game, boolean noMana, boolean ignoreTiming, ApprovingObject approvingObject) { + public boolean playCard(Card card, Game game, boolean noMana, ApprovingObject approvingObject) { if (card == null) { return false; } + + // play without timing and from any zone boolean result; if (card.isLand(game)) { - result = playLand(card, game, ignoreTiming); + result = playLand(card, game, true); } else { - result = cast(card.getSpellAbility(), game, noMana, approvingObject); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); + result = cast(this.chooseAbilityForCast(card, game, noMana), game, noMana, approvingObject); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); } + if (!result) { game.informPlayer(this, "You can't play " + card.getIdName() + '.'); }