mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
Adding targets (Part 2/3) (#13765)
Adds target and/or target adjuster to cards whose abilities have the word "target", cards H-R. fix EffectKeyValue text, NestOfScarabs Add X value to effects for CycleTriggeredAbility, use with ValorsFlagship and SharkTyphoon, add test
This commit is contained in:
parent
7be454fb92
commit
219cc53cf4
24 changed files with 321 additions and 817 deletions
|
|
@ -37,7 +37,7 @@ public final class GaleWaterdeepProdigy extends CardImpl {
|
||||||
// If a spell cast from your graveyard this way would be put into your graveyard, exile it instead.
|
// If a spell cast from your graveyard this way would be put into your graveyard, exile it instead.
|
||||||
Ability ability = new SpellCastControllerTriggeredAbility(Zone.BATTLEFIELD,
|
Ability ability = new SpellCastControllerTriggeredAbility(Zone.BATTLEFIELD,
|
||||||
new MayCastTargetCardEffect(true)
|
new MayCastTargetCardEffect(true)
|
||||||
.setText("you may cast up to one of the other type from your graveyard. If a spell cast from your graveyard this way would be put into your graveyard, exile it instead."),
|
.setText("you may cast up to one target card of the other type from your graveyard. If a spell cast from your graveyard this way would be put into your graveyard, exile it instead."),
|
||||||
StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY,
|
StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY,
|
||||||
false, SetTargetPointer.SPELL, Zone.HAND
|
false, SetTargetPointer.SPELL, Zone.HAND
|
||||||
);
|
);
|
||||||
|
|
@ -84,6 +84,6 @@ enum GaleWaterdeepProdigyAdjuster implements TargetAdjuster {
|
||||||
} else {
|
} else {
|
||||||
filter = SORCERY_FILTER;
|
filter = SORCERY_FILTER;
|
||||||
}
|
}
|
||||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
ability.addTarget(new TargetCardInYourGraveyard(0, 1, filter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,21 @@
|
||||||
package mage.cards.h;
|
package mage.cards.h;
|
||||||
|
|
||||||
import mage.ApprovingObject;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.common.MayCastTargetCardEffect;
|
||||||
import mage.cards.Card;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.SetTargetPointer;
|
||||||
|
import mage.constants.Zone;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.common.FilterInstantOrSorcerySpell;
|
import mage.filter.StaticFilters;
|
||||||
import mage.filter.predicate.mageobject.NamePredicate;
|
import mage.filter.predicate.mageobject.NamePredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.common.TargetCardInYourGraveyard;
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
import mage.watchers.common.CastFromHandWatcher;
|
import mage.target.targetadjustment.TargetAdjuster;
|
||||||
|
import mage.target.targetpointer.FirstTargetPointer;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -26,13 +24,20 @@ import java.util.UUID;
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public final class HarnessTheStorm extends CardImpl {
|
public final class HarnessTheStorm extends CardImpl {
|
||||||
|
static FilterCard filter = new FilterCard("card with the same name as that spell from your graveyard");
|
||||||
|
|
||||||
public HarnessTheStorm(UUID ownerId, CardSetInfo setInfo) {
|
public HarnessTheStorm(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}");
|
||||||
|
|
||||||
// Whenever you cast an instant or sorcery spell from your hand, you may cast
|
// Whenever you cast an instant or sorcery spell from your hand, you may cast
|
||||||
// target card with the same name as that spell from your graveyard.
|
// target card with the same name as that spell from your graveyard.
|
||||||
this.addAbility(new HarnessTheStormTriggeredAbility(), new CastFromHandWatcher());
|
Ability ability = new SpellCastControllerTriggeredAbility(
|
||||||
|
Zone.BATTLEFIELD, new MayCastTargetCardEffect(false), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY,
|
||||||
|
false, SetTargetPointer.SPELL, Zone.HAND
|
||||||
|
);
|
||||||
|
ability.addTarget(new TargetCardInYourGraveyard(filter)); // Only used for text generation
|
||||||
|
ability.setTargetAdjuster(HarnessTheStormAdjuster.instance);
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HarnessTheStorm(final HarnessTheStorm card) {
|
private HarnessTheStorm(final HarnessTheStorm card) {
|
||||||
|
|
@ -45,78 +50,20 @@ public final class HarnessTheStorm extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
enum HarnessTheStormAdjuster implements TargetAdjuster {
|
||||||
class HarnessTheStormTriggeredAbility extends SpellCastControllerTriggeredAbility {
|
instance;
|
||||||
|
|
||||||
private static final FilterInstantOrSorcerySpell filterSpell = new FilterInstantOrSorcerySpell("an instant or sorcery spell from your hand");
|
|
||||||
|
|
||||||
HarnessTheStormTriggeredAbility() {
|
|
||||||
super(new HarnessTheStormEffect(), filterSpell, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private HarnessTheStormTriggeredAbility(final HarnessTheStormTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public void adjustTargets(Ability ability, Game game) {
|
||||||
if (super.checkTrigger(event, game)) {
|
UUID spellId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability);
|
||||||
CastFromHandWatcher watcher = game.getState().getWatcher(CastFromHandWatcher.class);
|
ability.getTargets().clear();
|
||||||
if (watcher != null && watcher.spellWasCastFromHand(event.getSourceId())) {
|
ability.getAllEffects().setTargetPointer(new FirstTargetPointer());
|
||||||
Spell spell = game.getState().getStack().getSpell(event.getSourceId());
|
|
||||||
if (spell != null) {
|
Spell spell = game.getSpellOrLKIStack(spellId);
|
||||||
FilterCard filterCard = new FilterCard("a card named " + spell.getName() + " in your graveyard");
|
if (spell == null){
|
||||||
filterCard.add(new NamePredicate(spell.getName()));
|
return;
|
||||||
this.getTargets().clear();
|
|
||||||
this.getTargets().add(new TargetCardInYourGraveyard(filterCard));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
FilterCard filter = new FilterCard("a card named " + spell.getName() + " in your graveyard");
|
||||||
}
|
filter.add(new NamePredicate(spell.getName()));
|
||||||
|
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||||
@Override
|
|
||||||
public HarnessTheStormTriggeredAbility copy() {
|
|
||||||
return new HarnessTheStormTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class HarnessTheStormEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
HarnessTheStormEffect() {
|
|
||||||
super(Outcome.Benefit);
|
|
||||||
this.staticText = "you may cast target card with the same name as that "
|
|
||||||
+ "spell from your graveyard. <i>(You still pay its costs.)</i>";
|
|
||||||
}
|
|
||||||
|
|
||||||
private HarnessTheStormEffect(final HarnessTheStormEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HarnessTheStormEffect copy() {
|
|
||||||
return new HarnessTheStormEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
|
||||||
if (controller == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Card card = controller.getGraveyard().get(getTargetPointer().getFirst(game, source), game);
|
|
||||||
if (card == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (controller.chooseUse(outcome, "Cast " + card.getIdName() + " from your graveyard?", source, game)) {
|
|
||||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
|
||||||
controller.cast(controller.chooseAbilityForCast(card, game, false),
|
|
||||||
game, false, new ApprovingObject(source, game));
|
|
||||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,21 @@
|
||||||
|
|
||||||
package mage.cards.i;
|
package mage.cards.i;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbility;
|
||||||
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
|
import mage.abilities.common.AttacksTriggeredAbility;
|
||||||
import mage.abilities.effects.common.SacrificeSourceEffect;
|
import mage.abilities.effects.common.SacrificeSourceEffect;
|
||||||
import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect;
|
import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect;
|
||||||
import mage.abilities.keyword.HasteAbility;
|
import mage.abilities.keyword.HasteAbility;
|
||||||
import mage.abilities.keyword.TrampleAbility;
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
|
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.*;
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.Duration;
|
|
||||||
import mage.constants.TargetController;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
|
||||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -39,7 +34,12 @@ public final class ImpetuousDevils extends CardImpl {
|
||||||
// Haste
|
// Haste
|
||||||
this.addAbility(HasteAbility.getInstance());
|
this.addAbility(HasteAbility.getInstance());
|
||||||
// When Impetuous Devils attacks, up to one target creature defending player controls blocks it this combat if able.
|
// When Impetuous Devils attacks, up to one target creature defending player controls blocks it this combat if able.
|
||||||
this.addAbility(new ImpetuousDevilsAbility());
|
TriggeredAbility ability = new AttacksTriggeredAbility(new MustBeBlockedByTargetSourceEffect(Duration.EndOfCombat)
|
||||||
|
.setText("up to one target creature defending player controls blocks it this combat if able"), false, null, SetTargetPointer.PLAYER);
|
||||||
|
ability.setTriggerPhrase("When {this} attacks, ");
|
||||||
|
ability.addTarget(new TargetCreaturePermanent(0, 1));
|
||||||
|
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
// At the beginning of the end step, sacrifice Impetuous Devils.
|
// At the beginning of the end step, sacrifice Impetuous Devils.
|
||||||
this.addAbility(new BeginningOfEndStepTriggeredAbility(TargetController.NEXT, new SacrificeSourceEffect(), false));
|
this.addAbility(new BeginningOfEndStepTriggeredAbility(TargetController.NEXT, new SacrificeSourceEffect(), false));
|
||||||
|
|
@ -54,44 +54,3 @@ public final class ImpetuousDevils extends CardImpl {
|
||||||
return new ImpetuousDevils(this);
|
return new ImpetuousDevils(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImpetuousDevilsAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
public ImpetuousDevilsAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(Duration.EndOfCombat), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ImpetuousDevilsAbility(final ImpetuousDevilsAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.ATTACKER_DECLARED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (event.getSourceId().equals(this.getSourceId())) {
|
|
||||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls");
|
|
||||||
UUID defenderId = game.getCombat().getDefendingPlayerId(sourceId, game);
|
|
||||||
filter.add(new ControllerIdPredicate(defenderId));
|
|
||||||
|
|
||||||
this.getTargets().clear();
|
|
||||||
TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false);
|
|
||||||
this.addTarget(target);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "When {this} attacks, up to one target creature defending player controls blocks it this combat if able.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ImpetuousDevilsAbility copy() {
|
|
||||||
return new ImpetuousDevilsAbility(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
package mage.cards.k;
|
package mage.cards.k;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
|
|
@ -15,6 +14,9 @@ import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.targetadjustment.DefineByTriggerTargetAdjuster;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -25,7 +27,6 @@ public final class KarmicJustice extends CardImpl {
|
||||||
public KarmicJustice(UUID ownerId, CardSetInfo setInfo) {
|
public KarmicJustice(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}");
|
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}");
|
||||||
|
|
||||||
|
|
||||||
// Whenever a spell or ability an opponent controls destroys a noncreature permanent you control, you may destroy target permanent that opponent controls.
|
// Whenever a spell or ability an opponent controls destroys a noncreature permanent you control, you may destroy target permanent that opponent controls.
|
||||||
this.addAbility(new KarmicJusticeTriggeredAbility());
|
this.addAbility(new KarmicJusticeTriggeredAbility());
|
||||||
}
|
}
|
||||||
|
|
@ -45,6 +46,7 @@ class KarmicJusticeTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
KarmicJusticeTriggeredAbility() {
|
KarmicJusticeTriggeredAbility() {
|
||||||
super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true);
|
super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true);
|
||||||
this.setLeavesTheBattlefieldTrigger(true);
|
this.setLeavesTheBattlefieldTrigger(true);
|
||||||
|
this.setTargetAdjuster(DefineByTriggerTargetAdjuster.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KarmicJusticeTriggeredAbility(final KarmicJusticeTriggeredAbility ability) {
|
private KarmicJusticeTriggeredAbility(final KarmicJusticeTriggeredAbility ability) {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
package mage.cards.m;
|
package mage.cards.m;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.AttacksTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
|
@ -13,21 +13,21 @@ import mage.abilities.effects.common.UntapSourceEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.events.GameEvent.EventType;
|
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author fireshoes
|
* @author fireshoes
|
||||||
*/
|
*/
|
||||||
public final class MageRingResponder extends CardImpl {
|
public final class MageRingResponder extends CardImpl {
|
||||||
|
private static final FilterCreaturePermanent filter
|
||||||
|
= new FilterCreaturePermanent("creature defending player controls");
|
||||||
public MageRingResponder(UUID ownerId, CardSetInfo setInfo) {
|
public MageRingResponder(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{7}");
|
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{7}");
|
||||||
this.subtype.add(SubType.GOLEM);
|
this.subtype.add(SubType.GOLEM);
|
||||||
|
|
@ -41,7 +41,10 @@ public final class MageRingResponder extends CardImpl {
|
||||||
this.addAbility(new SimpleActivatedAbility(new UntapSourceEffect(), new ManaCostsImpl<>("{7}")));
|
this.addAbility(new SimpleActivatedAbility(new UntapSourceEffect(), new ManaCostsImpl<>("{7}")));
|
||||||
|
|
||||||
// Whenever Mage-Ring Responder attacks, it deals 7 damage to target creature defending player controls.
|
// Whenever Mage-Ring Responder attacks, it deals 7 damage to target creature defending player controls.
|
||||||
this.addAbility(new MageRingResponderAbility());
|
Ability ability = new AttacksTriggeredAbility(new DamageTargetEffect(7), false, null, SetTargetPointer.PLAYER);
|
||||||
|
ability.addTarget(new TargetCreaturePermanent(filter));
|
||||||
|
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MageRingResponder(final MageRingResponder card) {
|
private MageRingResponder(final MageRingResponder card) {
|
||||||
|
|
@ -53,44 +56,3 @@ public final class MageRingResponder extends CardImpl {
|
||||||
return new MageRingResponder(this);
|
return new MageRingResponder(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MageRingResponderAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
public MageRingResponderAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new DamageTargetEffect(7));
|
|
||||||
}
|
|
||||||
|
|
||||||
private MageRingResponderAbility(final MageRingResponderAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.ATTACKER_DECLARED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (event.getSourceId().equals(this.getSourceId())) {
|
|
||||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls");
|
|
||||||
UUID defenderId = game.getCombat().getDefenderId(sourceId);
|
|
||||||
filter.add(new ControllerIdPredicate(defenderId));
|
|
||||||
|
|
||||||
this.getTargets().clear();
|
|
||||||
TargetCreaturePermanent target = new TargetCreaturePermanent(filter);
|
|
||||||
this.addTarget(target);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "Whenever {this} attacks, it deals 7 damage to target creature defending player controls.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MageRingResponderAbility copy() {
|
|
||||||
return new MageRingResponderAbility(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,32 @@
|
||||||
|
|
||||||
package mage.cards.m;
|
package mage.cards.m;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
|
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.TargetController;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.targetadjustment.TargetAdjuster;
|
||||||
|
import mage.target.targetpointer.FirstTargetPointer;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
|
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
|
||||||
*/
|
*/
|
||||||
public final class MagusOfTheAbyss extends CardImpl {
|
public final class MagusOfTheAbyss extends CardImpl {
|
||||||
|
static FilterPermanent filter = new FilterPermanent("nonartifact creature that player controls of their choice");
|
||||||
|
|
||||||
public MagusOfTheAbyss(UUID ownerId, CardSetInfo setInfo) {
|
public MagusOfTheAbyss(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}");
|
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}");
|
||||||
|
|
@ -33,7 +36,11 @@ public final class MagusOfTheAbyss extends CardImpl {
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
// At the beginning of each player's upkeep, destroy target nonartifact creature that player controls of their choice. It can't be regenerated.
|
// At the beginning of each player's upkeep, destroy target nonartifact creature that player controls of their choice. It can't be regenerated.
|
||||||
this.addAbility(new MagusOfTheAbyssTriggeredAbility());
|
Ability ability = new BeginningOfUpkeepTriggeredAbility(TargetController.EACH_PLAYER,
|
||||||
|
new DestroyTargetEffect(true), false).withTargetPointerSet(true);
|
||||||
|
ability.addTarget(new TargetPermanent(filter)); // Only used for text generation
|
||||||
|
ability.setTargetAdjuster(MagusOfTheAbyssTargetAdjuster.instance);
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MagusOfTheAbyss(final MagusOfTheAbyss card) {
|
private MagusOfTheAbyss(final MagusOfTheAbyss card) {
|
||||||
|
|
@ -46,45 +53,24 @@ public final class MagusOfTheAbyss extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MagusOfTheAbyssTriggeredAbility extends TriggeredAbilityImpl {
|
enum MagusOfTheAbyssTargetAdjuster implements TargetAdjuster {
|
||||||
|
instance;
|
||||||
MagusOfTheAbyssTriggeredAbility() {
|
private static final FilterPermanent filter
|
||||||
super(Zone.BATTLEFIELD, new DestroyTargetEffect(true), false);
|
= new FilterPermanent("nonartifact creature that player controls of their choice");
|
||||||
|
static {
|
||||||
|
filter.add(Predicates.not(CardType.ARTIFACT.getPredicate()));
|
||||||
|
filter.add(CardType.CREATURE.getPredicate());
|
||||||
}
|
}
|
||||||
|
|
||||||
private MagusOfTheAbyssTriggeredAbility(final MagusOfTheAbyssTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MagusOfTheAbyssTriggeredAbility copy() {
|
public void adjustTargets(Ability ability, Game game) {
|
||||||
return new MagusOfTheAbyssTriggeredAbility(this);
|
UUID opponentId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability);
|
||||||
}
|
ability.getTargets().clear();
|
||||||
|
ability.getAllEffects().setTargetPointer(new FirstTargetPointer());
|
||||||
|
|
||||||
@Override
|
FilterPermanent adjustedFilter = filter.copy();
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
adjustedFilter.add(new ControllerIdPredicate(opponentId));
|
||||||
return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE;
|
Target newTarget = new TargetPermanent(adjustedFilter);
|
||||||
}
|
newTarget.setTargetController(opponentId);
|
||||||
|
ability.addTarget(newTarget);
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
Player player = game.getPlayer(event.getPlayerId());
|
|
||||||
if (player != null) {
|
|
||||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("nonartifact creature you control");
|
|
||||||
filter.add(Predicates.not(CardType.ARTIFACT.getPredicate()));
|
|
||||||
filter.add(new ControllerIdPredicate(player.getId()));
|
|
||||||
Target target = new TargetCreaturePermanent(filter);
|
|
||||||
target.setAbilityController(getControllerId());
|
|
||||||
target.setTargetController(player.getId());
|
|
||||||
this.getTargets().clear();
|
|
||||||
this.getTargets().add(target);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "At the beginning of each player's upkeep, destroy target nonartifact creature that player controls of their choice. It can't be regenerated.";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
package mage.cards.m;
|
package mage.cards.m;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility;
|
||||||
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
|
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
|
||||||
import mage.abilities.effects.common.TapTargetEffect;
|
import mage.abilities.effects.common.TapTargetEffect;
|
||||||
import mage.abilities.keyword.FlyingAbility;
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
|
@ -11,13 +11,10 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
import mage.target.common.TargetLandPermanent;
|
||||||
import mage.filter.common.FilterLandPermanent;
|
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
|
||||||
import mage.game.Game;
|
import java.util.UUID;
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.Permanent;
|
|
||||||
import mage.target.TargetPermanent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -34,7 +31,11 @@ public final class ManaSkimmer extends CardImpl {
|
||||||
// Flying
|
// Flying
|
||||||
this.addAbility(FlyingAbility.getInstance());
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
// Whenever Mana Skimmer deals damage to a player, tap target land that player controls. That land doesn't untap during its controller's next untap step.
|
// Whenever Mana Skimmer deals damage to a player, tap target land that player controls. That land doesn't untap during its controller's next untap step.
|
||||||
this.addAbility(new ManaSkimmerTriggeredAbility());
|
Ability ability = new DealsDamageToAPlayerTriggeredAbility(new TapTargetEffect(), false, true);
|
||||||
|
ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect("That land"));
|
||||||
|
ability.addTarget(new TargetLandPermanent().withTargetName("target land that player controls"));
|
||||||
|
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ManaSkimmer(final ManaSkimmer card) {
|
private ManaSkimmer(final ManaSkimmer card) {
|
||||||
|
|
@ -46,44 +47,3 @@ public final class ManaSkimmer extends CardImpl {
|
||||||
return new ManaSkimmer(this);
|
return new ManaSkimmer(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ManaSkimmerTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
ManaSkimmerTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new TapTargetEffect(), false);
|
|
||||||
addEffect(new DontUntapInControllersNextUntapStepTargetEffect());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ManaSkimmerTriggeredAbility(final ManaSkimmerTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ManaSkimmerTriggeredAbility copy() {
|
|
||||||
return new ManaSkimmerTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
Permanent source = game.getPermanent(event.getSourceId());
|
|
||||||
if (source != null && source.getId().equals(this.getSourceId())) {
|
|
||||||
FilterLandPermanent filter = new FilterLandPermanent("land that player controls");
|
|
||||||
filter.add(new ControllerIdPredicate(event.getPlayerId()));
|
|
||||||
filter.setMessage("land controlled by " + game.getPlayer(event.getTargetId()).getLogName());
|
|
||||||
this.getTargets().clear();
|
|
||||||
this.addTarget(new TargetPermanent(filter));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "Whenever {this} deals damage to a player, tap target land that player controls. That land doesn't untap during its controller's next untap step.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,31 @@
|
||||||
|
|
||||||
package mage.cards.m;
|
package mage.cards.m;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
|
||||||
import mage.cards.Card;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.SubType;
|
||||||
import mage.filter.common.FilterCreatureCard;
|
import mage.filter.common.FilterCreatureCard;
|
||||||
import mage.filter.predicate.card.OwnerIdPredicate;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
import mage.target.common.TargetCardInGraveyard;
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
import mage.target.common.TargetOpponent;
|
import mage.target.common.TargetOpponent;
|
||||||
|
import mage.target.targetadjustment.TargetAdjuster;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public final class MausoleumTurnkey extends CardImpl {
|
public final class MausoleumTurnkey extends CardImpl {
|
||||||
|
static FilterCreatureCard filter = new FilterCreatureCard("creature card of an opponent's choice");
|
||||||
|
|
||||||
public MausoleumTurnkey(UUID ownerId, CardSetInfo setInfo) {
|
public MausoleumTurnkey(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
|
||||||
|
|
@ -36,8 +36,10 @@ public final class MausoleumTurnkey extends CardImpl {
|
||||||
this.toughness = new MageInt(2);
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
// When Mausoleum Turnkey enters the battlefield, return target creature card of an opponent's choice from your graveyard to your hand.
|
// When Mausoleum Turnkey enters the battlefield, return target creature card of an opponent's choice from your graveyard to your hand.
|
||||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new MausoleumTurnkeyEffect(), false));
|
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect());
|
||||||
|
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||||
|
ability.setTargetAdjuster(MausoleumTurnkeyAdjuster.instance);
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MausoleumTurnkey(final MausoleumTurnkey card) {
|
private MausoleumTurnkey(final MausoleumTurnkey card) {
|
||||||
|
|
@ -50,50 +52,27 @@ public final class MausoleumTurnkey extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MausoleumTurnkeyEffect extends OneShotEffect {
|
// Exact copy of KarplusanMinotaurAdjuster
|
||||||
|
enum MausoleumTurnkeyAdjuster implements TargetAdjuster {
|
||||||
MausoleumTurnkeyEffect() {
|
instance;
|
||||||
super(Outcome.Benefit);
|
|
||||||
this.staticText = "return target creature card of an opponent's choice from your graveyard to your hand";
|
|
||||||
}
|
|
||||||
|
|
||||||
private MausoleumTurnkeyEffect(final MausoleumTurnkeyEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MausoleumTurnkeyEffect copy() {
|
public void adjustTargets(Ability ability, Game game) {
|
||||||
return new MausoleumTurnkeyEffect(this);
|
Player controller = game.getPlayer(ability.getControllerId());
|
||||||
}
|
if (controller == null) {
|
||||||
|
return;
|
||||||
@Override
|
}
|
||||||
public boolean apply(Game game, Ability source) {
|
UUID opponentId = null;
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
if (game.getOpponents(controller.getId()).size() > 1) {
|
||||||
if (controller != null) {
|
Target target = new TargetOpponent(true);
|
||||||
UUID opponentId = null;
|
if (controller.chooseTarget(Outcome.Neutral, target, ability, game)) {
|
||||||
if (game.getOpponents(controller.getId()).size() > 1) {
|
opponentId = target.getFirstTarget();
|
||||||
Target target = new TargetOpponent(true);
|
}
|
||||||
if (controller.chooseTarget(outcome, target, source, game)) {
|
} else {
|
||||||
opponentId = target.getFirstTarget();
|
opponentId = game.getOpponents(controller.getId()).iterator().next();
|
||||||
}
|
}
|
||||||
} else {
|
if (opponentId != null) {
|
||||||
opponentId = game.getOpponents(controller.getId()).iterator().next();
|
ability.getTargets().get(0).setTargetController(opponentId);
|
||||||
}
|
|
||||||
if (opponentId != null) {
|
|
||||||
Player opponent = game.getPlayer(opponentId);
|
|
||||||
if (opponent != null) {
|
|
||||||
FilterCreatureCard filter = new FilterCreatureCard("creature card from " + controller.getLogName() + " graveyard");
|
|
||||||
filter.add(new OwnerIdPredicate(controller.getId()));
|
|
||||||
Target target = new TargetCardInGraveyard(filter);
|
|
||||||
opponent.chooseTarget(outcome, target, source, game);
|
|
||||||
Card card = game.getCard(target.getFirstTarget());
|
|
||||||
if (card != null) {
|
|
||||||
controller.moveCards(card, Zone.HAND, source, game);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,30 @@
|
||||||
|
|
||||||
package mage.cards.n;
|
package mage.cards.n;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility;
|
import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility;
|
||||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||||
import mage.abilities.effects.Effect;
|
|
||||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
import mage.abilities.effects.common.DoIfCostPaid;
|
import mage.abilities.effects.common.DoIfCostPaid;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.target.Target;
|
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author MarcoMarin
|
* @author MarcoMarin
|
||||||
*/
|
*/
|
||||||
public final class Necrite extends CardImpl {
|
public final class Necrite extends CardImpl {
|
||||||
|
static FilterPermanent filter = new FilterCreaturePermanent("creature defending player controls");
|
||||||
|
|
||||||
public Necrite(UUID ownerId, CardSetInfo setInfo) {
|
public Necrite(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}");
|
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}");
|
||||||
|
|
@ -35,10 +34,10 @@ public final class Necrite extends CardImpl {
|
||||||
|
|
||||||
// Whenever Necrite attacks and isn't blocked, you may sacrifice it. If you do, destroy target creature defending player controls. It can't be regenerated.
|
// Whenever Necrite attacks and isn't blocked, you may sacrifice it. If you do, destroy target creature defending player controls. It can't be regenerated.
|
||||||
DoIfCostPaid effect = new DoIfCostPaid(new DestroyTargetEffect(true), new SacrificeSourceCost(), "Sacrifice {this} to destroy target creature defending player controls?");
|
DoIfCostPaid effect = new DoIfCostPaid(new DestroyTargetEffect(true), new SacrificeSourceCost(), "Sacrifice {this} to destroy target creature defending player controls?");
|
||||||
effect.setText("you may sacrifice it. If you do, destroy target creature defending player controls. It can't be regenerated.");
|
Ability ability = new AttacksAndIsNotBlockedTriggeredAbility(effect, false, SetTargetPointer.PLAYER);
|
||||||
Ability ability = new NecriteTriggeredAbility(effect);
|
ability.addTarget(new TargetPermanent(filter));
|
||||||
|
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Necrite(final Necrite card) {
|
private Necrite(final Necrite card) {
|
||||||
|
|
@ -50,33 +49,3 @@ public final class Necrite extends CardImpl {
|
||||||
return new Necrite(this);
|
return new Necrite(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NecriteTriggeredAbility extends AttacksAndIsNotBlockedTriggeredAbility{
|
|
||||||
|
|
||||||
public NecriteTriggeredAbility(Effect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
private NecriteTriggeredAbility(final NecriteTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NecriteTriggeredAbility copy() {
|
|
||||||
return new NecriteTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (super.checkTrigger(event, game)){
|
|
||||||
UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(getSourceId(), game);
|
|
||||||
FilterPermanent filter = new FilterCreaturePermanent();
|
|
||||||
filter.add(new ControllerIdPredicate(defendingPlayerId));
|
|
||||||
Target target = new TargetPermanent(filter);
|
|
||||||
this.getTargets().clear();
|
|
||||||
this.addTarget(target);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -20,8 +20,10 @@ public final class NestOfScarabs extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}");
|
||||||
|
|
||||||
// Whenever you put one or more -1/-1 counters on a creature, create that many 1/1 black Insect creature tokens.
|
// Whenever you put one or more -1/-1 counters on a creature, create that many 1/1 black Insect creature tokens.
|
||||||
this.addAbility(new PutCounterOnCreatureTriggeredAbility(new CreateTokenEffect(new NestOfScarabsBlackInsectToken(), new EffectKeyValue("countersAdded"))
|
this.addAbility(new PutCounterOnCreatureTriggeredAbility(
|
||||||
.setText("create that many 1/1 black Insect creature tokens"), CounterType.M1M1.createInstance()));
|
new CreateTokenEffect(new NestOfScarabsBlackInsectToken(),
|
||||||
|
new EffectKeyValue("countersAdded", "that many")),
|
||||||
|
CounterType.M1M1.createInstance()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private NestOfScarabs(final NestOfScarabs card) {
|
private NestOfScarabs(final NestOfScarabs card) {
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,26 @@
|
||||||
package mage.cards.o;
|
package mage.cards.o;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.TriggeredAbility;
|
||||||
|
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||||
|
import mage.abilities.condition.Condition;
|
||||||
import mage.abilities.effects.common.ExileTargetEffect;
|
import mage.abilities.effects.common.ExileTargetEffect;
|
||||||
import mage.abilities.keyword.FlyingAbility;
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
import mage.abilities.keyword.TrampleAbility;
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.SuperType;
|
||||||
|
import mage.constants.WatcherScope;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.common.FilterNonlandPermanent;
|
import mage.filter.common.FilterNonlandPermanent;
|
||||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.DamagedPlayerEvent;
|
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||||
|
import mage.util.CardUtil;
|
||||||
import mage.watchers.Watcher;
|
import mage.watchers.Watcher;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
@ -25,6 +29,7 @@ import java.util.*;
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
*/
|
*/
|
||||||
public final class OKagachiVengefulKami extends CardImpl {
|
public final class OKagachiVengefulKami extends CardImpl {
|
||||||
|
static FilterPermanent filter = new FilterNonlandPermanent("nonland permanent that player controls");
|
||||||
|
|
||||||
public OKagachiVengefulKami(UUID ownerId, CardSetInfo setInfo) {
|
public OKagachiVengefulKami(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}{B}{R}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}{B}{R}{G}");
|
||||||
|
|
@ -42,7 +47,11 @@ public final class OKagachiVengefulKami extends CardImpl {
|
||||||
this.addAbility(TrampleAbility.getInstance());
|
this.addAbility(TrampleAbility.getInstance());
|
||||||
|
|
||||||
// Whenever O-Kagachi, Vengeful Kami deals combat damage to a player, if that player attacked you during their last turn, exile target nonland permanent that player controls
|
// Whenever O-Kagachi, Vengeful Kami deals combat damage to a player, if that player attacked you during their last turn, exile target nonland permanent that player controls
|
||||||
this.addAbility(new OKagachiVengefulKamiTriggeredAbility());
|
TriggeredAbility ability = new DealsCombatDamageToAPlayerTriggeredAbility(new ExileTargetEffect(), false, true);
|
||||||
|
ability.addTarget(new TargetPermanent(filter));
|
||||||
|
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||||
|
ability.withInterveningIf(KagachiVengefulKamiCondition.instance);
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OKagachiVengefulKami(final OKagachiVengefulKami card) {
|
private OKagachiVengefulKami(final OKagachiVengefulKami card) {
|
||||||
|
|
@ -55,66 +64,25 @@ public final class OKagachiVengefulKami extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OKagachiVengefulKamiTriggeredAbility extends TriggeredAbilityImpl {
|
enum KagachiVengefulKamiCondition implements Condition {
|
||||||
|
instance;
|
||||||
OKagachiVengefulKamiTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new ExileTargetEffect(), false);
|
|
||||||
this.addWatcher(new OKagachiVengefulKamiWatcher());
|
|
||||||
}
|
|
||||||
|
|
||||||
private OKagachiVengefulKamiTriggeredAbility(final OKagachiVengefulKamiTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OKagachiVengefulKamiTriggeredAbility copy() {
|
public boolean apply(Game game, Ability source) {
|
||||||
return new OKagachiVengefulKamiTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
Player player = game.getPlayer(event.getTargetId());
|
|
||||||
if (player == null
|
|
||||||
|| !((DamagedPlayerEvent) event).isCombatDamage()
|
|
||||||
|| !event.getSourceId().equals(getSourceId())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.getEffects().setValue("damagedPlayer", event.getTargetId());
|
|
||||||
FilterPermanent filter = new FilterNonlandPermanent("nonland permanent controlled by " + player.getName());
|
|
||||||
filter.add(new ControllerIdPredicate(event.getTargetId()));
|
|
||||||
this.getTargets().clear();
|
|
||||||
this.addTarget(new TargetPermanent(filter));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkInterveningIfClause(Game game) {
|
|
||||||
OKagachiVengefulKamiWatcher watcher = game.getState().getWatcher(OKagachiVengefulKamiWatcher.class);
|
OKagachiVengefulKamiWatcher watcher = game.getState().getWatcher(OKagachiVengefulKamiWatcher.class);
|
||||||
if (watcher == null) {
|
if (watcher == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
UUID playerId = null;
|
return CardUtil.getEffectValueFromAbility(source, "damagedPlayer", UUID.class)
|
||||||
for (Effect effect : this.getEffects()) {
|
.filter(uuid -> watcher.checkPlayer(source.getControllerId(), uuid))
|
||||||
Object obj = effect.getValue("damagedPlayer");
|
.isPresent();
|
||||||
if (obj instanceof UUID) {
|
|
||||||
playerId = (UUID) obj;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return watcher.checkPlayer(getControllerId(), playerId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String toString() {
|
||||||
return "Whenever {this} deals combat damage to a player, " +
|
return "if that player attacked you during their last turn";
|
||||||
"if that player attacked you during their last turn, " +
|
|
||||||
"exile target nonland permanent that player controls.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class OKagachiVengefulKamiWatcher extends Watcher {
|
class OKagachiVengefulKamiWatcher extends Watcher {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,25 @@
|
||||||
package mage.cards.o;
|
package mage.cards.o;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.MageObject;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.common.DiesThisOrAnotherTriggeredAbility;
|
||||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||||
import mage.abilities.keyword.LifelinkAbility;
|
import mage.abilities.keyword.LifelinkAbility;
|
||||||
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.SuperType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayer;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
|
||||||
import mage.target.common.TargetCardInYourGraveyard;
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -21,6 +27,13 @@ import java.util.UUID;
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
*/
|
*/
|
||||||
public final class OrahSkyclaveHierophant extends CardImpl {
|
public final class OrahSkyclaveHierophant extends CardImpl {
|
||||||
|
static FilterPermanent filterTrigger = new FilterControlledPermanent("Cleric you control");
|
||||||
|
static FilterCard filterTarget = new FilterCard("Cleric card with lesser mana value");
|
||||||
|
static {
|
||||||
|
filterTrigger.add(SubType.CLERIC.getPredicate());
|
||||||
|
filterTarget.add(SubType.CLERIC.getPredicate());
|
||||||
|
filterTarget.add(OrahSkyclaveHierophantPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
public OrahSkyclaveHierophant(UUID ownerId, CardSetInfo setInfo) {
|
public OrahSkyclaveHierophant(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{B}");
|
||||||
|
|
@ -35,7 +48,9 @@ public final class OrahSkyclaveHierophant extends CardImpl {
|
||||||
this.addAbility(LifelinkAbility.getInstance());
|
this.addAbility(LifelinkAbility.getInstance());
|
||||||
|
|
||||||
// Whenever Orah, Skyclave Hierophant or another Cleric you control dies, return target Cleric card with lesser converted mana cost from your graveyard to the battlefield.
|
// Whenever Orah, Skyclave Hierophant or another Cleric you control dies, return target Cleric card with lesser converted mana cost from your graveyard to the battlefield.
|
||||||
this.addAbility(new OrahSkyclaveHierophantTriggeredAbility());
|
Ability ability = new DiesThisOrAnotherTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false, filterTrigger);
|
||||||
|
ability.addTarget(new TargetCardInYourGraveyard(filterTarget));
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OrahSkyclaveHierophant(final OrahSkyclaveHierophant card) {
|
private OrahSkyclaveHierophant(final OrahSkyclaveHierophant card) {
|
||||||
|
|
@ -48,57 +63,15 @@ public final class OrahSkyclaveHierophant extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OrahSkyclaveHierophantTriggeredAbility extends TriggeredAbilityImpl {
|
enum OrahSkyclaveHierophantPredicate implements ObjectSourcePlayerPredicate<Card> {
|
||||||
|
instance;
|
||||||
OrahSkyclaveHierophantTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect());
|
|
||||||
setLeavesTheBattlefieldTrigger(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private OrahSkyclaveHierophantTriggeredAbility(final OrahSkyclaveHierophantTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
|
||||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
return CardUtil.getEffectValueFromAbility(
|
||||||
}
|
input.getSource(), "creatureDied", Permanent.class
|
||||||
|
)
|
||||||
@Override
|
.filter(permanent -> input.getObject().getManaValue() < permanent.getManaValue())
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
.isPresent();
|
||||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
|
||||||
if (!zEvent.isDiesEvent()
|
|
||||||
|| !zEvent.getTarget().isControlledBy(getControllerId())
|
|
||||||
|| (!zEvent.getTarget().hasSubtype(SubType.CLERIC, game)
|
|
||||||
&& !zEvent.getTarget().getId().equals(getSourceId()))
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FilterCard filterCard = new FilterCard(
|
|
||||||
"Cleric card with mana value less than " + (zEvent.getTarget().getManaValue())
|
|
||||||
);
|
|
||||||
filterCard.add(SubType.CLERIC.getPredicate());
|
|
||||||
filterCard.add(new ManaValuePredicate(
|
|
||||||
ComparisonType.FEWER_THAN, zEvent.getTarget().getManaValue()
|
|
||||||
));
|
|
||||||
this.getTargets().clear();
|
|
||||||
this.addTarget(new TargetCardInYourGraveyard(filterCard));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public OrahSkyclaveHierophantTriggeredAbility copy() {
|
|
||||||
return new OrahSkyclaveHierophantTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "Whenever {this} or another Cleric you control dies, return target Cleric card " +
|
|
||||||
"with lesser mana value from your graveyard to the battlefield.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
|
||||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,20 +7,14 @@ import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.permanent.Permanent;
|
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.common.TargetLandPermanent;
|
import mage.target.common.TargetLandPermanent;
|
||||||
import mage.util.CardUtil;
|
import mage.target.targetadjustment.XTargetsCountAdjuster;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -38,9 +32,12 @@ public final class OrcishSettlers extends CardImpl {
|
||||||
this.toughness = new MageInt(1);
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
// {X}{X}{R}, {tap}, Sacrifice Orcish Settlers: Destroy X target lands.
|
// {X}{X}{R}, {tap}, Sacrifice Orcish Settlers: Destroy X target lands.
|
||||||
Ability ability = new SimpleActivatedAbility(new OrcishSettlersEffect(), new ManaCostsImpl<>("{X}{X}{R}"));
|
Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect().setText("Destroy X target lands"),
|
||||||
|
new ManaCostsImpl<>("{X}{X}{R}"));
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
ability.addCost(new SacrificeSourceCost());
|
ability.addCost(new SacrificeSourceCost());
|
||||||
|
ability.addTarget(new TargetLandPermanent());
|
||||||
|
ability.setTargetAdjuster(new XTargetsCountAdjuster());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,43 +50,3 @@ public final class OrcishSettlers extends CardImpl {
|
||||||
return new OrcishSettlers(this);
|
return new OrcishSettlers(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OrcishSettlersEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
OrcishSettlersEffect() {
|
|
||||||
super(Outcome.DestroyPermanent);
|
|
||||||
this.staticText = "Destroy X target lands";
|
|
||||||
}
|
|
||||||
|
|
||||||
private OrcishSettlersEffect(final OrcishSettlersEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public OrcishSettlersEffect copy() {
|
|
||||||
return new OrcishSettlersEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
int amount = CardUtil.getSourceCostsTag(game, source, "X", 0);
|
|
||||||
if (amount == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
TargetLandPermanent target = new TargetLandPermanent(amount);
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
|
||||||
if (controller != null
|
|
||||||
&& target.canChoose(controller.getId(), source, game)
|
|
||||||
&& controller.choose(Outcome.DestroyPermanent, target, source, game)) {
|
|
||||||
List<UUID> targets = target.getTargets();
|
|
||||||
targets.forEach((landId) -> {
|
|
||||||
Permanent land = game.getPermanent(landId);
|
|
||||||
if (land != null) {
|
|
||||||
land.destroy(source, game, false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.targetadjustment.DefineByTriggerTargetAdjuster;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -65,6 +66,7 @@ class PawpatchRecruitTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
public PawpatchRecruitTriggeredAbility() {
|
public PawpatchRecruitTriggeredAbility() {
|
||||||
super(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false);
|
super(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false);
|
||||||
|
this.setTargetAdjuster(DefineByTriggerTargetAdjuster.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PawpatchRecruitTriggeredAbility(final PawpatchRecruitTriggeredAbility ability) {
|
private PawpatchRecruitTriggeredAbility(final PawpatchRecruitTriggeredAbility ability) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
package mage.cards.r;
|
package mage.cards.r;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.DealsDamageToOpponentTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.dynamicvalue.common.SavedDamageValue;
|
import mage.abilities.dynamicvalue.common.SavedDamageValue;
|
||||||
|
|
@ -14,16 +15,15 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||||
import mage.filter.predicate.permanent.ProtectorIdPredicate;
|
import mage.filter.predicate.permanent.ProtectorIdPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.DamagedEvent;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.targetadjustment.TargetAdjuster;
|
||||||
|
import mage.target.targetpointer.FirstTargetPointer;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -51,7 +51,10 @@ public final class RampagingRaptor extends CardImpl {
|
||||||
));
|
));
|
||||||
|
|
||||||
// Whenever Rampaging Raptor deals combat damage to an opponent, it deals that much damage to target planeswalker that player controls or battle that player protects.
|
// Whenever Rampaging Raptor deals combat damage to an opponent, it deals that much damage to target planeswalker that player controls or battle that player protects.
|
||||||
this.addAbility(new RampagingRaptorTriggeredAbility());
|
Ability ability = new DealsDamageToOpponentTriggeredAbility(new DamageTargetEffect(SavedDamageValue.MUCH)
|
||||||
|
.withTargetDescription("target planeswalker that player controls or battle that player protects"), false, true, true);
|
||||||
|
ability.setTargetAdjuster(RampagingRaptorTargetAdjuster.instance);
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RampagingRaptor(final RampagingRaptor card) {
|
private RampagingRaptor(final RampagingRaptor card) {
|
||||||
|
|
@ -64,33 +67,17 @@ public final class RampagingRaptor extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RampagingRaptorTriggeredAbility extends TriggeredAbilityImpl {
|
enum RampagingRaptorTargetAdjuster implements TargetAdjuster {
|
||||||
|
instance;
|
||||||
RampagingRaptorTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new DamageTargetEffect(SavedDamageValue.MUCH), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RampagingRaptorTriggeredAbility(final RampagingRaptorTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RampagingRaptorTriggeredAbility copy() {
|
public void adjustTargets(Ability ability, Game game) {
|
||||||
return new RampagingRaptorTriggeredAbility(this);
|
UUID opponentId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability);
|
||||||
}
|
Player opponent = game.getPlayer(opponentId);
|
||||||
|
ability.getTargets().clear();
|
||||||
@Override
|
ability.getAllEffects().setTargetPointer(new FirstTargetPointer());
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
if (opponent == null) {
|
||||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
Player opponent = game.getPlayer(event.getPlayerId());
|
|
||||||
if (opponent == null
|
|
||||||
|| !event.getSourceId().equals(this.getSourceId())
|
|
||||||
|| !((DamagedEvent) event).isCombatDamage()) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
FilterPermanent filter = new FilterPermanent(
|
FilterPermanent filter = new FilterPermanent(
|
||||||
"planeswalker " + opponent.getLogName() + " controls " +
|
"planeswalker " + opponent.getLogName() + " controls " +
|
||||||
|
|
@ -106,15 +93,6 @@ class RampagingRaptorTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
new ProtectorIdPredicate(opponent.getId())
|
new ProtectorIdPredicate(opponent.getId())
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
this.getEffects().setValue("damage", event.getAmount());
|
ability.addTarget(new TargetPermanent(filter));
|
||||||
this.getTargets().clear();
|
|
||||||
this.addTarget(new TargetPermanent(filter));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "Whenever {this} deals combat damage to an opponent, it deals that much damage " +
|
|
||||||
"to target planeswalker that player controls or battle that player protects.";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,21 @@
|
||||||
package mage.cards.r;
|
package mage.cards.r;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.common.ZoneChangeTriggeredAbility;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.CycleTriggeredAbility;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.dynamicvalue.common.EffectKeyValue;
|
||||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
import mage.abilities.hint.StaticHint;
|
|
||||||
import mage.abilities.keyword.CyclingAbility;
|
import mage.abilities.keyword.CyclingAbility;
|
||||||
import mage.abilities.keyword.TrampleAbility;
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.game.Game;
|
import mage.filter.common.FilterArtifactPermanent;
|
||||||
import mage.game.events.GameEvent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.game.stack.StackObject;
|
import mage.target.targetadjustment.TargetsCountAdjuster;
|
||||||
import mage.target.common.TargetArtifactPermanent;
|
|
||||||
import mage.util.CardUtil;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -24,6 +23,7 @@ import java.util.UUID;
|
||||||
* @author Susucr
|
* @author Susucr
|
||||||
*/
|
*/
|
||||||
public final class RampagingWarMammoth extends CardImpl {
|
public final class RampagingWarMammoth extends CardImpl {
|
||||||
|
static FilterPermanent filter = new FilterArtifactPermanent("up to X target artifacts");
|
||||||
|
|
||||||
public RampagingWarMammoth(UUID ownerId, CardSetInfo setInfo) {
|
public RampagingWarMammoth(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}");
|
||||||
|
|
@ -39,7 +39,10 @@ public final class RampagingWarMammoth extends CardImpl {
|
||||||
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{2}{R}")));
|
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{2}{R}")));
|
||||||
|
|
||||||
// When you cycle Rampaging War Mammoth, destroy up to X target artifacts.
|
// When you cycle Rampaging War Mammoth, destroy up to X target artifacts.
|
||||||
this.addAbility(new RampagingWarMammothTriggeredAbility());
|
Ability ability = new CycleTriggeredAbility(new DestroyTargetEffect());
|
||||||
|
ability.addTarget(new TargetPermanent(0,1, filter));
|
||||||
|
ability.setTargetAdjuster(new TargetsCountAdjuster(new EffectKeyValue("cycleXValue")));
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RampagingWarMammoth(final RampagingWarMammoth card) {
|
private RampagingWarMammoth(final RampagingWarMammoth card) {
|
||||||
|
|
@ -51,56 +54,3 @@ public final class RampagingWarMammoth extends CardImpl {
|
||||||
return new RampagingWarMammoth(this);
|
return new RampagingWarMammoth(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RampagingWarMammothTriggeredAbility extends ZoneChangeTriggeredAbility {
|
|
||||||
|
|
||||||
RampagingWarMammothTriggeredAbility() {
|
|
||||||
super(Zone.ALL, null, "", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RampagingWarMammothTriggeredAbility(RampagingWarMammothTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (!event.getSourceId().equals(this.getSourceId())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
StackObject object = game.getStack().getStackObject(event.getSourceId());
|
|
||||||
if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CyclingAbility cyclingAbility = (CyclingAbility) object.getStackAbility();
|
|
||||||
// If X is 0, or cycling from another ability that does not have {X} in cost,
|
|
||||||
// this should trigger (but do nothing).
|
|
||||||
int xValue = CardUtil.getSourceCostsTag(game, cyclingAbility, "X", 0);
|
|
||||||
|
|
||||||
this.getEffects().clear();
|
|
||||||
this.getTargets().clear();
|
|
||||||
|
|
||||||
this.addEffect(new DestroyTargetEffect());
|
|
||||||
// Target up to X artifacts
|
|
||||||
this.addTarget(new TargetArtifactPermanent(0, xValue));
|
|
||||||
this.getHints().clear();
|
|
||||||
this.addHint(new StaticHint("X = " + xValue));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RampagingWarMammothTriggeredAbility copy() {
|
|
||||||
return new RampagingWarMammothTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "When you cycle {this}, destroy up to X target artifacts.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ package mage.cards.r;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.DamageMultiEffect;
|
import mage.abilities.effects.common.DamageMultiEffect;
|
||||||
import mage.abilities.keyword.DevourAbility;
|
import mage.abilities.keyword.DevourAbility;
|
||||||
|
|
@ -12,10 +14,10 @@ import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
import mage.target.common.TargetCreaturePermanentAmount;
|
import mage.target.common.TargetCreaturePermanentAmount;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -39,7 +41,11 @@ public final class RavenousGigantotherium extends CardImpl {
|
||||||
this.addAbility(new DevourAbility(3));
|
this.addAbility(new DevourAbility(3));
|
||||||
|
|
||||||
// When Ravenous Gigantotherium enters the battlefield, it deals X damage divided as you choose among up to X target creatures, where X is its power. Each of those creatures deals damage equal to its power to Ravenous Gigantotherium.
|
// When Ravenous Gigantotherium enters the battlefield, it deals X damage divided as you choose among up to X target creatures, where X is its power. Each of those creatures deals damage equal to its power to Ravenous Gigantotherium.
|
||||||
this.addAbility(new RavenousGigantotheriumAbility());
|
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageMultiEffect());
|
||||||
|
ability.addEffect(new RavenousGigantotheriumEffect());
|
||||||
|
ability.addTarget(new TargetCreaturePermanentAmount(RavenousGigantotheriumAmount.instance)
|
||||||
|
.withTargetName("up to X target creatures, where X is its power"));
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RavenousGigantotherium(final RavenousGigantotherium card) {
|
private RavenousGigantotherium(final RavenousGigantotherium card) {
|
||||||
|
|
@ -52,47 +58,28 @@ public final class RavenousGigantotherium extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RavenousGigantotheriumAbility extends EntersBattlefieldTriggeredAbility {
|
enum RavenousGigantotheriumAmount implements DynamicValue {
|
||||||
|
instance;
|
||||||
|
|
||||||
RavenousGigantotheriumAbility() {
|
@Override
|
||||||
super(null, false);
|
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||||
}
|
return CardUtil.getEffectValueFromAbility(sourceAbility, "permanentEnteredBattlefield", Permanent.class)
|
||||||
|
.map(permanent -> permanent.getPower().getValue()).orElse(0);
|
||||||
private RavenousGigantotheriumAbility(final RavenousGigantotheriumAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public DynamicValue copy() {
|
||||||
if (!super.checkTrigger(event, game)) {
|
return instance;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
|
|
||||||
if (permanent == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int power = Math.max(permanent.getPower().getValue(), 0);
|
|
||||||
this.getEffects().clear();
|
|
||||||
this.addEffect(new DamageMultiEffect());
|
|
||||||
this.addEffect(new RavenousGigantotheriumEffect());
|
|
||||||
this.getTargets().clear();
|
|
||||||
if (power < 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
this.addTarget(new TargetCreaturePermanentAmount(power, 0, power));
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getMessage() {
|
||||||
return "When {this} enters, it deals X damage " +
|
return "its power";
|
||||||
"divided as you choose among up to X target creatures, where X is its power. " +
|
|
||||||
"Each of those creatures deals damage equal to its power to {this}.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RavenousGigantotheriumAbility copy() {
|
public String toString() {
|
||||||
return new RavenousGigantotheriumAbility(this);
|
return "X";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,6 +87,7 @@ class RavenousGigantotheriumEffect extends OneShotEffect {
|
||||||
|
|
||||||
RavenousGigantotheriumEffect() {
|
RavenousGigantotheriumEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
|
this.setText("Each of those creatures deals damage equal to its power to {this}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private RavenousGigantotheriumEffect(final RavenousGigantotheriumEffect effect) {
|
private RavenousGigantotheriumEffect(final RavenousGigantotheriumEffect effect) {
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,21 @@ package mage.cards.r;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.DiesSourceTriggeredAbility;
|
import mage.abilities.common.DiesSourceTriggeredAbility;
|
||||||
|
import mage.abilities.costs.common.DynamicValueGenericManaCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.dynamicvalue.common.TargetManaValue;
|
||||||
import mage.abilities.effects.common.DoIfCostPaid;
|
import mage.abilities.effects.common.DoIfCostPaid;
|
||||||
|
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||||
import mage.abilities.effects.common.ReturnToHandSourceEffect;
|
import mage.abilities.effects.common.ReturnToHandSourceEffect;
|
||||||
import mage.abilities.keyword.MenaceAbility;
|
import mage.abilities.keyword.MenaceAbility;
|
||||||
import mage.cards.Card;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
|
import mage.filter.common.FilterCreatureCard;
|
||||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
|
||||||
import mage.game.Game;
|
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.common.TargetCardInYourGraveyard;
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
import mage.util.ManaUtil;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -26,6 +25,11 @@ import java.util.UUID;
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public final class RelentlessDead extends CardImpl {
|
public final class RelentlessDead extends CardImpl {
|
||||||
|
static FilterCard filter = new FilterCreatureCard("another target Zombie creature card with mana value X from your graveyard"); // This target defines X
|
||||||
|
static{
|
||||||
|
filter.add(SubType.ZOMBIE.getPredicate());
|
||||||
|
filter.add(AnotherPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
public RelentlessDead(UUID ownerId, CardSetInfo setInfo) {
|
public RelentlessDead(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}");
|
||||||
|
|
@ -40,7 +44,11 @@ public final class RelentlessDead extends CardImpl {
|
||||||
this.addAbility(new DiesSourceTriggeredAbility(new DoIfCostPaid(new ReturnToHandSourceEffect().setText("return it to its owner's hand"), new ManaCostsImpl<>("{B}"))));
|
this.addAbility(new DiesSourceTriggeredAbility(new DoIfCostPaid(new ReturnToHandSourceEffect().setText("return it to its owner's hand"), new ManaCostsImpl<>("{B}"))));
|
||||||
|
|
||||||
// When Relentless Dead dies, you may pay {X}. If you do, return another target Zombie creature card with converted mana cost X from your graveyard to the battlefield.
|
// When Relentless Dead dies, you may pay {X}. If you do, return another target Zombie creature card with converted mana cost X from your graveyard to the battlefield.
|
||||||
this.addAbility(new DiesSourceTriggeredAbility(new RelentlessDeadEffect()));
|
Ability ability = new DiesSourceTriggeredAbility(new DoIfCostPaid(
|
||||||
|
new ReturnFromGraveyardToBattlefieldTargetEffect(),
|
||||||
|
new DynamicValueGenericManaCost(TargetManaValue.instance, "{X}")));
|
||||||
|
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RelentlessDead(final RelentlessDead card) {
|
private RelentlessDead(final RelentlessDead card) {
|
||||||
|
|
@ -52,46 +60,3 @@ public final class RelentlessDead extends CardImpl {
|
||||||
return new RelentlessDead(this);
|
return new RelentlessDead(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RelentlessDeadEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
RelentlessDeadEffect() {
|
|
||||||
super(Outcome.PutCardInPlay);
|
|
||||||
this.staticText = "you may pay {X}. If you do, return another target Zombie creature card with mana value X from your graveyard to the battlefield";
|
|
||||||
}
|
|
||||||
|
|
||||||
private RelentlessDeadEffect(final RelentlessDeadEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RelentlessDeadEffect copy() {
|
|
||||||
return new RelentlessDeadEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
|
||||||
if (controller != null) {
|
|
||||||
if (controller.chooseUse(Outcome.Benefit, "Do you want to pay {X} to return zombie?", source, game)) {
|
|
||||||
int payCount = ManaUtil.playerPaysXGenericMana(true, "Relentless Dead", controller, source, game);
|
|
||||||
// can be 0
|
|
||||||
FilterCard filter = new FilterCard("Another target Zombie card with mana value {" + payCount + "}");
|
|
||||||
filter.add(SubType.ZOMBIE.getPredicate());
|
|
||||||
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, payCount));
|
|
||||||
filter.add(AnotherPredicate.instance);
|
|
||||||
TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filter);
|
|
||||||
if (controller.chooseTarget(outcome, target, source, game)) {
|
|
||||||
Card card = game.getCard(target.getFirstTarget());
|
|
||||||
if (card != null) {
|
|
||||||
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,20 @@
|
||||||
package mage.cards.s;
|
package mage.cards.s;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.CycleTriggeredAbility;
|
||||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
import mage.abilities.common.ZoneChangeTriggeredAbility;
|
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.CreateTokenEffect;
|
|
||||||
import mage.abilities.keyword.CyclingAbility;
|
import mage.abilities.keyword.CyclingAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.SetTargetPointer;
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.token.SharkToken;
|
import mage.game.permanent.token.SharkToken;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.game.stack.StackObject;
|
|
||||||
import mage.util.CardUtil;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -42,7 +37,7 @@ public final class SharkTyphoon extends CardImpl {
|
||||||
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{1}{U}")));
|
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{1}{U}")));
|
||||||
|
|
||||||
// When you cycle Shark Typhoon, create an X/X blue Shark creature token with flying.
|
// When you cycle Shark Typhoon, create an X/X blue Shark creature token with flying.
|
||||||
this.addAbility(new SharkTyphoonTriggeredAbility());
|
this.addAbility(new CycleTriggeredAbility(new SharkTyphoonCycleEffect()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private SharkTyphoon(final SharkTyphoon card) {
|
private SharkTyphoon(final SharkTyphoon card) {
|
||||||
|
|
@ -82,42 +77,29 @@ class SharkTyphoonCastEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SharkTyphoonTriggeredAbility extends ZoneChangeTriggeredAbility {
|
class SharkTyphoonCycleEffect extends OneShotEffect {
|
||||||
|
|
||||||
SharkTyphoonTriggeredAbility() {
|
SharkTyphoonCycleEffect() {
|
||||||
super(Zone.ALL, null, "", false);
|
super(Outcome.Benefit);
|
||||||
|
staticText = "create an X/X blue Shark creature token with flying";
|
||||||
}
|
}
|
||||||
|
|
||||||
private SharkTyphoonTriggeredAbility(SharkTyphoonTriggeredAbility ability) {
|
private SharkTyphoonCycleEffect(final SharkTyphoonCycleEffect effect) {
|
||||||
super(ability);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
public SharkTyphoonCycleEffect copy() {
|
||||||
return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY;
|
return new SharkTyphoonCycleEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean apply(Game game, Ability source) {
|
||||||
if (!event.getSourceId().equals(this.getSourceId())) {
|
Object xValueObject = getValue("cycleXValue");
|
||||||
return false;
|
int xValue = 0;
|
||||||
|
if (xValueObject instanceof Integer) {
|
||||||
|
xValue = (int) xValueObject;
|
||||||
}
|
}
|
||||||
StackObject object = game.getStack().getStackObject(event.getSourceId());
|
return new SharkToken(xValue).putOntoBattlefield(1, game, source, source.getControllerId());
|
||||||
if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.getEffects().clear();
|
|
||||||
this.addEffect(new CreateTokenEffect(new SharkToken(CardUtil.getSourceCostsTag(game, object.getStackAbility(), "X", 0))));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SharkTyphoonTriggeredAbility copy() {
|
|
||||||
return new SharkTyphoonTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "When you cycle this card, create an X/X blue Shark creature token with flying.";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
package mage.cards.v;
|
package mage.cards.v;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.common.CycleTriggeredAbility;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.dynamicvalue.common.EffectKeyValue;
|
||||||
import mage.abilities.effects.common.CreateTokenEffect;
|
import mage.abilities.effects.common.CreateTokenEffect;
|
||||||
import mage.abilities.keyword.*;
|
import mage.abilities.keyword.*;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
|
|
@ -10,12 +11,7 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.SuperType;
|
import mage.constants.SuperType;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.token.PilotSaddleCrewToken;
|
import mage.game.permanent.token.PilotSaddleCrewToken;
|
||||||
import mage.game.stack.StackObject;
|
|
||||||
import mage.util.CardUtil;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -48,7 +44,8 @@ public final class ValorsFlagship extends CardImpl {
|
||||||
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{2}{W}")));
|
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{2}{W}")));
|
||||||
|
|
||||||
// When you cycle this card, create X 1/1 colorless Pilot creature tokens with "This token saddles Mounts and crews Vehicles as though its power were 2 greater."
|
// When you cycle this card, create X 1/1 colorless Pilot creature tokens with "This token saddles Mounts and crews Vehicles as though its power were 2 greater."
|
||||||
this.addAbility(new ValorsFlagshipTriggeredAbility());
|
this.addAbility(new CycleTriggeredAbility(
|
||||||
|
new CreateTokenEffect(new PilotSaddleCrewToken(), new EffectKeyValue("cycleXValue", "X"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValorsFlagship(final ValorsFlagship card) {
|
private ValorsFlagship(final ValorsFlagship card) {
|
||||||
|
|
@ -60,45 +57,3 @@ public final class ValorsFlagship extends CardImpl {
|
||||||
return new ValorsFlagship(this);
|
return new ValorsFlagship(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ValorsFlagshipTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
ValorsFlagshipTriggeredAbility() {
|
|
||||||
super(Zone.ALL, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ValorsFlagshipTriggeredAbility(final ValorsFlagshipTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValorsFlagshipTriggeredAbility copy() {
|
|
||||||
return new ValorsFlagshipTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (!event.getSourceId().equals(this.getSourceId())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
StackObject object = game.getStack().getStackObject(event.getSourceId());
|
|
||||||
if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.getEffects().clear();
|
|
||||||
int amount = CardUtil.getSourceCostsTag(game, object.getStackAbility(), "X", 0);
|
|
||||||
this.addEffect(new CreateTokenEffect(new PilotSaddleCrewToken(), amount));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "When you cycle this card, create X 1/1 colorless Pilot creature tokens with " +
|
|
||||||
"\"This token saddles Mounts and crews Vehicles as though its power were 2 greater.\"";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,24 @@ public class CyclingTest extends CardTestPlayerBase {
|
||||||
assertPowerToughness(playerB, "Pillarfield Ox", 0, 2);
|
assertPowerToughness(playerB, "Pillarfield Ox", 0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that X value is correctly read by the resulting triggered ability
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void cycleSharkTyphoon() {
|
||||||
|
addCard(Zone.HAND, playerA, "Shark Typhoon", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 8);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling");
|
||||||
|
setChoice(playerA, "X=6");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
assertGraveyardCount(playerA, "Shark Typhoon", 1);
|
||||||
|
assertPowerToughness(playerA, "Shark Token", 6, 6);
|
||||||
|
assertTappedCount("Island", true, 8);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cycle from graveyard or battlefield should not work.
|
* Cycle from graveyard or battlefield should not work.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Plopman
|
* @author Plopman
|
||||||
|
|
@ -40,6 +41,7 @@ public class CycleTriggeredAbility extends ZoneChangeTriggeredAbility {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.getEffects().setValue("cycleCosts", object.getStackAbility().getCosts());
|
this.getEffects().setValue("cycleCosts", object.getStackAbility().getCosts());
|
||||||
|
this.getEffects().setValue("cycleXValue", CardUtil.getSourceCostsTag(game, object.getStackAbility(), "X", 0));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import mage.game.Game;
|
||||||
* @author stravant
|
* @author stravant
|
||||||
*/
|
*/
|
||||||
public class EffectKeyValue implements DynamicValue {
|
public class EffectKeyValue implements DynamicValue {
|
||||||
private String key;
|
private final String key;
|
||||||
private String description;
|
private final String description;
|
||||||
|
|
||||||
public EffectKeyValue(String key) {
|
public EffectKeyValue(String key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
|
|
@ -19,7 +19,7 @@ public class EffectKeyValue implements DynamicValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
public EffectKeyValue(String key, String description) {
|
public EffectKeyValue(String key, String description) {
|
||||||
this(key);
|
this.key = key;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,11 +35,11 @@ public class EffectKeyValue implements DynamicValue {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "equal to";
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return description;
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -111,7 +111,7 @@ public abstract class TargetImpl implements Target {
|
||||||
if (min > 0 && max == Integer.MAX_VALUE) {
|
if (min > 0 && max == Integer.MAX_VALUE) {
|
||||||
sb.append(CardUtil.numberToText(min));
|
sb.append(CardUtil.numberToText(min));
|
||||||
sb.append(" or more ");
|
sb.append(" or more ");
|
||||||
} else if (!targetName.startsWith("X ") && (min != 1 || max != 1)) {
|
} else if (!targetName.startsWith("X ") && !targetName.startsWith("up to ") && (min != 1 || max != 1)) {
|
||||||
targetName = targetName.replace("another", "other"); //If non-singular, use "other" instead of "another"
|
targetName = targetName.replace("another", "other"); //If non-singular, use "other" instead of "another"
|
||||||
|
|
||||||
if (getUseAnyNumber()) {
|
if (getUseAnyNumber()) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue