mirror of
https://github.com/correl/mage.git
synced 2024-12-26 19:16:54 +00:00
commit
45cccc75c4
29 changed files with 412 additions and 214 deletions
|
@ -28,8 +28,11 @@ public class Pioneer extends Constructed {
|
||||||
banned.add("Windswept Heath");
|
banned.add("Windswept Heath");
|
||||||
banned.add("Wooded Foothills");
|
banned.add("Wooded Foothills");
|
||||||
banned.add("Felidar Guardian");
|
banned.add("Felidar Guardian");
|
||||||
|
banned.add("Field of the Dead");
|
||||||
banned.add("Leyline of Abundance");
|
banned.add("Leyline of Abundance");
|
||||||
banned.add("Oath of Nissa");
|
banned.add("Oath of Nissa");
|
||||||
|
banned.add("Once Upon a Time");
|
||||||
|
banned.add("Smuggler's Copter");
|
||||||
banned.add("Veil of Summer");
|
banned.add("Veil of Summer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -975,7 +975,9 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else return response.getManaType() == null;
|
} else {
|
||||||
|
return response.getManaType() == null;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1256,7 +1258,6 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Map<String, Serializable> options = new HashMap<>();
|
Map<String, Serializable> options = new HashMap<>();
|
||||||
options.put(Constants.Option.POSSIBLE_ATTACKERS, (Serializable) possibleAttackers);
|
options.put(Constants.Option.POSSIBLE_ATTACKERS, (Serializable) possibleAttackers);
|
||||||
if (!possibleAttackers.isEmpty()) {
|
if (!possibleAttackers.isEmpty()) {
|
||||||
|
@ -1782,6 +1783,31 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpellAbility chooseAbilityForCast(Card card, Game game, boolean nonMana) {
|
||||||
|
MageObject object = game.getObject(card.getId());
|
||||||
|
if (object != null) {
|
||||||
|
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = getSpellAbilities(object, game.getState().getZone(object.getId()), game);
|
||||||
|
if (useableAbilities != null
|
||||||
|
&& useableAbilities.size() == 1) {
|
||||||
|
return (SpellAbility) useableAbilities.values().iterator().next();
|
||||||
|
} else if (useableAbilities != null
|
||||||
|
&& !useableAbilities.isEmpty()) {
|
||||||
|
prepareForResponse(game);
|
||||||
|
if (!isExecutingMacro()) {
|
||||||
|
game.fireGetChoiceEvent(playerId, name, object, new ArrayList<>(useableAbilities.values()));
|
||||||
|
}
|
||||||
|
waitForResponse(game);
|
||||||
|
if (response.getUUID() != null) {
|
||||||
|
if (useableAbilities.containsKey(response.getUUID())) {
|
||||||
|
return (SpellAbility) useableAbilities.get(response.getUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return card.getSpellAbility();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mode chooseMode(Modes modes, Ability source, Game game) {
|
public Mode chooseMode(Modes modes, Ability source, Game game) {
|
||||||
// choose mode to activate
|
// choose mode to activate
|
||||||
|
@ -1830,6 +1856,10 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (modes.getSelectedModes().size() >= modes.getMinModes()) {
|
||||||
|
/* let the player cancel mode selection if they do not need to select any further modes */
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
if (source.getAbilityType() != AbilityType.TRIGGERED) {
|
if (source.getAbilityType() != AbilityType.TRIGGERED) {
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
@ -2115,4 +2145,5 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
public String getHistory() {
|
public String getHistory() {
|
||||||
return "no available";
|
return "no available";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,35 @@
|
||||||
|
|
||||||
package mage.cards.c;
|
package mage.cards.c;
|
||||||
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.costs.CostAdjuster;
|
import mage.abilities.costs.CostAdjuster;
|
||||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
|
||||||
import mage.abilities.effects.ContinuousEffect;
|
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.InfoEffect;
|
import mage.abilities.effects.common.InfoEffect;
|
||||||
import mage.abilities.effects.common.continuous.SetPowerSourceEffect;
|
|
||||||
import mage.abilities.effects.common.continuous.SetToughnessSourceEffect;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.choices.Choice;
|
import mage.choices.Choice;
|
||||||
import mage.choices.ChoiceCreatureType;
|
import mage.choices.ChoiceCreatureType;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.FilterPermanent;
|
|
||||||
import mage.filter.predicate.mageobject.ChosenSubtypePredicate;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||||
|
import mage.abilities.effects.ContinuousEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jeffwadsworth
|
* @author jeffwadsworth
|
||||||
*/
|
*/
|
||||||
public final class CallerOfTheHunt extends CardImpl {
|
public final class CallerOfTheHunt extends CardImpl {
|
||||||
|
|
||||||
|
FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||||
|
|
||||||
public CallerOfTheHunt(UUID ownerId, CardSetInfo setInfo) {
|
public CallerOfTheHunt(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
|
||||||
|
|
||||||
|
@ -38,7 +39,9 @@ public final class CallerOfTheHunt extends CardImpl {
|
||||||
// Caller of the Hunt's power and toughness are each equal to the number of creatures of the chosen type on the battlefield.
|
// Caller of the Hunt's power and toughness are each equal to the number of creatures of the chosen type on the battlefield.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("as an additional cost to cast this spell, choose a creature type. \r"
|
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("as an additional cost to cast this spell, choose a creature type. \r"
|
||||||
+ "{this}'s power and toughness are each equal to the number of creatures of the chosen type on the battlefield")));
|
+ "{this}'s power and toughness are each equal to the number of creatures of the chosen type on the battlefield")));
|
||||||
|
|
||||||
this.getSpellAbility().setCostAdjuster(CallerOfTheHuntAdjuster.instance);
|
this.getSpellAbility().setCostAdjuster(CallerOfTheHuntAdjuster.instance);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CallerOfTheHunt(final CallerOfTheHunt card) {
|
public CallerOfTheHunt(final CallerOfTheHunt card) {
|
||||||
|
@ -58,19 +61,27 @@ enum CallerOfTheHuntAdjuster implements CostAdjuster {
|
||||||
public void adjustCosts(Ability ability, Game game) {
|
public void adjustCosts(Ability ability, Game game) {
|
||||||
MageObject mageObject = game.getObject(ability.getSourceId());
|
MageObject mageObject = game.getObject(ability.getSourceId());
|
||||||
Effect effect = new ChooseCreatureTypeEffect(Outcome.Benefit);
|
Effect effect = new ChooseCreatureTypeEffect(Outcome.Benefit);
|
||||||
if (mageObject != null
|
if (mageObject != null) {
|
||||||
&& effect.apply(game, ability)) {
|
effect.apply(game, ability);
|
||||||
FilterPermanent filter = new FilterPermanent();
|
}
|
||||||
filter.add(ChosenSubtypePredicate.instance);
|
if (mageObject != null) {
|
||||||
ContinuousEffect effectPower = new SetPowerSourceEffect(new PermanentsOnBattlefieldCount(filter), Duration.Custom);
|
SubType typeChoice = (SubType) game.getState().getValue(mageObject.getId() + "_type");
|
||||||
ContinuousEffect effectToughness = new SetToughnessSourceEffect(new PermanentsOnBattlefieldCount(filter), Duration.Custom);
|
if (typeChoice != null) {
|
||||||
game.addEffect(effectPower, ability);
|
FilterCreaturePermanent filter = new FilterCreaturePermanent("chosen creature type");
|
||||||
game.addEffect(effectToughness, ability);
|
filter.add(new SubtypePredicate(typeChoice));
|
||||||
|
ContinuousEffect effectPowerToughness = new SetPowerToughnessSourceEffect(
|
||||||
|
new PermanentsOnBattlefieldCount(filter), Duration.EndOfGame);
|
||||||
|
effectPowerToughness.setText("");
|
||||||
|
SimpleStaticAbility sa = new SimpleStaticAbility(Zone.ALL, effectPowerToughness);
|
||||||
|
GainAbilityTargetEffect effectTest = new GainAbilityTargetEffect(sa, Duration.EndOfGame);
|
||||||
|
effectTest.setTargetPointer(new FixedTarget(ability.getSourceId()));
|
||||||
|
game.getState().addEffect(effectTest, ability);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChooseCreatureTypeEffect extends OneShotEffect { // code by LevelX2, but that other version is not compatible with this card
|
class ChooseCreatureTypeEffect extends OneShotEffect {
|
||||||
|
|
||||||
public ChooseCreatureTypeEffect(Outcome outcome) {
|
public ChooseCreatureTypeEffect(Outcome outcome) {
|
||||||
super(outcome);
|
super(outcome);
|
||||||
|
@ -86,11 +97,15 @@ class ChooseCreatureTypeEffect extends OneShotEffect { // code by LevelX2, but t
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
MageObject mageObject = game.getObject(source.getSourceId());
|
MageObject mageObject = game.getObject(source.getSourceId());
|
||||||
Choice typeChoice = new ChoiceCreatureType(mageObject);
|
Choice typeChoice = new ChoiceCreatureType(mageObject);
|
||||||
if (controller != null && mageObject != null && controller.choose(outcome, typeChoice, game)) {
|
if (controller != null
|
||||||
|
&& mageObject != null
|
||||||
|
&& controller.choose(outcome, typeChoice, game)) {
|
||||||
if (!game.isSimulation()) {
|
if (!game.isSimulation()) {
|
||||||
game.informPlayers(mageObject.getName() + ": " + controller.getLogName() + " has chosen " + typeChoice.getChoice());
|
game.informPlayers(mageObject.getName() + ": "
|
||||||
|
+ controller.getLogName() + " has chosen " + typeChoice.getChoice());
|
||||||
}
|
}
|
||||||
game.getState().setValue(mageObject.getId() + "_type", SubType.byDescription(typeChoice.getChoice()));
|
game.getState().setValue(mageObject.getId()
|
||||||
|
+ "_type", SubType.byDescription(typeChoice.getChoice()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import mage.constants.Outcome;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.SuperType;
|
import mage.constants.SuperType;
|
||||||
import mage.constants.TargetController;
|
import mage.constants.TargetController;
|
||||||
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.command.emblems.ChandraTorchOfDefianceEmblem;
|
import mage.game.command.emblems.ChandraTorchOfDefianceEmblem;
|
||||||
import mage.players.Library;
|
import mage.players.Library;
|
||||||
|
@ -91,15 +92,19 @@ class ChandraTorchOfDefianceEffect extends OneShotEffect {
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
boolean exiledCardWasCast = false;
|
boolean exiledCardWasCast = false;
|
||||||
controller.moveCardsToExile(card, source, game, true, source.getSourceId(), sourceObject.getIdName());
|
controller.moveCardsToExile(card, source, game, true, source.getSourceId(), sourceObject.getIdName());
|
||||||
if (!card.getManaCost().isEmpty() && !card.isLand()) {
|
if (!card.getManaCost().isEmpty()
|
||||||
if (controller.chooseUse(Outcome.Benefit, "Cast " + card.getName() + "? (You still pay the costs)", source, game)) {
|
|| !card.isLand()) {
|
||||||
exiledCardWasCast = controller.cast(card.getSpellAbility(), game, false, new MageObjectReference(sourceObject, game));
|
if (controller.chooseUse(Outcome.Benefit, "Cast " + card.getName() + "? (You still pay the costs)", source, game)
|
||||||
|
&& (game.getState().getZone(card.getId()) == Zone.EXILED)) { // card must be in the exile zone
|
||||||
|
game.getState().setValue("CastFromExileEnabled" + card.getId(), Boolean.TRUE); // enable the card to be cast from the exile zone
|
||||||
|
exiledCardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, false),
|
||||||
|
game, false, new MageObjectReference(sourceObject, game));
|
||||||
|
game.getState().setValue("CastFromExileEnabled" + card.getId(), null); // reset to null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!exiledCardWasCast) {
|
if (!exiledCardWasCast) {
|
||||||
new DamagePlayersEffect(Outcome.Damage, new StaticValue(2), TargetController.OPPONENT).apply(game, source);
|
new DamagePlayersEffect(Outcome.Damage, new StaticValue(2), TargetController.OPPONENT).apply(game, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,13 +94,7 @@ class KrrikSonOfYawgmothPhyrexianEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
phyrexianBlack.setBlack(true);
|
phyrexianBlack.setBlack(true);
|
||||||
if (controller != null && sourcePermanent != null) {
|
if (controller != null && sourcePermanent != null) {
|
||||||
for (UUID playerId: game.getState().getPlayersInRange(controller.getId(), game)) {
|
controller.addPhyrexianToColors(phyrexianBlack);
|
||||||
Player player = game.getPlayer(playerId);
|
|
||||||
if (player != null)
|
|
||||||
{
|
|
||||||
player.addPhyrexianToColors(phyrexianBlack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -15,7 +15,6 @@ import mage.players.Player;
|
||||||
import mage.target.TargetPlayer;
|
import mage.target.TargetPlayer;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
|
@ -52,7 +51,7 @@ class LeadershipVacuumEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
LeadershipVacuumEffect() {
|
LeadershipVacuumEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Detriment);
|
||||||
staticText = "Target player returns each commander they control from the battlefield to the command zone.";
|
staticText = "Target player returns each commander they control from the battlefield to the command zone.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,30 @@
|
||||||
package mage.cards.l;
|
package mage.cards.l;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
|
||||||
import mage.abilities.effects.Effect;
|
|
||||||
import mage.abilities.effects.common.ChooseOpponentEffect;
|
import mage.abilities.effects.common.ChooseOpponentEffect;
|
||||||
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
|
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.StaticFilters;
|
|
||||||
import mage.game.Game;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.dynamicvalue.AdditiveDynamicValue;
|
||||||
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
*/
|
*/
|
||||||
public final class LostOrderOfJarkeld extends CardImpl {
|
public final class LostOrderOfJarkeld extends CardImpl {
|
||||||
|
|
||||||
|
protected FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||||
|
|
||||||
public LostOrderOfJarkeld(UUID ownerId, CardSetInfo setInfo) {
|
public LostOrderOfJarkeld(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}");
|
||||||
|
|
||||||
|
@ -36,8 +40,7 @@ public final class LostOrderOfJarkeld extends CardImpl {
|
||||||
this.addAbility(new SimpleStaticAbility(
|
this.addAbility(new SimpleStaticAbility(
|
||||||
Zone.ALL,
|
Zone.ALL,
|
||||||
new SetPowerToughnessSourceEffect(
|
new SetPowerToughnessSourceEffect(
|
||||||
LostOrderOfJarkeldValue.instance, Duration.Custom, SubLayer.CharacteristicDefining_7a
|
new AdditiveDynamicValue(new CreaturesControlledByChosenPlayer(), new StaticValue(1)), Duration.EndOfGame)
|
||||||
)
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,28 +54,32 @@ public final class LostOrderOfJarkeld extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LostOrderOfJarkeldValue implements DynamicValue {
|
class CreaturesControlledByChosenPlayer implements DynamicValue {
|
||||||
instance;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||||
if (game.getPermanent(sourceAbility.getSourceId()) == null) {
|
if (sourceAbility != null) {
|
||||||
return 1;
|
UUID playerId = (UUID) game.getState().getValue(sourceAbility.getSourceId() + ChooseOpponentEffect.VALUE_KEY);
|
||||||
|
Player chosenPlayer = game.getPlayer(playerId);
|
||||||
|
if (chosenPlayer != null) {
|
||||||
|
return game.getBattlefield().countAll(new FilterCreaturePermanent(), chosenPlayer.getId(), game);
|
||||||
}
|
}
|
||||||
Object obj = game.getState().getValue(sourceAbility.getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY);
|
|
||||||
if (!(obj instanceof UUID)) {
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
return 1 + game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, (UUID) obj, game).size();
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DynamicValue copy() {
|
public DynamicValue copy() {
|
||||||
return instance;
|
return new CreaturesControlledByChosenPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return "1 plus the number of creatures the chosen player controls.";
|
return "1 plus the number of creatures controlled by chosen player";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "1";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package mage.cards.o;
|
package mage.cards.o;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.MageObjectReference;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.DelayedTriggeredAbility;
|
import mage.abilities.DelayedTriggeredAbility;
|
||||||
import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
|
import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
|
||||||
|
@ -43,7 +42,8 @@ public final class ObzedatGhostCouncil extends CardImpl {
|
||||||
ability.addEffect(new GainLifeEffect(2).concatBy("and"));
|
ability.addEffect(new GainLifeEffect(2).concatBy("and"));
|
||||||
ability.addTarget(new TargetOpponent());
|
ability.addTarget(new TargetOpponent());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
//At the beginning of your end step you may exile Obzedat. If you do, return it to the battlefield under its owner's control at the beginning of your next upkeep. It gains haste.
|
//At the beginning of your end step you may exile Obzedat. If you do, return it to the battlefield under its owner's
|
||||||
|
//control at the beginning of your next upkeep. It gains haste.
|
||||||
Ability ability2 = new BeginningOfYourEndStepTriggeredAbility(new ObzedatGhostCouncilExileSourceEffect(), true);
|
Ability ability2 = new BeginningOfYourEndStepTriggeredAbility(new ObzedatGhostCouncilExileSourceEffect(), true);
|
||||||
this.addAbility(ability2);
|
this.addAbility(ability2);
|
||||||
}
|
}
|
||||||
|
@ -62,8 +62,8 @@ class ObzedatGhostCouncilExileSourceEffect extends OneShotEffect {
|
||||||
|
|
||||||
ObzedatGhostCouncilExileSourceEffect() {
|
ObzedatGhostCouncilExileSourceEffect() {
|
||||||
super(Outcome.Exile);
|
super(Outcome.Exile);
|
||||||
staticText = "exile {this}. If you do, return it to the battlefield under its owner's control " +
|
staticText = "exile {this}. If you do, return it to the battlefield under its owner's control "
|
||||||
"at the beginning of your next upkeep. It gains haste.";
|
+ "at the beginning of your next upkeep. It gains haste.";
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObzedatGhostCouncilExileSourceEffect(final ObzedatGhostCouncilExileSourceEffect effect) {
|
private ObzedatGhostCouncilExileSourceEffect(final ObzedatGhostCouncilExileSourceEffect effect) {
|
||||||
|
@ -77,13 +77,14 @@ class ObzedatGhostCouncilExileSourceEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||||
if (permanent == null || player == null
|
if (permanent == null
|
||||||
|| !player.moveCards(permanent, Zone.EXILED, source, game)) {
|
|| controller == null
|
||||||
|
|| !controller.moveCards(permanent, Zone.EXILED, source, game)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
game.addDelayedTriggeredAbility(new ObzedatGhostCouncilDelayedTriggeredAbility(new MageObjectReference(permanent, game)), source);
|
game.addDelayedTriggeredAbility(new ObzedatGhostCouncilDelayedTriggeredAbility(permanent), source);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,8 +92,8 @@ class ObzedatGhostCouncilExileSourceEffect extends OneShotEffect {
|
||||||
|
|
||||||
class ObzedatGhostCouncilDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
class ObzedatGhostCouncilDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
||||||
|
|
||||||
ObzedatGhostCouncilDelayedTriggeredAbility(MageObjectReference mor) {
|
ObzedatGhostCouncilDelayedTriggeredAbility(Card card) {
|
||||||
super(new ObzedatGhostCouncilReturnEffect(mor));
|
super(new ObzedatGhostCouncilReturnEffect(card));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObzedatGhostCouncilDelayedTriggeredAbility(ObzedatGhostCouncilDelayedTriggeredAbility ability) {
|
private ObzedatGhostCouncilDelayedTriggeredAbility(ObzedatGhostCouncilDelayedTriggeredAbility ability) {
|
||||||
|
@ -106,7 +107,7 @@ class ObzedatGhostCouncilDelayedTriggeredAbility extends DelayedTriggeredAbility
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
return event.getPlayerId().equals(this.controllerId);
|
return event.getPlayerId().equals(this.controllerId); // must be the controller who chooses
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -122,16 +123,16 @@ class ObzedatGhostCouncilDelayedTriggeredAbility extends DelayedTriggeredAbility
|
||||||
|
|
||||||
class ObzedatGhostCouncilReturnEffect extends OneShotEffect {
|
class ObzedatGhostCouncilReturnEffect extends OneShotEffect {
|
||||||
|
|
||||||
private final MageObjectReference mor;
|
private final Card card;
|
||||||
|
|
||||||
ObzedatGhostCouncilReturnEffect(MageObjectReference mor) {
|
ObzedatGhostCouncilReturnEffect(Card card) {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
this.mor = mor;
|
this.card = card;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObzedatGhostCouncilReturnEffect(final ObzedatGhostCouncilReturnEffect effect) {
|
private ObzedatGhostCouncilReturnEffect(final ObzedatGhostCouncilReturnEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
this.mor = effect.mor;
|
this.card = effect.card;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -141,17 +142,12 @@ class ObzedatGhostCouncilReturnEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Card card = mor.getCard(game);
|
|
||||||
if (card == null) {
|
if (card == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Zone zone = game.getState().getZone(source.getSourceId());
|
|
||||||
// return it from every public zone - http://www.mtgsalvation.com/forums/magic-fundamentals/magic-rulings/magic-rulings-archives/513186-obzedat-gc-as-edh-commander
|
|
||||||
if (zone == Zone.BATTLEFIELD || zone == Zone.LIBRARY || zone == Zone.HAND) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Player owner = game.getPlayer(card.getOwnerId());
|
Player owner = game.getPlayer(card.getOwnerId());
|
||||||
if (owner == null || !owner.moveCards(card, Zone.BATTLEFIELD, source, game)) {
|
if (owner == null
|
||||||
|
|| !owner.moveCards(card, Zone.BATTLEFIELD, source, game)) { // comes back from any zone
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield), source);
|
game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield), source);
|
||||||
|
|
|
@ -51,7 +51,7 @@ public final class RankleMasterOfPranks extends CardImpl {
|
||||||
// • Each player sacrifices a creature.
|
// • Each player sacrifices a creature.
|
||||||
ability.addMode(new Mode(new SacrificeAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT)));
|
ability.addMode(new Mode(new SacrificeAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT)));
|
||||||
|
|
||||||
ability.getModes().setMinModes(1);
|
ability.getModes().setMinModes(0);
|
||||||
ability.getModes().setMaxModes(3);
|
ability.getModes().setMaxModes(3);
|
||||||
ability.getModes().setChooseText("choose any number —");
|
ability.getModes().setChooseText("choose any number —");
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
|
@ -70,9 +70,8 @@ class TectonicHellionEffect extends OneShotEffect {
|
||||||
Map<UUID, Integer> landMap = new HashMap<>();
|
Map<UUID, Integer> landMap = new HashMap<>();
|
||||||
game.getState()
|
game.getState()
|
||||||
.getPlayersInRange(source.getControllerId(), game)
|
.getPlayersInRange(source.getControllerId(), game)
|
||||||
.stream()
|
.forEach(uuid -> landMap.put(uuid, game.getBattlefield().getActivePermanents(
|
||||||
.map(uuid -> landMap.put(uuid, game.getBattlefield().getActivePermanents(
|
StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, uuid, source.getSourceId(), game
|
||||||
StaticFilters.FILTER_LAND, uuid, source.getSourceId(), game
|
|
||||||
).size()));
|
).size()));
|
||||||
int max = landMap
|
int max = landMap
|
||||||
.values()
|
.values()
|
||||||
|
|
|
@ -21,6 +21,10 @@ import mage.target.common.TargetCreatureOrPlaneswalker;
|
||||||
import mage.target.common.TargetCreaturePermanentAmount;
|
import mage.target.common.TargetCreaturePermanentAmount;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
import mage.target.targetadjustment.TargetAdjuster;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
|
@ -36,19 +40,19 @@ public final class VivienArkbowRanger extends CardImpl {
|
||||||
|
|
||||||
// +1: Distribute two +1/+1 counters among up to two target creatures. They gain trample until end of turn.
|
// +1: Distribute two +1/+1 counters among up to two target creatures. They gain trample until end of turn.
|
||||||
Ability ability = new LoyaltyAbility(new DistributeCountersEffect(
|
Ability ability = new LoyaltyAbility(new DistributeCountersEffect(
|
||||||
CounterType.P1P1, 2, false, "up to two target creatures"
|
CounterType.P1P1, 2, false, "up to two target creatures"), 1);
|
||||||
), 1);
|
|
||||||
ability.addEffect(new GainAbilityTargetEffect(
|
ability.addEffect(new GainAbilityTargetEffect(
|
||||||
TrampleAbility.getInstance(), Duration.EndOfTurn,
|
TrampleAbility.getInstance(), Duration.EndOfTurn,
|
||||||
"They gain trample until end of turn"
|
"They gain trample until end of turn"
|
||||||
));
|
));
|
||||||
ability.addTarget(new TargetCreaturePermanentAmount(2));
|
ability.addTarget(new TargetCreaturePermanent(0, 2, new FilterCreaturePermanent(), false));
|
||||||
|
ability.setTargetAdjuster(VivienArkbowRangerAdjuster.instance);
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
// −3: Target creature you control deals damage equal to its power to target creature or planeswalker.
|
// −3: Target creature you control deals damage equal to its power to target creature or planeswalker.
|
||||||
ability = new LoyaltyAbility(
|
ability = new LoyaltyAbility(
|
||||||
new DamageWithPowerTargetEffect().setText("Target creature you control deals damage " +
|
new DamageWithPowerTargetEffect().setText("Target creature you control deals damage "
|
||||||
"equal to its power to target creature or planeswalker."), -3
|
+ "equal to its power to target creature or planeswalker."), -3
|
||||||
);
|
);
|
||||||
ability.addTarget(new TargetControlledCreaturePermanent());
|
ability.addTarget(new TargetControlledCreaturePermanent());
|
||||||
ability.addTarget(new TargetCreatureOrPlaneswalker());
|
ability.addTarget(new TargetCreatureOrPlaneswalker());
|
||||||
|
@ -66,4 +70,17 @@ public final class VivienArkbowRanger extends CardImpl {
|
||||||
public VivienArkbowRanger copy() {
|
public VivienArkbowRanger copy() {
|
||||||
return new VivienArkbowRanger(this);
|
return new VivienArkbowRanger(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum VivienArkbowRangerAdjuster implements TargetAdjuster {
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void adjustTargets(Ability ability, Game game) {
|
||||||
|
// if targets are available, switch over to a working target method
|
||||||
|
if (game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), game).size() > 0) {
|
||||||
|
ability.getTargets().clear();
|
||||||
|
ability.addTarget(new TargetCreaturePermanentAmount(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ public final class VolrathTheShapestealer extends CardImpl {
|
||||||
|
|
||||||
// At the beginning of combat on your turn, put a -1/-1 counter on up to one target creature.
|
// At the beginning of combat on your turn, put a -1/-1 counter on up to one target creature.
|
||||||
Ability ability = new BeginningOfCombatTriggeredAbility(
|
Ability ability = new BeginningOfCombatTriggeredAbility(
|
||||||
new AddCountersTargetEffect(CounterType.M1M1.createInstance()), TargetController.YOU, false
|
new AddCountersTargetEffect(CounterType.M1M1.createInstance(), Outcome.Detriment), TargetController.YOU, false
|
||||||
);
|
);
|
||||||
ability.addTarget(new TargetCreaturePermanent(0, 1));
|
ability.addTarget(new TargetCreaturePermanent(0, 1));
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
@ -73,8 +73,8 @@ class VolrathTheShapestealerEffect extends OneShotEffect {
|
||||||
|
|
||||||
VolrathTheShapestealerEffect() {
|
VolrathTheShapestealerEffect() {
|
||||||
super(Outcome.Copy);
|
super(Outcome.Copy);
|
||||||
staticText = "Until your next turn, {this} becomes a copy of target creature with a counter on it, " +
|
staticText = "Until your next turn, {this} becomes a copy of target creature with a counter on it, "
|
||||||
"except it's 7/5 and it has this ability.";
|
+ "except it's 7/5 and it has this ability.";
|
||||||
}
|
}
|
||||||
|
|
||||||
private VolrathTheShapestealerEffect(final VolrathTheShapestealerEffect effect) {
|
private VolrathTheShapestealerEffect(final VolrathTheShapestealerEffect effect) {
|
||||||
|
|
|
@ -28,11 +28,9 @@ import java.util.UUID;
|
||||||
|
|
||||||
import static mage.constants.Outcome.Benefit;
|
import static mage.constants.Outcome.Benefit;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jesusjbr
|
* @author jesusjbr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class XantchaSleeperAgent extends CardImpl {
|
public final class XantchaSleeperAgent extends CardImpl {
|
||||||
|
|
||||||
public XantchaSleeperAgent(UUID ownerId, CardSetInfo setInfo) {
|
public XantchaSleeperAgent(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
@ -145,14 +143,18 @@ class XantchaSleeperAgentAttackRestrictionEffect extends RestrictionEffect {
|
||||||
boolean allowAttack = true;
|
boolean allowAttack = true;
|
||||||
UUID ownerPlayerId = source.getSourcePermanentIfItStillExists(game).getOwnerId();
|
UUID ownerPlayerId = source.getSourcePermanentIfItStillExists(game).getOwnerId();
|
||||||
|
|
||||||
if (defenderId.equals(ownerPlayerId)) {
|
if (defenderId.equals(ownerPlayerId)
|
||||||
|
&& game.getPlayers().size() == 2) { // if only 2 players are left, it can't attack at all.
|
||||||
allowAttack = false;
|
allowAttack = false;
|
||||||
} else {
|
}
|
||||||
|
if (defenderId.equals(ownerPlayerId)) { // can't attack owner
|
||||||
|
allowAttack = false;
|
||||||
|
}
|
||||||
Permanent planeswalker = game.getPermanent(defenderId);
|
Permanent planeswalker = game.getPermanent(defenderId);
|
||||||
if (planeswalker != null && planeswalker.isControlledBy(ownerPlayerId)) {
|
if (planeswalker != null && planeswalker.isControlledBy(ownerPlayerId)) { // can't attack the owner's planeswalkers
|
||||||
allowAttack = false;
|
allowAttack = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return allowAttack;
|
return allowAttack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,4 +29,96 @@ public class PhyrexianManaTest extends CardTestPlayerBase {
|
||||||
Assert.assertTrue(life == 20 && hand == 1 || life == 18 && hand == 0);
|
Assert.assertTrue(life == 20 && hand == 1 || life == 18 && hand == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKrrikOnlyUsableByController() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "K'rrik, Son of Yawgmoth");
|
||||||
|
addCard(Zone.HAND, playerA, "Banehound");
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1);
|
||||||
|
addCard(Zone.HAND, playerB, "Banehound");
|
||||||
|
|
||||||
|
setChoice(playerA, "Yes");
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Banehound");
|
||||||
|
setChoice(playerB, "Yes");
|
||||||
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Banehound");
|
||||||
|
setStopAt(2, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
//PlayerA pays life but PlayerB cannot
|
||||||
|
assertLife(playerA, 18);
|
||||||
|
assertLife(playerB, 20);
|
||||||
|
assertPermanentCount(playerA, "Banehound", 1);
|
||||||
|
assertPermanentCount(playerB, "Banehound", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKrrikTriggeredAbility() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "K'rrik, Son of Yawgmoth");
|
||||||
|
addCard(Zone.HAND, playerA, "Banehound");
|
||||||
|
addCard(Zone.HAND, playerA, "Crypt Ghast");
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1);
|
||||||
|
|
||||||
|
setChoice(playerA, "Yes"); //yes to pay 2 life to cast Crypt Ghast
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Crypt Ghast"); //3 mana used, 2 life paid (18 life total)
|
||||||
|
setChoice(playerA, "Yes"); //yes to pay 2 life to cast Banehound
|
||||||
|
setChoice(playerA, "Yes"); //yes to Extort
|
||||||
|
setChoice(playerA, "Yes"); //yes to pay 2 life to Extort
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Banehound"); //0 mana used, 4 life paid, 1 life gained (15 life total)
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 15);
|
||||||
|
assertLife(playerB, 19);
|
||||||
|
assertPermanentCount(playerA, "Banehound", 1);
|
||||||
|
assertPermanentCount(playerA, "Crypt Ghast", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKrrikActivatedAbility() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "K'rrik, Son of Yawgmoth");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Frozen Shade");
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1);
|
||||||
|
|
||||||
|
setChoice(playerA, "Yes"); //yes to pay 2 life to activate Frozen Shade's +1/+1 ability
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{B}: {this} gets +1/+1 until end of turn.");
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 18);
|
||||||
|
assertLife(playerB, 20);
|
||||||
|
assertPowerToughness(playerA, "Frozen Shade", 1, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKrrikTrinispherePostPay() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "K'rrik, Son of Yawgmoth");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Trinisphere");
|
||||||
|
addCard(Zone.HAND, playerA, "Dismember");
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Banehound");
|
||||||
|
|
||||||
|
setChoice(playerA, "No"); //don't pay 2 life for Dismember's Phyrexian cost
|
||||||
|
setChoice(playerA, "No"); //don't pay 2 life for Dismember's Phyrexian cost
|
||||||
|
setChoice(playerA, "Yes"); //yes to pay 2 life for Dismember's {B} cost via K'rrik
|
||||||
|
setChoice(playerA, "Yes"); //yes to pay 2 life for Dismember's {B} cost via K'rrik
|
||||||
|
|
||||||
|
//Dismember costs {1} now + life paid. Normally this would be {3} + life paid with true Phyrexian mana and Trinisphere active.
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dismember", "Banehound");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 16);
|
||||||
|
assertLife(playerB, 20);
|
||||||
|
assertTappedCount("Swamp", true, 1);
|
||||||
|
assertGraveyardCount(playerA, "Dismember", 1);
|
||||||
|
assertGraveyardCount(playerB, "Banehound", 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3478,4 +3478,9 @@ public class TestPlayer implements Player {
|
||||||
public FilterMana getPhyrexianColors() {
|
public FilterMana getPhyrexianColors() {
|
||||||
return computerPlayer.getPhyrexianColors();
|
return computerPlayer.getPhyrexianColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpellAbility chooseAbilityForCast(Card card, Game game, boolean noMana) {
|
||||||
|
return card.getSpellAbility();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1387,4 +1387,9 @@ public class PlayerStub implements Player {
|
||||||
return (new FilterMana());
|
return (new FilterMana());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpellAbility chooseAbilityForCast(Card card, Game game, boolean noMana) {
|
||||||
|
return card.getSpellAbility();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -549,10 +549,6 @@ public abstract class AbilityImpl implements Ability {
|
||||||
Iterator<ManaCost> costIterator = manaCostsToPay.iterator();
|
Iterator<ManaCost> costIterator = manaCostsToPay.iterator();
|
||||||
while (costIterator.hasNext()) {
|
while (costIterator.hasNext()) {
|
||||||
ManaCost cost = costIterator.next();
|
ManaCost cost = costIterator.next();
|
||||||
PhyrexianManaCost tempPhyrexianCost = null;
|
|
||||||
Mana mana = cost.getMana();
|
|
||||||
|
|
||||||
FilterMana phyrexianColors = controller.getPhyrexianColors();
|
|
||||||
|
|
||||||
if (cost instanceof PhyrexianManaCost) {
|
if (cost instanceof PhyrexianManaCost) {
|
||||||
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost) cost;
|
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost) cost;
|
||||||
|
@ -563,37 +559,6 @@ public abstract class AbilityImpl implements Ability {
|
||||||
costs.add(payLifeCost);
|
costs.add(payLifeCost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* K'rrik, Son of Yawgmoth ability check */
|
|
||||||
else if (phyrexianColors != null) {
|
|
||||||
int phyrexianEnabledPips = mana.count(phyrexianColors);
|
|
||||||
if (phyrexianEnabledPips > 0) {
|
|
||||||
/* find which color mana is in the cost and set it in the temp Phyrexian cost */
|
|
||||||
if (phyrexianColors.isWhite() && mana.getWhite() > 0) {
|
|
||||||
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.W);
|
|
||||||
}
|
|
||||||
else if (phyrexianColors.isBlue() && mana.getBlue() > 0) {
|
|
||||||
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.U);
|
|
||||||
}
|
|
||||||
else if (phyrexianColors.isBlack() && mana.getBlack() > 0) {
|
|
||||||
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.B);
|
|
||||||
}
|
|
||||||
else if (phyrexianColors.isRed() && mana.getRed() > 0) {
|
|
||||||
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.R);
|
|
||||||
}
|
|
||||||
else if (phyrexianColors.isGreen() && mana.getGreen() > 0) {
|
|
||||||
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.G);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tempPhyrexianCost != null) {
|
|
||||||
PayLifeCost payLifeCost = new PayLifeCost(2);
|
|
||||||
if (payLifeCost.canPay(this, sourceId, controller.getId(), game)
|
|
||||||
&& controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + tempPhyrexianCost.getBaseText() + '?', this, game)) {
|
|
||||||
costIterator.remove();
|
|
||||||
costs.add(payLifeCost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -924,7 +889,7 @@ public abstract class AbilityImpl implements Ability {
|
||||||
if (getModes().getMode() != null) {
|
if (getModes().getMode() != null) {
|
||||||
return getModes().getMode().getTargets();
|
return getModes().getMode().getTargets();
|
||||||
}
|
}
|
||||||
return null;
|
return new Targets();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -63,6 +63,9 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
||||||
*/
|
*/
|
||||||
public boolean spellCanBeActivatedRegularlyNow(UUID playerId, Game game) {
|
public boolean spellCanBeActivatedRegularlyNow(UUID playerId, Game game) {
|
||||||
MageObject object = game.getObject(sourceId);
|
MageObject object = game.getObject(sourceId);
|
||||||
|
if ((Boolean) game.getState().getValue("CastFromExileEnabled" + object.getId()) != null) {
|
||||||
|
return (Boolean) game.getState().getValue("CastFromExileEnabled" + object.getId()); // card like Chandra, Torch of Defiance +1 loyal ability)
|
||||||
|
}
|
||||||
return null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game) // check this first to allow Offering in main phase
|
return null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game) // check this first to allow Offering in main phase
|
||||||
|| timing == TimingRule.INSTANT
|
|| timing == TimingRule.INSTANT
|
||||||
|| object.hasAbility(FlashAbility.getInstance().getId(), game)
|
|| object.hasAbility(FlashAbility.getInstance().getId(), game)
|
||||||
|
@ -72,7 +75,8 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
||||||
@Override
|
@Override
|
||||||
public ActivationStatus canActivate(UUID playerId, Game game) {
|
public ActivationStatus canActivate(UUID playerId, Game game) {
|
||||||
if (this.spellCanBeActivatedRegularlyNow(playerId, game)) {
|
if (this.spellCanBeActivatedRegularlyNow(playerId, game)) {
|
||||||
if (spellAbilityType == SpellAbilityType.SPLIT || spellAbilityType == SpellAbilityType.SPLIT_AFTERMATH) {
|
if (spellAbilityType == SpellAbilityType.SPLIT
|
||||||
|
|| spellAbilityType == SpellAbilityType.SPLIT_AFTERMATH) {
|
||||||
return ActivationStatus.getFalse();
|
return ActivationStatus.getFalse();
|
||||||
}
|
}
|
||||||
// fix for Gitaxian Probe and casting opponent's spells
|
// fix for Gitaxian Probe and casting opponent's spells
|
||||||
|
@ -93,7 +97,8 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
||||||
// Alternate spell abilities (Flashback, Overload) can't be cast with no mana to pay option
|
// Alternate spell abilities (Flashback, Overload) can't be cast with no mana to pay option
|
||||||
if (getSpellAbilityType() == SpellAbilityType.BASE_ALTERNATE) {
|
if (getSpellAbilityType() == SpellAbilityType.BASE_ALTERNATE) {
|
||||||
Player player = game.getPlayer(playerId);
|
Player player = game.getPlayer(playerId);
|
||||||
if (player != null && getSourceId().equals(player.getCastSourceIdWithAlternateMana())) {
|
if (player != null
|
||||||
|
&& getSourceId().equals(player.getCastSourceIdWithAlternateMana())) {
|
||||||
return ActivationStatus.getFalse();
|
return ActivationStatus.getFalse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
import mage.game.events.ZoneChangeEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,6 +18,8 @@ import mage.players.Player;
|
||||||
*/
|
*/
|
||||||
public class GodEternalDiesTriggeredAbility extends TriggeredAbilityImpl {
|
public class GodEternalDiesTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
|
Boolean applied;
|
||||||
|
|
||||||
public GodEternalDiesTriggeredAbility() {
|
public GodEternalDiesTriggeredAbility() {
|
||||||
super(Zone.ALL, null, true);
|
super(Zone.ALL, null, true);
|
||||||
}
|
}
|
||||||
|
@ -30,20 +33,32 @@ public class GodEternalDiesTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
|
if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
|
||||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||||
return zEvent.getFromZone() == Zone.BATTLEFIELD
|
return zEvent.getFromZone() == Zone.BATTLEFIELD
|
||||||
&& (zEvent.getToZone() == Zone.GRAVEYARD || zEvent.getToZone() == Zone.EXILED);
|
&& (zEvent.getToZone() == Zone.GRAVEYARD
|
||||||
|
|| zEvent.getToZone() == Zone.EXILED);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
applied = false;
|
||||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||||
if (zEvent.getTargetId().equals(this.getSourceId())) {
|
if (zEvent.getTargetId().equals(this.getSourceId())) {
|
||||||
|
Permanent permanent = game.getPermanentOrLKIBattlefield(this.getSourceId());
|
||||||
|
// for cases where its triggered ability is removed, ex: Kasmina's Transmutation
|
||||||
|
if (permanent != null) {
|
||||||
|
for (Ability a : permanent.getAbilities()) {
|
||||||
|
if (a instanceof GodEternalDiesTriggeredAbility) {
|
||||||
|
applied = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (applied) {
|
||||||
this.getEffects().clear();
|
this.getEffects().clear();
|
||||||
this.addEffect(new GodEternalEffect(new MageObjectReference(zEvent.getTarget(), game)));
|
this.addEffect(new GodEternalEffect(new MageObjectReference(zEvent.getTarget(), game)));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
|
return applied;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -118,6 +118,7 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
||||||
}
|
}
|
||||||
|
|
||||||
Player player = game.getPlayer(controllerId);
|
Player player = game.getPlayer(controllerId);
|
||||||
|
handleKrrikPhyrexianManaCosts(controllerId, ability, game);
|
||||||
if (!player.getManaPool().isForcedToPay()) {
|
if (!player.getManaPool().isForcedToPay()) {
|
||||||
assignPayment(game, ability, player.getManaPool(), this);
|
assignPayment(game, ability, player.getManaPool(), this);
|
||||||
}
|
}
|
||||||
|
@ -181,8 +182,27 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
||||||
tempCosts.add(payLifeCost);
|
tempCosts.add(payLifeCost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tempCosts.pay(source, game, source.getSourceId(), player.getId(), false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleKrrikPhyrexianManaCosts(UUID payingPlayerId, Ability source, Game game) {
|
||||||
|
Player player = game.getPlayer(payingPlayerId);
|
||||||
|
if (this == null || player == null) {
|
||||||
|
return; // nothing to be done without any mana costs. prevents NRE from occurring here
|
||||||
|
}
|
||||||
|
Iterator<T> manaCostIterator = this.iterator();
|
||||||
|
Costs<PayLifeCost> tempCosts = new CostsImpl<>();
|
||||||
|
|
||||||
|
while (manaCostIterator.hasNext()) {
|
||||||
|
ManaCost manaCost = manaCostIterator.next();
|
||||||
|
Mana mana = manaCost.getMana();
|
||||||
|
PhyrexianManaCost tempPhyrexianCost = null;
|
||||||
|
FilterMana phyrexianColors = player.getPhyrexianColors();
|
||||||
|
|
||||||
/* K'rrik, Son of Yawgmoth ability check */
|
/* K'rrik, Son of Yawgmoth ability check */
|
||||||
else if (phyrexianColors != null) {
|
if (phyrexianColors != null) {
|
||||||
int phyrexianEnabledPips = mana.count(phyrexianColors);
|
int phyrexianEnabledPips = mana.count(phyrexianColors);
|
||||||
if (phyrexianEnabledPips > 0) {
|
if (phyrexianEnabledPips > 0) {
|
||||||
/* find which color mana is in the cost and set it in the temp Phyrexian cost */
|
/* find which color mana is in the cost and set it in the temp Phyrexian cost */
|
||||||
|
@ -205,7 +225,7 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
||||||
if (tempPhyrexianCost != null) {
|
if (tempPhyrexianCost != null) {
|
||||||
PayLifeCost payLifeCost = new PayLifeCost(2);
|
PayLifeCost payLifeCost = new PayLifeCost(2);
|
||||||
if (payLifeCost.canPay(source, source.getSourceId(), player.getId(), game)
|
if (payLifeCost.canPay(source, source.getSourceId(), player.getId(), game)
|
||||||
&& player.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + tempPhyrexianCost.getBaseText() + '?', source, game)) {
|
&& player.chooseUse(Outcome.LoseLife, "Pay 2 life (using an active ability) instead of " + tempPhyrexianCost.getBaseText() + '?', source, game)) {
|
||||||
manaCostIterator.remove();
|
manaCostIterator.remove();
|
||||||
tempCosts.add(payLifeCost);
|
tempCosts.add(payLifeCost);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ public class ConditionalInterveningIfTriggeredAbility extends TriggeredAbilityIm
|
||||||
this.modes = ability.getModes();
|
this.modes = ability.getModes();
|
||||||
this.condition = condition;
|
this.condition = condition;
|
||||||
this.abilityText = text;
|
this.abilityText = text;
|
||||||
|
this.watchers = ability.getWatchers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConditionalInterveningIfTriggeredAbility(final ConditionalInterveningIfTriggeredAbility triggered) {
|
public ConditionalInterveningIfTriggeredAbility(final ConditionalInterveningIfTriggeredAbility triggered) {
|
||||||
|
@ -44,6 +45,7 @@ public class ConditionalInterveningIfTriggeredAbility extends TriggeredAbilityIm
|
||||||
this.ability = triggered.ability.copy();
|
this.ability = triggered.ability.copy();
|
||||||
this.condition = triggered.condition;
|
this.condition = triggered.condition;
|
||||||
this.abilityText = triggered.abilityText;
|
this.abilityText = triggered.abilityText;
|
||||||
|
this.watchers = triggered.watchers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -100,5 +102,4 @@ public class ConditionalInterveningIfTriggeredAbility extends TriggeredAbilityIm
|
||||||
public boolean isOptional() {
|
public boolean isOptional() {
|
||||||
return ability.isOptional();
|
return ability.isOptional();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,8 @@ public class EmergeAbility extends SpellAbility {
|
||||||
if (super.canActivate(playerId, game).canActivate()) {
|
if (super.canActivate(playerId, game).canActivate()) {
|
||||||
Player controller = game.getPlayer(this.getControllerId());
|
Player controller = game.getPlayer(this.getControllerId());
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
for (Permanent creature : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), this.getControllerId(), this.getSourceId(), game)) {
|
for (Permanent creature : game.getBattlefield().getActivePermanents(
|
||||||
|
new FilterControlledCreaturePermanent(), this.getControllerId(), this.getSourceId(), game)) {
|
||||||
ManaCost costToPay = CardUtil.reduceCost(emergeCost.copy(), creature.getConvertedManaCost());
|
ManaCost costToPay = CardUtil.reduceCost(emergeCost.copy(), creature.getConvertedManaCost());
|
||||||
if (costToPay.canPay(this, this.getSourceId(), this.getControllerId(), game)) {
|
if (costToPay.canPay(this, this.getSourceId(), this.getControllerId(), game)) {
|
||||||
return ActivationStatus.getTrue();
|
return ActivationStatus.getTrue();
|
||||||
|
|
|
@ -57,10 +57,13 @@ public class FlashbackAbility extends SpellAbility {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActivationStatus canActivate(UUID playerId, Game game) {
|
public ActivationStatus canActivate(UUID playerId, Game game) {
|
||||||
ActivationStatus activationStatus = super.canActivate(playerId, game);
|
if (super.canActivate(playerId, game).canActivate()) {
|
||||||
if (activationStatus.canActivate()) {
|
|
||||||
Card card = game.getCard(getSourceId());
|
Card card = game.getCard(getSourceId());
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
|
// Card must be in the graveyard zone
|
||||||
|
if (game.getState().getZone(card.getId()) != Zone.GRAVEYARD) {
|
||||||
|
return ActivationStatus.getFalse();
|
||||||
|
}
|
||||||
// Cards with no Mana Costs cant't be flashbacked (e.g. Ancestral Vision)
|
// Cards with no Mana Costs cant't be flashbacked (e.g. Ancestral Vision)
|
||||||
if (card.getManaCost().isEmpty()) {
|
if (card.getManaCost().isEmpty()) {
|
||||||
return ActivationStatus.getFalse();
|
return ActivationStatus.getFalse();
|
||||||
|
@ -76,7 +79,7 @@ public class FlashbackAbility extends SpellAbility {
|
||||||
return card.getSpellAbility().canActivate(playerId, game);
|
return card.getSpellAbility().canActivate(playerId, game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return activationStatus;
|
return ActivationStatus.getFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -45,8 +45,9 @@ public class SpectacleAbility extends SpellAbility {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActivationStatus canActivate(UUID playerId, Game game) {
|
public ActivationStatus canActivate(UUID playerId, Game game) {
|
||||||
if (OpponentsLostLifeCount.instance.calculate(game, playerId) > 0) {
|
if (OpponentsLostLifeCount.instance.calculate(game, playerId) > 0
|
||||||
return super.canActivate(playerId, game);
|
&& super.canActivate(playerId, game).canActivate()) {
|
||||||
|
return ActivationStatus.getTrue();
|
||||||
}
|
}
|
||||||
return ActivationStatus.getFalse();
|
return ActivationStatus.getFalse();
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,9 @@ public class SurgeAbility extends SpellAbility {
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
for (UUID playerToCheckId : game.getState().getPlayersInRange(playerId, game)) {
|
for (UUID playerToCheckId : game.getState().getPlayersInRange(playerId, game)) {
|
||||||
if (!player.hasOpponent(playerToCheckId, game)) {
|
if (!player.hasOpponent(playerToCheckId, game)) {
|
||||||
if (watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(playerToCheckId) > 0) {
|
if (watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(playerToCheckId) > 0
|
||||||
return super.canActivate(playerId, game);
|
&& super.canActivate(playerId, game).canActivate()) {
|
||||||
|
return ActivationStatus.getTrue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ import mage.filter.Filter;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
|
||||||
import mage.filter.predicate.mageobject.NamePredicate;
|
import mage.filter.predicate.mageobject.NamePredicate;
|
||||||
import mage.filter.predicate.mageobject.SupertypePredicate;
|
import mage.filter.predicate.mageobject.SupertypePredicate;
|
||||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||||
|
@ -69,6 +68,7 @@ import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
|
|
||||||
public abstract class GameImpl implements Game, Serializable {
|
public abstract class GameImpl implements Game, Serializable {
|
||||||
|
|
||||||
|
@ -1011,7 +1011,6 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void initGameDefaultWatchers() {
|
public void initGameDefaultWatchers() {
|
||||||
getState().addWatcher(new MorbidWatcher());
|
getState().addWatcher(new MorbidWatcher());
|
||||||
getState().addWatcher(new CastSpellLastTurnWatcher());
|
getState().addWatcher(new CastSpellLastTurnWatcher());
|
||||||
|
@ -1924,8 +1923,8 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Filter auraFilter = spellAbility.getTargets().get(0).getFilter();
|
Filter auraFilter = spellAbility.getTargets().get(0).getFilter();
|
||||||
if (auraFilter instanceof FilterControlledCreaturePermanent) {
|
if (auraFilter instanceof FilterControlledPermanent) {
|
||||||
if (!((FilterControlledCreaturePermanent) auraFilter).match(attachedTo, perm.getId(), perm.getControllerId(), this)
|
if (!((FilterControlledPermanent) auraFilter).match(attachedTo, perm.getId(), perm.getControllerId(), this)
|
||||||
|| attachedTo.cantBeAttachedBy(perm, this)) {
|
|| attachedTo.cantBeAttachedBy(perm, this)) {
|
||||||
if (movePermanentToGraveyardWithInfo(perm)) {
|
if (movePermanentToGraveyardWithInfo(perm)) {
|
||||||
somethingHappened = true;
|
somethingHappened = true;
|
||||||
|
|
|
@ -311,7 +311,7 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
void useDeck(Deck deck, Game game);
|
void useDeck(Deck deck, Game game);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called before each applyEffects, to rest all what can be applyed by
|
* Called before each applyEffects, to rest all what can be applied by
|
||||||
* continuous effects
|
* continuous effects
|
||||||
*/
|
*/
|
||||||
void reset();
|
void reset();
|
||||||
|
@ -326,6 +326,8 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
|
|
||||||
SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana);
|
SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana);
|
||||||
|
|
||||||
|
SpellAbility chooseAbilityForCast(Card card, Game game, boolean noMana);
|
||||||
|
|
||||||
boolean putInHand(Card card, Game game);
|
boolean putInHand(Card card, Game game);
|
||||||
|
|
||||||
boolean removeFromHand(Card card, Game game);
|
boolean removeFromHand(Card card, Game game);
|
||||||
|
@ -355,8 +357,9 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
boolean searchLibrary(TargetCardInLibrary target, Ability source, Game game, UUID targetPlayerId, boolean triggerEvents);
|
boolean searchLibrary(TargetCardInLibrary target, Ability source, Game game, UUID targetPlayerId, boolean triggerEvents);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reveals all players' libraries. Useful for abilities like Jace, Architect of Thought's -8
|
* Reveals all players' libraries. Useful for abilities like Jace, Architect
|
||||||
* that have effects that require information from all libraries.
|
* of Thought's -8 that have effects that require information from all
|
||||||
|
* libraries.
|
||||||
*
|
*
|
||||||
* @param source
|
* @param source
|
||||||
* @param game
|
* @param game
|
||||||
|
@ -660,7 +663,8 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
*
|
*
|
||||||
* @param card
|
* @param card
|
||||||
* @param game
|
* @param game
|
||||||
* @param abilitiesToActivate extra info about abilities that can be activated on NO option
|
* @param abilitiesToActivate extra info about abilities that can be
|
||||||
|
* activated on NO option
|
||||||
* @return player looked at the card
|
* @return player looked at the card
|
||||||
*/
|
*/
|
||||||
boolean lookAtFaceDownCard(Card card, Game game, int abilitiesToActivate);
|
boolean lookAtFaceDownCard(Card card, Game game, int abilitiesToActivate);
|
||||||
|
@ -700,8 +704,8 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
void addCommanderId(UUID commanderId);
|
void addCommanderId(UUID commanderId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the commanderIds of the player
|
* Get the commanderIds of the player Deprecated, use
|
||||||
* Deprecated, use game.getCommandersIds(xxx) instead
|
* game.getCommandersIds(xxx) instead
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@ -900,4 +904,5 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
void removePhyrexianFromColors(FilterMana colors);
|
void removePhyrexianFromColors(FilterMana colors);
|
||||||
|
|
||||||
FilterMana getPhyrexianColors();
|
FilterMana getPhyrexianColors();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1462,6 +1462,12 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
for (Ability ability : object.getAbilities()) {
|
for (Ability ability : object.getAbilities()) {
|
||||||
if (ability instanceof SpellAbility) {
|
if (ability instanceof SpellAbility) {
|
||||||
switch (((SpellAbility) ability).getSpellAbilityType()) {
|
switch (((SpellAbility) ability).getSpellAbilityType()) {
|
||||||
|
case BASE_ALTERNATE:
|
||||||
|
ActivationStatus as = ((SpellAbility) ability).canActivate(playerId, game);
|
||||||
|
if (as.canActivate()) {
|
||||||
|
useable.put(ability.getId(), (SpellAbility) ability); // example: Chandra, Torch of Defiance +1 loyal ability
|
||||||
|
}
|
||||||
|
return useable;
|
||||||
case SPLIT_FUSED:
|
case SPLIT_FUSED:
|
||||||
if (zone == Zone.HAND) {
|
if (zone == Zone.HAND) {
|
||||||
if (ability.canChooseTarget(game)) {
|
if (ability.canChooseTarget(game)) {
|
||||||
|
@ -4345,4 +4351,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
public FilterMana getPhyrexianColors() {
|
public FilterMana getPhyrexianColors() {
|
||||||
return this.phyrexianColors;
|
return this.phyrexianColors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpellAbility chooseAbilityForCast(Card card, Game game, boolean noMana) {
|
||||||
|
return card.getSpellAbility();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.watchers.common;
|
package mage.watchers.common;
|
||||||
|
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
|
@ -30,13 +29,15 @@ public class ManaSpentToCastWatcher extends Watcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void watch(GameEvent event, Game game) {
|
public void watch(GameEvent event, Game game) {
|
||||||
if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getZone() == Zone.HAND) {
|
// There was a check for the from zone being the hand, but that should not matter
|
||||||
|
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
|
||||||
Spell spell = (Spell) game.getObject(event.getTargetId());
|
Spell spell = (Spell) game.getObject(event.getTargetId());
|
||||||
if (spell != null && this.getSourceId().equals(spell.getSourceId())) {
|
if (spell != null && this.getSourceId().equals(spell.getSourceId())) {
|
||||||
payment = spell.getSpellAbility().getManaCostsToPay().getPayment();
|
payment = spell.getSpellAbility().getManaCostsToPay().getPayment();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && this.getSourceId().equals(event.getSourceId())) {
|
if (event.getType() == GameEvent.EventType.ZONE_CHANGE
|
||||||
|
&& this.getSourceId().equals(event.getSourceId())) {
|
||||||
if (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) {
|
if (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) {
|
||||||
payment = null;
|
payment = null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue