Rework implementation of anchor words (#13518)

* refactor anchor word implementation

* fix error

* [TDM] Implement Windcrag Siege
This commit is contained in:
Evan Kranzler 2025-04-09 13:24:57 -04:00 committed by GitHub
parent 3c6e055f41
commit 56a05a7843
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 610 additions and 638 deletions

View file

@ -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. <i>(Zero is even.)</i>", ""));
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<Permanent> {
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<Permanent> 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);
}
}

View file

@ -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 &mdash; 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 &mdash; 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) {

View file

@ -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 &mdash; 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 &mdash; 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) {

View file

@ -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 &mdash; 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 &mdash; 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<Permanent> {
instance;
@Override
public boolean apply(Permanent input, Game game) {
return input.getControllerId().equals(game.getActivePlayerId());
}
}

View file

@ -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 &mdash; At the beginning of each of your main phases, add {G}{G}.";
private static final String ruleTrigger2 = "&bull Dragons &mdash; 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) {

View file

@ -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 = "&bull; Jeskai &mdash; 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"),
"&bull; Temur &mdash; 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) {

View file

@ -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"),
"&bull; Temur &mdash; 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("&bull; Sultai &mdash; You may play lands from your graveyard.")
));
this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(
PlayFromGraveyardControllerEffect.playLands(), ModeChoice.SULTAI
)));
}
private GlacierwoodSiege(final GlacierwoodSiege card) {

View file

@ -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;
}
}

View file

@ -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. <i>(Zero is even.)</i>"
));
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);
}

View file

@ -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 &mdash; Whenever you cast an artifact spell, " +
"create a 1/1 colorless Myr artifact creature token.";
private static final String ruleTrigger2 = "&bull Phyrexian &mdash; 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) {

View file

@ -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"),
"&bull; Khans &mdash; 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 = "&bull; Dragons &mdash; 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;
}

View file

@ -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 &mdash; 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 &mdash; 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) {

View file

@ -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 &mdash; At the beginning of your upkeep, return target creature card from your graveyard to your hand.";
private static final String ruleTrigger2 = "&bull Dragons &mdash; 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)));
}

View file

@ -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 &mdash; 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 &mdash; 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) {

View file

@ -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 &mdash; Whenever an Island an opponent controls becomes tapped, you gain 1 life";
private static final String ruleTrigger2 = "&bull Swamp &mdash; 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<Permanent> {
instance;
@Override
public boolean apply(ObjectSourcePlayer<Permanent> 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;
}
}
}

View file

@ -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 &mdash; 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 &mdash; 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) {

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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));

View file

@ -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.

View file

@ -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);
}
}

View file

@ -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<String> modes = new ArrayList<>();
protected final String choiceMessage;
protected final List<ModeChoice> 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", "<font color = 'blue'>Chosen mode: " + choice.getChoice() + "</font>", 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", "<font color = 'blue'>Chosen mode: " + choice.getChoice() + "</font>", 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<ModeChoice> modeChoices) {
return CardUtil.concatWithOr(
modeChoices
.stream()
.map(ModeChoice::toString)
.collect(Collectors.toList())
);
}
}

View file

@ -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" : "");
}
}

View file

@ -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 + " &mdash; " + 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);
}
}

View file

@ -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()));
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}