mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
Merge pull request #9386 from weirddan455/braids
[DMU] Implemented Braids, Arisen Nightmare
This commit is contained in:
commit
c140b073ad
7 changed files with 206 additions and 75 deletions
129
Mage.Sets/src/mage/cards/b/BraidsArisenNightmare.java
Normal file
129
Mage.Sets/src/mage/cards/b/BraidsArisenNightmare.java
Normal file
|
@ -0,0 +1,129 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.SharesCardTypePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author weirddan455
|
||||
*/
|
||||
public final class BraidsArisenNightmare extends CardImpl {
|
||||
|
||||
public BraidsArisenNightmare(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}");
|
||||
|
||||
this.addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.NIGHTMARE);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// At the beginning of your end step, you may sacrifice an artifact, creature, enchantment, land, or planeswalker.
|
||||
// If you do, each opponent may sacrifice a permanent that shares a card type with it.
|
||||
// For each opponent who doesn't, that player loses 2 life and you draw a card.
|
||||
this.addAbility(new BeginningOfYourEndStepTriggeredAbility(new BraidsArisenNightmareEffect(), true));
|
||||
}
|
||||
|
||||
private BraidsArisenNightmare(final BraidsArisenNightmare card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BraidsArisenNightmare copy() {
|
||||
return new BraidsArisenNightmare(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BraidsArisenNightmareEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterControlledPermanent filter = new FilterControlledPermanent("an artifact, creature, enchantment, land, or planeswalker");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
CardType.ARTIFACT.getPredicate(),
|
||||
CardType.CREATURE.getPredicate(),
|
||||
CardType.ENCHANTMENT.getPredicate(),
|
||||
CardType.LAND.getPredicate(),
|
||||
CardType.PLANESWALKER.getPredicate()
|
||||
));
|
||||
}
|
||||
|
||||
public BraidsArisenNightmareEffect() {
|
||||
super(Outcome.Sacrifice);
|
||||
this.staticText = "you may sacrifice an artifact, creature, enchantment, land, or planeswalker. " +
|
||||
"If you do, each opponent may sacrifice a permanent that shares a card type with it. " +
|
||||
"For each opponent who doesn't, that player loses 2 life and you draw a card";
|
||||
}
|
||||
|
||||
private BraidsArisenNightmareEffect(final BraidsArisenNightmareEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BraidsArisenNightmareEffect copy() {
|
||||
return new BraidsArisenNightmareEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true);
|
||||
if (!target.canChoose(controller.getId(), source, game)) {
|
||||
return false;
|
||||
}
|
||||
controller.chooseTarget(Outcome.Sacrifice, target, source, game);
|
||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
SharesCardTypePredicate predicate = new SharesCardTypePredicate(permanent.getCardType(game));
|
||||
FilterControlledPermanent opponentFilter = new FilterControlledPermanent(predicate.toString());
|
||||
opponentFilter.add(predicate);
|
||||
if (!permanent.sacrifice(source, game)) {
|
||||
return false;
|
||||
}
|
||||
for (UUID opponentId : game.getOpponents(controller.getId())) {
|
||||
Player opponent = game.getPlayer(opponentId);
|
||||
if (opponent == null) {
|
||||
continue;
|
||||
}
|
||||
if (!braidsSacrifice(opponent, opponentFilter, game, source)) {
|
||||
opponent.loseLife(2, game, source, false);
|
||||
controller.drawCards(1, source, game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean braidsSacrifice(Player opponent, FilterControlledPermanent opponentFilter, Game game, Ability source) {
|
||||
TargetControlledPermanent target = new TargetControlledPermanent(1, 1, opponentFilter, true);
|
||||
if (!target.canChoose(opponent.getId(), source, game)) {
|
||||
return false;
|
||||
}
|
||||
if (!opponent.chooseUse(Outcome.Sacrifice, "Sacrifice " + CardUtil.addArticle(opponentFilter.getMessage()) + '?', source, game)) {
|
||||
return false;
|
||||
}
|
||||
opponent.chooseTarget(Outcome.Sacrifice, target, source, game);
|
||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||
return permanent != null && permanent.sacrifice(source, game);
|
||||
}
|
||||
}
|
|
@ -13,15 +13,13 @@ import mage.constants.SetTargetPointer;
|
|||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.SharesCardTypePredicate;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
@ -85,22 +83,12 @@ enum ConfusionInTheRanksAdjuster implements TargetAdjuster {
|
|||
return;
|
||||
}
|
||||
ability.getTargets().clear();
|
||||
FilterPermanent filterTarget = new FilterPermanent();
|
||||
String message = "";
|
||||
SharesCardTypePredicate predicate = new SharesCardTypePredicate(enteringPermanent.getCardType(game));
|
||||
FilterPermanent filterTarget = new FilterPermanent(predicate.toString() + " you don't control");
|
||||
filterTarget.add(predicate);
|
||||
filterTarget.add(Predicates.not(new ControllerIdPredicate(enteringPermanent.getControllerId())));
|
||||
Set<CardType.CardTypePredicate> cardTypesPredicates = new HashSet<>(1);
|
||||
for (CardType cardTypeEntering : enteringPermanent.getCardType(game)) {
|
||||
cardTypesPredicates.add(cardTypeEntering.getPredicate());
|
||||
if (!message.isEmpty()) {
|
||||
message += "or ";
|
||||
}
|
||||
message += cardTypeEntering.toString().toLowerCase(Locale.ENGLISH) + ' ';
|
||||
}
|
||||
filterTarget.add(Predicates.or(cardTypesPredicates));
|
||||
message += "you don't control";
|
||||
filterTarget.setMessage(message);
|
||||
TargetPermanent target = new TargetPermanent(filterTarget);
|
||||
target.setTargetController(enteringPermanent.getControllerId());
|
||||
ability.getTargets().add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -9,17 +8,14 @@ import mage.cards.CardsImpl;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.SharesCardTypePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetSpell;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author BetaSteward
|
||||
|
@ -70,17 +66,9 @@ class CounterlashEffect extends OneShotEffect {
|
|||
if (stackObject == null || controller == null) {
|
||||
return false;
|
||||
}
|
||||
Set<Predicate<MageObject>> predicates = stackObject
|
||||
.getCardType(game)
|
||||
.stream()
|
||||
.map(CardType::getPredicate)
|
||||
.collect(Collectors.toSet());
|
||||
game.getStack().counter(source.getFirstTarget(), source, game);
|
||||
if (predicates.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(Predicates.or(predicates));
|
||||
filter.add(new SharesCardTypePredicate(stackObject.getCardType(game)));
|
||||
game.getStack().counter(source.getFirstTarget(), source, game);
|
||||
CardUtil.castSpellWithAttributesForFree(controller, source, game, new CardsImpl(controller.getHand()), filter);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import mage.constants.CardType;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.SharesCardTypePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
|
@ -112,24 +112,9 @@ class MartyrsBondEffect extends OneShotEffect {
|
|||
Permanent saccedPermanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source);
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null && saccedPermanent != null) {
|
||||
FilterControlledPermanent filter = new FilterControlledPermanent();
|
||||
String message = "permanent with type (";
|
||||
boolean firstType = true;
|
||||
|
||||
List<CardType.CardTypePredicate> cardTypes = new ArrayList<>();
|
||||
|
||||
for (CardType type : saccedPermanent.getCardType(game)) {
|
||||
cardTypes.add(type.getPredicate());
|
||||
if (firstType) {
|
||||
message += type;
|
||||
firstType = false;
|
||||
} else {
|
||||
message += " or " + type;
|
||||
}
|
||||
}
|
||||
message += ") to sacrifice";
|
||||
filter.add(Predicates.or(cardTypes));
|
||||
filter.setMessage(message);
|
||||
SharesCardTypePredicate predicate = new SharesCardTypePredicate(saccedPermanent.getCardType(game));
|
||||
FilterControlledPermanent filter = new FilterControlledPermanent(predicate.toString());
|
||||
filter.add(predicate);
|
||||
|
||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
|
@ -22,7 +20,7 @@ import mage.constants.Outcome;
|
|||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.common.FilterPermanentCard;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.mageobject.SharesCardTypePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
|
@ -85,8 +83,9 @@ class SpiritSistersCallDoIfEffect extends OneShotEffect {
|
|||
if (card == null || game.getState().getZone(targetId) != Zone.GRAVEYARD) {
|
||||
return false;
|
||||
}
|
||||
FilterControlledPermanent filter = new FilterControlledPermanent("a permanent that shares a card type with the chosen card");
|
||||
filter.add(new SpiritSistersCallPredicate(new HashSet<CardType>(card.getCardType(game))));
|
||||
SharesCardTypePredicate predicate = new SharesCardTypePredicate(card.getCardType(game));
|
||||
FilterControlledPermanent filter = new FilterControlledPermanent(predicate.toString());
|
||||
filter.add(predicate);
|
||||
return new DoIfCostPaid(new SpiritSistersCallReturnToBattlefieldEffect(), new SacrificeTargetCost(filter)).apply(game, source);
|
||||
}
|
||||
}
|
||||
|
@ -160,22 +159,3 @@ class SpiritSistersCallReplacementEffect extends ReplacementEffectImpl {
|
|||
&& zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() != Zone.EXILED;
|
||||
}
|
||||
}
|
||||
|
||||
class SpiritSistersCallPredicate implements Predicate<MageObject> {
|
||||
|
||||
private final HashSet<CardType> cardTypes;
|
||||
|
||||
public SpiritSistersCallPredicate(HashSet<CardType> cardTypes) {
|
||||
this.cardTypes = cardTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(MageObject input, Game game) {
|
||||
for (CardType type : input.getCardType(game)) {
|
||||
if (cardTypes.contains(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ public final class DominariaUnited extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Archangel of Wrath", 3, Rarity.RARE, mage.cards.a.ArchangelOfWrath.class));
|
||||
cards.add(new SetCardInfo("Aron, Benalia's Ruin", 292, Rarity.UNCOMMON, mage.cards.a.AronBenaliasRuin.class));
|
||||
cards.add(new SetCardInfo("Benalish Sleeper", 8, Rarity.COMMON, mage.cards.b.BenalishSleeper.class));
|
||||
cards.add(new SetCardInfo("Braids, Arisen Nightmare", 84, Rarity.RARE, mage.cards.b.BraidsArisenNightmare.class));
|
||||
cards.add(new SetCardInfo("Caves of Koilos", 244, Rarity.RARE, mage.cards.c.CavesOfKoilos.class));
|
||||
cards.add(new SetCardInfo("Charismatic Vanguard", 10, Rarity.COMMON, mage.cards.c.CharismaticVanguard.class));
|
||||
cards.add(new SetCardInfo("Cut Down", 89, Rarity.UNCOMMON, mage.cards.c.CutDown.class));
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package mage.filter.predicate.mageobject;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author weirddan455
|
||||
*/
|
||||
public class SharesCardTypePredicate implements Predicate<MageObject> {
|
||||
|
||||
private final LinkedHashSet<CardType> cardTypes;
|
||||
|
||||
public SharesCardTypePredicate(Collection<CardType> cardTypes) {
|
||||
this.cardTypes = new LinkedHashSet<>(cardTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(MageObject input, Game game) {
|
||||
for (CardType type : input.getCardType(game)) {
|
||||
if (cardTypes.contains(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
Iterator<CardType> it = cardTypes.iterator();
|
||||
switch(cardTypes.size()) {
|
||||
case 0:
|
||||
return "";
|
||||
case 1:
|
||||
return it.next().toString().toLowerCase(Locale.ENGLISH);
|
||||
case 2:
|
||||
return it.next().toString().toLowerCase(Locale.ENGLISH) + " or " + it.next().toString().toLowerCase(Locale.ENGLISH);
|
||||
default: {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(it.next().toString().toLowerCase(Locale.ENGLISH));
|
||||
while (it.hasNext()) {
|
||||
CardType type = it.next();
|
||||
sb.append(", ");
|
||||
if (!it.hasNext()) {
|
||||
sb.append("or ");
|
||||
}
|
||||
sb.append(type.toString().toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue