* Improved handling of asThoughtAs approval by abilities that allows a clear and easy assignment of the approving effect.

This commit is contained in:
LevelX2 2020-08-21 14:58:22 +02:00
parent 0565d32f55
commit 8105d8b26c
117 changed files with 523 additions and 442 deletions

View file

@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
import mage.ApprovingObject;
import mage.ConditionalMana;
import mage.MageObject;
import mage.MageObjectReference;
@ -1400,7 +1401,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
protected boolean playManaHandling(Ability ability, ManaCost unpaid, final Game game) {
// log.info("paying for " + unpaid.getText());
MageObjectReference permittingObject = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
ApprovingObject approvingObject = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
ManaCost cost;
List<MageObject> producers;
if (unpaid instanceof ManaCosts) {
@ -1444,7 +1445,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
if (cost instanceof ColoredManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || permittingObject != null) {
if (cost.testPay(netMana) || approvingObject != null) {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
@ -1459,7 +1460,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
if (cost instanceof SnowManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || permittingObject != null) {
if (cost.testPay(netMana) || approvingObject != null) {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
@ -1474,7 +1475,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
if (cost instanceof HybridManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || permittingObject != null) {
if (cost.testPay(netMana) || approvingObject != null) {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
@ -1489,7 +1490,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
if (cost instanceof MonoHybridManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || permittingObject != null) {
if (cost.testPay(netMana) || approvingObject != null) {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
@ -1504,7 +1505,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
if (cost instanceof ColorlessManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || permittingObject != null) {
if (cost.testPay(netMana) || approvingObject != null) {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
@ -1519,7 +1520,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
if (cost instanceof GenericManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || permittingObject != null) {
if (cost.testPay(netMana) || approvingObject != null) {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}
@ -1534,7 +1535,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
// pay phyrexian life costs
if (cost instanceof PhyrexianManaCost) {
return cost.pay(null, game, null, playerId, false, null) || permittingObject != null;
return cost.pay(null, game, null, playerId, false, null) || approvingObject != null;
}
// pay special mana like convoke cost (tap for pay)
@ -1545,7 +1546,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
ManaOptions specialMana = specialAction == null ? null : specialAction.getManaOptions(ability, game, unpaid);
if (specialMana != null) {
for (Mana netMana : specialMana) {
if (cost.testPay(netMana) || permittingObject != null) {
if (cost.testPay(netMana) || approvingObject != null) {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
continue;
}

View file

@ -2,7 +2,7 @@ package mage.cards.a;
import java.util.Set;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@ -88,7 +88,7 @@ class AetherworksMarvelEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
if (cardWasCast) {
cards.remove(card);

View file

@ -1,6 +1,5 @@
package mage.cards.a;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
@ -15,6 +14,7 @@ import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetOpponent;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author TheElk801
@ -88,7 +88,7 @@ class AllureOfTheUnknownEffect extends OneShotEffect {
if (opponent.chooseUse(outcome, "Cast the exiled card without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
opponent.cast(opponent.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
return true;

View file

@ -1,7 +1,7 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
@ -132,7 +132,7 @@ class AshiokNightmareMuseCastEffect extends OneShotEffect {
&& controller.chooseUse(outcome, "Cast " + chosenCard.getName() + " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(chosenCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), null);
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.RemoveVariableCountersSourceCost;
@ -106,7 +106,7 @@ class BrainInAJarCastEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -3,8 +3,8 @@ package mage.cards.b;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
@ -111,7 +111,7 @@ class BrilliantUltimatumEffect extends OneShotEffect {
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 MageObjectReference(source.getSourceObject(game), game))) {
if (controller.playCard(card, game, true, true, new ApprovingObject(source, game))) {
selectedPileCards.remove(card);
selectedPile.remove(card);
}

View file

@ -1,7 +1,7 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.ColorsOfManaSpentToCastCount;
import mage.abilities.effects.OneShotEffect;
@ -18,7 +18,6 @@ import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import org.apache.log4j.Logger;
/**
* @author LevelX2
@ -84,7 +83,7 @@ class BringToLightEffect extends OneShotEffect {
+ " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -1,6 +1,5 @@
package mage.cards.c;
import mage.MageObjectReference;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
@ -28,6 +27,7 @@ import mage.target.common.TargetDiscard;
import java.util.Set;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author North
@ -171,7 +171,7 @@ 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 MageObjectReference(source.getSourceObject(game), game));
player.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game));
cards.remove(card);
}
}

View file

@ -3,8 +3,8 @@ package mage.cards.c;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
@ -230,26 +230,26 @@ class ChandraPyromasterEffect3 extends OneShotEffect {
if (controller.chooseTarget(Outcome.PlayForFree, cards, target, source, game)) {
Card card = cards.get(target.getFirstTarget(), game);
if (card != null) {
MageObjectReference mor = new MageObjectReference(source.getSourceObject(game), game);
ApprovingObject approvingObject = new ApprovingObject(source, game);
if (controller.chooseUse(outcome, "Do you wish to cast copy 1 of " + card.getName(), source, game)) {
Card copy1 = game.copyCard(card, source, source.getControllerId());
game.getState().setValue("PlayFromNotOwnHandZone" + copy1.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copy1, game, true),
game, true, mor);
game, true, approvingObject);
game.getState().setValue("PlayFromNotOwnHandZone" + copy1.getId(), null);
}
if (controller.chooseUse(outcome, "Do you wish to cast copy 2 of " + card.getName(), source, game)) {
Card copy2 = game.copyCard(card, source, source.getControllerId());
game.getState().setValue("PlayFromNotOwnHandZone" + copy2.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copy2, game, true),
game, true, mor);
game, true, approvingObject);
game.getState().setValue("PlayFromNotOwnHandZone" + copy2.getId(), null);
}
if (controller.chooseUse(outcome, "Do you wish to cast copy 3 of " + card.getName(), source, game)) {
Card copy3 = game.copyCard(card, source, source.getControllerId());
game.getState().setValue("PlayFromNotOwnHandZone" + copy3.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copy3, game, true),
game, true, mor);
game, true, approvingObject);
game.getState().setValue("PlayFromNotOwnHandZone" + copy3.getId(), null);
}
return true;

View file

@ -1,8 +1,8 @@
package mage.cards.c;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageObject;
import mage.MageObjectReference;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
@ -98,7 +98,7 @@ class ChandraTorchOfDefianceEffect extends OneShotEffect {
&& (game.getState().getZone(card.getId()) == Zone.EXILED)) { // card must be in the exile zone
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); // enable the card to be cast from the exile zone
cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, false),
game, false, new MageObjectReference(sourceObject, game));
game, false, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); // reset to null
}
}

View file

@ -1,6 +1,5 @@
package mage.cards.c;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@ -15,6 +14,7 @@ import mage.players.Player;
import mage.target.common.TargetOpponent;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author TheElk801
@ -88,7 +88,7 @@ class ChaosWandEffect extends OneShotEffect {
+ " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
if (!cardWasCast) {

View file

@ -1,7 +1,6 @@
package mage.cards.c;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
@ -16,6 +15,7 @@ import mage.players.Player;
import mage.target.TargetCard;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author TheElk801
@ -103,7 +103,7 @@ class CollectedConjuringEffect extends OneShotEffect {
}
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
cardsToChoose.remove(card); // remove on non cast too (infinite freeze fix)
if (cardWasCast) {

View file

@ -3,8 +3,8 @@ package mage.cards.c;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -87,7 +87,7 @@ class CounterlashEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -1,8 +1,8 @@
package mage.cards.d;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -89,7 +89,7 @@ class DescendantsPathEffect extends OneShotEffect {
if (controller.chooseUse(Outcome.Benefit, "Cast the card?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
} else {
game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " canceled casting the card.");

View file

@ -1,7 +1,6 @@
package mage.cards.d;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
@ -26,6 +25,7 @@ import mage.target.targetadjustment.TargetAdjuster;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author LevelX2
@ -112,7 +112,7 @@ class DiluvianPrimordialEffect extends OneShotEffect {
if (controller.chooseUse(Outcome.PlayForFree, "Cast " + targetCard.getLogName() + '?', source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + targetCard.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(targetCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + targetCard.getId(), null);
if (cardWasCast) {
ContinuousEffect effect = new DiluvianPrimordialReplacementEffect();

View file

@ -2,9 +2,9 @@
package mage.cards.d;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
@ -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 MageObjectReference(source.getSourceObject(game), game))) {
|| !controller.playCard(card, game, true, true, new ApprovingObject(source, game))) {
controller.moveCards(card, Zone.EXILED, source, game);
}
return true;

View file

@ -1,7 +1,6 @@
package mage.cards.d;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
@ -25,6 +24,7 @@ import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author TheElk801
@ -109,7 +109,7 @@ class DreadhordeArcanistEffect extends OneShotEffect {
&& controller.chooseUse(Outcome.PlayForFree, "Cast " + card.getLogName() + '?', source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
ContinuousEffect effect = new DreadhordeArcanistReplacementEffect(card.getId());

View file

@ -1,7 +1,6 @@
package mage.cards.e;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@ -24,6 +23,7 @@ import mage.players.Player;
import mage.target.TargetCard;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author LevelX2
@ -165,7 +165,7 @@ class EliteArcanistCopyEffect extends OneShotEffect {
if (controller.chooseUse(Outcome.PlayForFree, "Cast the copied card without paying mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(copiedCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), null);
return cardWasCast;
}

View file

@ -1,7 +1,6 @@
package mage.cards.e;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSpellEffect;
@ -19,6 +18,7 @@ import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetOpponent;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author TheElk801
@ -109,7 +109,7 @@ class EmergentUltimatumEffect extends OneShotEffect {
}
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = player.cast(player.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
cards.remove(card); // remove on non cast too (infinite freeze fix)
if (cardWasCast) {

View file

@ -1,7 +1,6 @@
package mage.cards.e;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
@ -18,6 +17,7 @@ import mage.players.Player;
import mage.target.TargetCard;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author LevelX2
@ -91,7 +91,7 @@ class EpicExperimentEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
if (!cardWasCast) {
game.informPlayer(controller, "You're not able to cast "

View file

@ -2,7 +2,6 @@ package mage.cards.e;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -17,6 +16,7 @@ import mage.target.TargetCard;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author ciaccona007 & L_J
@ -110,7 +110,7 @@ class EtaliPrimalStormEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
if (!cardWasCast) {
game.informPlayer(controller, "You're not able to cast "

View file

@ -1,6 +1,5 @@
package mage.cards.e;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
@ -22,6 +21,7 @@ import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author spjspj
@ -152,7 +152,7 @@ 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 MageObjectReference(source.getSourceObject(game), game));
spellController.cast(copy.getSpellAbility(), game, true, new ApprovingObject(source, game));
}
}
}

View file

@ -1,6 +1,5 @@
package mage.cards.f;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.ContinuousEffect;
@ -25,6 +24,7 @@ import mage.target.targetpointer.FixedTarget;
import java.util.*;
import java.util.stream.Collectors;
import mage.ApprovingObject;
/**
* @author JayDi85
@ -138,7 +138,7 @@ class FinaleOfPromiseEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
ContinuousEffect effect = new FinaleOfPromiseReplacementEffect();
effect.setTargetPointer(new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId())));

View file

@ -1,8 +1,8 @@
package mage.cards.g;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -64,7 +64,7 @@ class GalvanothEffect extends OneShotEffect {
if (controller.chooseUse(Outcome.PlayForFree, "Cast " + card.getName() + " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.g;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.costs.mana.ManaCost;
@ -22,6 +21,7 @@ import mage.watchers.common.CommanderPlaysCountWatcher;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author spjspj, JayDi85
@ -117,7 +117,7 @@ class GeodeGolemEffect extends OneShotEffect {
if (commander.getSpellAbility() != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + commander.getId(), Boolean.TRUE);
Boolean commanderWasCast = controller.cast(controller.chooseAbilityForCast(commander, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + commander.getId(), null);
return commanderWasCast;
} else {

View file

@ -1,27 +1,25 @@
package mage.cards.g;
import java.util.HashSet;
import java.util.Set;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.Watcher;
import java.util.UUID;
import mage.MageIdentifier;
import mage.MageObjectReference;
import mage.game.permanent.Permanent;
/**
*
@ -41,7 +39,9 @@ public final class GisaAndGeralf extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new PutTopCardOfLibraryIntoGraveControllerEffect(4)));
// During each of your turns, you may cast a Zombie creature card from your graveyard.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GisaAndGeralfContinuousEffect()), new GisaAndGeralfWatcher());
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GisaAndGeralfCastFromGraveyardEffect())
.setIdentifier(MageIdentifier.GisaAndGeralfWatcher),
new GisaAndGeralfWatcher());
}
public GisaAndGeralf(final GisaAndGeralf card) {
@ -54,51 +54,11 @@ public final class GisaAndGeralf extends CardImpl {
}
}
class GisaAndGeralfContinuousEffect extends ContinuousEffectImpl {
private static final FilterCreatureCard filter = new FilterCreatureCard("Zombie creature card");
static {
filter.add(SubType.ZOMBIE.getPredicate());
}
GisaAndGeralfContinuousEffect() {
super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit);
staticText = "During each of your turns, you may cast a Zombie creature card from your graveyard";
}
GisaAndGeralfContinuousEffect(final GisaAndGeralfContinuousEffect effect) {
super(effect);
}
@Override
public GisaAndGeralfContinuousEffect copy() {
return new GisaAndGeralfContinuousEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
if (!game.isActivePlayer(player.getId())) {
return false;
}
for (Card card : player.getGraveyard().getCards(filter, game)) {
ContinuousEffect effect = new GisaAndGeralfCastFromGraveyardEffect();
effect.setTargetPointer(new FixedTarget(card.getId()));
game.addEffect(effect, source);
}
return true;
}
return false;
}
}
class GisaAndGeralfCastFromGraveyardEffect extends AsThoughEffectImpl {
GisaAndGeralfCastFromGraveyardEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
staticText = "You may cast a Zombie creature card from your graveyard";
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.PutCreatureInPlay);
staticText = "During each of your turns, you may cast a Zombie creature card from your graveyard";
}
GisaAndGeralfCastFromGraveyardEffect(final GisaAndGeralfCastFromGraveyardEffect effect) {
@ -117,10 +77,18 @@ class GisaAndGeralfCastFromGraveyardEffect extends AsThoughEffectImpl {
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (objectId.equals(getTargetPointer().getFirst(game, source))) {
if (affectedControllerId.equals(source.getControllerId())) {
GisaAndGeralfWatcher watcher = game.getState().getWatcher(GisaAndGeralfWatcher.class, source.getSourceId());
return watcher != null && !watcher.isAbilityUsed();
if (source.isControlledBy(affectedControllerId)
&& Zone.GRAVEYARD.equals(game.getState().getZone(objectId))) {
Card objectCard = game.getCard(objectId);
Permanent sourceObject = game.getPermanent(source.getSourceId());
if (sourceObject != null && objectCard != null
&& objectCard.isOwnedBy(source.getControllerId())
&& objectCard.isCreature()
&& objectCard.hasSubtype(SubType.ZOMBIE, game)
&& objectCard.getSpellAbility() != null
&& objectCard.getSpellAbility().spellCanBeActivatedRegularlyNow(affectedControllerId, game)) {
GisaAndGeralfWatcher watcher = game.getState().getWatcher(GisaAndGeralfWatcher.class);
return watcher != null && !watcher.isAbilityUsed(new MageObjectReference(sourceObject, game));
}
}
return false;
@ -129,29 +97,27 @@ class GisaAndGeralfCastFromGraveyardEffect extends AsThoughEffectImpl {
class GisaAndGeralfWatcher extends Watcher {
private boolean abilityUsed = false;
private final Set<MageObjectReference> usedFrom = new HashSet<>();
GisaAndGeralfWatcher() {
super(WatcherScope.CARD);
super(WatcherScope.GAME);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getZone() == Zone.GRAVEYARD) {
Spell spell = (Spell) game.getObject(event.getTargetId());
if (spell != null && spell.isCreature() && spell.hasSubtype(SubType.ZOMBIE, game)) {
abilityUsed = true;
}
if (GameEvent.EventType.SPELL_CAST.equals(event.getType())
&& event.hasApprovingIdentifier(MageIdentifier.GisaAndGeralfWatcher)) {
usedFrom.add(event.getAdditionalReference().getApprovingMageObjectReference());
}
}
@Override
public void reset() {
super.reset();
abilityUsed = false;
usedFrom.clear();
}
public boolean isAbilityUsed() {
return abilityUsed;
public boolean isAbilityUsed(MageObjectReference mor) {
return usedFrom.contains(mor);
}
}

View file

@ -1,8 +1,8 @@
package mage.cards.g;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
@ -93,7 +93,7 @@ class GoblinDarkDwellersEffect extends OneShotEffect {
if (controller.chooseUse(Outcome.PlayForFree, "Cast " + card.getLogName() + '?', source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
if (cardWasCast) {
ContinuousEffect effect = new GoblinDarkDwellersReplacementEffect(card.getId());

View file

@ -2,8 +2,8 @@ package mage.cards.g;
import java.awt.*;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.GodEternalDiesTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
@ -98,7 +98,7 @@ class GodEternalKefnetDrawCardReplacementEffect extends ReplacementEffectImpl {
blueprint.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(2)));
Card copiedCard = game.copyCard(blueprint, source, source.getControllerId());
you.moveCardToHandWithInfo(copiedCard, source.getSourceId(), game, true); // The copy is created in and cast from your hand.
you.cast(copiedCard.getSpellAbility(), game, false, new MageObjectReference(source.getSourceObject(game), game));
you.cast(copiedCard.getSpellAbility(), game, false, new ApprovingObject(source, game));
}
// draw (return false for default draw)

View file

@ -2,8 +2,8 @@
package mage.cards.g;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.PutIntoGraveFromAnywhereSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
@ -92,7 +92,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 MageObjectReference(source.getSourceObject(game), game));
controller.playCard(spellCard, game, true, true, new ApprovingObject(source, game));
}
return true;
}

View file

@ -1,7 +1,7 @@
package mage.cards.h;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.Effect;
@ -111,7 +111,7 @@ class HarnessTheStormEffect extends OneShotEffect {
if (controller.chooseUse(outcome.Benefit, "Cast " + card.getIdName() + " from your graveyard?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, false),
game, false, new MageObjectReference(source.getSourceObject(game), game));
game, false, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.h;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect;
@ -17,6 +16,7 @@ import mage.players.Player;
import mage.target.TargetCard;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author ciaccona007
@ -105,7 +105,7 @@ class HazoretsUndyingFuryEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
cardsToCast.remove(card);
if (!cardWasCast) {

View file

@ -1,7 +1,6 @@
package mage.cards.h;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -21,6 +20,7 @@ import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author jeffwadsworth & L_J
@ -103,7 +103,7 @@ class HellcarverDemonEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
cardsToCast.remove(card);
if (!cardWasCast) {

View file

@ -2,8 +2,8 @@
package mage.cards.h;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -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 MageObjectReference(source.getSourceObject(game), game));
controller.playCard(card, game, true, true, new ApprovingObject(source, game));
}
return true;
}

View file

@ -245,7 +245,7 @@ class IdolOfEnduranceWatcher extends Watcher {
if (event.getAdditionalReference() == null) {
return;
}
morMap.computeIfAbsent(event.getAdditionalReference(), m -> new HashMap<>())
morMap.computeIfAbsent(event.getAdditionalReference().getApprovingMageObjectReference(), m -> new HashMap<>())
.compute(event.getPlayerId(), (u, i) -> i == null ? 0 : Integer.sum(i, -1));
return;
}

View file

@ -1,7 +1,7 @@
package mage.cards.i;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@ -149,7 +149,7 @@ class IsochronScepterCopyEffect extends OneShotEffect {
if (copiedCard.getSpellAbility() != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copiedCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), null);
} else {
Logger.getLogger(IsochronScepterCopyEffect.class).error("Isochron Scepter: "

View file

@ -1,7 +1,6 @@
package mage.cards.i;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
@ -25,6 +24,7 @@ import mage.target.TargetCard;
import mage.target.common.TargetCardInExile;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author TheElk801
@ -118,7 +118,7 @@ class IzzetChemisterCastFromExileEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true), game, true,
new MageObjectReference(source.getSourceObject(game), game));
new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
cardsToExile.remove(card);
} else {

View file

@ -1,6 +1,5 @@
package mage.cards.j;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.LoyaltyAbility;
@ -29,6 +28,7 @@ import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.*;
import mage.ApprovingObject;
/**
* @author LevelX2
@ -299,7 +299,7 @@ class JaceArchitectOfThoughtEffect3 extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
cardsToChoose.remove(card);
if (cardWasCast) {

View file

@ -1,7 +1,6 @@
package mage.cards.j;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -20,6 +19,7 @@ import mage.target.common.TargetOpponent;
import java.util.Set;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author LevelX2
@ -104,7 +104,7 @@ class JaceMindseekerEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -3,9 +3,9 @@ package mage.cards.j;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -141,7 +141,7 @@ class JelevaNephaliasCastEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
return cardWasCast;
}

View file

@ -1,9 +1,9 @@
package mage.cards.k;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@ -136,7 +136,7 @@ class KahoMinamoHistorianCastEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -3,6 +3,7 @@ package mage.cards.k;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageIdentifier;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
@ -18,7 +19,6 @@ import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.util.CardUtil;
import mage.watchers.Watcher;
@ -44,7 +44,7 @@ public final class KaradorGhostChieftain extends CardImpl {
// During each of your turns, you may cast one creature card from your graveyard.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new KaradorGhostChieftainCastFromGraveyardEffect()),
new KaradorGhostChieftainCastFromGraveyardEffect()).setIdentifier(MageIdentifier.KaradorGhostChieftainWatcher),
new KaradorGhostChieftainWatcher());
}
@ -119,8 +119,7 @@ class KaradorGhostChieftainCastFromGraveyardEffect extends AsThoughEffectImpl {
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (source.isControlledBy(affectedControllerId)
&& Zone.GRAVEYARD.equals(game.getState().getZone(objectId))
) {
&& Zone.GRAVEYARD.equals(game.getState().getZone(objectId))) {
Card objectCard = game.getCard(objectId);
Permanent sourceObject = game.getPermanent(source.getSourceId()); // needs to be onto the battlefield
if (objectCard != null
@ -149,15 +148,9 @@ class KaradorGhostChieftainWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST
&& event.getZone() == Zone.GRAVEYARD) {
Spell spell = (Spell) game.getObject(event.getTargetId());
if (spell.isCreature()) {
MageObjectReference mor = event.getAdditionalReference(); // permitting source
if (mor != null) {
usedFrom.add(mor);
}
}
if (GameEvent.EventType.SPELL_CAST.equals(event.getType())
&& event.hasApprovingIdentifier(MageIdentifier.KaradorGhostChieftainWatcher)) {
usedFrom.add(event.getAdditionalReference().getApprovingMageObjectReference());
}
}

View file

@ -5,6 +5,7 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.MageIdentifier;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
@ -51,7 +52,8 @@ public final class KessDissidentMage extends CardImpl {
// During each of your turns, you may cast an instant or sorcery card from your graveyard. If a card cast this way would be put into your graveyard this turn, exile it instead.
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD,
new KessDissidentMageCastFromGraveyardEffect());
new KessDissidentMageCastFromGraveyardEffect())
.setIdentifier(MageIdentifier.KessDissidentMageWatcher);
ability.addEffect(new KessDissidentMageReplacementEffect());
this.addAbility(ability, new KessDissidentMageWatcher());
}
@ -164,16 +166,13 @@ class KessDissidentMageWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST
&& event.getZone() == Zone.GRAVEYARD) {
if (GameEvent.EventType.SPELL_CAST.equals(event.getType())
&& event.hasApprovingIdentifier(MageIdentifier.KessDissidentMageWatcher)) {
Spell spell = (Spell) game.getObject(event.getTargetId());
if (event.getAdditionalReference() != null
&& event.getAdditionalReference().getSourceId() != null
&& (spell.isInstant()
|| spell.isSorcery())) {
allowingObjects.add(event.getAdditionalReference());
if (spell != null) {
allowingObjects.add(event.getAdditionalReference().getApprovingMageObjectReference());
castSpells.put(new MageObjectReference(spell.getMainCard().getId(), game),
event.getAdditionalReference().getSourceId());
event.getAdditionalReference().getApprovingAbility().getSourceId());
}
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.k;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.ProwlAbility;
@ -77,7 +77,7 @@ class KnowledgeExploitationEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.k;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -27,6 +26,7 @@ import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author BetaSteward_at_googlemail.com
@ -156,7 +156,7 @@ 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 MageObjectReference(source.getSourceObject(game), game));
player.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game));
}
}
}

View file

@ -2,8 +2,8 @@
package mage.cards.l;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.abilityword.KinshipAbility;
import mage.abilities.effects.OneShotEffect;
@ -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 MageObjectReference(source.getSourceObject(game), game));
controller.playCard(card, game, true, true, new ApprovingObject(source, game));
}
return true;
}

View file

@ -1,6 +1,7 @@
package mage.cards.l;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
@ -185,7 +186,7 @@ class LivingLoreSacrificeEffect extends OneShotEffect {
if (exiledCard.getSpellAbility().canChooseTarget(game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + exiledCard.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(exiledCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + exiledCard.getId(), null);
}
}

View file

@ -3,14 +3,13 @@ package mage.cards.l;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageIdentifier;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.keyword.CompanionAbility;
import mage.abilities.keyword.CompanionCondition;
import mage.abilities.keyword.LifelinkAbility;
@ -18,15 +17,9 @@ import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.common.FilterPermanentCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.game.permanent.Permanent;
import mage.watchers.Watcher;
/**
@ -50,9 +43,9 @@ public final class LurrusOfTheDreamDen extends CardImpl {
this.addAbility(LifelinkAbility.getInstance());
// During each of your turns, you may cast one permanent spell with converted mana cost 2 or less from your graveyard.
this.addAbility(new SimpleStaticAbility(
new LurrusOfTheDreamDenContinuousEffect()
), new LurrusOfTheDreamDenWatcher());
this.addAbility(new SimpleStaticAbility(new LurrusOfTheDreamDenCastFromGraveyardEffect())
.setIdentifier(MageIdentifier.LurrusOfTheDreamDenWatcher),
new LurrusOfTheDreamDenWatcher());
}
private LurrusOfTheDreamDen(final LurrusOfTheDreamDen card) {
@ -83,57 +76,11 @@ enum LurrusOfTheDreamDenCompanionCondition implements CompanionCondition {
}
}
class LurrusOfTheDreamDenContinuousEffect extends ContinuousEffectImpl {
private static final FilterCard filter
= new FilterPermanentCard("permanent spell with converted mana cost 2 or less from your graveyard");
static {
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 3));
filter.add(Predicates.not(CardType.LAND.getPredicate()));
}
LurrusOfTheDreamDenContinuousEffect() {
super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit);
staticText = "During each of your turns, you may cast one permanent spell "
+ "with converted mana cost 2 or less from your graveyard";
}
private LurrusOfTheDreamDenContinuousEffect(final LurrusOfTheDreamDenContinuousEffect effect) {
super(effect);
}
@Override
public LurrusOfTheDreamDenContinuousEffect copy() {
return new LurrusOfTheDreamDenContinuousEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
if (game.isActivePlayer(player.getId())) {
LurrusOfTheDreamDenWatcher watcher = game.getState().getWatcher(LurrusOfTheDreamDenWatcher.class);
if (watcher != null && !watcher.isAbilityUsed(new MageObjectReference(source.getSourceId(), game))) {
// if not used yet, add effect per card in graveyard to cast it
for (Card card : player.getGraveyard().getCards(filter, game)) {
ContinuousEffect effect = new LurrusOfTheDreamDenCastFromGraveyardEffect();
effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source);
}
}
}
return true;
}
}
class LurrusOfTheDreamDenCastFromGraveyardEffect extends AsThoughEffectImpl {
LurrusOfTheDreamDenCastFromGraveyardEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
staticText = "You may cast one permanent spell with converted mana cost 2 or less from your graveyard";
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "During each of your turns, you may cast one permanent spell with converted mana cost 2 or less from your graveyard";
}
private LurrusOfTheDreamDenCastFromGraveyardEffect(final LurrusOfTheDreamDenCastFromGraveyardEffect effect) {
@ -152,6 +99,22 @@ class LurrusOfTheDreamDenCastFromGraveyardEffect extends AsThoughEffectImpl {
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (source.isControlledBy(affectedControllerId)
&& Zone.GRAVEYARD.equals(game.getState().getZone(objectId))) {
Card objectCard = game.getCard(objectId);
Permanent sourceObject = game.getPermanent(source.getSourceId());
if (sourceObject != null && objectCard != null
&& objectCard.isOwnedBy(source.getControllerId())
&& objectCard.getConvertedManaCost() < 3
&& objectCard.getSpellAbility() != null
&& objectCard.getSpellAbility().spellCanBeActivatedRegularlyNow(affectedControllerId, game)) {
LurrusOfTheDreamDenWatcher watcher = game.getState().getWatcher(LurrusOfTheDreamDenWatcher.class);
return watcher != null && !watcher.isAbilityUsed(new MageObjectReference(sourceObject, game));
}
}
if (!objectId.equals(getTargetPointer().getFirst(game, source))) {
return false;
}
@ -165,7 +128,7 @@ class LurrusOfTheDreamDenCastFromGraveyardEffect extends AsThoughEffectImpl {
class LurrusOfTheDreamDenWatcher extends Watcher {
private final Set<MageObjectReference> abilityUsed = new HashSet<>();
private final Set<MageObjectReference> usedFrom = new HashSet<>();
LurrusOfTheDreamDenWatcher() {
super(WatcherScope.GAME);
@ -173,25 +136,19 @@ class LurrusOfTheDreamDenWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() != GameEvent.EventType.SPELL_CAST
|| event.getZone() != Zone.GRAVEYARD
|| event.getAdditionalReference() == null) { // permitting source to cast from graveyard
return;
if (GameEvent.EventType.SPELL_CAST.equals(event.getType())
&&event.hasApprovingIdentifier(MageIdentifier.LurrusOfTheDreamDenWatcher)){
usedFrom.add(event.getAdditionalReference().getApprovingMageObjectReference());
}
Spell spell = game.getSpell(event.getTargetId());
if (spell == null || !spell.isPermanent() || spell.getConvertedManaCost() > 2) {
return;
}
abilityUsed.add(event.getAdditionalReference());
}
@Override
public void reset() {
super.reset();
abilityUsed.clear();
usedFrom.clear();
}
boolean isAbilityUsed(MageObjectReference mor) {
return abilityUsed.contains(mor);
return usedFrom.contains(mor);
}
}

View file

@ -1,8 +1,8 @@
package mage.cards.m;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -91,7 +91,7 @@ class MaelstromArchangelCastEffect extends OneShotEffect {
if (cardToCast != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(cardToCast, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), null);
}
}

View file

@ -1,8 +1,8 @@
package mage.cards.m;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -111,7 +111,7 @@ class MasterOfPredicamentsEffect extends OneShotEffect {
+ " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + cardFromHand.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(cardFromHand, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + cardFromHand.getId(), null);
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.m;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -76,7 +76,7 @@ class MemoryPlunderEffect extends OneShotEffect {
&& controller.chooseUse(Outcome.PlayForFree, "Cast " + card.getName() + " without paying cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
return cardWasCast;
}

View file

@ -2,9 +2,9 @@
package mage.cards.m;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -96,7 +96,7 @@ class MindclawShamanEffect extends OneShotEffect {
+ "paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(chosenCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), null);
} else {
game.informPlayers(sourceObject.getLogName() + ": "

View file

@ -1,8 +1,8 @@
package mage.cards.m;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -85,7 +85,7 @@ class MindleechMassEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -2,8 +2,8 @@ package mage.cards.m;
import java.util.List;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastOpponentTriggeredAbility;
import mage.abilities.effects.Effect;
@ -123,7 +123,7 @@ class MindsDilationEffect extends OneShotEffect {
+ " without paying its mana cost from exile?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -1,6 +1,5 @@
package mage.cards.m;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
@ -19,6 +18,7 @@ import mage.target.common.TargetCardInYourGraveyard;
import java.util.Set;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author LevelX2
@ -84,7 +84,7 @@ class MizzixsMasteryEffect extends OneShotEffect {
+ card.getName() + " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + cardCopy.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(cardCopy, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + cardCopy.getId(), null);
}
}
@ -138,7 +138,7 @@ class MizzixsMasteryOverloadEffect extends OneShotEffect {
&& selectedCard.getSpellAbility().canChooseTarget(game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + selectedCard.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(selectedCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + selectedCard.getId(), null);
}
copiedCards.remove(selectedCard);

View file

@ -5,6 +5,7 @@ import java.util.EnumSet;
import java.util.HashMap;
import java.util.Set;
import java.util.UUID;
import mage.MageIdentifier;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
@ -47,7 +48,9 @@ public final class MuldrothaTheGravetide extends CardImpl {
this.toughness = new MageInt(6);
// During each of your turns, you may play up to one permanent card of each permanent type from your graveyard.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MuldrothaTheGravetideCastFromGraveyardEffect()), new MuldrothaTheGravetideWatcher());
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MuldrothaTheGravetideCastFromGraveyardEffect())
.setIdentifier(MageIdentifier.MuldrothaTheGravetideWatcher),
new MuldrothaTheGravetideWatcher());
}
public MuldrothaTheGravetide(final MuldrothaTheGravetide card) {
@ -142,7 +145,9 @@ class MuldrothaTheGravetideWatcher extends Watcher {
}
private void addPermanentTypes(GameEvent event, Card mageObject, Game game) {
if (mageObject != null && event.getAdditionalReference() != null) {
if (mageObject != null
&& event.getAdditionalReference() != null
&& MageIdentifier.MuldrothaTheGravetideWatcher.equals(event.getAdditionalReference().getApprovingAbility().getIdentifier())) {
UUID playerId = null;
if (mageObject instanceof Spell) {
playerId = ((Spell) mageObject).getControllerId();
@ -150,10 +155,10 @@ class MuldrothaTheGravetideWatcher extends Watcher {
playerId = ((Permanent) mageObject).getControllerId();
}
if (playerId != null) {
Set<CardType> permanentTypes = sourcePlayedPermanentTypes.get(event.getAdditionalReference());
Set<CardType> permanentTypes = sourcePlayedPermanentTypes.get(event.getAdditionalReference().getApprovingMageObjectReference());
if (permanentTypes == null) {
permanentTypes = EnumSet.noneOf(CardType.class);
sourcePlayedPermanentTypes.put(event.getAdditionalReference(), permanentTypes);
sourcePlayedPermanentTypes.put(event.getAdditionalReference().getApprovingMageObjectReference(), permanentTypes);
}
Set<CardType> typesNotCast = EnumSet.noneOf(CardType.class);
for (CardType cardType : mageObject.getCardType()) {

View file

@ -47,10 +47,10 @@ public final class MythRealized extends CardImpl {
// Whenever you cast a noncreature spell, put a lore counter on Myth Realized.
this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.LORE.createInstance()), filterNonCreature, false));
// 2W: Put a lore counter on Myth Realized.
// {2}{W}: Put a lore counter on Myth Realized.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.LORE.createInstance()), new ManaCostsImpl("{2}{W}")));
// W: Until end of turn, Myth Realized becomes a Monk Avatar creature in addition to its other types and gains "This creature's power and toughness are each equal to the number of lore counters on it."
// {W}: Until end of turn, Myth Realized becomes a Monk Avatar creature in addition to its other types and gains "This creature's power and toughness are each equal to the number of lore counters on it."
Effect effect = new BecomesCreatureSourceEffect(new MythRealizedToken(), null, Duration.EndOfTurn);
effect.setText("Until end of turn, {this} becomes a Monk Avatar creature in addition to its other types");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{W}"));
@ -83,6 +83,7 @@ class MythRealizedToken extends TokenImpl {
super(token);
}
@Override
public MythRealizedToken copy() {
return new MythRealizedToken(this);
}

View file

@ -2,7 +2,7 @@
package mage.cards.o;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfDrawTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
@ -101,7 +101,7 @@ class OmenMachineEffect2 extends OneShotEffect {
if (card.isLand()) {
player.moveCards(card, Zone.BATTLEFIELD, source, game);
} else {
player.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game));
player.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game));
}
}
return true;

View file

@ -1,7 +1,6 @@
package mage.cards.o;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@ -23,6 +22,7 @@ import mage.target.Target;
import mage.target.common.TargetCardInHand;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author TheElk801
@ -103,7 +103,7 @@ class OmnispellAdeptEffect extends OneShotEffect {
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(cardToCast, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), null);
if (cardWasCast) {

View file

@ -1,8 +1,8 @@
package mage.cards.o;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -105,7 +105,7 @@ class OracleOfBonesCastEffect extends OneShotEffect {
if (cardToCast != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(cardToCast, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + cardToCast.getId(), null);
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.p;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@ -150,7 +150,7 @@ class PanopticMirrorCastEffect extends OneShotEffect {
if (controller.chooseUse(outcome.PlayForFree, "Cast the copied card without paying mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + copy.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copy, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + copy.getId(), null);
}
}

View file

@ -2,8 +2,8 @@ package mage.cards.p;
import java.util.ArrayList;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
@ -129,7 +129,7 @@ class PossibilityStormEffect extends OneShotEffect {
&& !card.isLand()
&& card.getSpellAbility().canChooseTarget(game)) {
if (spellController.chooseUse(Outcome.PlayForFree, "Cast " + card.getLogName() + " without paying cost?", source, game)) {
spellController.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game));
spellController.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game));
}
}

View file

@ -2,8 +2,8 @@ package mage.cards.r;
import java.util.List;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.Effect;
@ -135,7 +135,7 @@ class RashmiEternitiesCrafterEffect extends OneShotEffect {
+ " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
if (!cardWasCast) {

View file

@ -1,7 +1,7 @@
package mage.cards.r;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -84,7 +84,7 @@ class ReversalOfFortuneEffect extends OneShotEffect {
if (controller.chooseUse(Outcome.PlayForFree, "Cast the copied card without paying mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copiedCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), null);
}
} else {

View file

@ -1,7 +1,6 @@
package mage.cards.s;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
@ -22,6 +21,7 @@ import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author TheElk801
@ -97,7 +97,7 @@ class ScholarOfTheLostTroveEffect extends OneShotEffect {
}
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
if (!cardWasCast || !card.isInstantOrSorcery()) {
return true;

View file

@ -1,6 +1,7 @@
package mage.cards.s;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -147,7 +148,7 @@ class ShellOfTheLastKappaCastEffect extends OneShotEffect {
+ sourcePermanent.getLogName() + "?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
return cardWasCast;
}

View file

@ -1,7 +1,6 @@
package mage.cards.s;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -18,7 +17,7 @@ import mage.players.Player;
import mage.target.TargetCard;
import java.util.UUID;
import mage.MageObject;
import mage.ApprovingObject;
/**
* @author LevelX2
@ -96,7 +95,7 @@ class SilentBladeOniEffect extends OneShotEffect {
}
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
return cardWasCast;
}

View file

@ -3,9 +3,9 @@ package mage.cards.s;
import java.util.Set;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
@ -141,7 +141,7 @@ 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 MageObjectReference(source.getSourceObject(game), game));
cardOwner.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game));
}
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -182,7 +182,7 @@ class SpellbinderCopyEffect extends OneShotEffect {
if (copiedCard.getSpellAbility() != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copiedCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), null);
} else {
Logger.getLogger(SpellbinderCopyEffect.class).error(

View file

@ -2,7 +2,7 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CounterTargetEffect;
@ -78,7 +78,7 @@ 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 MageObjectReference(source.getSourceObject(game), game));
spellController.cast(toCast.getSpellAbility(), game, true, new ApprovingObject(source, game));
}
spellController.shuffleLibrary(source, game);
return true;

View file

@ -1,6 +1,7 @@
package mage.cards.s;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@ -88,14 +89,14 @@ class SpelltwineEffect extends OneShotEffect {
controller.moveCards(cardTwo, Zone.EXILED, source, game);
}
boolean castCardOne = true;
MageObjectReference mor = new MageObjectReference(source.getSourceObject(game), game);
ApprovingObject approvingObject = new ApprovingObject(source, game);
if (cardOne != null
&& controller.chooseUse(Outcome.Neutral, "Cast the copy of "
+ cardOne.getName() + " first?", source, game)) {
Card copyOne = game.copyCard(cardOne, source, controller.getId());
game.getState().setValue("PlayFromNotOwnHandZone" + copyOne.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copyOne, game, true),
game, true, mor);
game, true, approvingObject);
game.getState().setValue("PlayFromNotOwnHandZone" + copyOne.getId(), null);
castCardOne = false;
}
@ -103,7 +104,7 @@ class SpelltwineEffect extends OneShotEffect {
Card copyTwo = game.copyCard(cardTwo, source, controller.getId());
game.getState().setValue("PlayFromNotOwnHandZone" + copyTwo.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copyTwo, game, true),
game, true, mor);
game, true, approvingObject);
game.getState().setValue("PlayFromNotOwnHandZone" + copyTwo.getId(), null);
}
if (cardOne != null
@ -111,7 +112,7 @@ class SpelltwineEffect extends OneShotEffect {
Card copyOne = game.copyCard(cardOne, source, controller.getId());
game.getState().setValue("PlayFromNotOwnHandZone" + copyOne.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copyOne, game, true),
game, true, mor);
game, true, approvingObject);
game.getState().setValue("PlayFromNotOwnHandZone" + copyOne.getId(), null);
}
return true;

View file

@ -1,6 +1,5 @@
package mage.cards.s;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -23,6 +22,7 @@ import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author emerald000
@ -191,7 +191,7 @@ class SpellweaverHelixCastEffect extends OneShotEffect {
if (controller.chooseUse(Outcome.PlayForFree, "Cast " + copy.getIdName() + " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + copy.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copy, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + copy.getId(), null);
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -96,7 +96,7 @@ class SpellweaverVoluteEffect extends OneShotEffect {
if (copiedCard.getSpellAbility() != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(copiedCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), null);
}
if (controller.moveCards(enchantedCard, Zone.EXILED, source, game)) {

View file

@ -1,8 +1,8 @@
package mage.cards.s;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.Effect;
@ -137,7 +137,7 @@ class SunbirdsInvocationEffect extends OneShotEffect {
if (controller.chooseUse(Outcome.Benefit, "Cast " + card.getLogName() + " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
if (cardWasCast) {
cards.remove(card);

View file

@ -1,7 +1,7 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
@ -113,7 +113,7 @@ class SunforgerEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.t;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.condition.common.SpellMasteryCondition;
import mage.abilities.effects.OneShotEffect;
@ -18,6 +17,7 @@ import mage.target.common.TargetOpponent;
import java.util.Set;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author LevelX2
@ -106,7 +106,7 @@ class TalentOfTheTelepathEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
cardsToCast.remove(card);
if (cardWasCast) {

View file

@ -1,7 +1,7 @@
package mage.cards.t;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.common.ControlledCreaturesDealCombatDamagePlayerTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -75,7 +75,7 @@ class ThunderbladeChargeCastEffect extends OneShotEffect {
&& Zone.GRAVEYARD == game.getState().getZone(sourceCard.getId())) {
game.getState().setValue("PlayFromNotOwnHandZone" + sourceCard.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(sourceCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + sourceCard.getId(), null);
return cardWasCast;
}

View file

@ -1,8 +1,8 @@
package mage.cards.t;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
@ -91,7 +91,7 @@ class TorrentialGearhulkEffect extends OneShotEffect {
if (controller.chooseUse(outcome, "Cast " + card.getLogName() + '?', source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
if (cardWasCast) {
ContinuousEffect effect = new TorrentialGearhulkReplacementEffect(card.getId());

View file

@ -1,8 +1,8 @@
package mage.cards.t;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -94,7 +94,7 @@ class ToshiroUmezawaEffect extends OneShotEffect {
&& controller.getGraveyard().contains(card.getId())) { // must be in graveyard
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, false),
game, false, new MageObjectReference(source.getSourceObject(game), game));
game, false, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
game.addEffect(new ToshiroUmezawaReplacementEffect(card.getId()), source);
}

View file

@ -1,7 +1,6 @@
package mage.cards.t;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -16,7 +15,7 @@ import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
import mage.MageObject;
import mage.ApprovingObject;
/**
* @author fireshoes
@ -78,7 +77,7 @@ class TreasureKeeperEffect extends OneShotEffect {
&& controller.chooseUse(Outcome.PlayForFree, "Cast " + nonLandCard.getLogName() + " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + nonLandCard.getId(), Boolean.TRUE);
cardWasCast = controller.cast(controller.chooseAbilityForCast(nonLandCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + nonLandCard.getId(), null);
if (cardWasCast) {
toReveal.remove(nonLandCard);

View file

@ -1,7 +1,6 @@
package mage.cards.t;
import java.util.ArrayList;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@ -22,6 +21,7 @@ import mage.watchers.common.SpellsCastWatcher;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import mage.ApprovingObject;
import mage.filter.common.FilterNonlandCard;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.target.TargetCard;
@ -108,7 +108,7 @@ class TwinningGlassEffect extends OneShotEffect {
+ chosenCard.getName() + " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(chosenCard, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + chosenCard.getId(), null);
return cardWasCast;
}

View file

@ -1,7 +1,7 @@
package mage.cards.u;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -109,7 +109,7 @@ class UnexpectedResultEffect extends OneShotEffect {
+ " without paying its mana cost?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
return cardWasCast;
}

View file

@ -1,6 +1,5 @@
package mage.cards.u;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -17,6 +16,7 @@ import mage.game.stack.StackObject;
import mage.players.Player;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author TheElk801
@ -91,7 +91,7 @@ class UnpredictableCycloneReplacementEffect extends ReplacementEffectImpl {
if (toCast != null && player.chooseUse(outcome, "Cast the exiled card?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + toCast.getId(), Boolean.TRUE);
Boolean cardWasCast = player.cast(player.chooseAbilityForCast(toCast, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + toCast.getId(), null);
if (cardWasCast) {
cards.remove(toCast);

View file

@ -1,7 +1,6 @@
package mage.cards.v;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
@ -19,6 +18,7 @@ import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author LevelX2
@ -92,7 +92,7 @@ class VillainousWealthEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
if (cardWasCast) {
cardsToExile.remove(card);

View file

@ -1,8 +1,8 @@
package mage.cards.w;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -75,7 +75,7 @@ class WildEvocationEffect extends OneShotEffect {
} else if (card.getSpellAbility() != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
player.cast(player.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
} else {
game.informPlayers(GameLog.getColoredObjectName(card)

View file

@ -15,6 +15,7 @@ import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
import mage.ApprovingObject;
import mage.players.PlayerList;
import mage.target.common.TargetCardInGraveyard;
import mage.util.RandomUtil;
@ -108,7 +109,7 @@ class WildfireDevilsEffect extends OneShotEffect {
}
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), Boolean.TRUE);
Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(copiedCard, game, true), game, true,
new MageObjectReference(source.getSourceObject(game), game));
new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), null);
return cardWasCast;
}

View file

@ -1,8 +1,8 @@
package mage.cards.w;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -83,7 +83,7 @@ class WildfireEternalCastEffect extends OneShotEffect {
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.w;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -25,6 +24,7 @@ import mage.target.common.TargetOpponent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author L_J
@ -119,7 +119,7 @@ class WordOfCommandEffect extends OneShotEffect {
boolean canPlay = checkPlayability(card, targetPlayer, game, source);
while (canPlay
&& targetPlayer.canRespond()
&& !targetPlayer.playCard(card, game, false, true, new MageObjectReference(source.getSourceObject(game), game))) {
&& !targetPlayer.playCard(card, game, false, true, new ApprovingObject(source, game))) {
SpellAbility spellAbility = card.getSpellAbility();
if (spellAbility != null) {
spellAbility.getManaCostsToPay().clear();

View file

@ -1,8 +1,8 @@
package mage.cards.w;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
@ -141,7 +141,7 @@ class WrexialTheRisenDeepEffect extends OneShotEffect {
}
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, true),
game, true, new MageObjectReference(source.getSourceObject(game), game));
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
game.addEffect(new WrexialReplacementEffect(card.getId()), source);
return true;

View file

@ -1,8 +1,8 @@
package mage.cards.y;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -92,7 +92,7 @@ class YennettCrypticSovereignEffect extends OneShotEffect {
player.revealCards(source, new CardsImpl(card), game);
if (card.getConvertedManaCost() % 2 == 1) {
if (player.chooseUse(outcome, "Cast " + card.getLogName() + " without paying its mana cost?", source, game)) {
player.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game));
player.cast(card.getSpellAbility(), game, true, new ApprovingObject(source, game));
} else {
/*
7/13/2018 | If the revealed card doesnt have an odd converted mana cost or if that card does but you

View file

@ -3,6 +3,7 @@ package org.mage.test.cards.cost.modification;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@ -61,7 +62,7 @@ public class KaradorGhostChieftainTest extends CardTestPlayerBase {
}
@Test
public void castCastTwiceFromGraveyard() {
public void castCastMultipleFromGraveyard() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
@ -93,4 +94,51 @@ public class KaradorGhostChieftainTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Karador, Ghost Chieftain", 1);
}
@Test
@Ignore // It's not possible yet to select which ability to use to allow a asThoughtAs effect
public void test_castFromGraveyardWithDifferentApprovers() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
// {1}{B}: Target attacking Zombie gains indestructible until end of turn.
addCard(Zone.LIBRARY, playerA, "Accursed Horde", 1); // Creature Zombie {2}{B}{B}
skipInitShuffling();
addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion", 5);
// Karador, Ghost Chieftain costs {1} less to cast for each creature card in your graveyard.
// During each of your turns, you may cast one creature card from your graveyard.
addCard(Zone.HAND, playerA, "Karador, Ghost Chieftain");// {5}{B}{G}{W}
// When Gisa and Geralf enters the battlefield, put the top four cards of your library into your graveyard.
// During each of your turns, you may cast a Zombie creature card from your graveyard.
addCard(Zone.HAND, playerA, "Gisa and Geralf"); // CREATURE {2}{U}{B} (4/4)
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Karador, Ghost Chieftain");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gisa and Geralf");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Accursed Horde");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion");
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Karador, Ghost Chieftain", 1);
assertPermanentCount(playerA, "Gisa and Geralf", 1);
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertPermanentCount(playerA, "Accursed Horde", 1);
}
}

View file

@ -2833,15 +2833,15 @@ public class TestPlayer implements Player {
}
@Override
public boolean cast(SpellAbility ability, Game game, boolean noMana, MageObjectReference reference) {
public boolean cast(SpellAbility ability, Game game, boolean noMana, ApprovingObject approvingObject) {
// TestPlayer, ComputerPlayer always call inherited cast() from PlayerImpl
// that's why chooseSpellAbilityForCast will be ignored in TestPlayer, see workaround with TestComputerPlayerXXX
return computerPlayer.cast(ability, game, noMana, reference);
return computerPlayer.cast(ability, game, noMana, approvingObject);
}
@Override
public boolean playCard(Card card, Game game, boolean noMana, boolean ignoreTiming, MageObjectReference reference) {
return computerPlayer.playCard(card, game, noMana, ignoreTiming, reference);
public boolean playCard(Card card, Game game, boolean noMana, boolean ignoreTiming, ApprovingObject approvingObject) {
return computerPlayer.playCard(card, game, noMana, ignoreTiming, approvingObject);
}
@Override

View file

@ -41,6 +41,7 @@ import mage.target.common.TargetCardInLibrary;
import java.io.Serializable;
import java.util.*;
import mage.ApprovingObject;
import mage.Mana;
/**
@ -535,7 +536,7 @@ public class PlayerStub implements Player {
}
@Override
public boolean cast(SpellAbility ability, Game game, boolean noMana, MageObjectReference reference) {
public boolean cast(SpellAbility ability, Game game, boolean noMana, ApprovingObject approvingObject) {
return false;
}
@ -599,7 +600,7 @@ public class PlayerStub implements Player {
}
@Override
public boolean playCard(Card card, Game game, boolean noMana, boolean checkTiming, MageObjectReference reference) {
public boolean playCard(Card card, Game game, boolean noMana, boolean checkTiming, ApprovingObject approvingObject) {
return false;
}

View file

@ -0,0 +1,33 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage;
import mage.abilities.Ability;
import mage.game.Game;
/**
*
* @author LevelX2
*/
public class ApprovingObject {
private final Ability approvingAbility;
private final MageObjectReference approvingMageObjectReference;
public ApprovingObject(Ability source, Game game) {
this.approvingAbility = source;
this.approvingMageObjectReference = new MageObjectReference(source.getSourceId(), game);
}
public Ability getApprovingAbility() {
return approvingAbility;
}
public MageObjectReference getApprovingMageObjectReference() {
return approvingMageObjectReference;
}
}

View file

@ -0,0 +1,15 @@
package mage;
/**
* Used to identify specific actions/events and to be able to assign them to the
* correct watcher or other processing.
*
* @author LevelX2
*/
public enum MageIdentifier {
GisaAndGeralfWatcher,
KaradorGhostChieftainWatcher,
KessDissidentMageWatcher,
LurrusOfTheDreamDenWatcher,
MuldrothaTheGravetideWatcher
}

View file

@ -23,6 +23,7 @@ import mage.watchers.Watcher;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
import mage.MageIdentifier;
import mage.abilities.costs.common.TapSourceCost;
/**
@ -550,4 +551,8 @@ public interface Ability extends Controllable, Serializable {
* @return
*/
boolean isSameInstance(Ability ability);
MageIdentifier getIdentifier();
AbilityImpl setIdentifier(MageIdentifier mageIdentifier);
}

View file

@ -35,7 +35,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import mage.abilities.costs.common.TapSourceCost;
import mage.MageIdentifier;
/**
* @author BetaSteward_at_googlemail.com
@ -73,6 +73,7 @@ public abstract class AbilityImpl implements Ability {
protected CostAdjuster costAdjuster = null;
protected List<Hint> hints = new ArrayList<>();
protected Outcome customOutcome = null; // uses for AI decisions instead effects
protected MageIdentifier identifier; // used to identify specific ability (e.g. to match with corresponding watcher)
public AbilityImpl(AbilityType abilityType, Zone zone) {
this.id = UUID.randomUUID();
@ -123,6 +124,7 @@ public abstract class AbilityImpl implements Ability {
this.hints.add(hint.copy());
}
this.customOutcome = ability.customOutcome;
this.identifier = ability.identifier;
}
@Override
@ -1306,4 +1308,15 @@ public abstract class AbilityImpl implements Ability {
|| (this.getOriginalId().equals(ability.getOriginalId()))
|| (this.getClass() == ability.getClass() && this.getRule(true).equals(ability.getRule(true)));
}
@Override
public MageIdentifier getIdentifier() {
return identifier;
}
@Override
public AbilityImpl setIdentifier(MageIdentifier identifier) {
this.identifier = identifier;
return this;
}
}

View file

@ -7,6 +7,7 @@ import mage.constants.TargetController;
import mage.game.Game;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author BetaSteward_at_googlemail.com
@ -16,19 +17,19 @@ public interface ActivatedAbility extends Ability {
final class ActivationStatus {
private final boolean canActivate;
private final MageObjectReference permittingObject;
private final ApprovingObject approvingObject;
public ActivationStatus(boolean canActivate, MageObjectReference permittingObject) {
public ActivationStatus(boolean canActivate, ApprovingObject approvingObject) {
this.canActivate = canActivate;
this.permittingObject = permittingObject;
this.approvingObject = approvingObject;
}
public boolean canActivate() {
return canActivate;
}
public MageObjectReference getPermittingObject() {
return permittingObject;
public ApprovingObject getApprovingObject() {
return approvingObject;
}
public static ActivationStatus getFalse() {
@ -36,12 +37,11 @@ public interface ActivatedAbility extends Ability {
}
/**
* @param permittingObjectAbility card or permanent that allows to activate current ability
* @param approvingObjectAbility ability that allows to activate/use current ability
*/
public static ActivationStatus getTrue(Ability permittingObjectAbility, Game game) {
MageObject object = permittingObjectAbility == null ? null : permittingObjectAbility.getSourceObject(game);
MageObjectReference ref = object == null ? null : new MageObjectReference(object, game);
return new ActivationStatus(true, ref);
public static ActivationStatus getTrue(Ability approvingObjectAbility, Game game) {
ApprovingObject approvingObject = approvingObjectAbility == null ? null : new ApprovingObject(approvingObjectAbility, game);
return new ActivationStatus(true, approvingObject);
}
}

View file

@ -1,7 +1,6 @@
package mage.abilities;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.condition.Condition;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
@ -20,6 +19,7 @@ import mage.game.permanent.Permanent;
import mage.util.CardUtil;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author BetaSteward_at_googlemail.com
@ -184,7 +184,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
return ActivationStatus.getFalse();
}
//20091005 - 602.5d/602.5e
MageObjectReference permittingObject = game.getContinuousEffects()
ApprovingObject approvingObject = game.getContinuousEffects()
.asThough(sourceId,
AsThoughEffectType.ACTIVATE_AS_INSTANT,
this,
@ -192,11 +192,11 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
game);
if (timing == TimingRule.INSTANT
|| game.canPlaySorcery(playerId)
|| null != permittingObject) {
|| null != approvingObject) {
if (costs.canPay(this, sourceId, playerId, game)
&& canChooseTarget(game)) {
this.activatorId = playerId;
return new ActivationStatus(true, permittingObject);
return new ActivationStatus(true, approvingObject);
}
}
return ActivationStatus.getFalse();

View file

@ -1,7 +1,7 @@
package mage.abilities;
import java.util.UUID;
import mage.MageObjectReference;
import mage.ApprovingObject;
import mage.constants.AbilityType;
import mage.constants.AsThoughEffectType;
import mage.constants.Zone;
@ -25,15 +25,15 @@ public class PlayLandAbility extends ActivatedAbilityImpl {
@Override
public ActivationStatus canActivate(UUID playerId, Game game) {
MageObjectReference permittingObject = game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, playerId, game);
if (!controlsAbility(playerId, game) && null == permittingObject) {
ApprovingObject approvingObject = game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, playerId, game);
if (!controlsAbility(playerId, game) && null == approvingObject) {
return ActivationStatus.getFalse();
}
//20091005 - 114.2a
return new ActivationStatus(game.isActivePlayer(playerId)
&& game.getPlayer(playerId).canPlayLand()
&& game.canPlaySorcery(playerId),
permittingObject);
approvingObject);
}
@Override

View file

@ -1,7 +1,6 @@
package mage.abilities;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCost;
import mage.abilities.costs.mana.ManaCost;
@ -16,6 +15,7 @@ import mage.players.Player;
import java.util.Optional;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author BetaSteward_at_googlemail.com
@ -82,8 +82,8 @@ public class SpellAbility extends ActivatedAbilityImpl {
return ActivationStatus.getFalse();
}
// fix for Gitaxian Probe and casting opponent's spells
MageObjectReference permittingSource = game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, playerId, game);
if (permittingSource == null) {
ApprovingObject approvingObject = game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, playerId, game);
if (approvingObject == null) {
Card card = game.getCard(sourceId);
if (!(card != null && card.isOwnedBy(playerId))) {
return ActivationStatus.getFalse();
@ -118,7 +118,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
return ActivationStatus.getFalse();
} else {
return new ActivationStatus(canChooseTarget(game), permittingSource);
return new ActivationStatus(canChooseTarget(game), approvingObject);
}
}
}

Some files were not shown because too many files have changed in this diff Show more