made some abilities properly copiable

This commit is contained in:
Evan Kranzler 2020-04-19 12:54:25 -04:00
parent 1468f89ce6
commit 4e5dea5097
2 changed files with 85 additions and 96 deletions

View file

@ -1,54 +1,62 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.MageItem;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ChooseNewTargetsTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterStackObject;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game;
import mage.game.stack.StackObject;
import mage.target.Target;
import mage.target.TargetStackObject;
import mage.target.Targets;
import java.util.Collection;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Stream;
/**
*
* @author LevelX2
*/
public final class SilverWyvern extends CardImpl {
private static final FilterStackObject filter = new FilterStackObject();
static {
filter.add(SilverWyvernPredicate.instance);
}
public SilverWyvern(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
this.subtype.add(SubType.DRAKE);
this.power = new MageInt(4);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// {U}: Change the target of target spell or ability that targets only Silver Wyvern. The new target must be a creature.
Effect effect = new ChooseNewTargetsTargetEffect(true, true);
effect.setText("Change the target of target spell or ability that targets only {this}. The new target must be a creature");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{U}"));
FilterStackObject filter = new FilterStackObject();
filter.add(new TargetsOnlySourcePredicate(getId()));
Ability ability = new SimpleActivatedAbility(
new ChooseNewTargetsTargetEffect(true, true)
.setText("Change the target of target spell or ability that targets only {this}. " +
"The new target must be a creature"),
new ManaCostsImpl("{U}")
);
ability.addTarget(new TargetStackObject(filter));
this.addAbility(ability);
}
public SilverWyvern(final SilverWyvern card) {
private SilverWyvern(final SilverWyvern card) {
super(card);
}
@ -58,35 +66,21 @@ public final class SilverWyvern extends CardImpl {
}
}
class TargetsOnlySourcePredicate implements Predicate<MageObject> {
private final UUID sourceId;
public TargetsOnlySourcePredicate(UUID sourceId) {
this.sourceId = sourceId;
}
enum SilverWyvernPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<StackObject>> {
instance;
@Override
public boolean apply(MageObject input, Game game) {
StackObject stackObject = game.getStack().getStackObject(input.getId());
if (stackObject != null) {
Targets spellTargets = stackObject.getStackAbility().getTargets();
int numberOfTargets = 0;
for (Target target : spellTargets) {
if (target.getFirstTarget() == null || !target.getFirstTarget().toString().equals(sourceId.toString())) { // UUID != UUID does not work - it's always false
return false;
}
numberOfTargets += target.getTargets().size();
}
if (numberOfTargets == 1) {
return true;
}
}
return false;
}
@Override
public String toString() {
return "target spell or ability that targets only source";
public boolean apply(ObjectSourcePlayer<StackObject> input, Game game) {
Stream<UUID> stream = input.getObject()
.getStackAbility()
.getTargets()
.stream()
.map(Target::getTargets)
.flatMap(Collection::stream)
.map(game::getPermanent)
.filter(Objects::nonNull)
.map(MageItem::getId);
return stream.allMatch(input.getSourceId()::equals)
&& stream.anyMatch(input.getSourceId()::equals);
}
}

View file

@ -1,12 +1,8 @@
package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.MageItem;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.costs.mana.GenericManaCost;
@ -17,50 +13,68 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.constants.SubType;
import mage.filter.FilterSpell;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.game.stack.StackObject;
import mage.target.Target;
import mage.target.TargetSpell;
import mage.target.common.TargetCreaturePermanent;
import java.util.Collection;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Stream;
/**
*
* @author emerald000
*/
public final class Torchling extends CardImpl {
private static final FilterSpell filter = new FilterSpell();
static {
filter.add(TorchlingPredicate.instance);
}
public Torchling(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}");
this.subtype.add(SubType.SHAPESHIFTER);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// {R}: Untap Torchling.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapSourceEffect(), new ColoredManaCost(ColoredManaSymbol.R)));
this.addAbility(new SimpleActivatedAbility(new UntapSourceEffect(), new ColoredManaCost(ColoredManaSymbol.R)));
// {R}: Target creature blocks Torchling this turn if able.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(), new ColoredManaCost(ColoredManaSymbol.R));
Ability ability = new SimpleActivatedAbility(
new MustBeBlockedByTargetSourceEffect(), new ColoredManaCost(ColoredManaSymbol.R)
);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
// {R}: Change the target of target spell that targets only Torchling.
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChooseNewTargetsTargetEffect(true, true), new ColoredManaCost(ColoredManaSymbol.R));
FilterSpell filter = new FilterSpell("spell that targets only " + this.getName());
filter.add(new TorchlingTargetPredicate(this.getId()));
ability = new SimpleActivatedAbility(
new ChooseNewTargetsTargetEffect(true, true)
.setText("change the target of target spell that targets only {this}"),
new ColoredManaCost(ColoredManaSymbol.R)
);
ability.addTarget(new TargetSpell(filter));
this.addAbility(ability);
// {1}: Torchling gets +1/-1 until end of turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, -1, Duration.EndOfTurn), new GenericManaCost(1)));
this.addAbility(new SimpleActivatedAbility(
new BoostSourceEffect(1, -1, Duration.EndOfTurn), new GenericManaCost(1)
));
// {1}: Torchling gets -1/+1 until end of turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(-1, 1, Duration.EndOfTurn), new GenericManaCost(1)));
this.addAbility(new SimpleActivatedAbility(
new BoostSourceEffect(-1, 1, Duration.EndOfTurn), new GenericManaCost(1)
));
}
public Torchling(final Torchling card) {
@ -73,40 +87,21 @@ public final class Torchling extends CardImpl {
}
}
class TorchlingTargetPredicate implements Predicate<MageObject> {
private final UUID sourceId;
TorchlingTargetPredicate(UUID sourceId) {
this.sourceId = sourceId;
}
enum TorchlingPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<StackObject>> {
instance;
@Override
public boolean apply(MageObject input, Game game) {
Spell spell = game.getStack().getSpell(input.getId());
if (spell != null) {
int numberOfTargets = 0;
for (SpellAbility spellAbility : spell.getSpellAbilities()) {
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
Mode mode = spellAbility.getModes().get(modeId);
for (Target target : mode.getTargets()) {
for (UUID targetId : target.getTargets()) {
if (!targetId.equals(sourceId)) {
return false;
} else {
numberOfTargets++;
}
}
}
}
}
return numberOfTargets > 0;
}
return false;
}
@Override
public String toString() {
return "target spell that targets only {this}";
public boolean apply(ObjectSourcePlayer<StackObject> input, Game game) {
Stream<UUID> stream = input.getObject()
.getStackAbility()
.getTargets()
.stream()
.map(Target::getTargets)
.flatMap(Collection::stream)
.map(game::getPermanent)
.filter(Objects::nonNull)
.map(MageItem::getId);
return stream.allMatch(input.getSourceId()::equals)
&& stream.anyMatch(input.getSourceId()::equals);
}
}