Reworked Delve ability (#768)

This commit is contained in:
Oleg Agafonov 2020-06-19 13:21:03 +04:00
parent fb1e284960
commit 56a5fd5851
2 changed files with 143 additions and 27 deletions

View file

@ -5,9 +5,14 @@ import mage.abilities.Ability;
import mage.abilities.SpecialAction;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.ExileFromGraveCost;
import mage.abilities.costs.mana.ActivationManaAbilityStep;
import mage.abilities.costs.mana.AlternateManaPaymentAbility;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.hint.ValueHint;
import mage.abilities.mana.ManaOptions;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
@ -17,6 +22,7 @@ import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.ManaPool;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
@ -25,35 +31,42 @@ import mage.util.CardUtil;
import java.util.List;
/**
* 702.65. Delve 702.65a Delve is a static ability that functions while the
* spell with delve is on the stack. Delve means For each generic mana in
* this spell's total cost, you may exile a card from your graveyard rather than
* pay that mana. The delve ability isn't an additional or alternative cost and
* applies only after the total cost of the spell with delve is determined.
* 702.65b Multiple instances of delve on the same spell are redundant.
* 702.65. Delve
* <p>
* The rules for delve have changed slightly since it was last in an expansion.
* Previously, delve reduced the cost to cast a spell. Under the current rules,
* you exile cards from your graveyard at the same time you pay the spell's
* cost. Exiling a card this way is simply another way to pay that cost. * Delve
* doesn't change a spell's mana cost or converted mana cost. For example, Dead
* Drop's converted mana cost is 10 even if you exiled three cards to cast it. *
* You can't exile cards to pay for the colored mana requirements of a spell
* with delve. * You can't exile more cards than the generic mana requirement of
* a spell with delve. For example, you can't exile more than nine cards from
* your graveyard to cast Dead Drop. * Because delve isn't an alternative cost,
* it can be used in conjunction with alternative costs.
* 702.65a Delve is a static ability that functions while the spell with delve is on the stack. Delve means For
* each generic mana in this spells total cost, you may exile a card from your graveyard rather than pay that mana.
* <p>
* 702.65b The delve ability isnt an additional or alternative cost and applies only after the total cost of the spell
* with delve is determined.
* <p>
* 702.65c Multiple instances of delve on the same spell are redundant.
* <p>
* The rules for delve have changed slightly since it was last in an expansion. Previously, delve reduced the cost
* to cast a spell. Under the current rules, you exile cards from your graveyard at the same time you pay the spells
* cost. Exiling a card this way is simply another way to pay that cost. (This is similar to the change made to
* convoke for the Magic 2015 Core Set.)
* <p>
* You cant exile cards to pay for the colored mana requirements of a spell with delve.
* <p>
* You cant exile more cards than the generic mana requirement of a spell with delve. For example, you cant exile more
* than nine cards from your graveyard to cast Dead Drop.
* <p>
* Because delve isnt an alternative cost, it can be used in conjunction with alternative costs.
*
* @author LevelX2
* @author LevelX2, JayDi85
* <p>
* TODO: Change card exiling to a way to pay mana costs, now it's maybe not
* possible to pay costs from effects that increase the mana costs.
* If it real bug then possible fix: choose cards on apply like convoke and improvise, not as cost
*/
public class DelveAbility extends SimpleStaticAbility implements AlternateManaPaymentAbility {
private static final DynamicValue cardsInGraveyard = new CardsInControllerGraveyardCount();
public DelveAbility() {
super(Zone.STACK, null);
super(Zone.ALL, null);
this.setRuleAtTheTop(true);
this.addHint(new ValueHint("Cards in your graveyard", cardsInGraveyard));
}
public DelveAbility(final DelveAbility ability) {
@ -70,12 +83,17 @@ public class DelveAbility extends SimpleStaticAbility implements AlternateManaPa
return "Delve <i>(Each card you exile from your graveyard while casting this spell pays for {1}.)</i>";
}
@Override
public ActivationManaAbilityStep useOnActivationManaAbilityStep() {
return ActivationManaAbilityStep.AFTER;
}
@Override
public void addSpecialAction(Ability source, Game game, ManaCost unpaid) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null && !controller.getGraveyard().isEmpty()) {
if (unpaid.getMana().getGeneric() > 0 && source.getAbilityType() == AbilityType.SPELL) {
SpecialAction specialAction = new DelveSpecialAction();
if (source.getAbilityType() == AbilityType.SPELL && unpaid.getMana().getGeneric() > 0) {
SpecialAction specialAction = new DelveSpecialAction(this);
specialAction.setControllerId(source.getControllerId());
specialAction.setSourceId(source.getSourceId());
int unpaidAmount = unpaid.getMana().getGeneric();
@ -84,19 +102,30 @@ public class DelveAbility extends SimpleStaticAbility implements AlternateManaPa
}
specialAction.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(
0, Math.min(controller.getGraveyard().size(), unpaidAmount),
new FilterCard("cards to exile for delve's pay from your graveyard"), true)));
new FilterCard("cards from your graveyard"), true)));
if (specialAction.canActivate(source.getControllerId(), game).canActivate()) {
game.getState().getSpecialActions().add(specialAction);
}
}
}
}
@Override
public ManaOptions getManaOptions(Ability source, Game game, ManaCost unpaid) {
ManaOptions options = new ManaOptions();
Player controller = game.getPlayer(source.getControllerId());
int graveCount = cardsInGraveyard.calculate(game, source, null);
if (controller != null && graveCount > 0) {
options.addMana(Mana.GenericMana(Math.min(unpaid.getMana().getGeneric(), graveCount)));
}
return options;
}
}
class DelveSpecialAction extends SpecialAction {
public DelveSpecialAction() {
super(Zone.ALL, true);
public DelveSpecialAction(AlternateManaPaymentAbility manaAbility) {
super(Zone.ALL, manaAbility);
this.addEffect(new DelveEffect());
}
@ -129,9 +158,9 @@ class DelveEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Spell spell = game.getStack().getSpell(source.getSourceId());
if (controller != null && spell != null) {
ExileFromGraveCost exileFromGraveCost = (ExileFromGraveCost) source.getCosts().get(0);
List<Card> exiledCards = exileFromGraveCost.getExiledCards();
if (!exiledCards.isEmpty()) {
Cards toDelve = new CardsImpl();
@ -139,7 +168,7 @@ class DelveEffect extends OneShotEffect {
toDelve.add(card);
}
ManaPool manaPool = controller.getManaPool();
manaPool.addMana(new Mana(0, 0, 0, 0, 0, 0, 0, toDelve.size()), game, source);
manaPool.addMana(Mana.ColorlessMana(toDelve.size()), game, source);
manaPool.unlockManaType(ManaType.COLORLESS);
String keyString = CardUtil.getCardZoneString("delvedCards", source.getSourceId(), game);
@SuppressWarnings("unchecked")
@ -149,6 +178,9 @@ class DelveEffect extends OneShotEffect {
} else {
delvedCards.addAll(toDelve);
}
// can't use mana abilities after that (delve cost must be payed after mana abilities only)
spell.setCurrentActivatingManaAbilitiesStep(ActivationManaAbilityStep.AFTER);
}
return true;
}