mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
Cost reduction effects - refactor, removed redundant custom effects, added card hints;
This commit is contained in:
parent
e4ebf50d42
commit
cf3feff76a
35 changed files with 506 additions and 643 deletions
|
@ -1,31 +1,25 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.DiesTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.AttackingCreatureCount;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.CostModificationType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.AttackingPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.StoneTrapIdolToken;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AncientStoneIdol extends CardImpl {
|
||||
|
@ -41,7 +35,10 @@ public final class AncientStoneIdol extends CardImpl {
|
|||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// This spell costs {1} less to cast for each attacking creature.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AncientStoneIdolCostReductionEffect()));
|
||||
DynamicValue xValue = new AttackingCreatureCount();
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue))
|
||||
.addHint(new ValueHint("Attacking creatures", xValue))
|
||||
);
|
||||
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
@ -59,41 +56,3 @@ public final class AncientStoneIdol extends CardImpl {
|
|||
return new AncientStoneIdol(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AncientStoneIdolCostReductionEffect extends CostModificationEffectImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
|
||||
static {
|
||||
filter.add(AttackingPredicate.instance);
|
||||
}
|
||||
|
||||
public AncientStoneIdolCostReductionEffect() {
|
||||
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
staticText = "This spell costs {1} less to cast for each attacking creature";
|
||||
}
|
||||
|
||||
protected AncientStoneIdolCostReductionEffect(AncientStoneIdolCostReductionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
int reductionAmount = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
|
||||
CardUtil.reduceCost(abilityToModify, reductionAmount);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if ((abilityToModify instanceof SpellAbility) && abilityToModify.getSourceId().equals(source.getSourceId())) {
|
||||
return game.getCard(abilityToModify.getSourceId()) != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AncientStoneIdolCostReductionEffect copy() {
|
||||
return new AncientStoneIdolCostReductionEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,9 @@ import mage.MageInt;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.dynamicvalue.common.OpponentsCount;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionSourceForOpponentsEffect;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
@ -35,7 +36,8 @@ public final class AvatarOfGrowth extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// This spell costs {1} less to cast for each opponent you have.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceForOpponentsEffect("This spell costs {1} less to cast for each opponent you have")));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, OpponentsCount.instance)
|
||||
.setText("This spell costs {1} less to cast for each opponent you have")));
|
||||
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
|
@ -8,7 +7,7 @@ import mage.abilities.common.SimpleStaticAbility;
|
|||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.effects.common.discard.DiscardHandControllerEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.keyword.ProwessAbility;
|
||||
|
@ -26,27 +25,25 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class BedlamReveler extends CardImpl {
|
||||
|
||||
private static final DynamicValue cardsCount = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY);
|
||||
|
||||
public BedlamReveler(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{R}{R}");
|
||||
this.subtype.add(SubType.DEVIL, SubType.HORROR);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Bedlam Reveler costs {1} less to cast for each instant or sorcery card in your graveyard.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY)
|
||||
).addHint(new ValueHint("Instant and sorcery cards in your graveyard", cardsCount)));
|
||||
// This spell costs {1} less to cast for each instant and sorcery card in your graveyard.
|
||||
DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY);
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
|
||||
ability.setRuleAtTheTop(true);
|
||||
ability.addHint(new ValueHint("Instant or sourcery card in your graveyard", xValue));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Prowess
|
||||
this.addAbility(new ProwessAbility());
|
||||
|
||||
// When Bedlam Reveler enters the battlefield, discard your hand, then draw three cards.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(
|
||||
new DiscardHandControllerEffect().setText("discard your hand,")
|
||||
);
|
||||
ability.addEffect(new DrawCardSourceControllerEffect(3).setText("then draw three cards"));
|
||||
ability = new EntersBattlefieldTriggeredAbility(new DiscardHandControllerEffect());
|
||||
ability.addEffect(new DrawCardSourceControllerEffect(3).concatBy(", then"));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -21,8 +20,13 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class BrineGiant extends CardImpl {
|
||||
|
||||
private static final DynamicValue xValue
|
||||
= new PermanentsOnBattlefieldCount(BrineGiantCostReductionEffect.filter);
|
||||
static final FilterControlledPermanent filter = new FilterControlledPermanent("enchantment you control");
|
||||
|
||||
static {
|
||||
filter.add(CardType.ENCHANTMENT.getPredicate());
|
||||
}
|
||||
|
||||
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
|
||||
|
||||
public BrineGiant(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{U}");
|
||||
|
@ -33,7 +37,7 @@ public final class BrineGiant extends CardImpl {
|
|||
|
||||
// This spell costs {1} less to cast for each enchantment you control.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
Zone.ALL, new BrineGiantCostReductionEffect()
|
||||
Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue)
|
||||
).addHint(new ValueHint("Enchantments you control", xValue)));
|
||||
}
|
||||
|
||||
|
@ -45,39 +49,4 @@ public final class BrineGiant extends CardImpl {
|
|||
public BrineGiant copy() {
|
||||
return new BrineGiant(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BrineGiantCostReductionEffect extends CostModificationEffectImpl {
|
||||
|
||||
static final FilterControlledPermanent filter = new FilterControlledPermanent();
|
||||
|
||||
static {
|
||||
filter.add(CardType.ENCHANTMENT.getPredicate());
|
||||
}
|
||||
|
||||
BrineGiantCostReductionEffect() {
|
||||
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
staticText = "This spell costs {1} less to cast for each enchantment you control";
|
||||
}
|
||||
|
||||
private BrineGiantCostReductionEffect(final BrineGiantCostReductionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
int count = game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game).size();
|
||||
CardUtil.reduceCost(abilityToModify, count);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
return abilityToModify.getSourceId().equals(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrineGiantCostReductionEffect copy() {
|
||||
return new BrineGiantCostReductionEffect(this);
|
||||
}
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||
import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
@ -12,7 +13,6 @@ import mage.constants.CardType;
|
|||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -21,8 +21,6 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class CrypticSerpent extends CardImpl {
|
||||
|
||||
private static final DynamicValue cardsCount = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY);
|
||||
|
||||
public CrypticSerpent(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}");
|
||||
|
||||
|
@ -31,8 +29,11 @@ public final class CrypticSerpent extends CardImpl {
|
|||
this.toughness = new MageInt(5);
|
||||
|
||||
// Cryptic Serpent costs {1} less to cast for each instant and sorcery card in your graveyard.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(new FilterInstantOrSorceryCard()))
|
||||
.addHint(new ValueHint("Instant and sorcery card in your graveyard", cardsCount)));
|
||||
DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY);
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
|
||||
ability.setRuleAtTheTop(true);
|
||||
ability.addHint(new ValueHint("Instant and sorcery card in your graveyard", xValue));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
public CrypticSerpent(final CrypticSerpent card) {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.d;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
|
@ -10,21 +8,22 @@ import mage.abilities.keyword.EnchantAbility;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author maxlebedev
|
||||
*/
|
||||
public final class DreamLeash extends CardImpl {
|
||||
|
||||
public DreamLeash(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{U}{U}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}");
|
||||
this.subtype.add(SubType.AURA);
|
||||
|
||||
// Enchant permanent
|
||||
|
@ -55,7 +54,7 @@ class DreamLeashTarget extends TargetPermanent {
|
|||
@Override
|
||||
public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
|
||||
|
||||
if(super.canTarget(controllerId, id, source, game)){
|
||||
if (super.canTarget(controllerId, id, source, game)) {
|
||||
Permanent permanent = game.getPermanent(id);
|
||||
return permanent.isTapped();
|
||||
}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
package mage.cards.e;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.AttackingCreatureCount;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.keyword.DoubleStrikeAbility;
|
||||
import mage.abilities.keyword.EquipAbility;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
|
@ -15,12 +17,8 @@ import mage.abilities.keyword.TrampleAbility;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.AttackingPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -39,7 +37,10 @@ public final class Embercleave extends CardImpl {
|
|||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// This spell costs {1} less to cast for each attacking creature you control.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new EmbercleaveCostReductionEffect()));
|
||||
DynamicValue xValue = new AttackingCreatureCount(StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED);
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL,
|
||||
new SpellCostReductionForEachSourceEffect(1, xValue)
|
||||
).addHint(new ValueHint("Attacking creature you control", xValue)));
|
||||
|
||||
// When Embercleave enters the battlefield, attach it to target creature you control.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new AttachEffect(
|
||||
|
@ -71,41 +72,3 @@ public final class Embercleave extends CardImpl {
|
|||
return new Embercleave(this);
|
||||
}
|
||||
}
|
||||
|
||||
class EmbercleaveCostReductionEffect extends CostModificationEffectImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
|
||||
|
||||
static {
|
||||
filter.add(AttackingPredicate.instance);
|
||||
}
|
||||
|
||||
EmbercleaveCostReductionEffect() {
|
||||
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
staticText = "This spell costs {1} less to cast for each attacking creature you control";
|
||||
}
|
||||
|
||||
private EmbercleaveCostReductionEffect(EmbercleaveCostReductionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
int reductionAmount = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
|
||||
CardUtil.reduceCost(abilityToModify, reductionAmount);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if ((abilityToModify instanceof SpellAbility) && abilityToModify.getSourceId().equals(source.getSourceId())) {
|
||||
return game.getCard(abilityToModify.getSourceId()) != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbercleaveCostReductionEffect copy() {
|
||||
return new EmbercleaveCostReductionEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,21 +2,21 @@ package mage.cards.e;
|
|||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.common.ArtifactYouControlHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -35,7 +35,9 @@ public final class EmryLurkerOfTheLoch extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// This spell costs {1} less to cast for each artifact you control.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new EmryLurkerOfTheLochCostReductionEffect()));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL,
|
||||
new SpellCostReductionForEachSourceEffect(1, ArtifactYouControlCount.instance)
|
||||
).addHint(ArtifactYouControlHint.instance));
|
||||
|
||||
// When Emry, Lurker of the Loch enters the battlefield, put the top four cards of your library into your graveyard.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(
|
||||
|
@ -58,40 +60,6 @@ public final class EmryLurkerOfTheLoch extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class EmryLurkerOfTheLochCostReductionEffect extends CostModificationEffectImpl {
|
||||
|
||||
EmryLurkerOfTheLochCostReductionEffect() {
|
||||
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
staticText = "This spell costs {1} less to cast for each artifact you control";
|
||||
}
|
||||
|
||||
private EmryLurkerOfTheLochCostReductionEffect(final EmryLurkerOfTheLochCostReductionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
int reductionAmount = game.getBattlefield().count(
|
||||
StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT,
|
||||
source.getSourceId(), source.getControllerId(), game
|
||||
);
|
||||
CardUtil.reduceCost(abilityToModify, reductionAmount);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
return abilityToModify instanceof SpellAbility
|
||||
&& abilityToModify.getSourceId().equals(source.getSourceId())
|
||||
&& game.getCard(abilityToModify.getSourceId()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmryLurkerOfTheLochCostReductionEffect copy() {
|
||||
return new EmryLurkerOfTheLochCostReductionEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
class EmryLurkerOfTheLochPlayEffect extends AsThoughEffectImpl {
|
||||
|
||||
EmryLurkerOfTheLochPlayEffect() {
|
||||
|
|
|
@ -1,28 +1,26 @@
|
|||
|
||||
package mage.cards.f;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.common.AttackingFilterCreatureCount;
|
||||
import mage.abilities.dynamicvalue.common.AttackingCreatureCount;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetOpponent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class FoulTongueShriek extends CardImpl {
|
||||
|
||||
public FoulTongueShriek(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
|
||||
|
||||
// Target opponent loses 1 life for each attacking creature you control. You gain that much life.
|
||||
this.getSpellAbility().addEffect(new FoulTongueShriekEffect());
|
||||
|
@ -41,12 +39,7 @@ public final class FoulTongueShriek extends CardImpl {
|
|||
}
|
||||
|
||||
class FoulTongueShriekEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
static {
|
||||
filter.add(TargetController.YOU.getControllerPredicate());
|
||||
}
|
||||
|
||||
|
||||
public FoulTongueShriekEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "Target opponent loses 1 life for each attacking creature you control. You gain that much life";
|
||||
|
@ -66,7 +59,7 @@ class FoulTongueShriekEffect extends OneShotEffect {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player targetOpponent = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (controller != null && targetOpponent != null) {
|
||||
int amount = new AttackingFilterCreatureCount(filter).calculate(game, source, this);
|
||||
int amount = new AttackingCreatureCount(StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED).calculate(game, source, this);
|
||||
if (amount > 0) {
|
||||
targetOpponent.loseLife(amount, game, false);
|
||||
controller.gainLife(amount, game, source);
|
||||
|
|
|
@ -5,9 +5,11 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
|
||||
import mage.abilities.common.SimpleEvasionAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.dynamicvalue.common.GateYouControlCount;
|
||||
import mage.abilities.effects.common.PutOnLibrarySourceEffect;
|
||||
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.common.GateYouControlHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
@ -39,8 +41,10 @@ public final class GateColossus extends CardImpl {
|
|||
this.toughness = new MageInt(8);
|
||||
|
||||
// This spell costs {1} less to cast for each Gate you control.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new GateColossusCostReductionEffect())
|
||||
.addHint(GateYouControlHint.instance));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL,
|
||||
new SpellCostReductionForEachSourceEffect(1, GateYouControlCount.instance))
|
||||
.addHint(GateYouControlHint.instance)
|
||||
);
|
||||
|
||||
// Gate Colossus can't be blocked by creatures with power 2 or less.
|
||||
this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield)));
|
||||
|
|
|
@ -29,7 +29,7 @@ public final class GatekeeperGargoyle extends CardImpl {
|
|||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Gargoyle Guardian enters the battlefield with a +1/+1 counter on it for each Gate you control.
|
||||
// Gatekeeper Gargoyle enters the battlefield with a +1/+1 counter on it for each Gate you control.
|
||||
this.addAbility(new EntersBattlefieldAbility(
|
||||
new AddCountersSourceEffect(
|
||||
CounterType.P1P1.createInstance(),
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
package mage.cards.g;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
|
||||
import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.common.ArtifactYouControlHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.util.CardUtil;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -28,7 +29,9 @@ public final class GearseekerSerpent extends CardImpl {
|
|||
this.toughness = new MageInt(6);
|
||||
|
||||
// Gearseeker Serpent costs {1} less to cast for each artifact you control
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new GearseekerSerpentCostReductionEffect()));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL,
|
||||
new SpellCostReductionForEachSourceEffect(1, ArtifactYouControlCount.instance)
|
||||
).addHint(ArtifactYouControlHint.instance));
|
||||
|
||||
// 5U: Gearseeker Serpent can't be blocked this turn.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
|
@ -45,38 +48,3 @@ public final class GearseekerSerpent extends CardImpl {
|
|||
return new GearseekerSerpent(this);
|
||||
}
|
||||
}
|
||||
|
||||
class GearseekerSerpentCostReductionEffect extends CostModificationEffectImpl {
|
||||
|
||||
private static final FilterControlledPermanent filter = new FilterControlledPermanent();
|
||||
|
||||
static {
|
||||
filter.add(CardType.ARTIFACT.getPredicate());
|
||||
}
|
||||
|
||||
public GearseekerSerpentCostReductionEffect() {
|
||||
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
staticText = "This spell costs {1} less to cast for each artifact you control";
|
||||
}
|
||||
|
||||
protected GearseekerSerpentCostReductionEffect(final GearseekerSerpentCostReductionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
int count = game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game).size();
|
||||
CardUtil.reduceCost(abilityToModify, count);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
return abilityToModify.getSourceId().equals(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public GearseekerSerpentCostReductionEffect copy() {
|
||||
return new GearseekerSerpentCostReductionEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package mage.cards.g;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
@ -11,8 +14,9 @@ import mage.constants.SubType;
|
|||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author North
|
||||
*/
|
||||
public final class Ghoultree extends CardImpl {
|
||||
|
@ -26,7 +30,11 @@ public final class Ghoultree extends CardImpl {
|
|||
this.toughness = new MageInt(10);
|
||||
|
||||
// Ghoultree costs {1} less to cast for each creature card in your graveyard.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(StaticFilters.FILTER_CARD_CREATURE)));
|
||||
DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE);
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
|
||||
ability.setRuleAtTheTop(true);
|
||||
ability.addHint(new ValueHint("Creature card in your graveyard", xValue));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
public Ghoultree(final Ghoultree card) {
|
||||
|
|
|
@ -29,10 +29,7 @@ public final class GlaiveOfTheGuildpact extends CardImpl {
|
|||
this.subtype.add(SubType.EQUIPMENT);
|
||||
|
||||
// Equipped creature gets +1/+0 for each Gate you control and has vigilance and menace.
|
||||
Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(
|
||||
GateYouControlCount.instance,
|
||||
StaticValue.get(0)
|
||||
).setText("Equipped creature gets +1/+0 for each Gate you control"));
|
||||
Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(GateYouControlCount.instance, StaticValue.get(0)));
|
||||
ability.addEffect(new GainAbilityAttachedEffect(
|
||||
VigilanceAbility.getInstance(), AttachmentType.EQUIPMENT
|
||||
).setText("and has vigilance"));
|
||||
|
|
|
@ -13,7 +13,7 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -25,13 +25,14 @@ public final class HoldTheGates extends CardImpl {
|
|||
public HoldTheGates(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
|
||||
|
||||
|
||||
// Creatures you control get +0/+1 for each Gate you control and have vigilance.
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||
new BoostControlledEffect(StaticValue.get(0), GateYouControlCount.instance, Duration.WhileOnBattlefield)
|
||||
.setText("Creatures you control get +0/+1 for each Gate you control "));
|
||||
ability.addEffect(new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield, new FilterControlledCreaturePermanent("Creatures"))
|
||||
.setText("and have vigilance"));
|
||||
);
|
||||
ability.addEffect(
|
||||
new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED)
|
||||
.setText("and have vigilance")
|
||||
);
|
||||
ability.addHint(GateYouControlHint.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
|
@ -1,48 +1,52 @@
|
|||
|
||||
package mage.cards.k;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author maurer.it_at_gmail.com
|
||||
*/
|
||||
public final class KhalniHydra extends CardImpl {
|
||||
|
||||
private static final FilterControlledCreaturePermanent filter;
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("green creature you control");
|
||||
|
||||
static {
|
||||
filter = new FilterControlledCreaturePermanent();
|
||||
filter.add(new ColorPredicate(ObjectColor.GREEN));
|
||||
}
|
||||
|
||||
public KhalniHydra(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{G}{G}{G}{G}{G}{G}{G}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}{G}{G}{G}{G}{G}{G}");
|
||||
this.subtype.add(SubType.HYDRA);
|
||||
|
||||
this.power = new MageInt(8);
|
||||
this.toughness = new MageInt(8);
|
||||
|
||||
|
||||
// This spell costs {G} less to cast for each green creature you control.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new KhalniHydraCostReductionEffect()));
|
||||
|
||||
ManaCosts<ManaCost> manaReduce = new ManaCostsImpl<>("{G}");
|
||||
DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL,
|
||||
new SpellCostReductionForEachSourceEffect(manaReduce, xValue))
|
||||
.addHint(new ValueHint("Green creature you control", xValue))
|
||||
);
|
||||
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
}
|
||||
|
@ -51,47 +55,8 @@ public final class KhalniHydra extends CardImpl {
|
|||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
super.adjustCosts(ability, game);
|
||||
int reductionAmount = game.getBattlefield().count(filter, ability.getSourceId(), ability.getControllerId(), game);
|
||||
Iterator<ManaCost> iter = ability.getManaCostsToPay().iterator();
|
||||
|
||||
while ( reductionAmount > 0 && iter.hasNext() ) {
|
||||
ManaCost manaCostEntry = iter.next();
|
||||
if (manaCostEntry.getMana().getGreen() > 0) { // in case another effect adds additional mana cost
|
||||
iter.remove();
|
||||
reductionAmount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public KhalniHydra copy() {
|
||||
return new KhalniHydra(this);
|
||||
}
|
||||
}
|
||||
|
||||
class KhalniHydraCostReductionEffect extends OneShotEffect {
|
||||
private static final String effectText = "{this} costs {G} less to cast for each green creature you control";
|
||||
|
||||
KhalniHydraCostReductionEffect ( ) {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = effectText;
|
||||
}
|
||||
|
||||
KhalniHydraCostReductionEffect ( KhalniHydraCostReductionEffect effect ) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KhalniHydraCostReductionEffect copy() {
|
||||
return new KhalniHydraCostReductionEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,25 +1,28 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterLandCard;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class Molderhulk extends CardImpl {
|
||||
|
@ -36,8 +39,11 @@ public final class Molderhulk extends CardImpl {
|
|||
this.toughness = new MageInt(6);
|
||||
|
||||
// Undergrowth — This spell costs {1} less to cast for each creature card in your graveyard.
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(StaticFilters.FILTER_CARD_CREATURE));
|
||||
DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE);
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
|
||||
ability.setAbilityWord(AbilityWord.UNDERGROWTH);
|
||||
ability.setRuleAtTheTop(true);
|
||||
ability.addHint(new ValueHint("Creature card in your graveyard", xValue));
|
||||
this.addAbility(ability);
|
||||
|
||||
// When Molderhulk enters the battlefield, return target land card from your graveyard to the battlefield.
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package mage.cards.n;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.keyword.MonstrosityAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
@ -16,6 +18,8 @@ import mage.game.Game;
|
|||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
@ -29,8 +33,10 @@ public final class NemesisOfMortals extends CardImpl {
|
|||
this.toughness = new MageInt(5);
|
||||
|
||||
// Nemesis of Mortals costs {1} less to cast for each creature card in your graveyard.
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(StaticFilters.FILTER_CARD_CREATURE));
|
||||
DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE);
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
|
||||
ability.setRuleAtTheTop(true);
|
||||
ability.addHint(new ValueHint("Creature card in your graveyard", xValue));
|
||||
this.addAbility(ability);
|
||||
|
||||
// {7}{G}{G}: Monstrosity 5. This ability costs {1} less to activate for each creature card in your graveyard.
|
||||
|
|
|
@ -3,7 +3,10 @@ package mage.cards.o;
|
|||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -28,10 +31,10 @@ public final class OreScaleGuardian extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// This spell costs {1} less to cast for each land card in your graveyard.
|
||||
Ability ability = new SimpleStaticAbility(
|
||||
Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(StaticFilters.FILTER_CARD_LAND)
|
||||
);
|
||||
DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_LAND);
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
|
||||
ability.setRuleAtTheTop(true);
|
||||
ability.addHint(new ValueHint("Land card in your graveyard", xValue));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Flying
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
|
||||
import mage.abilities.common.DiesCreatureTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.common.PayLifeCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||
import mage.abilities.effects.common.PutOnLibraryTargetEffect;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -34,7 +34,11 @@ public final class TheCauldronOfEternity extends CardImpl {
|
|||
this.addSuperType(SuperType.LEGENDARY);
|
||||
|
||||
// This spell costs {2} less to cast for each creature card in your graveyard.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new TheCauldronOfEternityCostReductionEffect()));
|
||||
DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE);
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(2, xValue));
|
||||
ability.setRuleAtTheTop(true);
|
||||
ability.addHint(new ValueHint("Creature card in your graveyard", xValue));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Whenever a creature you control dies, put it on the bottom of its owner's library.
|
||||
this.addAbility(new DiesCreatureTriggeredAbility(
|
||||
|
@ -43,7 +47,7 @@ public final class TheCauldronOfEternity extends CardImpl {
|
|||
));
|
||||
|
||||
// {2}{B}, {T}, Pay 2 life: Return target creature card from your graveyard to the battlefield. Activate this ability only any time you could cast a sorcery.
|
||||
Ability ability = new ActivateAsSorceryActivatedAbility(
|
||||
ability = new ActivateAsSorceryActivatedAbility(
|
||||
Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), new ManaCostsImpl("{2}{B}")
|
||||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
|
@ -61,44 +65,3 @@ public final class TheCauldronOfEternity extends CardImpl {
|
|||
return new TheCauldronOfEternity(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TheCauldronOfEternityCostReductionEffect extends CostModificationEffectImpl {
|
||||
|
||||
TheCauldronOfEternityCostReductionEffect() {
|
||||
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
staticText = "This spell costs {2} less to cast for each creature card in your graveyard";
|
||||
}
|
||||
|
||||
private TheCauldronOfEternityCostReductionEffect(final TheCauldronOfEternityCostReductionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
int reductionAmount = player
|
||||
.getGraveyard()
|
||||
.getCards(game)
|
||||
.stream()
|
||||
.filter(MageObject::isCreature)
|
||||
.mapToInt(card -> 2)
|
||||
.sum();
|
||||
CardUtil.reduceCost(abilityToModify, reductionAmount);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
return abilityToModify instanceof SpellAbility
|
||||
&& abilityToModify.getSourceId().equals(source.getSourceId())
|
||||
&& game.getCard(abilityToModify.getSourceId()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheCauldronOfEternityCostReductionEffect copy() {
|
||||
return new TheCauldronOfEternityCostReductionEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.KnightToken;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -27,10 +26,16 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class TheCircleOfLoyalty extends CardImpl {
|
||||
|
||||
private static final FilterSpell filter = new FilterSpell("a legendary spell");
|
||||
private static final FilterSpell filterLegendary = new FilterSpell("a legendary spell");
|
||||
|
||||
static {
|
||||
filter.add(SuperType.LEGENDARY.getPredicate());
|
||||
filterLegendary.add(SuperType.LEGENDARY.getPredicate());
|
||||
}
|
||||
|
||||
static final FilterControlledPermanent filterKnight = new FilterControlledPermanent("Knight you control");
|
||||
|
||||
static {
|
||||
filterKnight.add(SubType.KNIGHT.getPredicate());
|
||||
}
|
||||
|
||||
public TheCircleOfLoyalty(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
@ -39,7 +44,10 @@ public final class TheCircleOfLoyalty extends CardImpl {
|
|||
this.addSuperType(SuperType.LEGENDARY);
|
||||
|
||||
// This spell costs {1} less to cast for each Knight you control.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new TheCircleOfLoyaltyCostReductionEffect()));
|
||||
DynamicValue xValue = new PermanentsOnBattlefieldCount(filterKnight);
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue)
|
||||
).addHint(new ValueHint("Knight you control", xValue)));
|
||||
|
||||
// Creatures you control get +1/+1.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
|
@ -48,7 +56,7 @@ public final class TheCircleOfLoyalty extends CardImpl {
|
|||
|
||||
// Whenever you cast a legendary spell, create a 2/2 white Knight creature token with vigilance.
|
||||
this.addAbility(new SpellCastControllerTriggeredAbility(
|
||||
new CreateTokenEffect(new KnightToken()), filter, false
|
||||
new CreateTokenEffect(new KnightToken()), filterLegendary, false
|
||||
));
|
||||
|
||||
// {3}{W}, {T}: Create a 2/2 white Knight creature token with vigilance.
|
||||
|
@ -67,37 +75,4 @@ public final class TheCircleOfLoyalty extends CardImpl {
|
|||
public TheCircleOfLoyalty copy() {
|
||||
return new TheCircleOfLoyalty(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TheCircleOfLoyaltyCostReductionEffect extends CostModificationEffectImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterControlledPermanent(SubType.KNIGHT);
|
||||
|
||||
TheCircleOfLoyaltyCostReductionEffect() {
|
||||
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
staticText = "This spell costs {1} less to cast for each Knight you control";
|
||||
}
|
||||
|
||||
private TheCircleOfLoyaltyCostReductionEffect(final TheCircleOfLoyaltyCostReductionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
int reductionAmount = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
|
||||
CardUtil.reduceCost(abilityToModify, reductionAmount);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
return abilityToModify instanceof SpellAbility
|
||||
&& abilityToModify.getSourceId().equals(source.getSourceId())
|
||||
&& game.getCard(abilityToModify.getSourceId()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheCircleOfLoyaltyCostReductionEffect copy() {
|
||||
return new TheCircleOfLoyaltyCostReductionEffect(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,11 +4,13 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect;
|
||||
import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
|
@ -30,10 +32,11 @@ public final class TheMagicMirror extends CardImpl {
|
|||
this.addSuperType(SuperType.LEGENDARY);
|
||||
|
||||
// This spell costs {1} less to cast for each instant and sorcery card in your graveyard.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(
|
||||
StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY
|
||||
)).setRuleAtTheTop(true));
|
||||
DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY);
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
|
||||
ability.setRuleAtTheTop(true);
|
||||
ability.addHint(new ValueHint("Instant and sorcery card in your graveyard", xValue));
|
||||
this.addAbility(ability);
|
||||
|
||||
// You have no maximum hand size.
|
||||
this.addAbility(new SimpleStaticAbility(new MaximumHandSizeControllerEffect(
|
||||
|
@ -42,7 +45,7 @@ public final class TheMagicMirror extends CardImpl {
|
|||
)));
|
||||
|
||||
// At the beginning of your upkeep, put a knowledge counter on The Magic Mirror, then draw a card for each knowledge counter on The Magic Mirror.
|
||||
Ability ability = new BeginningOfUpkeepTriggeredAbility(
|
||||
ability = new BeginningOfUpkeepTriggeredAbility(
|
||||
new AddCountersSourceEffect(CounterType.KNOWLEDGE.createInstance())
|
||||
.setText("put a knowledge counter on {this},"),
|
||||
TargetController.YOU, false
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.t;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
|
@ -13,21 +11,16 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.CostModificationType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class TorgaarFamineIncarnate extends CardImpl {
|
||||
|
@ -107,8 +100,16 @@ class TorgaarFamineIncarnateEffectCostReductionEffect extends CostModificationEf
|
|||
SpellAbility spellAbility = (SpellAbility) abilityToModify;
|
||||
for (Cost cost : spellAbility.getCosts()) {
|
||||
if (cost instanceof SacrificeXTargetCost) {
|
||||
int reduction = ((SacrificeXTargetCost) cost).getAmount();
|
||||
CardUtil.adjustCost(spellAbility, reduction * 2);
|
||||
if (game.inCheckPlayableState()) {
|
||||
// allows to cast in getPlayable
|
||||
int reduction = ((SacrificeXTargetCost) cost).getMaxValue(spellAbility, game);
|
||||
CardUtil.adjustCost(spellAbility, reduction * 2);
|
||||
} else {
|
||||
// real cast
|
||||
int reduction = ((SacrificeXTargetCost) cost).getAmount();
|
||||
CardUtil.adjustCost(spellAbility, reduction * 2);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
package org.mage.test.cards.cost.modification;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBaseWithAIHelps;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class CostReduceForEachTest extends CardTestPlayerBaseWithAIHelps {
|
||||
|
||||
@Test
|
||||
public void test_AncientStoneIdol_Attacking() {
|
||||
// {10}
|
||||
// Flash
|
||||
// This spell costs {1} less to cast for each attacking creature.
|
||||
addCard(Zone.HAND, playerA, "Ancient Stone Idol", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 10 - 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 2); // give 2 cost reduction
|
||||
|
||||
// before
|
||||
checkPlayableAbility("before attack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Ancient Stone Idol", false);
|
||||
|
||||
// prepare for attack
|
||||
attack(1, playerA, "Balduvian Bears");
|
||||
attack(1, playerA, "Balduvian Bears");
|
||||
|
||||
// on attack
|
||||
checkPlayableAbility("on attack", 1, PhaseStep.DECLARE_BLOCKERS, playerA, "Cast Ancient Stone Idol", true);
|
||||
castSpell(1, PhaseStep.DECLARE_BLOCKERS, playerA, "Ancient Stone Idol");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Ancient Stone Idol", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_AncientStoneIdol_AttackingWithSacrifice() {
|
||||
// The total cost to cast a spell is locked in before you pay that cost. For example, if you control five attacking
|
||||
// creatures, including one you can sacrifice to add {C} to your mana pool, Ancient Stone Idol costs {5} to cast.
|
||||
// Then you can sacrifice the creature when you activate mana abilities just before paying the cost, and it still
|
||||
// costs only {5} to cast.
|
||||
// (2018-07-13)
|
||||
|
||||
// {10}
|
||||
// Flash
|
||||
// This spell costs {1} less to cast for each attacking creature.
|
||||
addCard(Zone.HAND, playerA, "Ancient Stone Idol", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 10 - 4);
|
||||
//
|
||||
// Sacrifice Blood Pet: Add {B}.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Blood Pet", 2); // give 2 cost reduction + can be sacrificed as 2 mana
|
||||
|
||||
// before
|
||||
checkPlayableAbility("before attack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Ancient Stone Idol", false);
|
||||
|
||||
// prepare for attack
|
||||
attack(1, playerA, "Blood Pet");
|
||||
attack(1, playerA, "Blood Pet");
|
||||
|
||||
// on attack (must automaticly sacrifice creatures as mana pay)
|
||||
checkPlayableAbility("on attack", 1, PhaseStep.DECLARE_BLOCKERS, playerA, "Cast Ancient Stone Idol", true);
|
||||
castSpell(1, PhaseStep.DECLARE_BLOCKERS, playerA, "Ancient Stone Idol");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Ancient Stone Idol", 1);
|
||||
assertGraveyardCount(playerA, "Blood Pet", 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_KhalniHydra_ColorReduce() {
|
||||
// {G}{G}{G}{G}{G}{G}{G}{G}
|
||||
// This spell costs {G} less to cast for each green creature you control.
|
||||
addCard(Zone.HAND, playerA, "Khalni Hydra", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 8 - 2);
|
||||
addCard(Zone.HAND, playerA, "Balduvian Bears", 2); // give 2 cost reduction
|
||||
|
||||
checkPlayableAbility("no cost reduction 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Khalni Hydra", false);
|
||||
|
||||
// prepare creatures for reduce
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
checkPlayableAbility("no cost reduction 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Khalni Hydra", false);
|
||||
|
||||
// can cast on next turn
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Khalni Hydra");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Khalni Hydra", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_TorgaarFamineIncarnate_SacrificeXTargets() {
|
||||
// {6}{B}{B}
|
||||
// As an additional cost to cast this spell, you may sacrifice any number of creatures.
|
||||
// This spell costs {2} less to cast for each creature sacrificed this way.
|
||||
// When Torgaar, Famine Incarnate enters the battlefield, up to one target player's life total becomes half their starting life total, rounded down.
|
||||
addCard(Zone.HAND, playerA, "Torgaar, Famine Incarnate", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8 - 4 - 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
addCard(Zone.HAND, playerA, "Balduvian Bears", 2); // give 4 cost reduction on sacrifice
|
||||
|
||||
checkPlayableAbility("no cost reduction 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Torgaar, Famine Incarnate", false);
|
||||
|
||||
// prepare creatures for reduce
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
checkPlayableAbility("no cost reduction 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Torgaar, Famine Incarnate", false);
|
||||
|
||||
// can cast on next turn
|
||||
checkPlayableAbility("must reduce", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Torgaar, Famine Incarnate", true);
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Torgaar, Famine Incarnate");
|
||||
setChoice(playerA, "X=2"); // two creatures sacrifice
|
||||
setChoice(playerA, "Balduvian Bears");
|
||||
setChoice(playerA, "Balduvian Bears");
|
||||
addTarget(playerA, playerB); // target player for half life
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Torgaar, Famine Incarnate", 1);
|
||||
assertLife(playerB, 20 / 2);
|
||||
}
|
||||
}
|
|
@ -1663,16 +1663,20 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
|
||||
public void attack(int turnNum, TestPlayer player, String attacker) {
|
||||
//Assert.assertNotEquals("", attacker);
|
||||
assertAliaseSupportInActivateCommand(attacker, false); // it uses old special notation like card_name:index
|
||||
player.addAction(turnNum, PhaseStep.DECLARE_ATTACKERS, "attack:" + attacker);
|
||||
}
|
||||
|
||||
public void attack(int turnNum, TestPlayer player, String attacker, TestPlayer defendingPlayer) {
|
||||
//Assert.assertNotEquals("", attacker);
|
||||
assertAliaseSupportInActivateCommand(attacker, false); // it uses old special notation like card_name:index
|
||||
player.addAction(turnNum, PhaseStep.DECLARE_ATTACKERS, "attack:" + attacker + "$defendingPlayer=" + defendingPlayer.getName());
|
||||
}
|
||||
|
||||
public void attack(int turnNum, TestPlayer player, String attacker, String planeswalker) {
|
||||
//Assert.assertNotEquals("", attacker);
|
||||
assertAliaseSupportInActivateCommand(attacker, false); // it uses old special notation like card_name:index
|
||||
assertAliaseSupportInActivateCommand(planeswalker, false);
|
||||
player.addAction(turnNum, PhaseStep.DECLARE_ATTACKERS, new StringBuilder("attack:").append(attacker).append("$planeswalker=").append(planeswalker).toString());
|
||||
}
|
||||
|
||||
|
@ -1683,6 +1687,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
public void block(int turnNum, TestPlayer player, String blocker, String attacker) {
|
||||
//Assert.assertNotEquals("", blocker);
|
||||
//Assert.assertNotEquals("", attacker);
|
||||
assertAliaseSupportInActivateCommand(blocker, false); // it uses old special notation like card_name:index
|
||||
assertAliaseSupportInActivateCommand(attacker, false);
|
||||
player.addAction(turnNum, PhaseStep.DECLARE_BLOCKERS, "block:" + blocker + '$' + attacker);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,38 +1,60 @@
|
|||
|
||||
package mage.abilities.dynamicvalue.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.combat.CombatGroup;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class AttackingCreatureCount implements DynamicValue {
|
||||
|
||||
private String message;
|
||||
private FilterCreaturePermanent filter;
|
||||
|
||||
public AttackingCreatureCount() {
|
||||
this("attacking creature");
|
||||
}
|
||||
|
||||
public AttackingCreatureCount(FilterCreaturePermanent filter) {
|
||||
this(filter, "attacking " + filter.getMessage());
|
||||
}
|
||||
|
||||
public AttackingCreatureCount(String message) {
|
||||
this(null, message);
|
||||
}
|
||||
|
||||
public AttackingCreatureCount(FilterCreaturePermanent filter, String message) {
|
||||
this.message = message;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public AttackingCreatureCount(final AttackingCreatureCount dynamicValue) {
|
||||
super();
|
||||
this.message = dynamicValue.message;
|
||||
this.filter = dynamicValue.filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
int count = 0;
|
||||
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
|
||||
count += combatGroup.getAttackers().size();
|
||||
for (UUID permId : combatGroup.getAttackers()) {
|
||||
if (filter != null) {
|
||||
Permanent attacker = game.getPermanent(permId);
|
||||
if (attacker != null && filter.match(attacker, sourceAbility.getSourceId(), sourceAbility.getControllerId(), game)) {
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
|
||||
package mage.abilities.dynamicvalue.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.combat.CombatGroup;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
|
||||
*/
|
||||
public class AttackingFilterCreatureCount implements DynamicValue {
|
||||
|
||||
private FilterCreaturePermanent filter;
|
||||
private String message;
|
||||
|
||||
public AttackingFilterCreatureCount(FilterCreaturePermanent filter) {
|
||||
this(filter, "attacking creature");
|
||||
}
|
||||
|
||||
public AttackingFilterCreatureCount(FilterCreaturePermanent filter, String message) {
|
||||
this.filter = filter;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public AttackingFilterCreatureCount(final AttackingFilterCreatureCount dynamicValue) {
|
||||
super();
|
||||
this.message = dynamicValue.message;
|
||||
this.filter = dynamicValue.filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
int count = 0;
|
||||
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
|
||||
for (UUID permId : combatGroup.getAttackers()) {
|
||||
Permanent attacker = game.getPermanent(permId);
|
||||
if (filter.match(attacker, sourceAbility.getSourceId(), sourceAbility.getControllerId(), game)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttackingFilterCreatureCount copy() {
|
||||
return new AttackingFilterCreatureCount(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "X";
|
||||
}
|
||||
}
|
|
@ -32,11 +32,11 @@ public enum GateYouControlCount implements DynamicValue {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "X";
|
||||
return "1"; // uses "for each" effects, so must be 1, not X
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "gate you control";
|
||||
return "Gate you control";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import java.util.Iterator;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
|
@ -16,8 +14,9 @@ import mage.filter.common.FilterCreaturePermanent;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class BoostControlledEffect extends ContinuousEffectImpl {
|
||||
|
@ -56,10 +55,10 @@ public class BoostControlledEffect extends ContinuousEffectImpl {
|
|||
* @param power
|
||||
* @param toughness
|
||||
* @param duration
|
||||
* @param filter AnotherPredicate is not working, you need to use the
|
||||
* excludeSource option
|
||||
* @param lockedIn if true, power and toughness will be calculated only
|
||||
* once, when the ability resolves
|
||||
* @param filter AnotherPredicate is not working, you need to use the
|
||||
* excludeSource option
|
||||
* @param lockedIn if true, power and toughness will be calculated only
|
||||
* once, when the ability resolves
|
||||
* @param excludeSource
|
||||
*/
|
||||
public BoostControlledEffect(DynamicValue power, DynamicValue toughness, Duration duration, FilterCreaturePermanent filter, boolean excludeSource, boolean lockedIn) {
|
||||
|
@ -105,7 +104,7 @@ public class BoostControlledEffect extends ContinuousEffectImpl {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
if (this.affectedObjectsSet) {
|
||||
for (Iterator<MageObjectReference> it = affectedObjectList.iterator(); it.hasNext();) {
|
||||
for (Iterator<MageObjectReference> it = affectedObjectList.iterator(); it.hasNext(); ) {
|
||||
Permanent permanent = it.next().getPermanent(game);
|
||||
if (permanent != null) {
|
||||
permanent.addPower(power.calculate(game, source, this));
|
||||
|
@ -126,7 +125,6 @@ public class BoostControlledEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
|
||||
private void setText() {
|
||||
String message = null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (excludeSource) {
|
||||
sb.append("other ");
|
||||
|
@ -150,6 +148,9 @@ public class BoostControlledEffect extends ContinuousEffectImpl {
|
|||
sb.append(t);
|
||||
|
||||
sb.append((duration == Duration.EndOfTurn ? " until end of turn" : ""));
|
||||
|
||||
// where X
|
||||
String message = null;
|
||||
if (t.equals("X")) {
|
||||
message = toughness.getMessage();
|
||||
} else if (p.equals("X")) {
|
||||
|
@ -158,6 +159,17 @@ public class BoostControlledEffect extends ContinuousEffectImpl {
|
|||
if (message != null && !message.isEmpty()) {
|
||||
sb.append(", where X is ").append(message);
|
||||
}
|
||||
|
||||
// for each
|
||||
if (message == null) {
|
||||
message = toughness.getMessage();
|
||||
if (message.isEmpty()) {
|
||||
message = power.getMessage();
|
||||
}
|
||||
if (!message.isEmpty()) {
|
||||
sb.append(" for each " + message);
|
||||
}
|
||||
}
|
||||
staticText = sb.toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,12 @@ import mage.game.Game;
|
|||
/**
|
||||
* Simple implementation of a {@link CostModificationEffect} offering simplified
|
||||
* construction to setup the object for use by the mage framework.
|
||||
* <p>
|
||||
* WARNING, if you implement custom effect and it can works on stack only (e.g. it need spell's targets to check) then
|
||||
* use different apply code:
|
||||
* - one for get playable mode before spell puts on stack (apply maximum possible cost reduction, use game.inCheckPlayableState()).
|
||||
* - one for normal mode after spell puts on stack (apply real cost reduction)
|
||||
* Example: TorgaarFamineIncarnate
|
||||
*
|
||||
* @author maurer.it_at_gmail.com
|
||||
*/
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
package mage.abilities.effects.common.cost;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.constants.CostModificationType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* @author Styxo
|
||||
*/
|
||||
public class SourceCostReductionForEachCardInGraveyardEffect extends CostModificationEffectImpl {
|
||||
|
||||
private FilterCard filter;
|
||||
|
||||
public SourceCostReductionForEachCardInGraveyardEffect() {
|
||||
this(StaticFilters.FILTER_CARD);
|
||||
}
|
||||
|
||||
public SourceCostReductionForEachCardInGraveyardEffect(FilterCard filter) {
|
||||
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
this.filter = filter;
|
||||
staticText = "{this} costs {1} less to cast for each " + filter.getMessage() + " in your graveyard";
|
||||
}
|
||||
|
||||
private SourceCostReductionForEachCardInGraveyardEffect(SourceCostReductionForEachCardInGraveyardEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
int reductionAmount = player.getGraveyard().count(filter, game);
|
||||
CardUtil.reduceCost(abilityToModify, reductionAmount);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if ((abilityToModify instanceof SpellAbility) && abilityToModify.getSourceId().equals(source.getSourceId())) {
|
||||
return game.getCard(abilityToModify.getSourceId()) != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceCostReductionForEachCardInGraveyardEffect copy() {
|
||||
return new SourceCostReductionForEachCardInGraveyardEffect(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package mage.abilities.effects.common.cost;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.constants.CostModificationType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class SpellCostReductionForEachSourceEffect extends CostModificationEffectImpl {
|
||||
|
||||
private final DynamicValue eachAmount;
|
||||
private ManaCosts<ManaCost> reduceManaCosts;
|
||||
private final int reduceGenericMana;
|
||||
|
||||
public SpellCostReductionForEachSourceEffect(int reduceGenericMana, DynamicValue eachAmount) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
this.eachAmount = eachAmount;
|
||||
this.reduceManaCosts = null;
|
||||
this.reduceGenericMana = reduceGenericMana;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("this spell costs {")
|
||||
.append(this.reduceGenericMana)
|
||||
.append("} less to cast for each ")
|
||||
.append(this.eachAmount.getMessage());
|
||||
this.staticText = sb.toString();
|
||||
}
|
||||
|
||||
public SpellCostReductionForEachSourceEffect(ManaCosts<ManaCost> reduceManaCosts, DynamicValue eachAmount) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
this.eachAmount = eachAmount;
|
||||
this.reduceManaCosts = reduceManaCosts;
|
||||
this.reduceGenericMana = 0;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("this spell costs ");
|
||||
for (String manaSymbol : reduceManaCosts.getSymbols()) {
|
||||
sb.append(manaSymbol);
|
||||
}
|
||||
sb.append(" less to cast for each ").append(this.eachAmount.getMessage());
|
||||
this.staticText = sb.toString();
|
||||
}
|
||||
|
||||
|
||||
protected SpellCostReductionForEachSourceEffect(final SpellCostReductionForEachSourceEffect effect) {
|
||||
super(effect);
|
||||
this.eachAmount = effect.eachAmount;
|
||||
this.reduceManaCosts = effect.reduceManaCosts;
|
||||
this.reduceGenericMana = effect.reduceGenericMana;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
int needReduceAmount = eachAmount.calculate(game, source, this);
|
||||
if (needReduceAmount > 0) {
|
||||
if (reduceManaCosts != null) {
|
||||
// color reduce
|
||||
ManaCosts<ManaCost> needReduceMana = new ManaCostsImpl<>();
|
||||
for (int i = 0; i <= needReduceAmount; i++) {
|
||||
needReduceMana.add(reduceManaCosts.copy());
|
||||
}
|
||||
CardUtil.adjustCost((SpellAbility) abilityToModify, needReduceMana, false);
|
||||
} else {
|
||||
// generic reduce
|
||||
CardUtil.reduceCost(abilityToModify, needReduceAmount * this.reduceGenericMana);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if (abilityToModify.getSourceId().equals(source.getSourceId()) && (abilityToModify instanceof SpellAbility)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellCostReductionForEachSourceEffect copy() {
|
||||
return new SpellCostReductionForEachSourceEffect(this);
|
||||
}
|
||||
}
|
|
@ -37,11 +37,10 @@ public class SpellCostReductionSourceEffect extends CostModificationEffectImpl {
|
|||
for (String manaSymbol : manaCostsToReduce.getSymbols()) {
|
||||
sb.append(manaSymbol);
|
||||
}
|
||||
sb.append(" less");
|
||||
sb.append(" less to cast");
|
||||
if (this.condition != null) {
|
||||
sb.append(" to if ").append(this.condition.toString());
|
||||
sb.append(" if ").append(this.condition.toString());
|
||||
}
|
||||
|
||||
this.staticText = sb.toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
package mage.abilities.effects.common.cost;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.constants.CostModificationType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
public class SpellCostReductionSourceForOpponentsEffect extends CostModificationEffectImpl {
|
||||
|
||||
public SpellCostReductionSourceForOpponentsEffect() {
|
||||
this("undaunted <i>(This spell costs {1} less to cast for each opponent.)</i>");
|
||||
}
|
||||
|
||||
public SpellCostReductionSourceForOpponentsEffect(String newStaticText) {
|
||||
super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
staticText = newStaticText;
|
||||
}
|
||||
|
||||
public SpellCostReductionSourceForOpponentsEffect(final SpellCostReductionSourceForOpponentsEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
int count = game.getOpponents(source.getControllerId()).size();
|
||||
CardUtil.reduceCost(abilityToModify, count);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
return abilityToModify instanceof SpellAbility && abilityToModify.getSourceId().equals(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellCostReductionSourceForOpponentsEffect copy() {
|
||||
return new SpellCostReductionSourceForOpponentsEffect(this);
|
||||
}
|
||||
}
|
|
@ -1,12 +1,8 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionSourceForOpponentsEffect;
|
||||
import mage.abilities.dynamicvalue.common.OpponentsCount;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
|
@ -15,7 +11,7 @@ import mage.constants.Zone;
|
|||
public class UndauntedAbility extends SimpleStaticAbility {
|
||||
|
||||
public UndauntedAbility() {
|
||||
super(Zone.ALL, new SpellCostReductionSourceForOpponentsEffect("undaunted <i>(This spell costs {1} less to cast for each opponent.)</i>"));
|
||||
super(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, OpponentsCount.instance));
|
||||
setRuleAtTheTop(true);
|
||||
}
|
||||
|
||||
|
@ -28,4 +24,8 @@ public class UndauntedAbility extends SimpleStaticAbility {
|
|||
return new UndauntedAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "undaunted <i>(This spell costs {1} less to cast for each opponent.)</i>";
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue