finished refactoring cost adjuster methods

This commit is contained in:
Evan Kranzler 2021-03-23 20:23:58 -04:00
parent 238509552c
commit bfd1a76bda
8 changed files with 224 additions and 240 deletions

View file

@ -2,16 +2,14 @@ package mage.cards.g;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.CostAdjuster;
import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect;
import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.util.CardUtil; import mage.util.CardUtil;
@ -29,35 +27,15 @@ public final class GhostfireBlade extends CardImpl {
this.subtype.add(SubType.EQUIPMENT); this.subtype.add(SubType.EQUIPMENT);
// Equipped creature gets +2/+2 // Equipped creature gets +2/+2
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2))); this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(2, 2)));
// Equip {3} // Equip {3}
this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(3))); // todo Ability ability = new EquipAbility(3);
ability.setCostAdjuster(GhostfireBladeAdjuster.instance);
this.addAbility(ability);
// Ghostfire Blade's equip ability costs {2} less to activate if it targets a colorless creature. // Ghostfire Blade's equip ability costs {2} less to activate if it targets a colorless creature.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("{this}'s equip ability costs {2} less to activate if it targets a colorless creature"))); this.addAbility(new SimpleStaticAbility(new InfoEffect("{this}'s equip ability costs {2} less to activate if it targets a colorless creature")));
}
@Override
public void adjustCosts(Ability ability, Game game) {
if (ability instanceof EquipAbility) {
if (game.inCheckPlayableState()) {
// checking state
boolean canSelectColorlessCreature = CardUtil.getAllPossibleTargets(ability, game).stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.anyMatch(permanent -> permanent.getColor(game).isColorless());
if (canSelectColorlessCreature) {
CardUtil.reduceCost(ability, 2);
}
} else {
// real cast state
Permanent targetCreature = game.getPermanent(ability.getTargets().getFirstTarget());
if (targetCreature != null && targetCreature.getColor(game).isColorless()) {
CardUtil.reduceCost(ability, 2);
}
}
}
} }
private GhostfireBlade(final GhostfireBlade card) { private GhostfireBlade(final GhostfireBlade card) {
@ -69,3 +47,28 @@ public final class GhostfireBlade extends CardImpl {
return new GhostfireBlade(this); return new GhostfireBlade(this);
} }
} }
enum GhostfireBladeAdjuster implements CostAdjuster {
instance;
@Override
public void adjustCosts(Ability ability, Game game) {
// checking state
if (game.inCheckPlayableState()) {
if (CardUtil
.getAllPossibleTargets(ability, game)
.stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.noneMatch(permanent -> permanent.getColor(game).isColorless())) {
return;
}
} else {
Permanent permanent = game.getPermanent(ability.getFirstTarget());
if (permanent == null || !permanent.getColor(game).isColorless()) {
return;
}
}
CardUtil.reduceCost(ability, 2);
}
}

View file

@ -1,10 +1,9 @@
package mage.cards.k; package mage.cards.k;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost; import mage.abilities.costs.Cost;
import mage.abilities.costs.CostAdjuster;
import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.dynamicvalue.common.ManacostVariableValue;
@ -17,11 +16,12 @@ import mage.constants.Zone;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.game.Game; import mage.game.Game;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetAnyTarget; import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetCardInHand;
import java.util.UUID;
/** /**
*
* @author anonymous * @author anonymous
*/ */
public final class KnollspineInvocation extends CardImpl { public final class KnollspineInvocation extends CardImpl {
@ -35,26 +35,10 @@ public final class KnollspineInvocation extends CardImpl {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance, true), new ManaCostsImpl<>("{X}")); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance, true), new ManaCostsImpl<>("{X}"));
ability.addCost(new DiscardTargetCost(new TargetCardInHand(filter))); ability.addCost(new DiscardTargetCost(new TargetCardInHand(filter)));
ability.addTarget(new TargetAnyTarget()); ability.addTarget(new TargetAnyTarget());
ability.setCostAdjuster(KnollspineInvocationAdjuster.instance);
this.addAbility(ability); this.addAbility(ability);
} }
@Override
public void adjustCosts(Ability ability, Game game) {
if (ability instanceof SimpleActivatedAbility) {
int xValue = ability.getManaCostsToPay().getX();
for (Cost cost : ability.getCosts()) {
if (cost instanceof DiscardTargetCost) {
DiscardTargetCost discardCost = (DiscardTargetCost) cost;
discardCost.getTargets().clear();
FilterCard adjustedFilter = filter.copy(); // don't use it directly, it's static!!!!
adjustedFilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue));
discardCost.addTarget(new TargetCardInHand(adjustedFilter));
return;
}
}
}
}
private KnollspineInvocation(final KnollspineInvocation card) { private KnollspineInvocation(final KnollspineInvocation card) {
super(card); super(card);
} }
@ -64,3 +48,23 @@ public final class KnollspineInvocation extends CardImpl {
return new KnollspineInvocation(this); return new KnollspineInvocation(this);
} }
} }
enum KnollspineInvocationAdjuster implements CostAdjuster {
instance;
@Override
public void adjustCosts(Ability ability, Game game) {
int xValue = ability.getManaCostsToPay().getX();
for (Cost cost : ability.getCosts()) {
if (!(cost instanceof DiscardTargetCost)) {
continue;
}
DiscardTargetCost discardCost = (DiscardTargetCost) cost;
discardCost.getTargets().clear();
FilterCard adjustedFilter = new FilterCard("a card with converted mana cost X");
adjustedFilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue));
discardCost.addTarget(new TargetCardInHand(adjustedFilter));
return;
}
}
}

View file

@ -3,6 +3,7 @@ package mage.cards.l;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.CostAdjuster;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect;
@ -11,15 +12,17 @@ import mage.abilities.keyword.EquipAbility;
import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
/** /**
*
* @author Styxo * @author Styxo
*/ */
public final class Lightsaber extends CardImpl { public final class Lightsaber extends CardImpl {
@ -29,25 +32,18 @@ public final class Lightsaber extends CardImpl {
this.subtype.add(SubType.EQUIPMENT); this.subtype.add(SubType.EQUIPMENT);
// Equiped creature gets +1/+0 and has firsttrike // Equiped creature gets +1/+0 and has firsttrike
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 0))); this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(1, 0)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT))); this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect(
FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT
).setText("and has first strike")));
// Equip 3 // Equip 3
this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(3))); Ability ability = new EquipAbility(3);
ability.setCostAdjuster(LightsaberAdjuster.instance);
this.addAbility(ability);
// Lightsaber's equip ability costs {1} if it targets a Jedi or Sith. // Lightsaber's equip ability costs {1} if it targets a Jedi or Sith.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("{this}'s equip ability costs {1} if it targets a Jedi or Sith"))); this.addAbility(new SimpleStaticAbility(new InfoEffect("{this}'s equip ability costs {1} if it targets a Jedi or Sith")));
}
@Override
public void adjustCosts(Ability ability, Game game) {
if (ability instanceof EquipAbility) {
Permanent targetCreature = game.getPermanent(ability.getTargets().getFirstTarget());
if (targetCreature != null && (targetCreature.hasSubtype(SubType.SITH, game) || targetCreature.hasSubtype(SubType.JEDI, game))) {
CardUtil.increaseCost(ability, 1 - ability.getManaCostsToPay().convertedManaCost());
}
}
} }
private Lightsaber(final Lightsaber card) { private Lightsaber(final Lightsaber card) {
@ -59,3 +55,30 @@ public final class Lightsaber extends CardImpl {
return new Lightsaber(this); return new Lightsaber(this);
} }
} }
enum LightsaberAdjuster implements CostAdjuster {
instance;
@Override
public void adjustCosts(Ability ability, Game game) {
if (game.inCheckPlayableState()) {
if (CardUtil
.getAllPossibleTargets(ability, game)
.stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.noneMatch(permanent -> permanent.hasSubtype(SubType.SITH, game)
|| permanent.hasSubtype(SubType.JEDI, game))) {
return;
}
} else {
Permanent permanent = game.getPermanent(ability.getFirstTarget());
if (permanent == null || !(permanent.hasSubtype(SubType.SITH, game)
|| permanent.hasSubtype(SubType.JEDI, game))) {
return;
}
}
ability.getCosts().clear();
ability.addCost(new GenericManaCost(1));
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.m; package mage.cards.m;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.Mode; import mage.abilities.Mode;
@ -22,10 +21,9 @@ import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -35,8 +33,9 @@ import mage.players.Player;
import mage.target.common.TargetAnyTarget; import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public final class MarathWillOfTheWild extends CardImpl { public final class MarathWillOfTheWild extends CardImpl {
@ -58,7 +57,7 @@ public final class MarathWillOfTheWild extends CardImpl {
// {X}, Remove X +1/+1 counters from Marath: Choose one - Put X +1/+1 counters on target creature; // {X}, Remove X +1/+1 counters from Marath: Choose one - Put X +1/+1 counters on target creature;
effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(0), ManacostVariableValue.instance); effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(0), ManacostVariableValue.instance);
effect.setText("Put X +1/+1 counters on target creature"); effect.setText("Put X +1/+1 counters on target creature");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); Ability ability = new SimpleActivatedAbility(effect, new ManaCostsImpl("{X}"));
ability.addCost(new MarathWillOfTheWildRemoveCountersCost()); ability.addCost(new MarathWillOfTheWildRemoveCountersCost());
ability.addTarget(new TargetCreaturePermanent()); ability.addTarget(new TargetCreaturePermanent());
@ -83,24 +82,6 @@ public final class MarathWillOfTheWild extends CardImpl {
this.addAbility(ability); this.addAbility(ability);
} }
@Override
public void adjustCosts(Ability ability, Game game) {
if (ability instanceof SimpleActivatedAbility && ability.getModes().size() == 3) {
Permanent sourcePermanent = game.getPermanent(ability.getSourceId());
if (sourcePermanent != null) {
int amount = sourcePermanent.getCounters(game).getCount(CounterType.P1P1);
if (amount > 0) {
for (VariableCost cost : ability.getManaCostsToPay().getVariableCosts()) {
if (cost instanceof VariableManaCost) {
((VariableManaCost) cost).setMaxX(amount);
break;
}
}
}
}
}
}
private MarathWillOfTheWild(final MarathWillOfTheWild card) { private MarathWillOfTheWild(final MarathWillOfTheWild card) {
super(card); super(card);
} }
@ -113,12 +94,12 @@ public final class MarathWillOfTheWild extends CardImpl {
class MarathWillOfTheWildCreateTokenEffect extends OneShotEffect { class MarathWillOfTheWildCreateTokenEffect extends OneShotEffect {
public MarathWillOfTheWildCreateTokenEffect() { MarathWillOfTheWildCreateTokenEffect() {
super(Outcome.PutCreatureInPlay); super(Outcome.PutCreatureInPlay);
staticText = "create an X/X green Elemental creature token"; staticText = "create an X/X green Elemental creature token";
} }
public MarathWillOfTheWildCreateTokenEffect(final MarathWillOfTheWildCreateTokenEffect effect) { private MarathWillOfTheWildCreateTokenEffect(final MarathWillOfTheWildCreateTokenEffect effect) {
super(effect); super(effect);
} }
@ -144,12 +125,12 @@ class MarathWillOfTheWildCreateTokenEffect extends OneShotEffect {
class MarathWillOfTheWildRemoveCountersCost extends CostImpl { class MarathWillOfTheWildRemoveCountersCost extends CostImpl {
public MarathWillOfTheWildRemoveCountersCost() { MarathWillOfTheWildRemoveCountersCost() {
this.text = "Remove X +1/+1 counters from Marath"; this.text = "Remove X +1/+1 counters from Marath";
} }
public MarathWillOfTheWildRemoveCountersCost(MarathWillOfTheWildRemoveCountersCost cost) { private MarathWillOfTheWildRemoveCountersCost(MarathWillOfTheWildRemoveCountersCost cost) {
super(cost); super(cost);
} }

View file

@ -4,6 +4,7 @@ import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.CostAdjuster;
import mage.abilities.costs.VariableCost; import mage.abilities.costs.VariableCost;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
@ -35,11 +36,14 @@ public final class PrototypePortal extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// Imprint - When Prototype Portal enters the battlefield, you may exile an artifact card from your hand. // Imprint - When Prototype Portal enters the battlefield, you may exile an artifact card from your hand.
this.addAbility(new EntersBattlefieldTriggeredAbility(new PrototypePortalEffect(), true)); this.addAbility(new EntersBattlefieldTriggeredAbility(
new PrototypePortalEffect(), true, "<i>Imprint</i> &mdash; "
));
// {X}, {tap}: Create a token that's a copy of the exiled card. X is the converted mana cost of that card. // {X}, {tap}: Create a token that's a copy of the exiled card. X is the converted mana cost of that card.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PrototypePortalCreateTokenEffect(), new ManaCostsImpl("{X}")); Ability ability = new SimpleActivatedAbility(new PrototypePortalCreateTokenEffect(), new ManaCostsImpl("{X}"));
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
ability.setCostAdjuster(PrototypePortalAdjuster.instance);
this.addAbility(ability); this.addAbility(ability);
} }
@ -47,6 +51,15 @@ public final class PrototypePortal extends CardImpl {
super(card); super(card);
} }
@Override
public PrototypePortal copy() {
return new PrototypePortal(this);
}
}
enum PrototypePortalAdjuster implements CostAdjuster {
instance;
@Override @Override
public void adjustCosts(Ability ability, Game game) { public void adjustCosts(Ability ability, Game game) {
Permanent card = game.getPermanent(ability.getSourceId()); Permanent card = game.getPermanent(ability.getSourceId());
@ -66,21 +79,16 @@ public final class PrototypePortal extends CardImpl {
} }
} }
} }
@Override
public PrototypePortal copy() {
return new PrototypePortal(this);
}
} }
class PrototypePortalEffect extends OneShotEffect { class PrototypePortalEffect extends OneShotEffect {
public PrototypePortalEffect() { PrototypePortalEffect() {
super(Outcome.Benefit); super(Outcome.Benefit);
staticText = "exile an artifact card from your hand"; staticText = "exile an artifact card from your hand";
} }
public PrototypePortalEffect(PrototypePortalEffect effect) { private PrototypePortalEffect(PrototypePortalEffect effect) {
super(effect); super(effect);
} }
@ -115,12 +123,12 @@ class PrototypePortalEffect extends OneShotEffect {
class PrototypePortalCreateTokenEffect extends OneShotEffect { class PrototypePortalCreateTokenEffect extends OneShotEffect {
public PrototypePortalCreateTokenEffect() { PrototypePortalCreateTokenEffect() {
super(Outcome.PutCreatureInPlay); super(Outcome.PutCreatureInPlay);
this.staticText = "Create a token that's a copy of the exiled card. X is the converted mana cost of that card"; this.staticText = "Create a token that's a copy of the exiled card. X is the converted mana cost of that card";
} }
public PrototypePortalCreateTokenEffect(final PrototypePortalCreateTokenEffect effect) { private PrototypePortalCreateTokenEffect(final PrototypePortalCreateTokenEffect effect) {
super(effect); super(effect);
} }

View file

@ -1,26 +1,24 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.CostAdjuster;
import mage.abilities.costs.common.ExileFromGraveCost; import mage.abilities.costs.common.ExileFromGraveCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.game.Game; import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
/** /**
*
* @author jeffwadsworth * @author jeffwadsworth
*/ */
public final class SkeletalScrying extends CardImpl { public final class SkeletalScrying extends CardImpl {
@ -28,87 +26,45 @@ public final class SkeletalScrying extends CardImpl {
public SkeletalScrying(UUID ownerId, CardSetInfo setInfo) { public SkeletalScrying(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{B}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{B}");
// As an additional cost to cast Skeletal Scrying, exile X cards from your graveyard. // As an additional cost to cast Skeletal Scrying, exile X cards from your graveyard.
Ability ability = new SimpleStaticAbility(Zone.ALL, new SkeletalScryingRuleEffect()); Ability ability = new SimpleStaticAbility(
Zone.ALL,
new InfoEffect(
"as an additional cost to cast this spell, " +
"exile X cards from your graveyard"
));
ability.setRuleAtTheTop(true); ability.setRuleAtTheTop(true);
this.addAbility(ability); this.addAbility(ability);
// You draw X cards and you lose X life. this.getSpellAbility().setCostAdjuster(SkeletalScryingAdjuster.instance);
this.getSpellAbility().addEffect(new SkeletalScryingEffect(ManacostVariableValue.instance));
// You draw X cards and you lose X life.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(
ManacostVariableValue.instance
).setText("you draw X cards"));
this.getSpellAbility().addEffect(new GainLifeEffect(
ManacostVariableValue.instance
).concatBy("and"));
} }
private SkeletalScrying(final SkeletalScrying card) { private SkeletalScrying(final SkeletalScrying card) {
super(card); super(card);
} }
@Override
public void adjustCosts(Ability ability, Game game) {
int xValue = ability.getManaCostsToPay().getX();
if (xValue > 0) {
ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(xValue, xValue, new FilterCard("cards from your graveyard"))));
}
}
@Override @Override
public SkeletalScrying copy() { public SkeletalScrying copy() {
return new SkeletalScrying(this); return new SkeletalScrying(this);
} }
} }
class SkeletalScryingRuleEffect extends OneShotEffect { enum SkeletalScryingAdjuster implements CostAdjuster {
instance;
public SkeletalScryingRuleEffect() { private static final FilterCard filter = new FilterCard("cards from your graveyard");
super(Outcome.Benefit);
this.staticText = "as an additional cost to cast this spell, exile X cards from your graveyard";
}
public SkeletalScryingRuleEffect(final SkeletalScryingRuleEffect effect) {
super(effect);
}
@Override @Override
public SkeletalScryingRuleEffect copy() { public void adjustCosts(Ability ability, Game game) {
return new SkeletalScryingRuleEffect(this); int xValue = ability.getManaCostsToPay().getX();
} if (xValue > 0) {
ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(xValue, xValue, filter)));
@Override
public boolean apply(Game game, Ability source) {
return true;
} }
} }
class SkeletalScryingEffect extends OneShotEffect {
protected DynamicValue amount;
public SkeletalScryingEffect(int amount) {
this(StaticValue.get(amount));
}
public SkeletalScryingEffect(DynamicValue amount) {
super(Outcome.Neutral);
this.amount = amount.copy();
staticText = "You draw " + amount + " cards and you lose " + amount + " life";
}
public SkeletalScryingEffect(final SkeletalScryingEffect effect) {
super(effect);
this.amount = effect.amount;
}
@Override
public SkeletalScryingEffect copy() {
return new SkeletalScryingEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if ( controller != null ) {
controller.drawCards(amount.calculate(game, source, this), source, game);
controller.loseLife(amount.calculate(game, source, this), game, source, false);
return true;
}
return false;
}
} }

View file

@ -1,10 +1,9 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.CostAdjuster;
import mage.abilities.costs.VariableCost; import mage.abilities.costs.VariableCost;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
@ -26,8 +25,9 @@ import mage.target.TargetCard;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.UUID;
/** /**
*
* @author jeffwadsworth * @author jeffwadsworth
*/ */
public final class SoulFoundry extends CardImpl { public final class SoulFoundry extends CardImpl {
@ -36,22 +36,32 @@ public final class SoulFoundry extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// Imprint - When Soul Foundry enters the battlefield, you may exile a creature card from your hand. // Imprint - When Soul Foundry enters the battlefield, you may exile a creature card from your hand.
this.addAbility(new EntersBattlefieldTriggeredAbility(new SoulFoundryImprintEffect(), true, "<i>Imprint</i> &mdash; ")); this.addAbility(new EntersBattlefieldTriggeredAbility(
new SoulFoundryImprintEffect(), true, "<i>Imprint</i> &mdash; "
));
// {X}, {T}: Create a token that's a copy of the exiled card. X is the converted mana cost of that card. // {X}, {T}: Create a token that's a copy of the exiled card. X is the converted mana cost of that card.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SoulFoundryEffect(), new ManaCostsImpl("{X}")); Ability ability = new SimpleActivatedAbility(new SoulFoundryEffect(), new ManaCostsImpl("{X}"));
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
ability.setCostAdjuster(SoulFoundryAdjuster.instance);
this.addAbility(ability); this.addAbility(ability);
} }
private SoulFoundry(final SoulFoundry card) { private SoulFoundry(final SoulFoundry card) {
super(card); super(card);
} }
@Override
public SoulFoundry copy() {
return new SoulFoundry(this);
}
}
enum SoulFoundryAdjuster implements CostAdjuster {
instance;
@Override @Override
public void adjustCosts(Ability ability, Game game) { public void adjustCosts(Ability ability, Game game) {
if (ability instanceof SimpleActivatedAbility) {
Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); Permanent sourcePermanent = game.getPermanent(ability.getSourceId());
if (sourcePermanent != null) { if (sourcePermanent != null) {
if (!sourcePermanent.getImprinted().isEmpty()) { if (!sourcePermanent.getImprinted().isEmpty()) {
@ -72,12 +82,6 @@ public final class SoulFoundry extends CardImpl {
} }
} }
@Override
public SoulFoundry copy() {
return new SoulFoundry(this);
}
}
class SoulFoundryImprintEffect extends OneShotEffect { class SoulFoundryImprintEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard("creature card from your hand"); private static final FilterCard filter = new FilterCard("creature card from your hand");
@ -86,12 +90,12 @@ class SoulFoundryImprintEffect extends OneShotEffect {
filter.add(CardType.CREATURE.getPredicate()); filter.add(CardType.CREATURE.getPredicate());
} }
public SoulFoundryImprintEffect() { SoulFoundryImprintEffect() {
super(Outcome.Neutral); super(Outcome.Neutral);
staticText = "you may exile a creature card from your hand"; staticText = "you may exile a creature card from your hand";
} }
public SoulFoundryImprintEffect(SoulFoundryImprintEffect effect) { private SoulFoundryImprintEffect(SoulFoundryImprintEffect effect) {
super(effect); super(effect);
} }
@ -128,12 +132,12 @@ class SoulFoundryImprintEffect extends OneShotEffect {
class SoulFoundryEffect extends OneShotEffect { class SoulFoundryEffect extends OneShotEffect {
public SoulFoundryEffect() { SoulFoundryEffect() {
super(Outcome.PutCreatureInPlay); super(Outcome.PutCreatureInPlay);
this.staticText = "Create a token that's a copy of the exiled card. X is the converted mana cost of that card"; this.staticText = "Create a token that's a copy of the exiled card. X is the converted mana cost of that card";
} }
public SoulFoundryEffect(final SoulFoundryEffect effect) { private SoulFoundryEffect(final SoulFoundryEffect effect) {
super(effect); super(effect);
} }

View file

@ -1,18 +1,16 @@
package mage.cards.v; package mage.cards.v;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.condition.InvertCondition; import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.SourceTappedCondition; import mage.abilities.condition.common.SourceTappedCondition;
import mage.abilities.costs.VariableCost; import mage.abilities.costs.CostAdjuster;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.DamageControllerEffect;
import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DamageTargetEffect;
@ -22,14 +20,14 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.TargetController; import mage.constants.TargetController;
import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.common.TargetAnyTarget; import mage.target.common.TargetAnyTarget;
import java.util.UUID;
/** /**
*
* @author L_J * @author L_J
*/ */
public final class VoodooDoll extends CardImpl { public final class VoodooDoll extends CardImpl {
@ -38,35 +36,28 @@ public final class VoodooDoll extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}");
// At the beginning of your upkeep, put a pin counter on Voodoo Doll. // At the beginning of your upkeep, put a pin counter on Voodoo Doll.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.PIN.createInstance()), TargetController.YOU, false)); this.addAbility(new BeginningOfUpkeepTriggeredAbility(
new AddCountersSourceEffect(CounterType.PIN.createInstance()), TargetController.YOU, false
));
// At the beginning of your end step, if Voodoo Doll is untapped, destroy Voodoo Doll and it deals damage to you equal to the number of pin counters on it. // At the beginning of your end step, if Voodoo Doll is untapped, destroy Voodoo Doll and it deals damage to you equal to the number of pin counters on it.
Ability ability = new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new DestroySourceEffect(), TargetController.YOU, Ability ability = new ConditionalInterveningIfTriggeredAbility(
new InvertCondition(SourceTappedCondition.instance), false); new BeginningOfEndStepTriggeredAbility(
new DestroySourceEffect(), TargetController.YOU, false
), new InvertCondition(SourceTappedCondition.instance), "At the beginning of your end step, " +
"if {this} is untapped, destroy {this} and it deals damage to you equal to the number of pin counters on it."
);
ability.addEffect(new DamageControllerEffect(new CountersSourceCount(CounterType.PIN))); ability.addEffect(new DamageControllerEffect(new CountersSourceCount(CounterType.PIN)));
this.addAbility(ability); this.addAbility(ability);
// {X}{X}, {T}: Voodoo Doll deals damage equal to the number of pin counters on it to any target. X is the number of pin counters on Voodoo Doll.
Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.PIN)), new ManaCostsImpl("{X}{X}"));
ability2.addCost(new TapSourceCost());
ability2.addTarget(new TargetAnyTarget());
for (VariableCost cost : ability2.getManaCosts().getVariableCosts()) {
if (cost instanceof VariableManaCost) {
((VariableManaCost) cost).setMaxX(0);
break;
}
}
this.addAbility(ability2);
}
@Override // {X}{X}, {T}: Voodoo Doll deals damage equal to the number of pin counters on it to any target. X is the number of pin counters on Voodoo Doll.
public void adjustCosts(Ability ability, Game game) { ability = new SimpleActivatedAbility(
if (ability instanceof SimpleActivatedAbility) { new DamageTargetEffect(new CountersSourceCount(CounterType.PIN)), new ManaCostsImpl("{X}{X}")
Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); );
if (sourcePermanent != null) { ability.addCost(new TapSourceCost());
int pin = sourcePermanent.getCounters(game).getCount(CounterType.PIN); ability.addTarget(new TargetAnyTarget());
ability.getManaCostsToPay().clear(); ability.setCostAdjuster(VoodooDollAdjuster.instance);
ability.getManaCostsToPay().add(0, new GenericManaCost(pin * 2)); this.addAbility(ability);
}
}
} }
private VoodooDoll(final VoodooDoll card) { private VoodooDoll(final VoodooDoll card) {
@ -78,3 +69,17 @@ public final class VoodooDoll extends CardImpl {
return new VoodooDoll(this); return new VoodooDoll(this);
} }
} }
enum VoodooDollAdjuster implements CostAdjuster {
instance;
@Override
public void adjustCosts(Ability ability, Game game) {
Permanent sourcePermanent = game.getPermanent(ability.getSourceId());
if (sourcePermanent != null) {
int pin = sourcePermanent.getCounters(game).getCount(CounterType.PIN);
ability.getManaCostsToPay().clear();
ability.getManaCostsToPay().add(0, new GenericManaCost(pin * 2));
}
}
}