forked from External/mage
[CMM] Implement Narci, Fable Singer (#10685)
This commit is contained in:
parent
286696800e
commit
b79964530e
5 changed files with 202 additions and 91 deletions
|
|
@ -80,7 +80,7 @@ class HistoriansBoonTriggeredAbility extends TriggeredAbilityImpl {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
StackObject stackObject = game.getStack().getStackObject(event.getTargetId());
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
|
||||
if (stackObject == null
|
||||
|| permanent == null
|
||||
|| !permanent.isControlledBy(getControllerId())
|
||||
|
|
|
|||
87
Mage.Sets/src/mage/cards/n/NarciFableSinger.java
Normal file
87
Mage.Sets/src/mage/cards/n/NarciFableSinger.java
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package mage.cards.n;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.FinalChapterAbilityResolvesTriggeredAbility;
|
||||
import mage.abilities.common.SacrificePermanentTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
||||
import mage.abilities.keyword.LifelinkAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class NarciFableSinger extends CardImpl {
|
||||
|
||||
public NarciFableSinger(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{B}{G}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.BARD);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Lifelink
|
||||
this.addAbility(LifelinkAbility.getInstance());
|
||||
|
||||
// Whenever you sacrifice an enchantment, draw a card.
|
||||
this.addAbility(new SacrificePermanentTriggeredAbility(
|
||||
new DrawCardSourceControllerEffect(1),
|
||||
StaticFilters.FILTER_PERMANENT_ENCHANTMENT
|
||||
));
|
||||
|
||||
// Whenever the final chapter ability of a Saga you control resolves, each opponent loses X life and you gain X life, where X is that Saga's mana value.
|
||||
this.addAbility(new FinalChapterAbilityResolvesTriggeredAbility(
|
||||
new NarciFableSingerEffect(), true
|
||||
));
|
||||
}
|
||||
|
||||
private NarciFableSinger(final NarciFableSinger card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NarciFableSinger copy() {
|
||||
return new NarciFableSinger(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NarciFableSingerEffect extends OneShotEffect {
|
||||
|
||||
NarciFableSingerEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "each opponent loses X life and you gain X life, where X is that Saga's mana value.";
|
||||
}
|
||||
|
||||
private NarciFableSingerEffect(final NarciFableSingerEffect ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NarciFableSingerEffect copy() {
|
||||
return new NarciFableSingerEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
int value = (int) getValue("SAGA_MANACOST");
|
||||
if (value > 0) {
|
||||
new LoseLifeOpponentsEffect(value).apply(game, source);
|
||||
new GainLifeEffect(value).apply(game, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +1,25 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.SagaAbility;
|
||||
import mage.abilities.common.FinalChapterAbilityResolvesTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.CountersOnPermanentsCondition;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||
import mage.abilities.hint.common.CountersOnPermanentsHint;
|
||||
import mage.abilities.keyword.HexproofAbility;
|
||||
import mage.abilities.keyword.IndestructibleAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
import mage.abilities.hint.common.CountersOnPermanentsHint;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author alexander-novo
|
||||
|
|
@ -49,21 +40,17 @@ public final class TomBombadil extends CardImpl {
|
|||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// As long as there are four or more lore counters among Sagas you control, Tom
|
||||
// Bombadil has hexproof and indestructible.
|
||||
// As long as there are four or more lore counters among Sagas you control, Tom Bombadil has hexproof and indestructible.
|
||||
Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
new GainAbilitySourceEffect(HexproofAbility.getInstance()),
|
||||
condition,
|
||||
"As long as there are four or more lore counters among Sagas you control, {this} has hexproof"));
|
||||
new GainAbilitySourceEffect(HexproofAbility.getInstance()),
|
||||
condition,
|
||||
"As long as there are four or more lore counters among Sagas you control, {this} has hexproof"));
|
||||
ability.addEffect(new ConditionalContinuousEffect(
|
||||
new GainAbilitySourceEffect(IndestructibleAbility.getInstance()), condition, "and indestructible"));
|
||||
new GainAbilitySourceEffect(IndestructibleAbility.getInstance()), condition, "and indestructible"));
|
||||
this.addAbility(ability.addHint(hint));
|
||||
|
||||
// Whenever the final chapter ability of a Saga you control resolves, reveal
|
||||
// cards from the top of your library until you reveal a Saga card. Put that
|
||||
// card onto the battlefield and the rest on the bottom of your library in a
|
||||
// random order. This ability triggers only once each turn.
|
||||
this.addAbility(new TomBombadilTriggeredAbility().setTriggersOnceEachTurn(true));
|
||||
// Whenever the final chapter ability of a Saga you control resolves, reveal cards from the top of your library until you reveal a Saga card. Put that card onto the battlefield and the rest on the bottom of your library in a random order. This ability triggers only once each turn.
|
||||
this.addAbility(new FinalChapterAbilityResolvesTriggeredAbility(new TomBombadilEffect()).setTriggersOnceEachTurn(true));
|
||||
}
|
||||
|
||||
private TomBombadil(final TomBombadil card) {
|
||||
|
|
@ -76,71 +63,6 @@ public final class TomBombadil extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class TomBombadilTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public TomBombadilTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new TomBombadilEffect(), false);
|
||||
setTriggerPhrase("Whenever the final chapter ability of a Saga you control resolves, ");
|
||||
}
|
||||
|
||||
public TomBombadilTriggeredAbility(final TomBombadilTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TomBombadilTriggeredAbility copy() {
|
||||
return new TomBombadilTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.RESOLVING_ABILITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
// At this point, the stack ability no longer exists, so we can only reference
|
||||
// the ability that it came from. For EventType.RESOLVING_ABILITY, targetID is
|
||||
// the ID of the original ability (on the permanent) that the resolving ability
|
||||
// came from.
|
||||
Optional<Ability> ability_opt = game.getAbility(event.getTargetId(), event.getSourceId());
|
||||
if (!ability_opt.isPresent())
|
||||
return false;
|
||||
|
||||
// Make sure it was a triggered ability (needed for checking if it's a chapter
|
||||
// ability)
|
||||
Ability ability = ability_opt.get();
|
||||
if (!(ability instanceof TriggeredAbility))
|
||||
return false;
|
||||
|
||||
// Make sure it was a chapter ability
|
||||
TriggeredAbility triggeredAbility = (TriggeredAbility) ability;
|
||||
if (!SagaAbility.isChapterAbility(triggeredAbility))
|
||||
return false;
|
||||
|
||||
// There's a chance that the permanent that this abiltiy came from no longer
|
||||
// exists, so try and find it on the battlefield or check last known
|
||||
// information.
|
||||
// This permanent is needed to check if the resolving ability was the final
|
||||
// chapter ability on that permanent.
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
|
||||
if (permanent == null
|
||||
|| !permanent.isControlledBy(getControllerId())
|
||||
|| !permanent.hasSubtype(SubType.SAGA, game)) {
|
||||
return false;
|
||||
}
|
||||
// Find the max chapter number from that permanent
|
||||
int maxChapter = CardUtil
|
||||
.castStream(permanent.getAbilities(game).stream(), SagaAbility.class)
|
||||
.map(SagaAbility::getMaxChapter)
|
||||
.mapToInt(SagaChapter::getNumber)
|
||||
.sum();
|
||||
// Check if the ability was the last one
|
||||
return SagaAbility.isFinalAbility(triggeredAbility, maxChapter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// From PrismaticBridgeEffect
|
||||
class TomBombadilEffect extends OneShotEffect {
|
||||
|
||||
|
|
|
|||
|
|
@ -420,6 +420,7 @@ public final class CommanderMasters extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Nadier's Nightblade", 175, Rarity.COMMON, mage.cards.n.NadiersNightblade.class));
|
||||
cards.add(new SetCardInfo("Nahiri, the Harbinger", 929, Rarity.MYTHIC, mage.cards.n.NahiriTheHarbinger.class));
|
||||
cards.add(new SetCardInfo("Nahiri, the Lithomancer", 45, Rarity.RARE, mage.cards.n.NahiriTheLithomancer.class));
|
||||
cards.add(new SetCardInfo("Narci, Fable Singer", 710, Rarity.MYTHIC, mage.cards.n.NarciFableSinger.class));
|
||||
cards.add(new SetCardInfo("Narset of the Ancient Way", 930, Rarity.MYTHIC, mage.cards.n.NarsetOfTheAncientWay.class));
|
||||
cards.add(new SetCardInfo("Narset, Enlightened Master", 931, Rarity.MYTHIC, mage.cards.n.NarsetEnlightenedMaster.class));
|
||||
cards.add(new SetCardInfo("Narset, Parter of Veils", 853, Rarity.UNCOMMON, mage.cards.n.NarsetParterOfVeils.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.SagaChapter;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author alexander-novo, Susucr
|
||||
*/
|
||||
public class FinalChapterAbilityResolvesTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private final boolean rememberSaga;
|
||||
|
||||
public FinalChapterAbilityResolvesTriggeredAbility(Effect effect) {
|
||||
this(effect, false);
|
||||
}
|
||||
|
||||
public FinalChapterAbilityResolvesTriggeredAbility(Effect effect, boolean rememberSaga) {
|
||||
super(Zone.BATTLEFIELD, effect, false);
|
||||
this.rememberSaga = rememberSaga;
|
||||
setTriggerPhrase("Whenever the final chapter ability of a Saga you control resolves, ");
|
||||
}
|
||||
|
||||
private FinalChapterAbilityResolvesTriggeredAbility(final FinalChapterAbilityResolvesTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.rememberSaga = ability.rememberSaga;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FinalChapterAbilityResolvesTriggeredAbility copy() {
|
||||
return new FinalChapterAbilityResolvesTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.RESOLVING_ABILITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
// At this point, the stack ability no longer exists, so we can only reference
|
||||
// the ability that it came from. For EventType.RESOLVING_ABILITY, targetID is
|
||||
// the ID of the original ability (on the permanent) that the resolving ability
|
||||
// came from.
|
||||
Optional<Ability> ability_opt = game.getAbility(event.getTargetId(), event.getSourceId());
|
||||
if (!ability_opt.isPresent())
|
||||
return false;
|
||||
|
||||
// Make sure it was a triggered ability (needed for checking if it's a chapter
|
||||
// ability)
|
||||
Ability ability = ability_opt.get();
|
||||
if (!(ability instanceof TriggeredAbility))
|
||||
return false;
|
||||
|
||||
// Make sure it was a chapter ability
|
||||
TriggeredAbility triggeredAbility = (TriggeredAbility) ability;
|
||||
if (!SagaAbility.isChapterAbility(triggeredAbility))
|
||||
return false;
|
||||
|
||||
// There's a chance that the permanent that this abiltiy came from no longer
|
||||
// exists, so try and find it on the battlefield or check last known
|
||||
// information.
|
||||
// This permanent is needed to check if the resolving ability was the final
|
||||
// chapter ability on that permanent.
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
|
||||
if (permanent == null
|
||||
|| !permanent.isControlledBy(getControllerId())
|
||||
|| !permanent.hasSubtype(SubType.SAGA, game)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the max chapter number from that permanent
|
||||
int maxChapter = CardUtil
|
||||
.castStream(permanent.getAbilities(game).stream(), SagaAbility.class)
|
||||
.map(SagaAbility::getMaxChapter)
|
||||
.mapToInt(SagaChapter::getNumber)
|
||||
.sum();
|
||||
|
||||
// Check if the ability was the last one
|
||||
if (!SagaAbility.isFinalAbility(triggeredAbility, maxChapter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rememberSaga) {
|
||||
getEffects().setTargetPointer(new FixedTarget(permanent.getId(), game));
|
||||
getEffects().setValue("SAGA_MANACOST", permanent.getManaValue());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue