mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
- [KHC] Added Cosmic Intervention, Ethereal Valkyrie, Hero of Bretagard, and Ranar, the Ever-Watchful.
This commit is contained in:
parent
14f7c02b1f
commit
3b8e67c670
7 changed files with 816 additions and 6 deletions
114
Mage.Sets/src/mage/cards/c/CosmicIntervention.java
Normal file
114
Mage.Sets/src/mage/cards/c/CosmicIntervention.java
Normal file
|
@ -0,0 +1,114 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.common.ExileTargetForSourceEffect;
|
||||
import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect;
|
||||
import mage.abilities.keyword.ForetellAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class CosmicIntervention extends CardImpl {
|
||||
|
||||
public CosmicIntervention(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{W}");
|
||||
|
||||
// If a permanent you control would be put into a graveyard from the battlefield this turn, exile it instead. Return it to the battlefield under its owner's control at the beginning of the next end step.
|
||||
this.getSpellAbility().addEffect(new CosmicInterventionReplacementEffect());
|
||||
|
||||
// Foretell 1W
|
||||
this.addAbility(new ForetellAbility(this, "{1}{W}"));
|
||||
|
||||
}
|
||||
|
||||
public CosmicIntervention(final CosmicIntervention card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CosmicIntervention copy() {
|
||||
return new CosmicIntervention(this);
|
||||
}
|
||||
}
|
||||
|
||||
class CosmicInterventionReplacementEffect extends ReplacementEffectImpl {
|
||||
|
||||
CosmicInterventionReplacementEffect() {
|
||||
super(Duration.EndOfTurn, Outcome.Benefit);
|
||||
staticText = "If a permanent you control would be put into a graveyard from the battlefield this turn, exile it instead. Return it to the battlefield under its owner's control at the beginning of the next end step";
|
||||
}
|
||||
|
||||
private CosmicInterventionReplacementEffect(final CosmicInterventionReplacementEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CosmicInterventionReplacementEffect copy() {
|
||||
return new CosmicInterventionReplacementEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null) {
|
||||
Card card = game.getCard(event.getTargetId());
|
||||
if (card != null) {
|
||||
ExileTargetForSourceEffect exileEffect = new ExileTargetForSourceEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(card.getId(), game));
|
||||
exileEffect.apply(game, source);
|
||||
Effect returnEffect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false);
|
||||
returnEffect.setTargetPointer(new FixedTarget(card.getId(), game));
|
||||
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(returnEffect);
|
||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD
|
||||
&& (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD)) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
|
||||
if (permanent == null
|
||||
|| controller == null
|
||||
|| permanent.getControllerId() == controller.getId()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
324
Mage.Sets/src/mage/cards/e/EtherealValkyrie.java
Normal file
324
Mage.Sets/src/mage/cards/e/EtherealValkyrie.java
Normal file
|
@ -0,0 +1,324 @@
|
|||
package mage.cards.e;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.ForetellAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.ModalDoubleFacesCard;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SpellAbilityCastMode;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class EtherealValkyrie extends CardImpl {
|
||||
|
||||
public EtherealValkyrie(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{U}");
|
||||
|
||||
this.subtype.add(SubType.SPIRIT);
|
||||
this.subtype.add(SubType.ANGEL);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Whenever Ethereal Valkyrie enters the battlefield or attacks, draw a card, then exile a card from your hand face down. It becomes foretold. Its foretell cost is its mana cost reduced by {2}.
|
||||
this.addAbility(new EtherealValkyrieTriggeredAbility(new EtherealValkyrieEffect()));
|
||||
|
||||
}
|
||||
|
||||
private EtherealValkyrie(final EtherealValkyrie card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EtherealValkyrie copy() {
|
||||
return new EtherealValkyrie(this);
|
||||
}
|
||||
}
|
||||
|
||||
class EtherealValkyrieTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
EtherealValkyrieTriggeredAbility(Effect effect) {
|
||||
super(Zone.BATTLEFIELD, effect, false);
|
||||
}
|
||||
|
||||
EtherealValkyrieTriggeredAbility(final EtherealValkyrieTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EtherealValkyrieTriggeredAbility copy() {
|
||||
return new EtherealValkyrieTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD
|
||||
|| event.getType() == GameEvent.EventType.ATTACKER_DECLARED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent p = game.getPermanent(event.getSourceId());
|
||||
Permanent pETB = game.getPermanent(event.getTargetId());
|
||||
if (p != null
|
||||
&& p.getId() == sourceId) {
|
||||
return true;
|
||||
}
|
||||
if (pETB != null
|
||||
&& pETB.getId() == sourceId) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} enters the battlefield or attacks, " + super.getRule();
|
||||
}
|
||||
}
|
||||
|
||||
class EtherealValkyrieEffect extends OneShotEffect {
|
||||
|
||||
public EtherealValkyrieEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "draw a card, then exile a card from your hand face down. It becomes foretold. Its foretell cost is its mana cost reduced by {2}";
|
||||
}
|
||||
|
||||
public EtherealValkyrieEffect(final EtherealValkyrieEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EtherealValkyrieEffect copy() {
|
||||
return new EtherealValkyrieEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
controller.drawCards(1, source, game);
|
||||
TargetCardInHand targetCard = new TargetCardInHand(new FilterCard("card to exile face down. It becomes foretold."));
|
||||
if (controller.chooseTarget(Outcome.Benefit, targetCard, source, game)) {
|
||||
Card exileCard = game.getCard(targetCard.getFirstTarget());
|
||||
if (exileCard == null) {
|
||||
return false;
|
||||
}
|
||||
String foretellCost = CardUtil.reduceCost(exileCard.getSpellAbility().getManaCostsToPay(), 2).getText();
|
||||
game.getState().setValue(exileCard.getId().toString() + "Foretell Cost", foretellCost);
|
||||
game.getState().setValue(exileCard.getId().toString() + "Foretell Turn Number", game.getTurnNum());
|
||||
UUID exileId = CardUtil.getExileZoneId(exileCard.getId().toString() + "foretellAbility", game);
|
||||
controller.moveCardsToExile(exileCard, source, game, true, exileId, " Foretell Turn Number: " + game.getTurnNum());
|
||||
exileCard.setFaceDown(true, game);
|
||||
ForetellAbility foretellAbility = new ForetellAbility(exileCard, foretellCost);
|
||||
foretellAbility.setSourceId(exileCard.getId());
|
||||
foretellAbility.setControllerId(exileCard.getOwnerId());
|
||||
game.getState().addOtherAbility(exileCard, foretellAbility);
|
||||
foretellAbility.activate(game, true);
|
||||
game.addEffect(new ForetellAddCostEffect(new MageObjectReference(exileCard, game)), source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class ForetellAddCostEffect extends ContinuousEffectImpl {
|
||||
|
||||
private final MageObjectReference mor;
|
||||
|
||||
public ForetellAddCostEffect(MageObjectReference mor) {
|
||||
super(Duration.EndOfGame, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
|
||||
this.mor = mor;
|
||||
staticText = "Foretold card";
|
||||
}
|
||||
|
||||
public ForetellAddCostEffect(final ForetellAddCostEffect effect) {
|
||||
super(effect);
|
||||
this.mor = effect.mor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Card card = mor.getCard(game);
|
||||
if (card != null
|
||||
&& game.getState().getZone(card.getId()) == Zone.EXILED) {
|
||||
String foretellCost = (String) game.getState().getValue(card.getId().toString() + "Foretell Cost");
|
||||
Ability ability = new ForetellCostAbility(foretellCost);
|
||||
ability.setSourceId(card.getId());
|
||||
ability.setControllerId(source.getControllerId());
|
||||
game.getState().addOtherAbility(card, ability);
|
||||
} else {
|
||||
discard();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForetellAddCostEffect copy() {
|
||||
return new ForetellAddCostEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ForetellCostAbility extends SpellAbility {
|
||||
|
||||
private String abilityName;
|
||||
private SpellAbility spellAbilityToResolve;
|
||||
|
||||
public ForetellCostAbility(String foretellCost) {
|
||||
super(null, "Testing", Zone.EXILED, SpellAbilityType.BASE_ALTERNATE, SpellAbilityCastMode.NORMAL);
|
||||
this.setAdditionalCostsRuleVisible(false);
|
||||
this.name = "Foretell " + foretellCost;
|
||||
this.addCost(new ManaCostsImpl(foretellCost));
|
||||
}
|
||||
|
||||
public ForetellCostAbility(final ForetellCostAbility ability) {
|
||||
super(ability);
|
||||
this.spellAbilityType = ability.spellAbilityType;
|
||||
this.abilityName = ability.abilityName;
|
||||
this.spellAbilityToResolve = ability.spellAbilityToResolve;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivatedAbility.ActivationStatus canActivate(UUID playerId, Game game) {
|
||||
if (super.canActivate(playerId, game).canActivate()) {
|
||||
Card card = game.getCard(getSourceId());
|
||||
if (card != null) {
|
||||
// Card must be in the exile zone
|
||||
if (game.getState().getZone(card.getId()) != Zone.EXILED) {
|
||||
return ActivatedAbility.ActivationStatus.getFalse();
|
||||
}
|
||||
// Card must be Foretold
|
||||
if (game.getState().getValue(card.getId().toString() + "Foretell Turn Number") == null
|
||||
&& game.getState().getValue(card.getId().toString() + "foretellAbility") == null) {
|
||||
return ActivatedAbility.ActivationStatus.getFalse();
|
||||
}
|
||||
// Can't be cast if the turn it was Foretold is the same
|
||||
if ((int) game.getState().getValue(card.getId().toString() + "Foretell Turn Number") == game.getTurnNum()) {
|
||||
return ActivatedAbility.ActivationStatus.getFalse();
|
||||
}
|
||||
// Check that the card is actually in the exile zone (ex: Oblivion Ring exiles it after it was Foretold, etc)
|
||||
UUID exileId = (UUID) game.getState().getValue(card.getId().toString() + "foretellAbility");
|
||||
ExileZone exileZone = game.getState().getExile().getExileZone(exileId);
|
||||
if (exileZone != null
|
||||
&& exileZone.isEmpty()) {
|
||||
return ActivatedAbility.ActivationStatus.getFalse();
|
||||
}
|
||||
if (card instanceof SplitCard) {
|
||||
if (((SplitCard) card).getLeftHalfCard().getName().equals(abilityName)) {
|
||||
return ((SplitCard) card).getLeftHalfCard().getSpellAbility().canActivate(playerId, game);
|
||||
} else if (((SplitCard) card).getRightHalfCard().getName().equals(abilityName)) {
|
||||
return ((SplitCard) card).getRightHalfCard().getSpellAbility().canActivate(playerId, game);
|
||||
}
|
||||
} else if (card instanceof ModalDoubleFacesCard) {
|
||||
if (((ModalDoubleFacesCard) card).getLeftHalfCard().getName().equals(abilityName)) {
|
||||
return ((ModalDoubleFacesCard) card).getLeftHalfCard().getSpellAbility().canActivate(playerId, game);
|
||||
} else if (((ModalDoubleFacesCard) card).getRightHalfCard().getName().equals(abilityName)) {
|
||||
return ((ModalDoubleFacesCard) card).getRightHalfCard().getSpellAbility().canActivate(playerId, game);
|
||||
}
|
||||
}
|
||||
return card.getSpellAbility().canActivate(playerId, game);
|
||||
}
|
||||
}
|
||||
return ActivatedAbility.ActivationStatus.getFalse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAbility getSpellAbilityToResolve(Game game) {
|
||||
Card card = game.getCard(getSourceId());
|
||||
if (card != null) {
|
||||
if (spellAbilityToResolve == null) {
|
||||
SpellAbility spellAbilityCopy = null;
|
||||
if (card instanceof SplitCard) {
|
||||
if (((SplitCard) card).getLeftHalfCard().getName().equals(abilityName)) {
|
||||
spellAbilityCopy = ((SplitCard) card).getLeftHalfCard().getSpellAbility().copy();
|
||||
} else if (((SplitCard) card).getRightHalfCard().getName().equals(abilityName)) {
|
||||
spellAbilityCopy = ((SplitCard) card).getRightHalfCard().getSpellAbility().copy();
|
||||
}
|
||||
} else if (card instanceof ModalDoubleFacesCard) {
|
||||
if (((ModalDoubleFacesCard) card).getLeftHalfCard().getName().equals(abilityName)) {
|
||||
spellAbilityCopy = ((ModalDoubleFacesCard) card).getLeftHalfCard().getSpellAbility().copy();
|
||||
} else if (((ModalDoubleFacesCard) card).getRightHalfCard().getName().equals(abilityName)) {
|
||||
spellAbilityCopy = ((ModalDoubleFacesCard) card).getRightHalfCard().getSpellAbility().copy();
|
||||
}
|
||||
} else {
|
||||
spellAbilityCopy = card.getSpellAbility().copy();
|
||||
}
|
||||
if (spellAbilityCopy == null) {
|
||||
return null;
|
||||
}
|
||||
spellAbilityCopy.setId(this.getId());
|
||||
spellAbilityCopy.getManaCosts().clear();
|
||||
spellAbilityCopy.getManaCostsToPay().clear();
|
||||
spellAbilityCopy.getCosts().addAll(this.getCosts().copy());
|
||||
spellAbilityCopy.addCost(this.getManaCosts().copy());
|
||||
spellAbilityCopy.setSpellAbilityCastMode(this.getSpellAbilityCastMode());
|
||||
spellAbilityToResolve = spellAbilityCopy;
|
||||
}
|
||||
}
|
||||
return spellAbilityToResolve;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Costs<Cost> getCosts() {
|
||||
if (spellAbilityToResolve == null) {
|
||||
return super.getCosts();
|
||||
}
|
||||
return spellAbilityToResolve.getCosts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForetellCostAbility copy() {
|
||||
return new ForetellCostAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule(boolean all) {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for split card in PlayerImpl method:
|
||||
* getOtherUseableActivatedAbilities
|
||||
*
|
||||
* @param abilityName
|
||||
*/
|
||||
public void setAbilityName(String abilityName) {
|
||||
this.abilityName = abilityName;
|
||||
}
|
||||
|
||||
}
|
195
Mage.Sets/src/mage/cards/h/HeroOfBretagard.java
Normal file
195
Mage.Sets/src/mage/cards/h/HeroOfBretagard.java
Normal file
|
@ -0,0 +1,195 @@
|
|||
package mage.cards.h;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.SourceMatchesFilterCondition;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.AddCardSubTypeSourceEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.IndestructibleAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.filter.predicate.Predicate;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class HeroOfBretagard extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent();
|
||||
|
||||
static {
|
||||
filter.add(test1.instance);
|
||||
filter2.add(test2.instance);
|
||||
}
|
||||
|
||||
public HeroOfBretagard(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
|
||||
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.WARRIOR);
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// Whenever you exile one or more cards from your hand and/or permanents from the battlefield, put that many +1/+1 counters on Hero of Bretagard.
|
||||
this.addAbility(new HeroOfBretagardTriggeredAbility(new HeroOfBretagardEffect()));
|
||||
|
||||
// As long as Hero of Bretagard has five or more counters on it, it has flying and is an Angel in addition to its other types.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||
new ConditionalContinuousEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield),
|
||||
new SourceMatchesFilterCondition(filter),
|
||||
"As long as Hero of Bretagard has five or more counters on it, it has flying ")));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||
new ConditionalContinuousEffect(new AddCardSubTypeSourceEffect(Duration.WhileOnBattlefield, SubType.ANGEL), new SourceMatchesFilterCondition(filter),
|
||||
"and is an Angel in addition to its other types.")));
|
||||
|
||||
// As long as Hero of Bretagard has ten or more counters on it, it has indestructible and is a God in addition to its other types.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||
new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
|
||||
new SourceMatchesFilterCondition(filter2),
|
||||
"As long as Hero of Bretagard has ten or more counters on it, it has indestructible ")));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||
new ConditionalContinuousEffect(new AddCardSubTypeSourceEffect(Duration.WhileOnBattlefield, SubType.GOD), new SourceMatchesFilterCondition(filter2),
|
||||
"and is a God in addition to its other types.")));
|
||||
|
||||
}
|
||||
|
||||
private HeroOfBretagard(final HeroOfBretagard card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeroOfBretagard copy() {
|
||||
return new HeroOfBretagard(this);
|
||||
}
|
||||
}
|
||||
|
||||
class HeroOfBretagardTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
HeroOfBretagardTriggeredAbility(Effect effect) {
|
||||
super(Zone.BATTLEFIELD, effect, false);
|
||||
}
|
||||
|
||||
HeroOfBretagardTriggeredAbility(final HeroOfBretagardTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeroOfBretagardTriggeredAbility copy() {
|
||||
return new HeroOfBretagardTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
if (zEvent != null
|
||||
&& Zone.HAND == zEvent.getFromZone()
|
||||
&& Zone.EXILED == zEvent.getToZone()
|
||||
&& zEvent.getTargetId() != null) {
|
||||
Card card = game.getCard(zEvent.getTargetId());
|
||||
if (card != null) {
|
||||
UUID cardOwnerId = card.getOwnerId();
|
||||
if (cardOwnerId != null
|
||||
&& card.isOwnedBy(getControllerId())) {
|
||||
this.getEffects().get(0).setValue("number", 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (zEvent != null
|
||||
&& Zone.BATTLEFIELD == zEvent.getFromZone()
|
||||
&& Zone.EXILED == zEvent.getToZone()
|
||||
&& zEvent.getTargetId() != null) {
|
||||
Card card = game.getCard(zEvent.getTargetId());
|
||||
if (card != null) {
|
||||
UUID cardOwnerId = card.getOwnerId();
|
||||
if (cardOwnerId != null
|
||||
&& card.isOwnedBy(getControllerId())) {
|
||||
this.getEffects().get(0).setValue("number", 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever you exile one or more cards from your hand and/or permanents from the battlefield, put that many +1/+1 counters on {this}";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class HeroOfBretagardEffect extends OneShotEffect {
|
||||
|
||||
public HeroOfBretagardEffect() {
|
||||
super(Outcome.Benefit);
|
||||
}
|
||||
|
||||
public HeroOfBretagardEffect(final HeroOfBretagardEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeroOfBretagardEffect copy() {
|
||||
return new HeroOfBretagardEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return new AddCountersSourceEffect(CounterType.P1P1.createInstance((Integer) this.getValue("number"))).apply(game, source);
|
||||
}
|
||||
}
|
||||
|
||||
enum test1 implements Predicate<Permanent> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
return input.getCounters(game).values().stream().anyMatch(counter -> counter.getCount() > 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "any counter";
|
||||
}
|
||||
}
|
||||
|
||||
enum test2 implements Predicate<Permanent> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
return input.getCounters(game).values().stream().anyMatch(counter -> counter.getCount() > 9);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "any counter";
|
||||
}
|
||||
}
|
149
Mage.Sets/src/mage/cards/r/RanarTheEverWatchful.java
Normal file
149
Mage.Sets/src/mage/cards/r/RanarTheEverWatchful.java
Normal file
|
@ -0,0 +1,149 @@
|
|||
package mage.cards.r;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.ForetellAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeGroupEvent;
|
||||
import mage.game.permanent.token.SpiritWhiteToken;
|
||||
import mage.watchers.common.ForetoldWatcher;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class RanarTheEverWatchful extends CardImpl {
|
||||
|
||||
public RanarTheEverWatchful(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}");
|
||||
|
||||
this.addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.SPIRIT);
|
||||
this.subtype.add(SubType.WARRIOR);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Vigilance
|
||||
this.addAbility(VigilanceAbility.getInstance());
|
||||
|
||||
// The first card you foretell each turn costs 0 to foretell
|
||||
Ability ability = new SimpleStaticAbility(new RanarTheEverWatchfulCostReductionEffect());
|
||||
this.addAbility(ability);
|
||||
|
||||
// Whenever you exile one or more cards from your hand and/or permanents from the battlefield, create a 1/1 white Spirit creature token with flying.
|
||||
this.addAbility(new RanarTheEverWatchfulTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken())));
|
||||
|
||||
}
|
||||
|
||||
private RanarTheEverWatchful(final RanarTheEverWatchful card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RanarTheEverWatchful copy() {
|
||||
return new RanarTheEverWatchful(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RanarTheEverWatchfulCostReductionEffect extends CostModificationEffectImpl {
|
||||
|
||||
RanarTheEverWatchfulCostReductionEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Neutral, CostModificationType.REDUCE_COST);
|
||||
staticText = "The first card you foretell each turn costs 0 to foretell";
|
||||
}
|
||||
|
||||
private RanarTheEverWatchfulCostReductionEffect(RanarTheEverWatchfulCostReductionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RanarTheEverWatchfulCostReductionEffect copy() {
|
||||
return new RanarTheEverWatchfulCostReductionEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
abilityToModify.getManaCostsToPay().clear();
|
||||
abilityToModify.getManaCostsToPay().addAll(new ManaCostsImpl<>("{0}"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
ForetoldWatcher watcher = game.getState().getWatcher(ForetoldWatcher.class);
|
||||
return (watcher != null
|
||||
&& watcher.countNumberForetellThisTurn() == 0
|
||||
&& abilityToModify.isControlledBy(source.getControllerId())
|
||||
&& abilityToModify instanceof ForetellAbility);
|
||||
}
|
||||
}
|
||||
|
||||
class RanarTheEverWatchfulTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
RanarTheEverWatchfulTriggeredAbility(Effect effect) {
|
||||
super(Zone.BATTLEFIELD, effect, false);
|
||||
}
|
||||
|
||||
RanarTheEverWatchfulTriggeredAbility(final RanarTheEverWatchfulTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RanarTheEverWatchfulTriggeredAbility copy() {
|
||||
return new RanarTheEverWatchfulTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE_GROUP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
ZoneChangeGroupEvent zEvent = (ZoneChangeGroupEvent) event;
|
||||
if (zEvent != null
|
||||
&& Zone.HAND == zEvent.getFromZone()
|
||||
&& Zone.EXILED == zEvent.getToZone()
|
||||
&& zEvent.getCards() != null) {
|
||||
for (Card card : zEvent.getCards()) {
|
||||
if (card != null) {
|
||||
UUID cardOwnerId = card.getOwnerId();
|
||||
if (cardOwnerId != null
|
||||
&& card.isOwnedBy(getControllerId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (zEvent != null
|
||||
&& Zone.BATTLEFIELD == zEvent.getFromZone()
|
||||
&& Zone.EXILED == zEvent.getToZone()
|
||||
&& zEvent.getCards() != null) {
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever you exile one or more cards from your hand and/or permanents from the battlefield, " + super.getRule();
|
||||
}
|
||||
}
|
|
@ -39,6 +39,7 @@ public final class KaldheimCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Cloudgoat Ranger", 21, Rarity.UNCOMMON, mage.cards.c.CloudgoatRanger.class));
|
||||
cards.add(new SetCardInfo("Command Tower", 108, Rarity.COMMON, mage.cards.c.CommandTower.class));
|
||||
cards.add(new SetCardInfo("Commander's Sphere", 99, Rarity.COMMON, mage.cards.c.CommandersSphere.class));
|
||||
cards.add(new SetCardInfo("Cosmic Intervention", 3, Rarity.RARE, mage.cards.c.CosmicIntervention.class));
|
||||
cards.add(new SetCardInfo("Crown of Skemfar", 13, Rarity.RARE, mage.cards.c.CrownOfSkemfar.class));
|
||||
cards.add(new SetCardInfo("Cryptic Caves", 109, Rarity.UNCOMMON, mage.cards.c.CrypticCaves.class));
|
||||
cards.add(new SetCardInfo("Cultivator of Blades", 55, Rarity.RARE, mage.cards.c.CultivatorOfBlades.class));
|
||||
|
@ -53,6 +54,7 @@ public final class KaldheimCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Elvish Rejuvenator", 60, Rarity.COMMON, mage.cards.e.ElvishRejuvenator.class));
|
||||
cards.add(new SetCardInfo("Empyrean Eagle", 85, Rarity.UNCOMMON, mage.cards.e.EmpyreanEagle.class));
|
||||
cards.add(new SetCardInfo("End-Raze Forerunners", 61, Rarity.RARE, mage.cards.e.EndRazeForerunners.class));
|
||||
cards.add(new SetCardInfo("Ethereal Valkyrie", 16, Rarity.RARE, mage.cards.e.EtherealValkyrie.class));
|
||||
cards.add(new SetCardInfo("Evangel of Heliod", 23, Rarity.UNCOMMON, mage.cards.e.EvangelOfHeliod.class));
|
||||
cards.add(new SetCardInfo("Eyeblight Cullers", 48, Rarity.COMMON, mage.cards.e.EyeblightCullers.class));
|
||||
cards.add(new SetCardInfo("Eyeblight Massacre", 49, Rarity.UNCOMMON, mage.cards.e.EyeblightMassacre.class));
|
||||
|
@ -67,6 +69,7 @@ public final class KaldheimCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Golgari Guildgate", 111, Rarity.COMMON, mage.cards.g.GolgariGuildgate.class));
|
||||
cards.add(new SetCardInfo("Golgari Rot Farm", 112, Rarity.UNCOMMON, mage.cards.g.GolgariRotFarm.class));
|
||||
cards.add(new SetCardInfo("Harvest Season", 63, Rarity.RARE, mage.cards.h.HarvestSeason.class));
|
||||
cards.add(new SetCardInfo("Hero of Bretagard", 4, Rarity.RARE, mage.cards.h.HeroOfBretagard.class));
|
||||
cards.add(new SetCardInfo("Imperious Perfect", 64, Rarity.RARE, mage.cards.i.ImperiousPerfect.class));
|
||||
cards.add(new SetCardInfo("Inspired Sphinx", 40, Rarity.MYTHIC, mage.cards.i.InspiredSphinx.class));
|
||||
cards.add(new SetCardInfo("Jagged-Scar Archers", 65, Rarity.UNCOMMON, mage.cards.j.JaggedScarArchers.class));
|
||||
|
@ -100,6 +103,7 @@ public final class KaldheimCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Pride of the Perfect", 52, Rarity.UNCOMMON, mage.cards.p.PrideOfThePerfect.class));
|
||||
cards.add(new SetCardInfo("Prowess of the Fair", 53, Rarity.UNCOMMON, mage.cards.p.ProwessOfTheFair.class));
|
||||
cards.add(new SetCardInfo("Putrefy", 91, Rarity.UNCOMMON, mage.cards.p.Putrefy.class));
|
||||
cards.add(new SetCardInfo("Ranar the Ever-Watchful", 2, Rarity.RARE, mage.cards.r.RanarTheEverWatchful.class));
|
||||
cards.add(new SetCardInfo("Reclamation Sage", 72, Rarity.UNCOMMON, mage.cards.r.ReclamationSage.class));
|
||||
cards.add(new SetCardInfo("Restoration Angel", 31, Rarity.COMMON, mage.cards.r.RestorationAngel.class));
|
||||
cards.add(new SetCardInfo("Return to Dust", 32, Rarity.UNCOMMON, mage.cards.r.ReturnToDust.class));
|
||||
|
|
|
@ -17,7 +17,7 @@ public enum ForetoldCondition implements Condition {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
ForetoldWatcher watcher = game.getState().getWatcher(ForetoldWatcher.class);
|
||||
if (watcher != null) {
|
||||
return watcher.foretoldSpellWasCast(source.getSourceId());
|
||||
return watcher.cardWasForetold(source.getSourceId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -26,4 +26,4 @@ public enum ForetoldCondition implements Condition {
|
|||
public String toString() {
|
||||
return "this spell was foretold";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ package mage.watchers.common;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.keyword.ForetellAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
@ -21,9 +23,9 @@ import mage.watchers.Watcher;
|
|||
* @author jeffwadsworth
|
||||
*/
|
||||
public class ForetoldWatcher extends Watcher {
|
||||
|
||||
// If a card was Foretold during a turn, this list stores it. Cleared at the end of the turn.
|
||||
|
||||
// If foretell was activated or a card was Foretold by the controller this turn, this list stores it. Cleared at the end of the turn.
|
||||
private final Set<UUID> foretellCardsThisTurn = new HashSet<>();
|
||||
private final Set<UUID> foretoldCardsThisTurn = new HashSet<>();
|
||||
|
||||
public ForetoldWatcher() {
|
||||
|
@ -32,10 +34,19 @@ public class ForetoldWatcher extends Watcher {
|
|||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.TAKEN_SPECIAL_ACTION) {
|
||||
Card card = game.getCard(event.getSourceId());
|
||||
if (card != null
|
||||
&& card.getAbilities(game).containsClass(ForetellAbility.class)
|
||||
&& controllerId == event.getPlayerId()) {
|
||||
foretellCardsThisTurn.add(card.getId());
|
||||
}
|
||||
}
|
||||
if (event.getType() == GameEvent.EventType.SPELL_CAST
|
||||
&& event.getZone() == Zone.EXILED) {
|
||||
Spell spell = (Spell) game.getObject(event.getTargetId());
|
||||
if (spell != null) {
|
||||
if (spell != null
|
||||
&& controllerId == event.getPlayerId()) {
|
||||
UUID exileId = CardUtil.getExileZoneId(spell.getSourceId().toString() + "foretellAbility", game);
|
||||
if (exileId != null) {
|
||||
foretoldCardsThisTurn.add(spell.getSourceId());
|
||||
|
@ -44,13 +55,26 @@ public class ForetoldWatcher extends Watcher {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean foretoldSpellWasCast(UUID sourceId) {
|
||||
public boolean cardUsedForetell(UUID sourceId) {
|
||||
return foretellCardsThisTurn.contains(sourceId);
|
||||
}
|
||||
|
||||
public boolean cardWasForetold(UUID sourceId) {
|
||||
return foretoldCardsThisTurn.contains(sourceId);
|
||||
}
|
||||
|
||||
public int countNumberForetellThisTurn() {
|
||||
return foretellCardsThisTurn.size();
|
||||
}
|
||||
|
||||
public int countNumberForetoldThisTurn() {
|
||||
return foretoldCardsThisTurn.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
foretellCardsThisTurn.clear();
|
||||
foretoldCardsThisTurn.clear();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue