diff --git a/Mage.Sets/src/mage/cards/a/AshlingsPrerogative.java b/Mage.Sets/src/mage/cards/a/AshlingsPrerogative.java index 84d3a3c59a1..56e862bef7e 100644 --- a/Mage.Sets/src/mage/cards/a/AshlingsPrerogative.java +++ b/Mage.Sets/src/mage/cards/a/AshlingsPrerogative.java @@ -1,11 +1,8 @@ package mage.cards.a; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.PermanentsEnterBattlefieldTappedEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; @@ -14,31 +11,44 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.ModeChoice; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; -import mage.game.events.EntersTheBattlefieldEvent; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author Eirkei */ public final class AshlingsPrerogative extends CardImpl { + private static final FilterPermanent filterMatch + = new FilterCreaturePermanent("each creature with mana value of the chosen quality"); + private static final FilterPermanent filterNotMatch + = new FilterCreaturePermanent("each creature without mana value of the chosen quality"); + + static { + filterMatch.add(AshlingsPrerogativePredicate.WITH); + filterNotMatch.add(AshlingsPrerogativePredicate.WITHOUT); + } + public AshlingsPrerogative(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); // As Ashling's Prerogative enters the battlefield, choose odd or even. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Odd or even?", "Odd", "Even"), null, "As {this} enters, choose odd or even. (Zero is even.)", "")); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.ODD, ModeChoice.EVEN))); // Each creature with converted mana cost of the chosen value has haste. - this.addAbility(new SimpleStaticAbility(new AshlingsPrerogativeCorrectOddityEffect())); + this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect( + HasteAbility.getInstance(), Duration.WhileOnBattlefield, filterMatch + ))); // Each creature without converted mana cost of the chosen value enters the battlefield tapped. - this.addAbility(new SimpleStaticAbility(new AshlingsPrerogativeIncorrectOddityEffect())); - + this.addAbility(new SimpleStaticAbility(new PermanentsEnterBattlefieldTappedEffect(filterNotMatch))); } private AshlingsPrerogative(final AshlingsPrerogative card) { @@ -51,67 +61,23 @@ public final class AshlingsPrerogative extends CardImpl { } } -class AshlingsPrerogativeIncorrectOddityEffect extends PermanentsEnterBattlefieldTappedEffect { +enum AshlingsPrerogativePredicate implements ObjectSourcePlayerPredicate { + WITH(true), + WITHOUT(false); + private final boolean match; - private static final FilterCreaturePermanent creaturefilter = new FilterCreaturePermanent("Each creature without mana value of the chosen quality"); - private static final ModeChoiceSourceCondition oddCondition = new ModeChoiceSourceCondition("Odd"); - - public AshlingsPrerogativeIncorrectOddityEffect() { - super(creaturefilter); - staticText = "Each creature without mana value of the chosen quality enters the battlefield tapped."; - } - - private AshlingsPrerogativeIncorrectOddityEffect(final AshlingsPrerogativeIncorrectOddityEffect effect) { - super(effect); + AshlingsPrerogativePredicate(boolean match) { + this.match = match; } @Override - public boolean applies(GameEvent event, Ability source, Game game) { - int incorrectModResult; - - if (oddCondition.apply(game, source)) { - incorrectModResult = 0; + public boolean apply(ObjectSourcePlayer input, Game game) { + if (ModeChoice.ODD.checkMode(game, input.getSource())) { + return (input.getObject().getManaValue() % 2 == 1) == match; + } else if (ModeChoice.EVEN.checkMode(game, input.getSource())) { + return (input.getObject().getManaValue() % 2 == 0) == match; } else { - incorrectModResult = 1; + return false; } - - Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); - - return permanent != null && creaturefilter.match(permanent, game) && permanent.getManaValue() % 2 == incorrectModResult; - } - - @Override - public AshlingsPrerogativeIncorrectOddityEffect copy() { - return new AshlingsPrerogativeIncorrectOddityEffect(this); - } -} - -class AshlingsPrerogativeCorrectOddityEffect extends GainAbilityAllEffect { - - private static final FilterCreaturePermanent creaturefilter = new FilterCreaturePermanent("Each creature with mana value of the chosen quality"); - private static final ModeChoiceSourceCondition oddCondition = new ModeChoiceSourceCondition("Odd"); - - public AshlingsPrerogativeCorrectOddityEffect() { - super(HasteAbility.getInstance(), Duration.WhileOnBattlefield, creaturefilter); - staticText = "Each creature with mana value of the chosen quality has haste."; - } - private AshlingsPrerogativeCorrectOddityEffect(final AshlingsPrerogativeCorrectOddityEffect effect) { - super(effect); - } - - @Override - protected boolean selectedByRuntimeData(Permanent permanent, Ability source, Game game) { - int correctModResult; - if (oddCondition.apply(game, source)) { - correctModResult = 1; - } else { - correctModResult = 0; - } - return permanent != null && creaturefilter.match(permanent, game) && permanent.getManaValue() % 2 == correctModResult; - } - - @Override - public AshlingsPrerogativeCorrectOddityEffect copy() { - return new AshlingsPrerogativeCorrectOddityEffect(this); } } diff --git a/Mage.Sets/src/mage/cards/b/BarrensteppeSiege.java b/Mage.Sets/src/mage/cards/b/BarrensteppeSiege.java index 5bac6c137fd..b4370e0ab64 100644 --- a/Mage.Sets/src/mage/cards/b/BarrensteppeSiege.java +++ b/Mage.Sets/src/mage/cards/b/BarrensteppeSiege.java @@ -1,17 +1,17 @@ package mage.cards.b; -import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.condition.Condition; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.CreatureDiedControlledCondition; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.SacrificeOpponentsEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; import mage.abilities.effects.common.counter.AddCountersAllEffect; import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ModeChoice; import mage.counters.CounterType; import mage.filter.StaticFilters; @@ -22,35 +22,25 @@ import java.util.UUID; */ public final class BarrensteppeSiege extends CardImpl { - private static final Condition condition1 = new ModeChoiceSourceCondition("Abzan"); - private static final String rule1 = "&bull Abzan — At the beginning of your end step, " + - "put a +1/+1 counter on each creature you control."; - private static final Condition condition2 = new ModeChoiceSourceCondition("Mardu"); - private static final String rule2 = "&bull Mardu — At the beginning of your end step, " + - "if a creature died under your control this turn, each opponent sacrifices a creature of their choice."; - public BarrensteppeSiege(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{B}"); // As this enchantment enters, choose Abzan or Mardu. - this.addAbility(new EntersBattlefieldAbility( - new ChooseModeEffect("Abzan or Mardu?", "Abzan", "Mardu"), - null, "As {this} enters, choose Abzan or Mardu.", "" - )); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.ABZAN, ModeChoice.MARDU))); // * Abzan -- At the beginning of your end step, put a +1/+1 counter on each creature you control. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( new BeginningOfEndStepTriggeredAbility(new AddCountersAllEffect( CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE - )), condition1, rule1 - )); + )), ModeChoice.ABZAN + ))); // * Mardu -- At the beginning of your end step, if a creature died under your control this turn, each opponent sacrifices a creature of their choice. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( new BeginningOfEndStepTriggeredAbility( new SacrificeOpponentsEffect(StaticFilters.FILTER_PERMANENT_CREATURE) - ).withInterveningIf(CreatureDiedControlledCondition.instance), condition2, rule2 - )); + ).withInterveningIf(CreatureDiedControlledCondition.instance), ModeChoice.MARDU + ))); } private BarrensteppeSiege(final BarrensteppeSiege card) { diff --git a/Mage.Sets/src/mage/cards/b/BattleOfHooverDam.java b/Mage.Sets/src/mage/cards/b/BattleOfHooverDam.java index fa2a607a372..b8e39e72ee1 100644 --- a/Mage.Sets/src/mage/cards/b/BattleOfHooverDam.java +++ b/Mage.Sets/src/mage/cards/b/BattleOfHooverDam.java @@ -1,33 +1,35 @@ package mage.cards.b; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.DiesCreatureTriggeredAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldWithCounterTargetEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; +import mage.constants.ModeChoice; import mage.counters.CounterType; +import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** * @author Cguy7777 */ public final class BattleOfHooverDam extends CardImpl { - private static final FilterCreatureCard filter = new FilterCreatureCard(); + private static final FilterCard filter = new FilterCreatureCard(); static { filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4)); @@ -37,32 +39,23 @@ public final class BattleOfHooverDam extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); // As Battle of Hoover Dam enters the battlefield, choose NCR or Legion. - this.addAbility(new AsEntersBattlefieldAbility( - new ChooseModeEffect("NCR or Legion?", "NCR", "Legion"))); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.NCR, ModeChoice.LEGION))); // * NCR -- At the beginning of your end step, return target creature card with mana value 3 or less // from your graveyard to the battlefield with a finality counter on it. - Ability ncrAbility = new ConditionalTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - new ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(CounterType.FINALITY.createInstance()) - ), - new ModeChoiceSourceCondition("NCR"), - "&bull NCR — At the beginning of your end step, return target creature card with " + - "mana value 3 or less from your graveyard to the battlefield with a finality counter on it."); - ncrAbility.addTarget(new TargetCardInYourGraveyard(filter)); - this.addAbility(ncrAbility); + Ability ability = new BeginningOfEndStepTriggeredAbility( + new ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(CounterType.FINALITY.createInstance()) + ); + ability.addTarget(new TargetCardInYourGraveyard(filter)); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.NCR))); // * Legion -- Whenever a creature you control dies, put two +1/+1 counters on target creature you control. - Ability legionAbility = new ConditionalTriggeredAbility( - new DiesCreatureTriggeredAbility( - new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)), - false, - StaticFilters.FILTER_CONTROLLED_A_CREATURE), - new ModeChoiceSourceCondition("Legion"), - "&bull Legion — Whenever a creature you control dies, " + - "put two +1/+1 counters on target creature you control."); - legionAbility.addTarget(new TargetControlledCreaturePermanent()); - this.addAbility(legionAbility); + ability = new DiesCreatureTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)), + false, StaticFilters.FILTER_CONTROLLED_A_CREATURE + ); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.LEGION))); } private BattleOfHooverDam(final BattleOfHooverDam card) { diff --git a/Mage.Sets/src/mage/cards/c/CitadelSiege.java b/Mage.Sets/src/mage/cards/c/CitadelSiege.java index 793ee47f43d..edbafe2556e 100644 --- a/Mage.Sets/src/mage/cards/c/CitadelSiege.java +++ b/Mage.Sets/src/mage/cards/c/CitadelSiege.java @@ -1,23 +1,20 @@ - package mage.cards.c; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; -import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ModeChoice; import mage.constants.TargetController; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicate; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -28,36 +25,29 @@ import java.util.UUID; */ public final class CitadelSiege extends CardImpl { - private static final String ruleTrigger1 = "&bull Khans — At the beginning of combat on your turn, put two +1/+1 counters on target creature you control."; - private static final String ruleTrigger2 = "&bull Dragons — At the beginning of combat on each opponent's turn, tap target creature that player controls."; private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature controlled by the active player"); static { - filter.add(CitadelSiegePredicate.instance); + filter.add(TargetController.ACTIVE.getControllerPredicate()); } public CitadelSiege(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // As Citadel Siege enters the battlefield, choose Khans or Dragons. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Khans or Dragons?", "Khans", "Dragons"), null, - "As {this} enters, choose Khans or Dragons.", "")); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.KHANS, ModeChoice.DRAGONS))); // * Khans - At the beginning of combat on your turn, put two +1/+1 counters on target creature you control. - Ability ability = new ConditionalTriggeredAbility( - new BeginningOfCombatTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2))), - new ModeChoiceSourceCondition("Khans"), - ruleTrigger1); + Ability ability = new BeginningOfCombatTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2))); ability.addTarget(new TargetControlledCreaturePermanent()); - this.addAbility(ability); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.KHANS))); // * Dragons - At the beginning of combat on each opponent's turn, tap target creature that player controls. - ability = new ConditionalTriggeredAbility( - new BeginningOfCombatTriggeredAbility(TargetController.OPPONENT, new TapTargetEffect(), false), - new ModeChoiceSourceCondition("Dragons"), - ruleTrigger2); + ability = new BeginningOfCombatTriggeredAbility( + TargetController.OPPONENT, new TapTargetEffect("tap target creature that player controls"), false + ); ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(ability); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.DRAGONS))); } private CitadelSiege(final CitadelSiege card) { @@ -69,12 +59,3 @@ public final class CitadelSiege extends CardImpl { return new CitadelSiege(this); } } - -enum CitadelSiegePredicate implements Predicate { - instance; - - @Override - public boolean apply(Permanent input, Game game) { - return input.getControllerId().equals(game.getActivePlayerId()); - } -} diff --git a/Mage.Sets/src/mage/cards/f/FrontierSiege.java b/Mage.Sets/src/mage/cards/f/FrontierSiege.java index 87b2e5bfcfa..c18360d64e2 100644 --- a/Mage.Sets/src/mage/cards/f/FrontierSiege.java +++ b/Mage.Sets/src/mage/cards/f/FrontierSiege.java @@ -3,17 +3,18 @@ package mage.cards.f; import mage.Mana; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ChooseModeEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; import mage.abilities.effects.mana.AddManaToManaPoolSourceControllerEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; @@ -29,37 +30,28 @@ import java.util.UUID; */ public final class FrontierSiege extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature with flying"); + private static final FilterPermanent filter = new FilterCreaturePermanent("a creature with flying you control"); static { filter.add(TargetController.YOU.getControllerPredicate()); filter.add(new AbilityPredicate(FlyingAbility.class)); } - private static final String ruleTrigger1 = "&bull Khans — At the beginning of each of your main phases, add {G}{G}."; - private static final String ruleTrigger2 = "&bull Dragons — Whenever a creature with flying you control enters, you may have it fight target creature you don't control."; - public FrontierSiege(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); // As Frontier Siege enters the battlefield, choose Khans or Dragons. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Khans or Dragons?", "Khans", "Dragons"), null, - "As {this} enters, choose Khans or Dragons.", "")); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.KHANS, ModeChoice.DRAGONS))); // * Khans - At the beginning of each of your main phases, add {G}{G}. - this.addAbility(new ConditionalTriggeredAbility( - new FrontierSiegeKhansTriggeredAbility(), - new ModeChoiceSourceCondition("Khans"), - ruleTrigger1)); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(new FrontierSiegeKhansTriggeredAbility(), ModeChoice.KHANS))); // * Dragons - Whenever a creature with flying you control enters, you may have it fight target creature you don't control. - Ability ability2 = new ConditionalTriggeredAbility( - new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new FrontierSiegeFightEffect(), filter, true, SetTargetPointer.PERMANENT), - new ModeChoiceSourceCondition("Dragons"), - ruleTrigger2); - ability2.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); - this.addAbility(ability2); - + Ability ability = new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new FrontierSiegeFightEffect(), filter, true, SetTargetPointer.PERMANENT + ); + ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.DRAGONS))); } private FrontierSiege(final FrontierSiege card) { diff --git a/Mage.Sets/src/mage/cards/f/FrostcliffSiege.java b/Mage.Sets/src/mage/cards/f/FrostcliffSiege.java index 61ce64fc2b5..1f4199d77e6 100644 --- a/Mage.Sets/src/mage/cards/f/FrostcliffSiege.java +++ b/Mage.Sets/src/mage/cards/f/FrostcliffSiege.java @@ -1,65 +1,54 @@ package mage.cards.f; -import java.util.UUID; - import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.ModeChoice; import mage.filter.StaticFilters; +import java.util.UUID; + /** - * * @author androosss */ public final class FrostcliffSiege extends CardImpl { - private static final String rule1Trigger = "• Jeskai — Whenever one or more creatures you control deal combat damage to a player, draw a card."; - public FrostcliffSiege(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}{R}"); - // As this enchantment enters, choose Jeskai or Temur. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Jeskai or Temur?", "Jeskai", "Temur"), null, - "As {this} enters, choose Jeskai or Temur.", "")); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.JESKAI, ModeChoice.TEMUR))); // * Jeskai -- Whenever one or more creatures you control deal combat damage to a player, draw a card. - this.addAbility(new ConditionalTriggeredAbility( - new OneOrMoreCombatDamagePlayerTriggeredAbility(new DrawCardSourceControllerEffect(1)), - new ModeChoiceSourceCondition("Jeskai"), - rule1Trigger)); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( + new OneOrMoreCombatDamagePlayerTriggeredAbility(new DrawCardSourceControllerEffect(1)), ModeChoice.JESKAI + ))); // * Temur -- Creatures you control get +1/+0 and have trample and haste. - Ability temurAbility = new SimpleStaticAbility(new ConditionalContinuousEffect( - new BoostControlledEffect(1, 0, Duration.WhileOnBattlefield), - new ModeChoiceSourceCondition("Temur"), - "• Temur — Creatures you control get +1/+0" - )); - temurAbility.addEffect(new ConditionalContinuousEffect( - new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES), - new ModeChoiceSourceCondition("Temur"), - "and have trample" - )); - temurAbility.addEffect(new ConditionalContinuousEffect( - new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES), - new ModeChoiceSourceCondition("Temur"), - "and haste." - )); - this.addAbility(temurAbility); + Ability ability = new SimpleStaticAbility( + new BoostControlledEffect(1, 0, Duration.WhileOnBattlefield) + ); + ability.addEffect(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), Duration.WhileOnBattlefield, + StaticFilters.FILTER_PERMANENT_CREATURES + ).setText("and have trample")); + ability.addEffect(new GainAbilityControlledEffect( + HasteAbility.getInstance(), Duration.WhileOnBattlefield, + StaticFilters.FILTER_PERMANENT_CREATURES + ).setText("and haste")); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.TEMUR))); } private FrostcliffSiege(final FrostcliffSiege card) { diff --git a/Mage.Sets/src/mage/cards/g/GlacierwoodSiege.java b/Mage.Sets/src/mage/cards/g/GlacierwoodSiege.java index 693845f7cd6..6452cc88eb6 100644 --- a/Mage.Sets/src/mage/cards/g/GlacierwoodSiege.java +++ b/Mage.Sets/src/mage/cards/g/GlacierwoodSiege.java @@ -1,58 +1,45 @@ package mage.cards.g; -import java.util.UUID; - -import mage.abilities.TriggeredAbility; -import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.Ability; +import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalAsThoughEffect; -import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.MillCardsTargetEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; import mage.abilities.effects.common.ruleModifying.PlayFromGraveyardControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.FilterSpell; -import mage.filter.predicate.Predicates; +import mage.constants.ModeChoice; +import mage.filter.StaticFilters; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author androosss */ public final class GlacierwoodSiege extends CardImpl { - private static final FilterSpell filter = new FilterSpell("an instant or sorcery spell"); - - static { - filter.add(Predicates.or( - CardType.INSTANT.getPredicate(), - CardType.SORCERY.getPredicate())); - } - public GlacierwoodSiege(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}{U}"); - + // As this enchantment enters, choose Temur or Sultai. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Temur or Sultai?", "Temur", "Sultai"), null, - "As {this} enters, choose Temur or Sultai.", "")); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.TEMUR, ModeChoice.SULTAI))); // * Temur -- Whenever you cast an instant or sorcery spell, target player mills four cards. - TriggeredAbility temurAbility = new SpellCastControllerTriggeredAbility(new MillCardsTargetEffect(4), filter, false); - temurAbility.addTarget(new TargetPlayer()); - this.addAbility(new ConditionalTriggeredAbility( - temurAbility, - new ModeChoiceSourceCondition("Temur"), - "• Temur — Whenever you cast an instant or sorcery spell, target player mills four cards.")); + Ability ability = new SpellCastControllerTriggeredAbility( + new MillCardsTargetEffect(4), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false + ); + ability.addTarget(new TargetPlayer()); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.TEMUR))); // * Sultai -- You may play lands from your graveyard. - this.addAbility(new SimpleStaticAbility(new ConditionalAsThoughEffect( - PlayFromGraveyardControllerEffect.playLands(), - new ModeChoiceSourceCondition("Sultai")).setText("• Sultai — You may play lands from your graveyard.") - )); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( + PlayFromGraveyardControllerEffect.playLands(), ModeChoice.SULTAI + ))); } private GlacierwoodSiege(final GlacierwoodSiege card) { diff --git a/Mage.Sets/src/mage/cards/i/IsshinTwoHeavensAsOne.java b/Mage.Sets/src/mage/cards/i/IsshinTwoHeavensAsOne.java index 31f9cf1c370..689ed56b8b3 100644 --- a/Mage.Sets/src/mage/cards/i/IsshinTwoHeavensAsOne.java +++ b/Mage.Sets/src/mage/cards/i/IsshinTwoHeavensAsOne.java @@ -1,16 +1,13 @@ package mage.cards.i; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.replacement.AdditionalTriggersAttackingReplacementEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.NumberOfTriggersEvent; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; import java.util.UUID; @@ -29,7 +26,7 @@ public final class IsshinTwoHeavensAsOne extends CardImpl { this.toughness = new MageInt(4); // If a creature attacking causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. - this.addAbility(new SimpleStaticAbility(new IsshinTwoHeavensAsOneEffect())); + this.addAbility(new SimpleStaticAbility(new AdditionalTriggersAttackingReplacementEffect(false))); } private IsshinTwoHeavensAsOne(final IsshinTwoHeavensAsOne card) { @@ -41,54 +38,3 @@ public final class IsshinTwoHeavensAsOne extends CardImpl { return new IsshinTwoHeavensAsOne(this); } } - -class IsshinTwoHeavensAsOneEffect extends ReplacementEffectImpl { - - IsshinTwoHeavensAsOneEffect() { - super(Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "if a creature attacking causes a triggered ability " + - "of a permanent you control to trigger, that ability triggers an additional time"; - } - - private IsshinTwoHeavensAsOneEffect(final IsshinTwoHeavensAsOneEffect effect) { - super(effect); - } - - @Override - public IsshinTwoHeavensAsOneEffect copy() { - return new IsshinTwoHeavensAsOneEffect(this); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.NUMBER_OF_TRIGGERS; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event; - Permanent sourcePermanent = game.getPermanent(numberOfTriggersEvent.getSourceId()); - if (sourcePermanent == null || !sourcePermanent.isControlledBy(source.getControllerId())) { - return false; - } - - GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); - if (sourceEvent == null) { - return false; - } - - switch (sourceEvent.getType()) { - case ATTACKER_DECLARED: - case DECLARED_ATTACKERS: - case DEFENDER_ATTACKED: - return true; - } - return false; - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - event.setAmount(event.getAmount() + 1); - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/l/LavabrinkVenturer.java b/Mage.Sets/src/mage/cards/l/LavabrinkVenturer.java index 97c807b7924..a51d0ff8407 100644 --- a/Mage.Sets/src/mage/cards/l/LavabrinkVenturer.java +++ b/Mage.Sets/src/mage/cards/l/LavabrinkVenturer.java @@ -10,6 +10,7 @@ import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ModeChoice; import mage.constants.SubType; import mage.filter.FilterObject; import mage.filter.predicate.mageobject.ManaValueParityPredicate; @@ -31,10 +32,7 @@ public final class LavabrinkVenturer extends CardImpl { this.toughness = new MageInt(3); // As Lavabrink Venturer enters the battlefield, choose odd or even. - this.addAbility(new AsEntersBattlefieldAbility( - new ChooseModeEffect("Odd or even?", "Odd", "Even"), - "choose odd or even. (Zero is even.)" - )); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.ODD, ModeChoice.EVEN))); // Lavabrink Venturer has protection from each converted mana cost of the chosen value. this.addAbility(new SimpleStaticAbility(new LavabrinkVenturerEffect())); @@ -75,20 +73,13 @@ class LavabrinkVenturerEffect extends GainAbilitySourceEffect { @Override public boolean apply(Game game, Ability source) { - String chosenMode = (String) game.getState().getValue(source.getSourceId() + "_modeChoice"); - if (chosenMode == null) { + if (ModeChoice.ODD.checkMode(game, source)) { + this.ability = new ProtectionAbility(oddFilter); + } else if (ModeChoice.EVEN.checkMode(game, source)) { + this.ability = new ProtectionAbility(evenFilter); + } else { return false; } - switch (chosenMode) { - case "Odd": - this.ability = new ProtectionAbility(oddFilter); - break; - case "Even": - this.ability = new ProtectionAbility(evenFilter); - break; - default: - return false; - } return super.apply(game, source); } diff --git a/Mage.Sets/src/mage/cards/m/MirrodinBesieged.java b/Mage.Sets/src/mage/cards/m/MirrodinBesieged.java index 6af67534394..459afeaa1d6 100644 --- a/Mage.Sets/src/mage/cards/m/MirrodinBesieged.java +++ b/Mage.Sets/src/mage/cards/m/MirrodinBesieged.java @@ -1,22 +1,21 @@ package mage.cards.m; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; -import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ModeChoice; import mage.constants.Outcome; -import mage.filter.FilterSpell; import mage.filter.StaticFilters; -import mage.filter.common.FilterArtifactSpell; import mage.game.Game; import mage.game.permanent.token.MyrToken; import mage.players.Player; @@ -29,33 +28,23 @@ import java.util.UUID; */ public final class MirrodinBesieged extends CardImpl { - private static final String ruleTrigger1 = "&bull Mirran — Whenever you cast an artifact spell, " + - "create a 1/1 colorless Myr artifact creature token."; - private static final String ruleTrigger2 = "&bull Phyrexian — At the beginning of your end step, " + - "draw a card, then discard a card. Then if there are fifteen or more artifact cards in your graveyard, " + - "target opponent loses the game."; - private static final FilterSpell filter = new FilterArtifactSpell(); - public MirrodinBesieged(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // As Mirrodin Besieged enters the battlefield, choose Mirran or Phyrexian. - this.addAbility(new EntersBattlefieldAbility( - new ChooseModeEffect("Mirran or Phyrexian?", "Mirran", "Phyrexian"), - null, "As {this} enters, choose Mirran or Phyrexian.", "" - )); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.MIRRAN, ModeChoice.PHYREXIAN))); // • Mirran — Whenever you cast an artifact spell, create a 1/1 colorless Myr artifact creature token. - this.addAbility(new ConditionalTriggeredAbility(new SpellCastControllerTriggeredAbility( - new CreateTokenEffect(new MyrToken()), filter, false - ), new ModeChoiceSourceCondition("Mirran"), ruleTrigger1)); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( + new SpellCastControllerTriggeredAbility( + new CreateTokenEffect(new MyrToken()), StaticFilters.FILTER_SPELL_AN_ARTIFACT, false + ), ModeChoice.MIRRAN + ))); // • Phyrexian — At the beginning of your end step, draw a card, then discard a card. Then if there are fifteen or more artifact cards in your graveyard, target opponent loses the game. - Ability ability = new ConditionalTriggeredAbility(new BeginningOfEndStepTriggeredAbility( - new MirrodinBesiegedEffect() - ), new ModeChoiceSourceCondition("Phyrexian"), ruleTrigger2); + Ability ability = new BeginningOfEndStepTriggeredAbility(new MirrodinBesiegedEffect()); ability.addTarget(new TargetOpponent()); - this.addAbility(ability); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.PHYREXIAN))); } private MirrodinBesieged(final MirrodinBesieged card) { diff --git a/Mage.Sets/src/mage/cards/m/MonasterySiege.java b/Mage.Sets/src/mage/cards/m/MonasterySiege.java index ab0074437dd..69bab804c13 100644 --- a/Mage.Sets/src/mage/cards/m/MonasterySiege.java +++ b/Mage.Sets/src/mage/cards/m/MonasterySiege.java @@ -2,14 +2,13 @@ package mage.cards.m; import mage.abilities.Ability; import mage.abilities.SpellAbility; -import mage.abilities.triggers.BeginningOfDrawTriggeredAbility; -import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.abilities.triggers.BeginningOfDrawTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -31,17 +30,19 @@ public final class MonasterySiege extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // As Monastery Siege enters the battlefield, choose Khans or Dragons. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Khans or Dragons?", "Khans", "Dragons"), null, - "As {this} enters, choose Khans or Dragons.", "")); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.KHANS, ModeChoice.DRAGONS))); // * Khans - At the beginning of your draw step, draw an additional card, then discard a card. - this.addAbility(new ConditionalTriggeredAbility( - new BeginningOfDrawTriggeredAbility(new DrawDiscardControllerEffect(1, 1), false), - new ModeChoiceSourceCondition("Khans"), - "• Khans — At the beginning of your draw step, draw an additional card, then discard a card.")); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( + new BeginningOfDrawTriggeredAbility( + new DrawDiscardControllerEffect(1, 1), false + ), ModeChoice.KHANS + ))); // * Dragons - Spells your opponents cast that target you or a permanent you control cost {2} more to cast. - this.addAbility(new SimpleStaticAbility(new MonasterySiegeCostIncreaseEffect())); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( + new MonasterySiegeCostIncreaseEffect(), ModeChoice.DRAGONS + ))); } private MonasterySiege(final MonasterySiege card) { @@ -56,11 +57,9 @@ public final class MonasterySiege extends CardImpl { class MonasterySiegeCostIncreaseEffect extends CostModificationEffectImpl { - private static final ModeChoiceSourceCondition modeDragons = new ModeChoiceSourceCondition("Dragons"); - MonasterySiegeCostIncreaseEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST); - staticText = "• Dragons — Spells your opponents cast that target you or a permanent you control cost {2} more to cast"; + staticText = "spells your opponents cast that target you or a permanent you control cost {2} more to cast"; } private MonasterySiegeCostIncreaseEffect(final MonasterySiegeCostIncreaseEffect effect) { @@ -75,10 +74,6 @@ class MonasterySiegeCostIncreaseEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (!modeDragons.apply(game, source)) { - return false; - } - if (!(abilityToModify instanceof SpellAbility)) { return false; } diff --git a/Mage.Sets/src/mage/cards/o/OutpostSiege.java b/Mage.Sets/src/mage/cards/o/OutpostSiege.java index 449ac8d4711..47827489fe1 100644 --- a/Mage.Sets/src/mage/cards/o/OutpostSiege.java +++ b/Mage.Sets/src/mage/cards/o/OutpostSiege.java @@ -1,54 +1,48 @@ package mage.cards.o; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.common.ZoneChangeAllTriggeredAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.LeavesBattlefieldAllTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.constants.ModeChoice; +import mage.filter.StaticFilters; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class OutpostSiege extends CardImpl { - private static final String ruleTrigger1 = "&bull Khans — At the beginning of your upkeep, exile the top card of your library. Until end of turn, you may play that card."; - private static final String ruleTrigger2 = "&bull Dragons — Whenever a creature you control leaves the battlefield, {this} deals 1 damage to any target."; - public OutpostSiege(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); // As Outpost Siege enters the battlefield, choose Khans or Dragons. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Khans or Dragons?", "Khans", "Dragons"), null, - "As {this} enters, choose Khans or Dragons.", "")); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.KHANS, ModeChoice.DRAGONS))); // * Khans - At the beginning of your upkeep, exile the top card of your library. Until end of turn, you may play that card. - this.addAbility(new ConditionalTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new ExileTopXMayPlayUntilEffect(1, Duration.EndOfTurn)), - new ModeChoiceSourceCondition("Khans"), - ruleTrigger1)); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( + new BeginningOfUpkeepTriggeredAbility( + new ExileTopXMayPlayUntilEffect(1, Duration.EndOfTurn) + ), ModeChoice.KHANS + ))); // * Dragons - Whenever a creature you control leaves the battlefield, Outpost Siege deals 1 damage to any target. - Ability ability2 = new ConditionalTriggeredAbility( - new ZoneChangeAllTriggeredAbility(Zone.BATTLEFIELD, Zone.BATTLEFIELD, null, new DamageTargetEffect(1), - new FilterControlledCreaturePermanent(), "", false), - new ModeChoiceSourceCondition("Dragons"), - ruleTrigger2); - ability2.addTarget(new TargetAnyTarget()); - this.addAbility(ability2); - + Ability ability = new LeavesBattlefieldAllTriggeredAbility( + new DamageTargetEffect(1), StaticFilters.FILTER_CONTROLLED_A_CREATURE + ); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.DRAGONS))); } private OutpostSiege(final OutpostSiege card) { diff --git a/Mage.Sets/src/mage/cards/p/PalaceSiege.java b/Mage.Sets/src/mage/cards/p/PalaceSiege.java index 445a1411d5d..24b4a86a524 100644 --- a/Mage.Sets/src/mage/cards/p/PalaceSiege.java +++ b/Mage.Sets/src/mage/cards/p/PalaceSiege.java @@ -1,55 +1,43 @@ package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; -import mage.abilities.effects.Effect; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ModeChoice; import mage.filter.StaticFilters; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class PalaceSiege extends CardImpl { - private static final String ruleTrigger1 = "&bull Khans — At the beginning of your upkeep, return target creature card from your graveyard to your hand."; - private static final String ruleTrigger2 = "&bull Dragons — At the beginning of your upkeep, each opponent loses 2 life and you gain 2 life."; - public PalaceSiege(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}"); // As Palace Siege enters the battlefield, choose Khans or Dragons. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Khans or Dragons?", "Khans", "Dragons"), null, - "As {this} enters, choose Khans or Dragons.", "")); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.KHANS, ModeChoice.DRAGONS))); // * Khans - At the beginning of your upkeep, return target creature card from your graveyard to your hand. - Ability ability1 = new ConditionalTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()), - new ModeChoiceSourceCondition("Khans"), - ruleTrigger1); + Ability ability1 = new BeginningOfUpkeepTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()); ability1.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE)); - this.addAbility(ability1); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability1, ModeChoice.KHANS))); // * Dragons - At the beginning of your upkeep, each opponent loses 2 life and you gain 2 life. - Ability ability2 = new ConditionalTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new LoseLifeOpponentsEffect(2)), - new ModeChoiceSourceCondition("Dragons"), - ruleTrigger2); - Effect effect = new GainLifeEffect(2); - effect.setText("and you gain 2 life"); - ability2.addEffect(effect); - this.addAbility(ability2); + Ability ability2 = new BeginningOfUpkeepTriggeredAbility(new LoseLifeOpponentsEffect(2)); + ability2.addEffect(new GainLifeEffect(2).setText("and you gain 2 life")); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability2, ModeChoice.DRAGONS))); } diff --git a/Mage.Sets/src/mage/cards/p/PhenomenonInvestigators.java b/Mage.Sets/src/mage/cards/p/PhenomenonInvestigators.java index 366fe7c8fa9..2170f980cb3 100644 --- a/Mage.Sets/src/mage/cards/p/PhenomenonInvestigators.java +++ b/Mage.Sets/src/mage/cards/p/PhenomenonInvestigators.java @@ -1,23 +1,21 @@ package mage.cards.p; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.DiesCreatureTriggeredAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; -import mage.constants.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterNonlandPermanent; @@ -27,6 +25,8 @@ import mage.game.permanent.token.HorrorEnchantmentCreatureToken; import mage.players.Player; import mage.target.TargetPermanent; +import java.util.UUID; + /** * @author Cguy7777 */ @@ -41,28 +41,23 @@ public final class PhenomenonInvestigators extends CardImpl { this.toughness = new MageInt(4); // As Phenomenon Investigators enters, choose Believe or Doubt. - this.addAbility(new AsEntersBattlefieldAbility( - new ChooseModeEffect("Believe or Doubt?", "Believe", "Doubt"))); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.BELIEVE, ModeChoice.DOUBT))); // * Believe -- Whenever a nontoken creature you control dies, create a 2/2 black Horror enchantment creature token. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( new DiesCreatureTriggeredAbility( new CreateTokenEffect(new HorrorEnchantmentCreatureToken()), - false, - StaticFilters.FILTER_CONTROLLED_CREATURE_NON_TOKEN), - new ModeChoiceSourceCondition("Believe"), - "&bull Believe — Whenever a nontoken creature you control dies, " + - "create a 2/2 black Horror enchantment creature token.")); + false, StaticFilters.FILTER_CONTROLLED_CREATURE_NON_TOKEN + ), ModeChoice.BELIEVE + ))); // * Doubt -- At the beginning of your end step, you may return a nonland permanent you own to your hand. If you do, draw a card. - this.addAbility(new ConditionalTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - new DoIfCostPaid( - new DrawCardSourceControllerEffect(1), - new PhenomenonInvestigatorsReturnCost())), - new ModeChoiceSourceCondition("Doubt"), - "&bull Doubt — At the beginning of your end step, you may return a nonland permanent " + - "you own to your hand. If you do, draw a card.")); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( + new BeginningOfEndStepTriggeredAbility(new DoIfCostPaid( + new DrawCardSourceControllerEffect(1), + new PhenomenonInvestigatorsReturnCost() + )), ModeChoice.DOUBT + ))); } private PhenomenonInvestigators(final PhenomenonInvestigators card) { diff --git a/Mage.Sets/src/mage/cards/r/RootsOfLife.java b/Mage.Sets/src/mage/cards/r/RootsOfLife.java index facf5d46af3..933133ec13b 100644 --- a/Mage.Sets/src/mage/cards/r/RootsOfLife.java +++ b/Mage.Sets/src/mage/cards/r/RootsOfLife.java @@ -1,57 +1,44 @@ package mage.cards.r; -import java.util.UUID; +import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.BecomesTappedTriggeredAbility; -import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.ChooseModeEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ModeChoice; import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.FilterPermanent; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; /** - * * @author fubs */ public final class RootsOfLife extends CardImpl { - private static final String ruleTrigger1 = "&bull Island — Whenever an Island an opponent controls becomes tapped, you gain 1 life"; - private static final String ruleTrigger2 = "&bull Swamp — Whenever a Swamp an opponent controls becomes tapped, you gain 1 life"; - - private static final FilterPermanent islandFilter = new FilterPermanent("an Island an opponent controls"); - private static final FilterPermanent swampFilter = new FilterPermanent("a Swamp an opponent controls"); + private static final FilterPermanent filter = new FilterLandPermanent("a land of the chosen type an opponent controls"); static { - islandFilter.add(SubType.ISLAND.getPredicate()); - islandFilter.add(TargetController.OPPONENT.getControllerPredicate()); - swampFilter.add(SubType.SWAMP.getPredicate()); - swampFilter.add(TargetController.OPPONENT.getControllerPredicate()); + filter.add(TargetController.OPPONENT.getControllerPredicate()); + filter.add(RootsOfLifePredicate.instance); } public RootsOfLife(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}{G}"); // As Roots of Life enters the battlefield, choose Island or Swamp. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Island or Swamp?", "Island", "Swamp"), null, - "As {this} enters, choose Island or Swamp.", "")); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.ISLAND, ModeChoice.SWAMP))); // Whenever a land of the chosen type an opponent controls becomes tapped, you gain 1 life. - // * Island chosen - this.addAbility(new ConditionalTriggeredAbility( - new BecomesTappedTriggeredAbility(new GainLifeEffect(1), false, islandFilter), - new ModeChoiceSourceCondition("Island"), - ruleTrigger1)); - - // * Swamp chosen - this.addAbility(new ConditionalTriggeredAbility( - new BecomesTappedTriggeredAbility(new GainLifeEffect(1), false, swampFilter), - new ModeChoiceSourceCondition("Swamp"), - ruleTrigger2)); + this.addAbility(new BecomesTappedTriggeredAbility(new GainLifeEffect(1), false, filter)); } private RootsOfLife(final RootsOfLife card) { @@ -63,3 +50,18 @@ public final class RootsOfLife extends CardImpl { return new RootsOfLife(this); } } + +enum RootsOfLifePredicate implements ObjectSourcePlayerPredicate { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + if (ModeChoice.ISLAND.checkMode(game, input.getSource())) { + return input.getObject().hasSubtype(SubType.ISLAND, game); + } else if (ModeChoice.SWAMP.checkMode(game, input.getSource())) { + return input.getObject().hasSubtype(SubType.SWAMP, game); + } else { + return false; + } + } +} diff --git a/Mage.Sets/src/mage/cards/s/StruggleForProjectPurity.java b/Mage.Sets/src/mage/cards/s/StruggleForProjectPurity.java index 1599ab4bb2c..5a46b36aeb4 100644 --- a/Mage.Sets/src/mage/cards/s/StruggleForProjectPurity.java +++ b/Mage.Sets/src/mage/cards/s/StruggleForProjectPurity.java @@ -2,18 +2,19 @@ package mage.cards.s; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.condition.common.ModeChoiceSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ChooseModeEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ModeChoice; import mage.constants.Outcome; import mage.constants.Zone; import mage.counters.CounterType; @@ -34,29 +35,21 @@ import java.util.stream.Collectors; */ public final class StruggleForProjectPurity extends CardImpl { - private static final String ruleTrigger1 = "&bull Brotherhood — At the beginning of your upkeep, each opponent draws a card. You draw a card for each card drawn this way."; - private static final String ruleTrigger2 = "&bull Enclave — Whenever a player attacks you with one or more creatures, that player gets twice that many rad counters."; - public StruggleForProjectPurity(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}"); // As Struggle for Project Purity enters, choose Brotherhood or Enclave. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Brotherhood or Enclave?", "Brotherhood", "Enclave"), null, - "As {this} enters, choose Brotherhood or Enclave.", "")); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.BROTHERHOOD, ModeChoice.ENCLAVE))); // * Brotherhood - At the beginning of your upkeep, each opponent draws a card. You draw a card for each card drawn this way. - Ability ability = new ConditionalTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new StruggleForProjectDrawEffect()), - new ModeChoiceSourceCondition("Brotherhood"), - ruleTrigger1); - this.addAbility(ability); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( + new BeginningOfUpkeepTriggeredAbility(new StruggleForProjectDrawEffect()), ModeChoice.BROTHERHOOD + ))); // * Enclave - Whenever a player attacks you with one or more creatures, that player gets twice that many rad counters. - ability = new ConditionalTriggeredAbility( - new StruggleForProjectRadCountersTriggeredAbility(), - new ModeChoiceSourceCondition("Enclave"), - ruleTrigger2); - this.addAbility(ability); + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( + new StruggleForProjectRadCountersTriggeredAbility(), ModeChoice.ENCLAVE + ))); } private StruggleForProjectPurity(final StruggleForProjectPurity card) { diff --git a/Mage.Sets/src/mage/cards/w/WindcragSiege.java b/Mage.Sets/src/mage/cards/w/WindcragSiege.java new file mode 100644 index 00000000000..dac881a8419 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WindcragSiege.java @@ -0,0 +1,87 @@ +package mage.cards.w; + +import mage.abilities.Ability; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseModeEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect; +import mage.abilities.effects.common.replacement.AdditionalTriggersAttackingReplacementEffect; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.ModeChoice; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.token.GoblinToken; +import mage.game.permanent.token.Token; +import mage.target.targetpointer.FixedTargets; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WindcragSiege extends CardImpl { + + public WindcragSiege(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{W}"); + + // As this enchantment enters, choose Mardu or Jeskai. + this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.MARDU, ModeChoice.JESKAI))); + + // * Mardu -- If a creature attacking causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( + new AdditionalTriggersAttackingReplacementEffect(false), ModeChoice.MARDU + ))); + + // * Jeskai -- At the beginning of your upkeep, create a 1/1 red Goblin creature token. It gains lifelink and haste until end of turn. + this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect( + new BeginningOfUpkeepTriggeredAbility(new WindcragSiegeEffect()), ModeChoice.JESKAI + ))); + } + + private WindcragSiege(final WindcragSiege card) { + super(card); + } + + @Override + public WindcragSiege copy() { + return new WindcragSiege(this); + } +} + +class WindcragSiegeEffect extends OneShotEffect { + + WindcragSiegeEffect() { + super(Outcome.Benefit); + staticText = "create a 1/1 red Goblin creature token. It gains lifelink and haste until end of turn"; + } + + private WindcragSiegeEffect(final WindcragSiegeEffect effect) { + super(effect); + } + + @Override + public WindcragSiegeEffect copy() { + return new WindcragSiegeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Token token = new GoblinToken(); + token.putOntoBattlefield(1, game, source); + game.addEffect(new GainAbilityTargetEffect( + LifelinkAbility.getInstance(), Duration.EndOfTurn + ).setTargetPointer(new FixedTargets(token, game)), source); + game.addEffect(new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setTargetPointer(new FixedTargets(token, game)), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/w/WulfgarOfIcewindDale.java b/Mage.Sets/src/mage/cards/w/WulfgarOfIcewindDale.java index 6b4c622c27d..798da523453 100644 --- a/Mage.Sets/src/mage/cards/w/WulfgarOfIcewindDale.java +++ b/Mage.Sets/src/mage/cards/w/WulfgarOfIcewindDale.java @@ -1,19 +1,14 @@ package mage.cards.w; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.replacement.AdditionalTriggersAttackingReplacementEffect; import mage.abilities.keyword.MeleeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Controllable; -import mage.game.Game; -import mage.game.events.DefenderAttackedEvent; -import mage.game.events.GameEvent; -import mage.game.events.NumberOfTriggersEvent; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; import java.util.UUID; @@ -35,7 +30,7 @@ public final class WulfgarOfIcewindDale extends CardImpl { this.addAbility(new MeleeAbility()); // If a creature you control attacking would cause a triggered ability of a permanent you control to trigger, that ability triggers an additional time. - this.addAbility(new SimpleStaticAbility(new WulfgarOfIcewindDaleEffect())); + this.addAbility(new SimpleStaticAbility(new AdditionalTriggersAttackingReplacementEffect(true))); } private WulfgarOfIcewindDale(final WulfgarOfIcewindDale card) { @@ -47,64 +42,3 @@ public final class WulfgarOfIcewindDale extends CardImpl { return new WulfgarOfIcewindDale(this); } } - -class WulfgarOfIcewindDaleEffect extends ReplacementEffectImpl { - - WulfgarOfIcewindDaleEffect() { - super(Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "if a creature you control attacking causes a triggered ability " + - "of a permanent you control to trigger, that ability triggers an additional time"; - } - - private WulfgarOfIcewindDaleEffect(final WulfgarOfIcewindDaleEffect effect) { - super(effect); - } - - @Override - public WulfgarOfIcewindDaleEffect copy() { - return new WulfgarOfIcewindDaleEffect(this); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.NUMBER_OF_TRIGGERS; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event; - Permanent sourcePermanent = game.getPermanent(numberOfTriggersEvent.getSourceId()); - if (sourcePermanent == null || !sourcePermanent.isControlledBy(source.getControllerId())) { - return false; - } - GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); - if (sourceEvent == null) { - return false; - } - - switch (sourceEvent.getType()) { - case ATTACKER_DECLARED: - return source.isControlledBy(sourceEvent.getPlayerId()); - case DECLARED_ATTACKERS: - return game - .getCombat() - .getAttackers() - .stream() - .map(game::getControllerId) - .anyMatch(source::isControlledBy); - case DEFENDER_ATTACKED: - return ((DefenderAttackedEvent) sourceEvent) - .getAttackers(game) - .stream() - .map(Controllable::getControllerId) - .anyMatch(source::isControlledBy); - } - return false; - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - event.setAmount(event.getAmount() + 1); - return false; - } -} diff --git a/Mage.Sets/src/mage/sets/TarkirDragonstorm.java b/Mage.Sets/src/mage/sets/TarkirDragonstorm.java index e9e25436f1b..74b45fe1e2d 100644 --- a/Mage.Sets/src/mage/sets/TarkirDragonstorm.java +++ b/Mage.Sets/src/mage/sets/TarkirDragonstorm.java @@ -274,6 +274,7 @@ public final class TarkirDragonstorm extends ExpansionSet { cards.add(new SetCardInfo("Whirlwing Stormbrood", 234, Rarity.UNCOMMON, mage.cards.w.WhirlwingStormbrood.class)); cards.add(new SetCardInfo("Wild Ride", 132, Rarity.COMMON, mage.cards.w.WildRide.class)); cards.add(new SetCardInfo("Wind-Scarred Crag", 271, Rarity.COMMON, mage.cards.w.WindScarredCrag.class)); + cards.add(new SetCardInfo("Windcrag Siege", 235, Rarity.RARE, mage.cards.w.WindcragSiege.class)); cards.add(new SetCardInfo("Wingblade Disciple", 65, Rarity.UNCOMMON, mage.cards.w.WingbladeDisciple.class)); cards.add(new SetCardInfo("Wingspan Stride", 66, Rarity.COMMON, mage.cards.w.WingspanStride.class)); cards.add(new SetCardInfo("Winternight Stories", 67, Rarity.RARE, mage.cards.w.WinternightStories.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/c19/PramikonSkyRampartTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/c19/PramikonSkyRampartTest.java index f51b08d613c..8e5f1b9cc16 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/c19/PramikonSkyRampartTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/c19/PramikonSkyRampartTest.java @@ -1,10 +1,6 @@ package org.mage.test.cards.single.c19; -import mage.abilities.effects.common.continuous.PlayerCanOnlyAttackInDirectionRestrictionEffect; -import mage.constants.MultiplayerAttackOption; -import mage.constants.PhaseStep; -import mage.constants.RangeOfInfluence; -import mage.constants.Zone; +import mage.constants.*; import mage.game.FreeForAll; import mage.game.Game; import mage.game.GameException; @@ -63,7 +59,7 @@ public class PramikonSkyRampartTest extends CardTestMultiPlayerBase { addCard(Zone.BATTLEFIELD, playerD, devil); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, pramikon); - setChoice(playerA, PlayerCanOnlyAttackInDirectionRestrictionEffect.ALLOW_ATTACKING_LEFT); + setChoice(playerA, ModeChoice.LEFT.toString()); // A has pramikon, and chose left. // @@ -128,7 +124,7 @@ public class PramikonSkyRampartTest extends CardTestMultiPlayerBase { addCard(Zone.BATTLEFIELD, playerD, devil); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, pramikon); - setChoice(playerA, PlayerCanOnlyAttackInDirectionRestrictionEffect.ALLOW_ATTACKING_RIGHT); + setChoice(playerA, ModeChoice.RIGHT.toString()); // A has pramikon, and chose right. // @@ -197,10 +193,10 @@ public class PramikonSkyRampartTest extends CardTestMultiPlayerBase { addCard(Zone.BATTLEFIELD, playerD, devil); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, pramikon); - setChoice(playerA, PlayerCanOnlyAttackInDirectionRestrictionEffect.ALLOW_ATTACKING_RIGHT); + setChoice(playerA, ModeChoice.RIGHT.toString()); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, pramikon); - setChoice(playerD, PlayerCanOnlyAttackInDirectionRestrictionEffect.ALLOW_ATTACKING_LEFT); + setChoice(playerD, ModeChoice.LEFT.toString()); // A has pramikon, and chose right. // D has pramikon, and chose left. @@ -270,10 +266,10 @@ public class PramikonSkyRampartTest extends CardTestMultiPlayerBase { addCard(Zone.BATTLEFIELD, playerD, devil); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, pramikon); - setChoice(playerA, PlayerCanOnlyAttackInDirectionRestrictionEffect.ALLOW_ATTACKING_LEFT); + setChoice(playerA, ModeChoice.LEFT.toString()); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, pramikon); - setChoice(playerD, PlayerCanOnlyAttackInDirectionRestrictionEffect.ALLOW_ATTACKING_RIGHT); + setChoice(playerD, ModeChoice.RIGHT.toString()); // A has pramikon, and chose left. // D has pramikon, and chose right. @@ -323,4 +319,4 @@ public class PramikonSkyRampartTest extends CardTestMultiPlayerBase { setStopAt(5, PhaseStep.END_TURN); execute(); } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/condition/common/ModeChoiceSourceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/ModeChoiceSourceCondition.java deleted file mode 100644 index 8ce77f24633..00000000000 --- a/Mage/src/main/java/mage/abilities/condition/common/ModeChoiceSourceCondition.java +++ /dev/null @@ -1,26 +0,0 @@ - -package mage.abilities.condition.common; - -import mage.abilities.Ability; -import mage.abilities.condition.Condition; -import mage.game.Game; - -/** - * - * @author LevelX2 - */ -public class ModeChoiceSourceCondition implements Condition { - - private final String mode; - - - public ModeChoiceSourceCondition(String mode) { - this.mode = mode; - } - - @Override - public boolean apply(Game game, Ability source) { - String chosenMode = (String) game.getState().getValue(source.getSourceId() + "_modeChoice"); - return chosenMode != null && chosenMode.equals(mode); - } -} diff --git a/Mage/src/main/java/mage/abilities/effects/common/ChooseModeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ChooseModeEffect.java index 5ca8e531c68..978e0cb8f2e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ChooseModeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ChooseModeEffect.java @@ -1,39 +1,41 @@ package mage.abilities.effects.common; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.choices.Choice; import mage.choices.ChoiceImpl; +import mage.constants.ModeChoice; import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.util.CardUtil; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + /** * @author LevelX2 */ public class ChooseModeEffect extends OneShotEffect { - protected final List modes = new ArrayList<>(); - protected final String choiceMessage; + protected final List modes = new ArrayList<>(); + protected final String message; - public ChooseModeEffect(String choiceMessage, String... modes) { + public ChooseModeEffect(ModeChoice... modes) { super(Outcome.Neutral); - this.choiceMessage = choiceMessage; this.modes.addAll(Arrays.asList(modes)); - this.staticText = setText(); + this.message = makeMessage(this.modes); + this.staticText = "choose " + this.message; } protected ChooseModeEffect(final ChooseModeEffect effect) { super(effect); this.modes.addAll(effect.modes); - this.choiceMessage = effect.choiceMessage; + this.message = effect.message; } @Override @@ -48,34 +50,27 @@ public class ChooseModeEffect extends OneShotEffect { if (sourcePermanent == null) { sourcePermanent = game.getPermanentEntering(source.getSourceId()); } - if (controller != null && sourcePermanent != null) { - Choice choice = new ChoiceImpl(true); - choice.setMessage(choiceMessage + CardUtil.getSourceLogName(game, source)); - choice.getChoices().addAll(modes); - if (controller.choose(Outcome.Neutral, choice, game)) { - if (!game.isSimulation()) { - game.informPlayers(sourcePermanent.getLogName() + ": " + controller.getLogName() + " has chosen " + choice.getChoice()); - } - game.getState().setValue(source.getSourceId() + "_modeChoice", choice.getChoice()); - sourcePermanent.addInfo("_modeChoice", "Chosen mode: " + choice.getChoice() + "", game); - return true; - } + if (controller == null || sourcePermanent == null) { + return false; } - return false; + Choice choice = new ChoiceImpl(true); + choice.setMessage(message + "? (" + CardUtil.getSourceLogName(game, source) + ')'); + choice.getChoices().addAll(modes.stream().map(ModeChoice::toString).collect(Collectors.toList())); + if (!controller.choose(Outcome.Neutral, choice, game)) { + return false; + } + game.informPlayers(sourcePermanent.getLogName() + ": " + controller.getLogName() + " has chosen " + choice.getChoice()); + game.getState().setValue(source.getSourceId() + "_modeChoice", choice.getChoice()); + sourcePermanent.addInfo("_modeChoice", "Chosen mode: " + choice.getChoice() + "", game); + return true; } - private String setText() { - StringBuilder sb = new StringBuilder("choose "); - int count = 0; - for (String choice : modes) { - count++; - sb.append(choice); - if (count + 1 < modes.size()) { - sb.append(", "); - } else if (count < modes.size()) { - sb.append(" or "); - } - } - return sb.toString(); + private static String makeMessage(List modeChoices) { + return CardUtil.concatWithOr( + modeChoices + .stream() + .map(ModeChoice::toString) + .collect(Collectors.toList()) + ); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/PermanentsEnterBattlefieldTappedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PermanentsEnterBattlefieldTappedEffect.java index e9d949ac4ec..7eb63a0be7f 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PermanentsEnterBattlefieldTappedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PermanentsEnterBattlefieldTappedEffect.java @@ -63,7 +63,7 @@ public class PermanentsEnterBattlefieldTappedEffect extends ReplacementEffectImp return staticText; } return filter.getMessage() - + " enter tapped" - + (duration == Duration.EndOfTurn ? " this turn" : ""); + + " enter" + (filter.getMessage().startsWith("each") ? "s" : "") + + " tapped" + (duration == Duration.EndOfTurn ? " this turn" : ""); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAnchorWordAbilitySourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAnchorWordAbilitySourceEffect.java new file mode 100644 index 00000000000..f4af6963691 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAnchorWordAbilitySourceEffect.java @@ -0,0 +1,52 @@ +package mage.abilities.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.Effect; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author TheElk801 + */ +public class GainAnchorWordAbilitySourceEffect extends ContinuousEffectImpl { + + private final Ability ability; + private final ModeChoice modeChoice; + + public GainAnchorWordAbilitySourceEffect(Effect effect, ModeChoice modeChoice) { + this(new SimpleStaticAbility(effect), modeChoice); + } + + public GainAnchorWordAbilitySourceEffect(Ability ability, ModeChoice modeChoice) { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + this.staticText = "&bull " + modeChoice + " — " + ability.getRule(); + this.ability = ability; + this.modeChoice = modeChoice; + this.ability.setRuleVisible(false); + this.generateGainAbilityDependencies(ability, null); + } + + private GainAnchorWordAbilitySourceEffect(final GainAnchorWordAbilitySourceEffect effect) { + super(effect); + this.modeChoice = effect.modeChoice; + this.ability = effect.ability; + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null || !modeChoice.checkMode(game, source)) { + return false; + } + permanent.addAbility(ability, source.getSourceId(), game); + return true; + } + + @Override + public GainAnchorWordAbilitySourceEffect copy() { + return new GainAnchorWordAbilitySourceEffect(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayerCanOnlyAttackInDirectionRestrictionEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayerCanOnlyAttackInDirectionRestrictionEffect.java index b74ab65717c..8aaefded6da 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayerCanOnlyAttackInDirectionRestrictionEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayerCanOnlyAttackInDirectionRestrictionEffect.java @@ -6,6 +6,7 @@ import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.common.ChooseModeEffect; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.ModeChoice; import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; @@ -19,9 +20,6 @@ import java.util.UUID; */ public class PlayerCanOnlyAttackInDirectionRestrictionEffect extends RestrictionEffect { - public static final String ALLOW_ATTACKING_LEFT = "Allow attacking left"; - public static final String ALLOW_ATTACKING_RIGHT = "Allow attacking right"; - public PlayerCanOnlyAttackInDirectionRestrictionEffect(Duration duration, String directionText) { super(duration, Outcome.Neutral); staticText = duration + (duration.toString().isEmpty() ? "" : ", ") @@ -39,10 +37,7 @@ public class PlayerCanOnlyAttackInDirectionRestrictionEffect extends Restriction } public static Effect choiceEffect() { - return new ChooseModeEffect( - "Choose a direction to allow attacking in.", - ALLOW_ATTACKING_LEFT, ALLOW_ATTACKING_RIGHT - ).setText("choose left or right"); + return new ChooseModeEffect(ModeChoice.LEFT, ModeChoice.RIGHT); } @Override @@ -55,10 +50,13 @@ public class PlayerCanOnlyAttackInDirectionRestrictionEffect extends Restriction if (defenderId == null) { return true; } - - String allowedDirection = (String) game.getState().getValue(source.getSourceId() + "_modeChoice"); - if (allowedDirection == null) { - return true; // If no choice was made, the ability has no effect. + boolean left; + if (ModeChoice.LEFT.checkMode(game, source)) { + left = true; + } else if (ModeChoice.RIGHT.checkMode(game, source)) { + left = false; + } else { + return false; // If no choice was made, the ability has no effect. } Player playerAttacking = game.getPlayer(attacker.getControllerId()); @@ -83,18 +81,7 @@ public class PlayerCanOnlyAttackInDirectionRestrictionEffect extends Restriction } PlayerList playerList = game.getState().getPlayerList(playerAttacking.getId()); - if (allowedDirection.equals(ALLOW_ATTACKING_LEFT) - && !playerList.getNext().equals(playerDefending.getId())) { - // the defender is not the player to the left - return false; - } - if (allowedDirection.equals(ALLOW_ATTACKING_RIGHT) - && !playerList.getPrevious().equals(playerDefending.getId())) { - // the defender is not the player to the right - return false; - } - - return true; + return (!left || playerList.getNext().equals(playerDefending.getId())) + && (left || playerList.getPrevious().equals(playerDefending.getId())); } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/replacement/AdditionalTriggersAttackingReplacementEffect.java b/Mage/src/main/java/mage/abilities/effects/common/replacement/AdditionalTriggersAttackingReplacementEffect.java new file mode 100644 index 00000000000..85516648f74 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/replacement/AdditionalTriggersAttackingReplacementEffect.java @@ -0,0 +1,80 @@ +package mage.abilities.effects.common.replacement; + +import mage.abilities.Ability; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Controllable; +import mage.game.Game; +import mage.game.events.DefenderAttackedEvent; +import mage.game.events.GameEvent; +import mage.game.events.NumberOfTriggersEvent; +import mage.game.permanent.Permanent; + +/** + * @author TheElk801 + */ +public class AdditionalTriggersAttackingReplacementEffect extends ReplacementEffectImpl { + + private final boolean onlyControlled; + + public AdditionalTriggersAttackingReplacementEffect(boolean onlyControlled) { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + this.onlyControlled = onlyControlled; + staticText = "if a creature " + (onlyControlled ? "you control " : "") + "attacking causes a triggered ability " + + "of a permanent you control to trigger, that ability triggers an additional time"; + } + + private AdditionalTriggersAttackingReplacementEffect(final AdditionalTriggersAttackingReplacementEffect effect) { + super(effect); + this.onlyControlled = effect.onlyControlled; + } + + @Override + public AdditionalTriggersAttackingReplacementEffect copy() { + return new AdditionalTriggersAttackingReplacementEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.NUMBER_OF_TRIGGERS; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event; + Permanent sourcePermanent = game.getPermanent(numberOfTriggersEvent.getSourceId()); + if (sourcePermanent == null || !sourcePermanent.isControlledBy(source.getControllerId())) { + return false; + } + GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); + if (sourceEvent == null) { + return false; + } + + switch (sourceEvent.getType()) { + case ATTACKER_DECLARED: + return !onlyControlled || source.isControlledBy(sourceEvent.getPlayerId()); + case DECLARED_ATTACKERS: + return !onlyControlled || game + .getCombat() + .getAttackers() + .stream() + .map(game::getControllerId) + .anyMatch(source::isControlledBy); + case DEFENDER_ATTACKED: + return !onlyControlled || ((DefenderAttackedEvent) sourceEvent) + .getAttackers(game) + .stream() + .map(Controllable::getControllerId) + .anyMatch(source::isControlledBy); + } + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + event.setAmount(event.getAmount() + 1); + return false; + } +} diff --git a/Mage/src/main/java/mage/constants/ModeChoice.java b/Mage/src/main/java/mage/constants/ModeChoice.java new file mode 100644 index 00000000000..1759d2dece8 --- /dev/null +++ b/Mage/src/main/java/mage/constants/ModeChoice.java @@ -0,0 +1,75 @@ +package mage.constants; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.game.Game; + +import java.util.Objects; + +public enum ModeChoice { + + KHANS("Khans"), + DRAGONS("Dragons"), + + MARDU("Mardu"), + TEMUR("Temur"), + ABZAN("Abzan"), + JESKAI("Jeskai"), + SULTAI("Sultai"), + + MIRRAN("Mirran"), + PHYREXIAN("Phyrexian "), + + ODD("odd"), + EVEN("even"), + + BELIEVE("Believe"), + DOUBT("Doubt"), + + NCR("NCR"), + LEGION("Legion"), + + BROTHERHOOD("Brotherhood"), + ENCLAVE("Enclave"), + + ISLAND("Island"), + SWAMP("Swamp"), + + LEFT("left"), + RIGHT("right"); + + private static class ModeChoiceCondition implements Condition { + + private final ModeChoice modeChoice; + + ModeChoiceCondition(ModeChoice modeChoice) { + this.modeChoice = modeChoice; + } + + @Override + public boolean apply(Game game, Ability source) { + return modeChoice.checkMode(game, source); + } + } + + private final String name; + private final ModeChoiceCondition condition; + + ModeChoice(String name) { + this.name = name; + this.condition = new ModeChoiceCondition(this); + } + + @Override + public String toString() { + return name; + } + + public ModeChoiceCondition getCondition() { + return condition; + } + + public boolean checkMode(Game game, Ability source) { + return Objects.equals(game.getState().getValue(source.getSourceId() + "_modeChoice"), name); + } +}