mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 03:22:00 -08:00
implement [MH3] Ripples of Undeath
This commit is contained in:
parent
876204c7ed
commit
a3b7bb785d
3 changed files with 184 additions and 0 deletions
126
Mage.Sets/src/mage/cards/r/RipplesOfUndeath.java
Normal file
126
Mage.Sets/src/mage/cards/r/RipplesOfUndeath.java
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
package mage.cards.r;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.BeginningOfPreCombatMainTriggeredAbility;
|
||||||
|
import mage.abilities.costs.Costs;
|
||||||
|
import mage.abilities.costs.CostsImpl;
|
||||||
|
import mage.abilities.costs.common.PayLifeCost;
|
||||||
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.DoIfCostPaid;
|
||||||
|
import mage.cards.*;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.TargetController;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.common.TargetCardInGraveyard;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public final class RipplesOfUndeath extends CardImpl {
|
||||||
|
|
||||||
|
public RipplesOfUndeath(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}");
|
||||||
|
|
||||||
|
// At the beginning of your precombat main phase, mill three cards. Then you may pay {1} and 3 life. If you do, put a card from among those cards into your hand.
|
||||||
|
this.addAbility(new BeginningOfPreCombatMainTriggeredAbility(
|
||||||
|
new RipplesOfUndeathEffect(), TargetController.YOU, false
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private RipplesOfUndeath(final RipplesOfUndeath card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RipplesOfUndeath copy() {
|
||||||
|
return new RipplesOfUndeath(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RipplesOfUndeathEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
RipplesOfUndeathEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
staticText = "mill three cards. Then you may pay {1} and 3 life. If you do, put a card from among those cards into your hand.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private RipplesOfUndeathEffect(final RipplesOfUndeathEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RipplesOfUndeathEffect copy() {
|
||||||
|
return new RipplesOfUndeathEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Cards milled = controller.millCards(3, source, game);
|
||||||
|
Costs cost = new CostsImpl();
|
||||||
|
cost.add(new GenericManaCost(1));
|
||||||
|
cost.add(new PayLifeCost(3));
|
||||||
|
|
||||||
|
new DoIfCostPaid(new RipplesOfUndeathReturnEffect(milled), cost)
|
||||||
|
.apply(game, source);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RipplesOfUndeathReturnEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
private final Set<UUID> milledCards;
|
||||||
|
|
||||||
|
RipplesOfUndeathReturnEffect(Set<UUID> milledCards) {
|
||||||
|
super(Outcome.DrawCard);
|
||||||
|
staticText = "put a card from among those cards into your hand";
|
||||||
|
this.milledCards = milledCards;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RipplesOfUndeathReturnEffect(final RipplesOfUndeathReturnEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
this.milledCards = new HashSet<>(effect.milledCards);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RipplesOfUndeathReturnEffect copy() {
|
||||||
|
return new RipplesOfUndeathReturnEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (milledCards.isEmpty() || controller == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Cards cards = new CardsImpl();
|
||||||
|
cards.addAll(milledCards);
|
||||||
|
TargetCardInGraveyard target = new TargetCardInGraveyard();
|
||||||
|
target.withNotTarget(true);
|
||||||
|
controller.choose(outcome, cards, target, source, game);
|
||||||
|
Set<Card> returned = target
|
||||||
|
.getTargets()
|
||||||
|
.stream()
|
||||||
|
.map(game::getCard)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
if (returned.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
controller.moveCards(returned, Zone.HAND, source, game);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -118,6 +118,7 @@ public final class ModernHorizons3 extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Recruiter of the Guard", 266, Rarity.MYTHIC, mage.cards.r.RecruiterOfTheGuard.class));
|
cards.add(new SetCardInfo("Recruiter of the Guard", 266, Rarity.MYTHIC, mage.cards.r.RecruiterOfTheGuard.class));
|
||||||
cards.add(new SetCardInfo("Reef Worm", 271, Rarity.UNCOMMON, mage.cards.r.ReefWorm.class));
|
cards.add(new SetCardInfo("Reef Worm", 271, Rarity.UNCOMMON, mage.cards.r.ReefWorm.class));
|
||||||
cards.add(new SetCardInfo("Revitalizing Repast", 256, Rarity.UNCOMMON, mage.cards.r.RevitalizingRepast.class));
|
cards.add(new SetCardInfo("Revitalizing Repast", 256, Rarity.UNCOMMON, mage.cards.r.RevitalizingRepast.class));
|
||||||
|
cards.add(new SetCardInfo("Ripples of Undeath", 107, Rarity.RARE, mage.cards.r.RipplesOfUndeath.class));
|
||||||
cards.add(new SetCardInfo("Roil Cartographer", 67, Rarity.UNCOMMON, mage.cards.r.RoilCartographer.class));
|
cards.add(new SetCardInfo("Roil Cartographer", 67, Rarity.UNCOMMON, mage.cards.r.RoilCartographer.class));
|
||||||
cards.add(new SetCardInfo("Ruby Medallion", 295, Rarity.RARE, mage.cards.r.RubyMedallion.class));
|
cards.add(new SetCardInfo("Ruby Medallion", 295, Rarity.RARE, mage.cards.r.RubyMedallion.class));
|
||||||
cards.add(new SetCardInfo("Rush of Inspiration", 257, Rarity.UNCOMMON, mage.cards.r.RushOfInspiration.class));
|
cards.add(new SetCardInfo("Rush of Inspiration", 257, Rarity.UNCOMMON, mage.cards.r.RushOfInspiration.class));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package org.mage.test.cards.single.mh3;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public class RipplesOfUndeathTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link mage.cards.r.RipplesOfUndeath Ripples of Undeath} {1}{B}
|
||||||
|
* Enchantment
|
||||||
|
* At the beginning of your precombat main phase, mill three cards. Then you may pay {1} and 3 life. If you do, put a card from among those cards into your hand.
|
||||||
|
*/
|
||||||
|
private static final String ripples = "Ripples of Undeath";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_CantPay() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, ripples);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Taiga", 3);
|
||||||
|
|
||||||
|
setChoice(playerA, false); // no to "you may pay"
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, "Taiga", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Pay() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, ripples);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Taiga", 2);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Savannah", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains");
|
||||||
|
|
||||||
|
setChoice(playerA, true); // yes to "you may pay"
|
||||||
|
setChoice(playerA, "Savannah"); // return this one
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, "Taiga", 2);
|
||||||
|
assertHandCount(playerA, "Savannah", 1);
|
||||||
|
assertTappedCount("Plains", true, 1);
|
||||||
|
assertLife(playerA, 20 - 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue