mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
refactor: remove notTarget targets from abilities (#13651)
Adds OneShotNonTargetEffect and PutCountersTargetCost Fixes the target timing of spells/abilities, as non-targets should be chosen on resolution.
This commit is contained in:
parent
8b2a81cb42
commit
3223d99b2a
28 changed files with 449 additions and 384 deletions
|
|
@ -1,23 +1,26 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.SavedDamageValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.PartnerWithAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.abilities.effects.OneShotNonTargetEffect;
|
||||
import mage.abilities.keyword.DoctorsCompanionAbility;
|
||||
import mage.abilities.keyword.PartnerWithAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterSuspendedCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Skiwkr
|
||||
|
|
@ -41,10 +44,9 @@ public final class AmyPond extends CardImpl {
|
|||
this.addAbility(new PartnerWithAbility("Rory Williams"));
|
||||
|
||||
// Whenever Amy Pond deals combat damage to a player, choose a suspended card you own and remove that many time counters from it.
|
||||
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new AmyPondEffect(SavedDamageValue.MANY),
|
||||
false, true);
|
||||
ability.addTarget(new TargetCardInExile(filter).withNotTarget(true));
|
||||
this.addAbility(ability);
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new OneShotNonTargetEffect(
|
||||
new AmyPondEffect(SavedDamageValue.MANY), new TargetCardInExile(filter)),
|
||||
false, true));
|
||||
|
||||
// Doctor's companion
|
||||
this.addAbility(DoctorsCompanionAbility.getInstance());
|
||||
|
|
@ -68,7 +70,7 @@ class AmyPondEffect extends OneShotEffect {
|
|||
AmyPondEffect(DynamicValue numberCounters) {
|
||||
super(Outcome.Benefit);
|
||||
this.numberCounters = numberCounters;
|
||||
this.staticText= "choose a suspended card you own and remove that many time counters from it";
|
||||
this.staticText = "choose a suspended card you own and remove that many time counters from it";
|
||||
}
|
||||
|
||||
private AmyPondEffect(final AmyPondEffect effect) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import mage.abilities.common.AttacksTriggeredAbility;
|
|||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.CompletedDungeonCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.OneShotNonTargetEffect;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
|
|
@ -50,11 +51,11 @@ public final class BarrowinOfClanUndurr extends CardImpl {
|
|||
|
||||
// Whenever Barrowin of Clan Undurr attacks, return up to one creature card with mana value 3 or less from your graveyard to the battlefield if you've completed a dungeon.
|
||||
Ability ability = new AttacksTriggeredAbility(new ConditionalOneShotEffect(
|
||||
new ReturnFromGraveyardToBattlefieldTargetEffect(),
|
||||
CompletedDungeonCondition.instance, "return up to one creature card " +
|
||||
"with mana value 3 or less from your graveyard to the battlefield if you've completed a dungeon"
|
||||
));
|
||||
ability.addTarget(new TargetCardInYourGraveyard(0, 1, filter, true));
|
||||
new OneShotNonTargetEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()
|
||||
.setText("return up to one creature card with mana value 3 or less from your graveyard to the battlefield"),
|
||||
new TargetCardInYourGraveyard(0, 1, filter, true)),
|
||||
CompletedDungeonCondition.instance
|
||||
).withConditionTextAtEnd(true));
|
||||
this.addAbility(ability.addHint(CompletedDungeonCondition.getHint()), new CompletedDungeonWatcher());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotNonTargetEffect;
|
||||
import mage.abilities.effects.common.ChooseNewTargetsTargetEffect;
|
||||
import mage.abilities.keyword.DisguiseAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -32,10 +32,9 @@ public final class Boltbender extends CardImpl {
|
|||
this.addAbility(new DisguiseAbility(this, new ManaCostsImpl<>("{1}{R}")));
|
||||
|
||||
// When Boltbender is turned face up, you may choose new targets for any number of other spells and/or abilities.
|
||||
Ability ability = new TurnedFaceUpSourceTriggeredAbility(new ChooseNewTargetsTargetEffect()
|
||||
.setText("you may choose new targets for any number of other spells and/or abilities"));
|
||||
ability.addTarget(new TargetStackObject(0, Integer.MAX_VALUE, StaticFilters.FILTER_SPELL_OR_ABILITY));
|
||||
this.addAbility(ability);
|
||||
this.addAbility(new TurnedFaceUpSourceTriggeredAbility(new OneShotNonTargetEffect(
|
||||
new ChooseNewTargetsTargetEffect().setText("you may choose new targets for any number of other spells and/or abilities"),
|
||||
new TargetStackObject(0, Integer.MAX_VALUE, StaticFilters.FILTER_SPELL_OR_ABILITY))));
|
||||
}
|
||||
|
||||
private Boltbender(final Boltbender card) {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
|
||||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DiesCreatureTriggeredAbility;
|
||||
import mage.abilities.effects.common.SacrificeEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -24,11 +20,9 @@ public final class BurningSands extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}");
|
||||
|
||||
// Whenever a creature dies, that creature's controller sacrifices a land.
|
||||
Ability ability = new DiesCreatureTriggeredAbility(new SacrificeEffect(
|
||||
StaticFilters.FILTER_LAND, 1, "that creature's controller"
|
||||
), false, false, true);
|
||||
ability.setTargetAdjuster(BurningSandsAdjuster.instance);
|
||||
this.addAbility(ability);
|
||||
this.addAbility(new DiesCreatureTriggeredAbility(
|
||||
new SacrificeEffect(StaticFilters.FILTER_LAND, 1, "that creature's controller"),
|
||||
SetTargetPointer.PLAYER));
|
||||
}
|
||||
|
||||
private BurningSands(final BurningSands card) {
|
||||
|
|
@ -40,16 +34,3 @@ public final class BurningSands extends CardImpl {
|
|||
return new BurningSands(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum BurningSandsAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
UUID creatureId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability);
|
||||
Permanent creature = game.getPermanentOrLKIBattlefield(creatureId);
|
||||
if (creature != null) {
|
||||
ability.getEffects().get(0).setTargetPointer(new FixedTarget(creature.getControllerId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -18,32 +17,23 @@ import mage.target.Target;
|
|||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.util.functions.EmptyCopyApplier;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class Cytoshape extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonlegendary creature");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate()));
|
||||
}
|
||||
|
||||
public Cytoshape(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}{U}");
|
||||
|
||||
// Choose a nonlegendary creature on the battlefield. Target creature becomes a copy of that creature until end of turn.
|
||||
this.getSpellAbility().addEffect(new CytoshapeEffect());
|
||||
Target target = new TargetCreaturePermanent(1, 1, filter, true);
|
||||
target.setTargetTag(1);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
|
||||
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("target creature that will become a copy of that chosen creature");
|
||||
target = new TargetCreaturePermanent(filter2);
|
||||
target.setTargetTag(2);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("target creature that will become a copy");
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
|
||||
}
|
||||
|
||||
private Cytoshape(final Cytoshape card) {
|
||||
|
|
@ -58,6 +48,11 @@ public final class Cytoshape extends CardImpl {
|
|||
|
||||
class CytoshapeEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonlegendary creature");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate()));
|
||||
}
|
||||
CytoshapeEffect() {
|
||||
super(Outcome.Copy);
|
||||
this.staticText = "Choose a nonlegendary creature on the battlefield. Target creature becomes a copy of that creature until end of turn.";
|
||||
|
|
@ -74,9 +69,11 @@ class CytoshapeEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability ability) {
|
||||
Permanent copyFrom = game.getPermanent(getTargetPointer().getFirst(game, ability));
|
||||
Target target = new TargetCreaturePermanent(1, 1, filter, true);
|
||||
target.choose(Outcome.Copy, ability.getControllerId(), ability, game);
|
||||
Permanent copyFrom = game.getPermanent(target.getFirstTarget());
|
||||
if (copyFrom != null) {
|
||||
Permanent copyTo = game.getPermanentOrLKIBattlefield(ability.getTargets().get(1).getFirstTarget());
|
||||
Permanent copyTo = game.getPermanentOrLKIBattlefield(ability.getTargets().get(0).getFirstTarget());
|
||||
if (copyTo != null) {
|
||||
game.copyPermanent(Duration.EndOfTurn, copyFrom, copyTo.getId(), ability, new EmptyCopyApplier());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,18 @@
|
|||
|
||||
package mage.cards.e;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.common.DiesCreatureTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.SacrificeEffect;
|
||||
import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect;
|
||||
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -34,7 +27,9 @@ public final class Earthlink extends CardImpl {
|
|||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl<>("{2}"))));
|
||||
|
||||
// Whenever a creature dies, that creature's controller sacrifices a land.
|
||||
this.addAbility(new DiesCreatureTriggeredAbility(new EarthlinkEffect(), false, false, true));
|
||||
this.addAbility(new DiesCreatureTriggeredAbility(
|
||||
new SacrificeEffect(StaticFilters.FILTER_LAND, 1, "that creature's controller"),
|
||||
SetTargetPointer.PLAYER));
|
||||
}
|
||||
|
||||
private Earthlink(final Earthlink card) {
|
||||
|
|
@ -46,34 +41,3 @@ public final class Earthlink extends CardImpl {
|
|||
return new Earthlink(this);
|
||||
}
|
||||
}
|
||||
|
||||
class EarthlinkEffect extends OneShotEffect {
|
||||
|
||||
EarthlinkEffect() {
|
||||
super(Outcome.DrawCard);
|
||||
this.staticText = "that creature's controller sacrifices a land";
|
||||
}
|
||||
|
||||
private EarthlinkEffect(final EarthlinkEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EarthlinkEffect copy() {
|
||||
return new EarthlinkEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = (Permanent) game.getLastKnownInformation(this.getTargetPointer().getFirst(game, source), Zone.BATTLEFIELD);
|
||||
if (permanent != null) {
|
||||
Player controller = game.getPlayer(permanent.getControllerId());
|
||||
if (controller != null) {
|
||||
Effect effect = new SacrificeEffect(StaticFilters.FILTER_LAND, 1, "that creature's controller");
|
||||
effect.setTargetPointer(new FixedTarget(controller.getId(), game));
|
||||
effect.apply(game, source);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,24 +3,16 @@ package mage.cards.h;
|
|||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.abilities.costs.common.PutCountersTargetCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetAnyTarget;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -38,15 +30,11 @@ public final class HatchetBully extends CardImpl {
|
|||
this.toughness = new MageInt(3);
|
||||
|
||||
// {2}{R}, {tap}, Put a -1/-1 counter on a creature you control: Hatchet Bully deals 2 damage to any target.
|
||||
Ability ability = new SimpleActivatedAbility(new HatchetBullyEffect(), new ManaCostsImpl<>("{2}{R}"));
|
||||
Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new ManaCostsImpl<>("{2}{R}"));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new HatchetBullyCost());
|
||||
ability.addCost(new PutCountersTargetCost(CounterType.M1M1.createInstance()));
|
||||
ability.addTarget(new TargetAnyTarget());
|
||||
Target target = new TargetControlledCreaturePermanent();
|
||||
target.withNotTarget(true);
|
||||
ability.addTarget(target);
|
||||
this.addAbility(ability);
|
||||
|
||||
}
|
||||
|
||||
private HatchetBully(final HatchetBully card) {
|
||||
|
|
@ -58,64 +46,3 @@ public final class HatchetBully extends CardImpl {
|
|||
return new HatchetBully(this);
|
||||
}
|
||||
}
|
||||
|
||||
class HatchetBullyCost extends CostImpl {
|
||||
|
||||
public HatchetBullyCost() {
|
||||
this.text = "Put a -1/-1 counter on a creature you control";
|
||||
}
|
||||
|
||||
private HatchetBullyCost(final HatchetBullyCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Permanent permanent = game.getPermanent(ability.getTargets().get(1).getFirstTarget());
|
||||
if (permanent != null) {
|
||||
permanent.addCounters(CounterType.M1M1.createInstance(), controllerId, ability, game);
|
||||
this.paid = true;
|
||||
}
|
||||
return paid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HatchetBullyCost copy() {
|
||||
return new HatchetBullyCost(this);
|
||||
}
|
||||
}
|
||||
|
||||
class HatchetBullyEffect extends OneShotEffect {
|
||||
|
||||
HatchetBullyEffect() {
|
||||
super(Outcome.Damage);
|
||||
staticText = "{this} deals 2 damage to any target";
|
||||
}
|
||||
|
||||
private HatchetBullyEffect(final HatchetBullyEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HatchetBullyEffect copy() {
|
||||
return new HatchetBullyEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
permanent.damage(2, source.getSourceId(), source, game, false, true);
|
||||
}
|
||||
Player player = game.getPlayer(source.getFirstTarget());
|
||||
if (player != null) {
|
||||
player.damage(2, source.getSourceId(), source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
package mage.cards.k;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.events.DamageEvent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
|
|
@ -12,18 +9,22 @@ import mage.abilities.costs.CostImpl;
|
|||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamageEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.TargetSource;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -40,8 +41,7 @@ public final class KithkinArmor extends CardImpl {
|
|||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
|
||||
Ability ability = new EnchantAbility(auraTarget);
|
||||
this.addAbility(ability);
|
||||
this.addAbility(new EnchantAbility(auraTarget));
|
||||
|
||||
// Enchanted creature can't be blocked by creatures with power 3 or greater.
|
||||
this.addAbility(new SimpleStaticAbility(new KithkinArmorRestrictionEffect()));
|
||||
|
|
@ -50,7 +50,6 @@ public final class KithkinArmor extends CardImpl {
|
|||
Ability protectionAbility = new SimpleActivatedAbility(
|
||||
new KithkinArmorPreventionEffect(),
|
||||
new KithkinArmorCost());
|
||||
protectionAbility.addTarget(new TargetSource());
|
||||
this.addAbility(protectionAbility);
|
||||
|
||||
}
|
||||
|
|
@ -137,6 +136,7 @@ class KithkinArmorRestrictionEffect extends RestrictionEffect {
|
|||
|
||||
class KithkinArmorPreventionEffect extends PreventionEffectImpl {
|
||||
|
||||
private MageObjectReference mageObjectReference;
|
||||
KithkinArmorPreventionEffect() {
|
||||
super(Duration.EndOfTurn, Integer.MAX_VALUE, false);
|
||||
staticText = "The next time a source of your choice would deal damage to enchanted creature this turn, prevent that damage";
|
||||
|
|
@ -144,13 +144,20 @@ class KithkinArmorPreventionEffect extends PreventionEffectImpl {
|
|||
|
||||
private KithkinArmorPreventionEffect(final KithkinArmorPreventionEffect effect) {
|
||||
super(effect);
|
||||
mageObjectReference = effect.mageObjectReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KithkinArmorPreventionEffect copy() {
|
||||
return new KithkinArmorPreventionEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
TargetSource target = new TargetSource();
|
||||
target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
|
||||
mageObjectReference = new MageObjectReference(target.getFirstTarget(), game);
|
||||
}
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (super.applies(event, source, game)
|
||||
|
|
|
|||
|
|
@ -1,33 +1,32 @@
|
|||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility;
|
||||
import mage.abilities.effects.common.DamageTargetControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterArtifactPermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author North
|
||||
*/
|
||||
public final class MagneticMine extends CardImpl {
|
||||
private static final FilterPermanent filter = new FilterArtifactPermanent("another artifact");
|
||||
|
||||
static {
|
||||
filter.add(AnotherPredicate.instance);
|
||||
}
|
||||
public MagneticMine(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
|
||||
|
||||
// Whenever another artifact is put into a graveyard from the battlefield, Magnetic Mine deals 2 damage to that artifact’s controller.
|
||||
MagneticMineTriggeredAbility ability = new MagneticMineTriggeredAbility(new DamageTargetEffect(2));
|
||||
ability.addTarget(new TargetPlayer().withNotTarget(true));
|
||||
this.addAbility(ability);
|
||||
this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility(
|
||||
new DamageTargetControllerEffect(2, "artifact"), false, filter, true));
|
||||
}
|
||||
|
||||
private MagneticMine(final MagneticMine card) {
|
||||
|
|
@ -39,41 +38,3 @@ public final class MagneticMine extends CardImpl {
|
|||
return new MagneticMine(this);
|
||||
}
|
||||
}
|
||||
|
||||
class MagneticMineTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public MagneticMineTriggeredAbility(Effect effect) {
|
||||
super(Zone.BATTLEFIELD, effect, false);
|
||||
}
|
||||
|
||||
private MagneticMineTriggeredAbility(final MagneticMineTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
if (zEvent.isDiesEvent()
|
||||
&& zEvent.getTarget().isArtifact(game)
|
||||
&& !Objects.equals(zEvent.getTarget().getId(), this.getSourceId())) {
|
||||
this.getTargets().get(0).add(zEvent.getTarget().getControllerId(), game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever another artifact is put into a graveyard from the battlefield, {this} deals 2 damage to that artifact's controller";
|
||||
}
|
||||
|
||||
@Override
|
||||
public MagneticMineTriggeredAbility copy() {
|
||||
return new MagneticMineTriggeredAbility(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,23 +3,20 @@ package mage.cards.s;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.condition.common.ControlACommanderCondition;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.OneShotNonTargetEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.SoldierToken;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -37,9 +34,15 @@ public final class SOLDIERMilitaryProgram extends CardImpl {
|
|||
Ability ability = new BeginningOfCombatTriggeredAbility(new CreateTokenEffect(new SoldierToken()));
|
||||
ability.getModes().setChooseText("choose one. If you control a commander, you may choose both instead.");
|
||||
ability.getModes().setMoreCondition(2, ControlACommanderCondition.instance);
|
||||
ability.getModes().setChooseText(
|
||||
"choose one. If you control a commander, you may choose both instead."
|
||||
);
|
||||
|
||||
// * Put a +1/+1 counter on each of up to two Soldiers you control.
|
||||
ability.addMode(new Mode(new SOLDIERMilitaryProgramEffect()));
|
||||
ability.addMode(new Mode(new OneShotNonTargetEffect(
|
||||
new AddCountersTargetEffect(CounterType.P1P1.createInstance())
|
||||
.setText("Put a +1/+1 counter on each of up to two Soldiers you control"),
|
||||
new TargetPermanent(0, 2, filter))));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -52,38 +55,3 @@ public final class SOLDIERMilitaryProgram extends CardImpl {
|
|||
return new SOLDIERMilitaryProgram(this);
|
||||
}
|
||||
}
|
||||
|
||||
class SOLDIERMilitaryProgramEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SOLDIER, "Soldiers you control");
|
||||
|
||||
SOLDIERMilitaryProgramEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "put a +1/+1 counter on each of up to two Soldiers you control";
|
||||
}
|
||||
|
||||
private SOLDIERMilitaryProgramEffect(final SOLDIERMilitaryProgramEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SOLDIERMilitaryProgramEffect copy() {
|
||||
return new SOLDIERMilitaryProgramEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
TargetPermanent target = new TargetPermanent(0, 2, filter, true);
|
||||
player.choose(Outcome.BoostCreature, target, source, game);
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
Optional.ofNullable(targetId)
|
||||
.map(game::getPermanent)
|
||||
.map(permanent -> permanent.addCounters(CounterType.P1P1.createInstance(), source, game));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
import mage.abilities.costs.common.ExileFromHandCost;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.ExileFromHandCostCardConvertedMana;
|
||||
import mage.abilities.effects.common.RedirectDamageFromSourceToTargetEffect;
|
||||
import mage.abilities.effects.RedirectionEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.common.FilterOwnedCard;
|
||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||
|
|
@ -50,7 +52,6 @@ public final class ShiningShoal extends CardImpl {
|
|||
this.getSpellAbility().addEffect(new ShiningShoalRedirectDamageTargetEffect(
|
||||
Duration.EndOfTurn, ExileFromHandCostCardConvertedMana.instance
|
||||
));
|
||||
this.getSpellAbility().addTarget(new TargetSource());
|
||||
this.getSpellAbility().addTarget(new TargetAnyTarget());
|
||||
}
|
||||
|
||||
|
|
@ -64,9 +65,10 @@ public final class ShiningShoal extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class ShiningShoalRedirectDamageTargetEffect extends RedirectDamageFromSourceToTargetEffect {
|
||||
class ShiningShoalRedirectDamageTargetEffect extends RedirectionEffect {
|
||||
|
||||
private final DynamicValue dynamicAmount;
|
||||
private MageObjectReference mageObjectReference;
|
||||
|
||||
public ShiningShoalRedirectDamageTargetEffect(Duration duration, DynamicValue dynamicAmount) {
|
||||
super(duration, 0, UsageType.ONE_USAGE_AT_THE_SAME_TIME);
|
||||
|
|
@ -77,6 +79,7 @@ class ShiningShoalRedirectDamageTargetEffect extends RedirectDamageFromSourceToT
|
|||
private ShiningShoalRedirectDamageTargetEffect(final ShiningShoalRedirectDamageTargetEffect effect) {
|
||||
super(effect);
|
||||
this.dynamicAmount = effect.dynamicAmount;
|
||||
this.mageObjectReference = effect.mageObjectReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -88,6 +91,9 @@ class ShiningShoalRedirectDamageTargetEffect extends RedirectDamageFromSourceToT
|
|||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
amountToRedirect = dynamicAmount.calculate(game, source, this);
|
||||
TargetSource target = new TargetSource();
|
||||
target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
|
||||
mageObjectReference = new MageObjectReference(target.getFirstTarget(), game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -96,15 +102,13 @@ class ShiningShoalRedirectDamageTargetEffect extends RedirectDamageFromSourceToT
|
|||
|
||||
// get source of the damage event
|
||||
MageObject sourceObject = game.getObject(event.getSourceId());
|
||||
// get the chosen damage source
|
||||
MageObject chosenSourceObject = game.getObject(source.getFirstTarget());
|
||||
// does the source of the damage exist?
|
||||
if (sourceObject == null) {
|
||||
game.informPlayers("Couldn't find source of damage");
|
||||
return false;
|
||||
}
|
||||
// do the 2 objects match?
|
||||
if (chosenSourceObject == null || !sourceObject.getId().equals(chosenSourceObject.getId())) {
|
||||
if (!mageObjectReference.refersTo(sourceObject, game)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +118,7 @@ class ShiningShoalRedirectDamageTargetEffect extends RedirectDamageFromSourceToT
|
|||
if (permanent != null && permanent.isCreature(game)) {
|
||||
if (permanent.isControlledBy(source.getControllerId())) {
|
||||
// it's your creature
|
||||
redirectTarget = source.getTargets().get(1);
|
||||
redirectTarget = source.getTargets().get(0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -123,7 +127,7 @@ class ShiningShoalRedirectDamageTargetEffect extends RedirectDamageFromSourceToT
|
|||
if (player != null) {
|
||||
if (player.getId().equals(source.getControllerId())) {
|
||||
// it is you
|
||||
redirectTarget = source.getTargets().get(1);
|
||||
redirectTarget = source.getTargets().get(0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package mage.cards.s;
|
|||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.common.ChoosePlayerEffect;
|
||||
import mage.abilities.effects.mana.ManaEffect;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -14,6 +13,7 @@ import mage.constants.Outcome;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPlayer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -30,8 +30,6 @@ public final class SpectralSearchlight extends CardImpl {
|
|||
// {T}: Choose a player. That player adds one mana of any color they chooses.
|
||||
ManaEffect effect = new SpectralSearchlightManaEffect();
|
||||
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
|
||||
// choosing player as first effect, before adding mana effect
|
||||
ability.getEffects().add(0, new ChoosePlayerEffect(Outcome.PutManaInPool));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +47,7 @@ class SpectralSearchlightManaEffect extends ManaEffect {
|
|||
|
||||
SpectralSearchlightManaEffect() {
|
||||
super();
|
||||
this.staticText = "That player adds one mana of any color they choose";
|
||||
this.staticText = "Choose a player. That player adds one mana of any color they choose";
|
||||
}
|
||||
|
||||
private SpectralSearchlightManaEffect(final SpectralSearchlightManaEffect effect) {
|
||||
|
|
@ -58,7 +56,13 @@ class SpectralSearchlightManaEffect extends ManaEffect {
|
|||
|
||||
@Override
|
||||
public Player getPlayer(Game game, Ability source) {
|
||||
return game.getPlayer((UUID) game.getState().getValue(source.getSourceId() + "_player"));
|
||||
if (!game.inCheckPlayableState()) {
|
||||
TargetPlayer target = new TargetPlayer(1, 1, true);
|
||||
if (target.choose(Outcome.PutManaInPool, source.getControllerId(), source, game)) {
|
||||
return game.getPlayer(target.getFirstTarget());
|
||||
}
|
||||
}
|
||||
return game.getPlayer(source.getControllerId()); // Count as controller's potential mana for card playability
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.abilities.dynamicvalue.common.MultikickerCount;
|
||||
import mage.abilities.effects.OneShotNonTargetEffect;
|
||||
import mage.abilities.effects.common.DamageAllEffect;
|
||||
import mage.abilities.effects.common.PhaseOutTargetEffect;
|
||||
import mage.abilities.keyword.KickerAbility;
|
||||
|
|
@ -35,10 +36,10 @@ public final class TemporalFirestorm extends CardImpl {
|
|||
this.addAbility(kickerAbility);
|
||||
|
||||
// Choose up to X creatures and/or planeswalkers you control, where X is the number of times this spell was kicked. Those permanents phase out.
|
||||
this.getSpellAbility().addEffect(new PhaseOutTargetEffect().setText("choose up to X creatures and/or " +
|
||||
"planeswalkers you control, where X is the number of times this spell was kicked. Those permanents phase out"));
|
||||
this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter, true));
|
||||
this.getSpellAbility().setTargetAdjuster(new TargetsCountAdjuster(MultikickerCount.instance));
|
||||
this.getSpellAbility().addEffect(new OneShotNonTargetEffect(new PhaseOutTargetEffect().setText("choose up to X creatures and/or " +
|
||||
"planeswalkers you control, where X is the number of times this spell was kicked. Those permanents phase out"),
|
||||
new TargetPermanent(0, 1, filter, true), new TargetsCountAdjuster(MultikickerCount.instance)
|
||||
));
|
||||
|
||||
// Temporal Firestorm deals 5 damage to each creature and each planeswalker.
|
||||
this.getSpellAbility().addEffect(new DamageAllEffect(
|
||||
|
|
|
|||
|
|
@ -1,26 +1,29 @@
|
|||
|
||||
package mage.cards.v;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.mana.AddManaToManaPoolTargetControllerEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.mana.ManaEffect;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
|
|
@ -48,10 +51,9 @@ public final class Valleymaker extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
|
||||
// {tap}, Sacrifice a Forest: Choose a player. That player adds {G}{G}{G}.
|
||||
Ability ability2 = new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaToManaPoolTargetControllerEffect(Mana.GreenMana(3), "chosen player")
|
||||
.setText("choose a player. That player adds {G}{G}{G}"), new TapSourceCost());
|
||||
Ability ability2 = new SimpleManaAbility(Zone.BATTLEFIELD, new ValleymakerManaEffect()
|
||||
.setText("That player adds {G}{G}{G}"), new TapSourceCost());
|
||||
ability2.addCost(new SacrificeTargetCost(filter2));
|
||||
ability2.addTarget(new TargetPlayer(1, 1, true));
|
||||
this.addAbility(ability2);
|
||||
}
|
||||
|
||||
|
|
@ -64,3 +66,37 @@ public final class Valleymaker extends CardImpl {
|
|||
return new Valleymaker(this);
|
||||
}
|
||||
}
|
||||
|
||||
//Based on Spectral Searchlight
|
||||
class ValleymakerManaEffect extends ManaEffect {
|
||||
|
||||
ValleymakerManaEffect() {
|
||||
super();
|
||||
this.staticText = "Choose a player. That player adds {G}{G}{G}.";
|
||||
}
|
||||
|
||||
private ValleymakerManaEffect(final ValleymakerManaEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer(Game game, Ability source) {
|
||||
if (!game.inCheckPlayableState()) {
|
||||
TargetPlayer target = new TargetPlayer(1, 1, true);
|
||||
if (target.choose(Outcome.PutManaInPool, source.getControllerId(), source, game)) {
|
||||
return game.getPlayer(target.getFirstTarget());
|
||||
}
|
||||
}
|
||||
return game.getPlayer(source.getControllerId()); // Count as controller's potential mana for card playability
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mana produceMana(Game game, Ability source) {
|
||||
return Mana.GreenMana(3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValleymakerManaEffect copy() {
|
||||
return new ValleymakerManaEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@ import mage.Mana;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.common.ChoosePlayerEffect;
|
||||
import mage.abilities.effects.mana.ManaEffect;
|
||||
import mage.abilities.effects.common.continuous.UntapSourceDuringEachOtherPlayersUntapStepEffect;
|
||||
import mage.abilities.effects.mana.ManaEffect;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -15,6 +14,7 @@ import mage.constants.Outcome;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPlayer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -33,8 +33,6 @@ public final class VictoryChimes extends CardImpl {
|
|||
ManaEffect effect = new VictoryChimesManaEffect("chosen player");
|
||||
effect.setText("a player of your choice adds {C}");
|
||||
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
|
||||
// choosing player as first effect, before adding mana effect
|
||||
ability.getEffects().add(0, new ChoosePlayerEffect(Outcome.PutManaInPool).setText(""));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +59,13 @@ class VictoryChimesManaEffect extends ManaEffect {
|
|||
|
||||
@Override
|
||||
public Player getPlayer(Game game, Ability source) {
|
||||
return game.getPlayer((UUID) game.getState().getValue(source.getSourceId() + "_player"));
|
||||
if (!game.inCheckPlayableState()) {
|
||||
TargetPlayer target = new TargetPlayer(1, 1, true);
|
||||
if (target.choose(Outcome.PutManaInPool, source.getControllerId(), source, game)) {
|
||||
return game.getPlayer(target.getFirstTarget());
|
||||
}
|
||||
}
|
||||
return game.getPlayer(source.getControllerId()); // Count as controller's potential mana for card playability
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
|
||||
package mage.cards.w;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.abilities.costs.common.PayLifeCost;
|
||||
import mage.abilities.costs.common.PutCountersTargetCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.PreventDamageToTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -15,17 +13,14 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.common.TargetPlayerOrPlaneswalker;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
|
|
@ -64,11 +59,8 @@ public final class WanderingMage extends CardImpl {
|
|||
// {B}, Put a -1/-1 counter on a creature you control: Prevent the next 2 damage that would be dealt to target player this turn.
|
||||
ability = new SimpleActivatedAbility(
|
||||
new PreventDamageToTargetEffect(Duration.EndOfTurn, 2), new ManaCostsImpl<>("{B}"));
|
||||
ability.addCost(new WanderingMageCost());
|
||||
ability.addCost(new PutCountersTargetCost(CounterType.M1M1.createInstance()));
|
||||
ability.addTarget(new TargetPlayerOrPlaneswalker());
|
||||
Target target = new TargetControlledCreaturePermanent();
|
||||
target.withNotTarget(true);
|
||||
ability.addTarget(target);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -81,34 +73,3 @@ public final class WanderingMage extends CardImpl {
|
|||
return new WanderingMage(this);
|
||||
}
|
||||
}
|
||||
|
||||
class WanderingMageCost extends CostImpl {
|
||||
|
||||
public WanderingMageCost() {
|
||||
this.text = "Put a -1/-1 counter on a creature you control";
|
||||
}
|
||||
|
||||
private WanderingMageCost(final WanderingMageCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Permanent permanent = game.getPermanent(ability.getTargets().get(1).getFirstTarget());
|
||||
if (permanent != null) {
|
||||
permanent.addCounters(CounterType.M1M1.createInstance(), controllerId, ability, game);
|
||||
this.paid = true;
|
||||
}
|
||||
return paid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WanderingMageCost copy() {
|
||||
return new WanderingMageCost(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
|
||||
package mage.cards.w;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotNonTargetEffect;
|
||||
import mage.abilities.effects.common.ExileTargetForSourceEffect;
|
||||
import mage.abilities.effects.common.ReturnFromExileForSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -14,18 +14,17 @@ import mage.constants.CardType;
|
|||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledLandPermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author tcontis
|
||||
*/
|
||||
public final class WormfangNewt extends CardImpl {
|
||||
|
||||
public WormfangNewt(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
|
||||
this.subtype.add(SubType.NIGHTMARE);
|
||||
this.subtype.add(SubType.SALAMANDER);
|
||||
this.subtype.add(SubType.BEAST);
|
||||
|
|
@ -34,10 +33,9 @@ public final class WormfangNewt extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// When Wormfang Turtle enters the battlefield, exile a land you control.
|
||||
Ability ability1 = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect(), false);
|
||||
Target target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_A_LAND).withNotTarget(true);
|
||||
ability1.addTarget(target);
|
||||
this.addAbility(ability1);
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new OneShotNonTargetEffect(
|
||||
new ExileTargetForSourceEffect().setText("exile a land you control"),
|
||||
new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_A_LAND))));
|
||||
|
||||
// When Wormfang Turtle leaves the battlefield, return the exiled card to the battlefield under its owner's control.
|
||||
Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
|
||||
package mage.cards.w;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotNonTargetEffect;
|
||||
import mage.abilities.effects.common.ExileTargetForSourceEffect;
|
||||
import mage.abilities.effects.common.ReturnFromExileForSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -14,11 +14,10 @@ import mage.constants.CardType;
|
|||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledLandPermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author tcontis
|
||||
*/
|
||||
|
|
@ -34,10 +33,10 @@ public final class WormfangTurtle extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// When Wormfang Turtle enters the battlefield, exile a land you control.
|
||||
Ability ability1 = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect(), false);
|
||||
Target target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_A_LAND).withNotTarget(true);
|
||||
ability1.addTarget(target);
|
||||
this.addAbility(ability1);
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new OneShotNonTargetEffect(
|
||||
new ExileTargetForSourceEffect().setText("exile a land you control"),
|
||||
new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_A_LAND))));
|
||||
|
||||
|
||||
// When Wormfang Turtle leaves the battlefield, return the exiled card to the battlefield under its owner's control.
|
||||
Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package mage.cards.y;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotNonTargetEffect;
|
||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -26,9 +26,9 @@ public final class YaroksWavecrasher extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// When Yarok’s Wavecrasher enters the battlefield, return another creature you control to its owner’s hand.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false);
|
||||
ability.addTarget(new TargetControlledPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL).withNotTarget(true));
|
||||
this.addAbility(ability);
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new OneShotNonTargetEffect(
|
||||
new ReturnToHandTargetEffect().setText("return another creature you control to its owner's hand"),
|
||||
new TargetControlledPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL))));
|
||||
}
|
||||
|
||||
private YaroksWavecrasher(final YaroksWavecrasher card) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package mage.cards.y;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotNonTargetEffect;
|
||||
import mage.abilities.effects.common.ExileReturnBattlefieldNextEndStepTargetEffect;
|
||||
import mage.abilities.keyword.CompanionAbility;
|
||||
import mage.abilities.keyword.CompanionCondition;
|
||||
|
|
@ -54,10 +54,9 @@ public final class YorionSkyNomad extends CardImpl {
|
|||
|
||||
// When Yorion enters the battlefield, exile any number of other nonland permanents you own
|
||||
// and control. Return those cards to the battlefield at the beginning of the next end step.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(
|
||||
new ExileReturnBattlefieldNextEndStepTargetEffect().setText(ruleText));
|
||||
ability.addTarget(new TargetPermanent(0, Integer.MAX_VALUE, filter, true));
|
||||
this.addAbility(ability);
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new OneShotNonTargetEffect(
|
||||
new ExileReturnBattlefieldNextEndStepTargetEffect().setText(ruleText),
|
||||
new TargetPermanent(0, Integer.MAX_VALUE, filter, true))));
|
||||
}
|
||||
|
||||
private YorionSkyNomad(final YorionSkyNomad card) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
package org.mage.test.cards.abilities.oneshot;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.player.TestPlayer;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
/**
|
||||
*
|
||||
* @author notgreat
|
||||
*/
|
||||
public class OneShotNonTargetTest extends CardTestPlayerBase {
|
||||
@Test
|
||||
public void YorionChooseAfterTriggerTest() {
|
||||
addCard(Zone.HAND, playerA, "Yorion, Sky Nomad");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 7);
|
||||
addCard(Zone.HAND, playerA, "Resolute Reinforcements");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yorion, Sky Nomad");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, true);
|
||||
checkPermanentCount("Yorion on battlefield", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yorion, Sky Nomad", 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Resolute Reinforcements");
|
||||
setChoice(playerA, "Resolute Reinforcements");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertTokenCount(playerA, "Soldier Token", 2);
|
||||
assertPermanentCount(playerA, "Yorion, Sky Nomad", 1);
|
||||
assertPermanentCount(playerA, "Resolute Reinforcements", 1);
|
||||
assertTappedCount("Plains", true, 7);
|
||||
}
|
||||
@Test
|
||||
public void NonTargetAdjusterTest() {
|
||||
addCard(Zone.HAND, playerA, "Temporal Firestorm");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Squire");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Python");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Watchwolf");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Temporal Firestorm");
|
||||
setChoice(playerA, true);
|
||||
setChoice(playerA, true);
|
||||
setChoice(playerA, "Squire^Python");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertGraveyardCount(playerA, "Squire", 0);
|
||||
assertGraveyardCount(playerA, "Python", 0);
|
||||
assertGraveyardCount(playerA, "Watchwolf", 1);
|
||||
}
|
||||
@Test
|
||||
public void ModeSelectionTest() {
|
||||
addCard(Zone.HAND, playerA, "SOLDIER Military Program");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Squire", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "SOLDIER Military Program");
|
||||
setModeChoice(playerA, "2");
|
||||
setChoice(playerA, "Squire");
|
||||
setChoice(playerA, TestPlayer.CHOICE_SKIP);
|
||||
|
||||
setModeChoice(playerA, "1");
|
||||
|
||||
setModeChoice(playerA, "2");
|
||||
setChoice(playerA, "Squire^Soldier Token");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(5, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertPowerToughness(playerA, "Squire", 3, 4);
|
||||
assertPowerToughness(playerA, "Soldier Token", 2, 2);
|
||||
}
|
||||
}
|
||||
|
|
@ -1749,6 +1749,10 @@ public abstract class AbilityImpl implements Ability {
|
|||
|
||||
@Override
|
||||
public AbilityImpl setTargetAdjuster(TargetAdjuster targetAdjuster) {
|
||||
if (targetAdjuster == null) {
|
||||
this.targetAdjuster = null;
|
||||
return this;
|
||||
}
|
||||
if (targetAdjuster instanceof GenericTargetAdjuster && this.getTargets().isEmpty()) {
|
||||
throw new IllegalStateException("Target adjuster being added but no targets are set!");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package mage.abilities.common;
|
|||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
|
|
@ -18,7 +19,7 @@ import mage.target.targetpointer.FixedTarget;
|
|||
public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
protected FilterPermanent filter;
|
||||
private boolean setTargetPointer;
|
||||
private SetTargetPointer setTargetPointer;
|
||||
|
||||
public DiesCreatureTriggeredAbility(Effect effect, boolean optional) {
|
||||
this(effect, optional, false);
|
||||
|
|
@ -33,7 +34,7 @@ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (another) {
|
||||
filter.add(AnotherPredicate.instance);
|
||||
}
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
this.setTargetPointer = (setTargetPointer ? SetTargetPointer.PERMANENT : SetTargetPointer.NONE);
|
||||
}
|
||||
|
||||
public DiesCreatureTriggeredAbility(Effect effect, boolean optional, FilterPermanent filter) {
|
||||
|
|
@ -44,7 +45,14 @@ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
|
|||
this(Zone.BATTLEFIELD, effect, optional, filter, setTargetPointer);
|
||||
}
|
||||
|
||||
public DiesCreatureTriggeredAbility(Effect effect, SetTargetPointer setTargetPointer) {
|
||||
this(Zone.BATTLEFIELD, effect, false, new FilterCreaturePermanent("a creature"), setTargetPointer);
|
||||
}
|
||||
|
||||
public DiesCreatureTriggeredAbility(Zone zone, Effect effect, boolean optional, FilterPermanent filter, boolean setTargetPointer) {
|
||||
this(zone, effect, optional, filter, (setTargetPointer ? SetTargetPointer.PERMANENT : SetTargetPointer.NONE));
|
||||
}
|
||||
public DiesCreatureTriggeredAbility(Zone zone, Effect effect, boolean optional, FilterPermanent filter, SetTargetPointer setTargetPointer) {
|
||||
super(zone, effect, optional);
|
||||
this.filter = filter;
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
|
|
@ -75,8 +83,17 @@ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
|
|||
return false;
|
||||
}
|
||||
getEffects().setValue("creatureDied", zEvent.getTarget());
|
||||
if (setTargetPointer) {
|
||||
this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
|
||||
switch (setTargetPointer) {
|
||||
case PLAYER:
|
||||
this.getAllEffects().setTargetPointer(new FixedTarget(event.getPlayerId(), game));
|
||||
break;
|
||||
case PERMANENT:
|
||||
this.getAllEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
|
||||
break;
|
||||
case NONE:
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported SetTargetPointer in DiesCreatureTriggeredAbility");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
package mage.abilities.costs.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author notgreat
|
||||
*/
|
||||
public class PutCountersTargetCost extends CostImpl {
|
||||
|
||||
private final Counter counter;
|
||||
|
||||
public PutCountersTargetCost(Counter counter){
|
||||
this(counter, new TargetControlledCreaturePermanent());
|
||||
}
|
||||
|
||||
public PutCountersTargetCost(Counter counter, TargetControlledPermanent target) {
|
||||
this.counter = counter.copy();
|
||||
target.withNotTarget(true);
|
||||
this.addTarget(target);
|
||||
this.text = "put " + counter.getDescription() + " on " + target.getDescription();
|
||||
}
|
||||
|
||||
public PutCountersTargetCost(PutCountersTargetCost cost) {
|
||||
super(cost);
|
||||
this.counter = cost.counter.copy();
|
||||
}
|
||||
|
||||
public PutCountersTargetCost copy() {
|
||||
return new PutCountersTargetCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Player player = game.getPlayer(ability.getControllerId());
|
||||
if (player == null || !this.getTargets().choose(Outcome.Exile, controllerId, source.getSourceId(), source, game)) {
|
||||
return paid;
|
||||
}
|
||||
for (UUID targetId : this.getTargets().get(0).getTargets()) {
|
||||
Permanent permanent = game.getPermanent(targetId);
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
paid |= permanent.addCounters(counter, controllerId, ability, game);
|
||||
}
|
||||
return paid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
return this.getTargets().canChoose(controllerId, source, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package mage.abilities.effects;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.Game;
|
||||
import mage.target.Target;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
import mage.target.targetpointer.TargetPointer;
|
||||
|
||||
/**
|
||||
* @author notgreat
|
||||
*/
|
||||
public class OneShotNonTargetEffect extends OneShotEffect {
|
||||
OneShotEffect effect;
|
||||
Target notTarget;
|
||||
TargetAdjuster adjuster;
|
||||
|
||||
public OneShotNonTargetEffect(OneShotEffect effect, Target notTarget) {
|
||||
this(effect, notTarget, null);
|
||||
}
|
||||
|
||||
public OneShotNonTargetEffect(OneShotEffect effect, Target notTarget, TargetAdjuster adjuster) {
|
||||
super(effect.outcome);
|
||||
this.effect = effect;
|
||||
this.notTarget = notTarget;
|
||||
this.notTarget.withNotTarget(true);
|
||||
this.adjuster = adjuster;
|
||||
if (effect.staticText == null || effect.staticText.equals("")){
|
||||
throw new IllegalArgumentException("Effect must use static text");
|
||||
}
|
||||
this.setText(effect.staticText);
|
||||
}
|
||||
|
||||
private OneShotNonTargetEffect(OneShotNonTargetEffect eff) {
|
||||
super(eff);
|
||||
this.effect = eff.effect.copy();
|
||||
this.notTarget = eff.notTarget.copy();
|
||||
this.adjuster = eff.adjuster;
|
||||
}
|
||||
|
||||
public OneShotNonTargetEffect copy() {
|
||||
return new OneShotNonTargetEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
boolean result = false;
|
||||
Target target = notTarget.copy();
|
||||
if (source.getTargetAdjuster() != null || !source.getTargets().isEmpty()){
|
||||
throw new IllegalStateException("source ability already has target but is using OneShotNonTargetEffect");
|
||||
}
|
||||
source.addTarget(target);
|
||||
if (adjuster != null) {
|
||||
adjuster.clearDefaultTargets();
|
||||
source.setTargetAdjuster(adjuster);
|
||||
source.adjustTargets(game);
|
||||
source.setTargetAdjuster(null);
|
||||
}
|
||||
|
||||
if (source.getTargets().choose(outcome, source.getControllerId(), source.getId(), source, game)) {
|
||||
result = effect.apply(game, source);
|
||||
}
|
||||
source.getTargets().clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OneShotEffect setTargetPointer(TargetPointer targetPointer) {
|
||||
if (targetPointer == null) {
|
||||
return null;
|
||||
}
|
||||
effect.setTargetPointer(targetPointer);
|
||||
return super.setTargetPointer(targetPointer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String key, Object value) {
|
||||
effect.setValue(key, value);
|
||||
super.setValue(key, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -71,6 +71,10 @@ public class ConditionalTargetAdjuster implements TargetAdjuster {
|
|||
blueprintTarget = ability.getTargets().get(0).copy();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void clearDefaultTargets() {
|
||||
blueprintTarget = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
|
|
|
|||
|
|
@ -14,4 +14,8 @@ public abstract class GenericTargetAdjuster implements TargetAdjuster {
|
|||
throw new IllegalStateException("Wrong code usage: target adjuster already has blueprint target - " + blueprintTarget);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void clearDefaultTargets() {
|
||||
blueprintTarget = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,4 +20,7 @@ public interface TargetAdjuster extends Serializable {
|
|||
*/
|
||||
default void addDefaultTargets(Ability ability) {
|
||||
}
|
||||
|
||||
default void clearDefaultTargets() {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue