mirror of
https://github.com/correl/mage.git
synced 2024-12-26 03:00:11 +00:00
[MID] Implemented Bloodthirsty Adversary
This commit is contained in:
parent
43b3f12b56
commit
d829094f90
5 changed files with 248 additions and 43 deletions
155
Mage.Sets/src/mage/cards/b/BloodthirstyAdversary.java
Normal file
155
Mage.Sets/src/mage/cards/b/BloodthirstyAdversary.java
Normal file
|
@ -0,0 +1,155 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DoIfAnyNumberCostPaid;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.*;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterInstantOrSorceryCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author weirddan455
|
||||
*/
|
||||
public final class BloodthirstyAdversary extends CardImpl {
|
||||
|
||||
public BloodthirstyAdversary(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
|
||||
|
||||
this.subtype.add(SubType.VAMPIRE);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Haste
|
||||
this.addAbility(HasteAbility.getInstance());
|
||||
|
||||
// When Bloodthirsty Adversary enters the battlefield, you may pay {2}{R} any number of times.
|
||||
// When you pay this cost one or more times, put that many +1/+1 counters on Bloodthirsty Adversary,
|
||||
// then exile up to that many target instant and/or sorcery cards with mana value 3 or less from your graveyard and copy them.
|
||||
// You may cast any number of the copies without paying their mana costs.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new DoIfAnyNumberCostPaid(
|
||||
new BloodthirstyAdversaryEffect(), new ManaCostsImpl<>("{2}{R}")
|
||||
)));
|
||||
}
|
||||
|
||||
private BloodthirstyAdversary(final BloodthirstyAdversary card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BloodthirstyAdversary copy() {
|
||||
return new BloodthirstyAdversary(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BloodthirstyAdversaryEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterInstantOrSorceryCard filter =
|
||||
new FilterInstantOrSorceryCard("instant and/or sorcery cards with mana value 3 or less from your graveyard");
|
||||
|
||||
static {
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4));
|
||||
}
|
||||
|
||||
public BloodthirstyAdversaryEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "put that many +1/+1 counters on {this}, " +
|
||||
"then exile up to that many target instant and/or sorcery cards with mana value 3 or less from your graveyard and copy them. " +
|
||||
"You may cast any number of the copies without paying their mana costs";
|
||||
}
|
||||
|
||||
private BloodthirstyAdversaryEffect(final BloodthirstyAdversaryEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BloodthirstyAdversaryEffect copy() {
|
||||
return new BloodthirstyAdversaryEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Integer timesPaid = (Integer) getValue("timesPaid");
|
||||
if (timesPaid == null || timesPaid <= 0) {
|
||||
return false;
|
||||
}
|
||||
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(timesPaid)),
|
||||
false, staticText
|
||||
);
|
||||
ability.addEffect(new BloodthirstyAdversaryCopyEffect());
|
||||
ability.addTarget(new TargetCardInYourGraveyard(0, timesPaid, filter));
|
||||
game.fireReflexiveTriggeredAbility(ability, source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class BloodthirstyAdversaryCopyEffect extends OneShotEffect {
|
||||
|
||||
public BloodthirstyAdversaryCopyEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
}
|
||||
|
||||
private BloodthirstyAdversaryCopyEffect(final BloodthirstyAdversaryCopyEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BloodthirstyAdversaryCopyEffect copy() {
|
||||
return new BloodthirstyAdversaryCopyEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Set<Card> cardsToExile = new LinkedHashSet<>();
|
||||
for (UUID cardId : targetPointer.getTargets(game, source)) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (card != null) {
|
||||
cardsToExile.add(card);
|
||||
}
|
||||
}
|
||||
if (cardsToExile.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
controller.moveCards(cardsToExile, Zone.EXILED, source, game);
|
||||
ApprovingObject approvingObject = new ApprovingObject(source, game);
|
||||
for (Card card : cardsToExile) {
|
||||
Card copiedCard = game.copyCard(card, source, controller.getId());
|
||||
if (copiedCard != null && controller.chooseUse(outcome, "Cast " + copiedCard.getName() + " for free?", source, game)) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), Boolean.TRUE);
|
||||
controller.cast(
|
||||
controller.chooseAbilityForCast(copiedCard, game, true),
|
||||
game, true, approvingObject
|
||||
);
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), null);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
|||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DoIfAnyNumberCostPaid;
|
||||
import mage.abilities.effects.common.PhaseOutTargetEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
|
@ -19,6 +20,7 @@ import mage.constants.SubType;
|
|||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
|
@ -44,7 +46,9 @@ public final class SpectralAdversary extends CardImpl {
|
|||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// When Spectral Adversary enters the battlefield, you may pay {1}{U} any number of times. When you pay this cost one or more times, put that many +1/+1 counters on Spectral Adversary, then up to that many other target artifacts, creatures, and/or enchantments phase out.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new SpectralAdversaryEffect()));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new DoIfAnyNumberCostPaid(
|
||||
new SpectralAdversaryEffect(), new ManaCostsImpl<>("{1}{U}")
|
||||
)));
|
||||
}
|
||||
|
||||
private SpectralAdversary(final SpectralAdversary card) {
|
||||
|
@ -60,7 +64,7 @@ public final class SpectralAdversary extends CardImpl {
|
|||
class SpectralAdversaryEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterPermanent filter
|
||||
= new FilterPermanent("artifacts, creatures, and/or enchantments");
|
||||
= new FilterPermanent("other artifacts, creatures, and/or enchantments");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
|
@ -68,12 +72,12 @@ class SpectralAdversaryEffect extends OneShotEffect {
|
|||
CardType.CREATURE.getPredicate(),
|
||||
CardType.ENCHANTMENT.getPredicate()
|
||||
));
|
||||
filter.add(AnotherPredicate.instance);
|
||||
}
|
||||
|
||||
SpectralAdversaryEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "you may pay {1}{U} any number of times. When you pay this cost one or more times, " +
|
||||
"put that many +1/+1 counters on {this}, then up to that many other target " +
|
||||
staticText = "put that many +1/+1 counters on {this}, then up to that many other target " +
|
||||
"artifacts, creatures, and/or enchantments phase out";
|
||||
}
|
||||
|
||||
|
@ -92,29 +96,16 @@ class SpectralAdversaryEffect extends OneShotEffect {
|
|||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Cost cost = new ManaCostsImpl<>("{1}{U}");
|
||||
int amount = 0;
|
||||
while (player.canRespond()) {
|
||||
cost.clearPaid();
|
||||
if (cost.canPay(source, source, source.getControllerId(), game)
|
||||
&& player.chooseUse(
|
||||
outcome, "Pay {1}{U}? You have paid this cost " +
|
||||
amount + " time" + (amount != 1 ? "s" : ""), source, game
|
||||
) && cost.pay(source, game, source, source.getControllerId(), false)) {
|
||||
amount++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (amount == 0) {
|
||||
Integer timesPaid = (Integer) getValue("timesPaid");
|
||||
if (timesPaid == null || timesPaid <= 0) {
|
||||
return false;
|
||||
}
|
||||
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(amount)),
|
||||
false, "put that many +1/+1 counters on {this}, then " +
|
||||
"up to that many other target artifacts, creatures, and/or enchantments phase out"
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(timesPaid)),
|
||||
false, staticText
|
||||
);
|
||||
ability.addEffect(new PhaseOutTargetEffect());
|
||||
ability.addTarget(new TargetPermanent(0, amount, filter));
|
||||
ability.addTarget(new TargetPermanent(0, timesPaid, filter));
|
||||
game.fireReflexiveTriggeredAbility(ability, source);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import mage.abilities.costs.Cost;
|
|||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.DoIfAnyNumberCostPaid;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.keyword.DeathtouchAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -38,7 +39,9 @@ public final class TaintedAdversary extends CardImpl {
|
|||
this.addAbility(DeathtouchAbility.getInstance());
|
||||
|
||||
// When Tainted Adversary enters the battlefield, you may pay {2}{B} any number of times. When you pay this cost one or more times, put that many +1/+1 counters on Tainted Adversary, then create twice that many black 2/2 Zombie creature tokens with decayed.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new TaintedAdversaryEffect()));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new DoIfAnyNumberCostPaid(
|
||||
new TaintedAdversaryEffect(), new ManaCostsImpl<>("{2}{B}")
|
||||
)));
|
||||
}
|
||||
|
||||
private TaintedAdversary(final TaintedAdversary card) {
|
||||
|
@ -55,8 +58,7 @@ class TaintedAdversaryEffect extends OneShotEffect {
|
|||
|
||||
TaintedAdversaryEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "you may pay {2}{B} any number of times. When you pay this cost " +
|
||||
"one or more times, put that many +1/+1 counters on {this}, " +
|
||||
staticText = "put that many +1/+1 counters on {this}, " +
|
||||
"then create twice that many black 2/2 Zombie creature tokens with decayed";
|
||||
}
|
||||
|
||||
|
@ -75,28 +77,15 @@ class TaintedAdversaryEffect extends OneShotEffect {
|
|||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Cost cost = new ManaCostsImpl<>("{2}{B}");
|
||||
int amount = 0;
|
||||
while (player.canRespond()) {
|
||||
cost.clearPaid();
|
||||
if (cost.canPay(source, source, source.getControllerId(), game)
|
||||
&& player.chooseUse(
|
||||
outcome, "Pay {2}{B}? You have paid this cost " +
|
||||
amount + " time" + (amount != 1 ? "s" : ""), source, game
|
||||
) && cost.pay(source, game, source, source.getControllerId(), false)) {
|
||||
amount++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (amount == 0) {
|
||||
Integer timesPaid = (Integer) getValue("timesPaid");
|
||||
if (timesPaid == null || timesPaid <= 0) {
|
||||
return false;
|
||||
}
|
||||
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(amount)),
|
||||
false, "put that many +1/+1 counters on {this}, then create " +
|
||||
"twice that many black 2/2 Zombie creature tokens with decayed"
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(timesPaid)),
|
||||
false, staticText
|
||||
);
|
||||
ability.addEffect(new CreateTokenEffect(new ZombieDecayedToken(), 2 * amount));
|
||||
ability.addEffect(new CreateTokenEffect(new ZombieDecayedToken(), 2 * timesPaid));
|
||||
game.fireReflexiveTriggeredAbility(ability, source);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ public final class InnistradMidnightHunt extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Arrogant Outlaw", 84, Rarity.COMMON, mage.cards.a.ArrogantOutlaw.class));
|
||||
cards.add(new SetCardInfo("Augur of Autumn", 168, Rarity.RARE, mage.cards.a.AugurOfAutumn.class));
|
||||
cards.add(new SetCardInfo("Bladestitched Skaab", 212, Rarity.UNCOMMON, mage.cards.b.BladestitchedSkaab.class));
|
||||
cards.add(new SetCardInfo("Bloodthirsty Adversary", 129, Rarity.MYTHIC, mage.cards.b.BloodthirstyAdversary.class));
|
||||
cards.add(new SetCardInfo("Briarbridge Tracker", 172, Rarity.RARE, mage.cards.b.BriarbridgeTracker.class));
|
||||
cards.add(new SetCardInfo("Brimstone Vandal", 130, Rarity.COMMON, mage.cards.b.BrimstoneVandal.class));
|
||||
cards.add(new SetCardInfo("Burly Breaker", 174, Rarity.UNCOMMON, mage.cards.b.BurlyBreaker.class));
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
public class DoIfAnyNumberCostPaid extends OneShotEffect {
|
||||
|
||||
private final Effect executingEffect;
|
||||
private final Cost cost;
|
||||
|
||||
public DoIfAnyNumberCostPaid(OneShotEffect effect, Cost cost) {
|
||||
super(Outcome.Benefit);
|
||||
this.executingEffect = effect;
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
private DoIfAnyNumberCostPaid(final DoIfAnyNumberCostPaid effect) {
|
||||
super(effect);
|
||||
this.executingEffect = effect.executingEffect.copy();
|
||||
this.cost = effect.cost.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoIfAnyNumberCostPaid copy() {
|
||||
return new DoIfAnyNumberCostPaid(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
String costText = cost.getText();
|
||||
int timesPaid = 0;
|
||||
while (controller.canRespond()) {
|
||||
cost.clearPaid();
|
||||
if (cost.canPay(source, source, source.getControllerId(), game)
|
||||
&& controller.chooseUse(
|
||||
outcome, "Pay " + costText + "? You have paid this cost " +
|
||||
timesPaid + " time" + (timesPaid != 1 ? "s" : ""), source, game
|
||||
) && cost.pay(source, game, source, source.getControllerId(), false)) {
|
||||
timesPaid++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (timesPaid > 0) {
|
||||
executingEffect.setValue("timesPaid", timesPaid);
|
||||
return executingEffect.apply(game, source);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
if (staticText != null && !staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
return "you may pay " + cost.getText() + " any number of times. When you pay this cost one or more times, "
|
||||
+ executingEffect.getText(mode);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue