mirror of
https://github.com/correl/mage.git
synced 2025-01-13 19:11:33 +00:00
[VOC] Implemented Mirage Phalanx (#8654)
* Implemented Mirage Phalanx * Changed based on first set of comments * Reordered variables in alphabetical order * Added support for removing abilities from a token before creating it. * Fixed typo in CreateTokenCopyTargetEffect, should have been getAddedPermanents not getAddedPermanent (with the s). * Updated how soulbond is removed from MiragePhalanx tokens * Fixed missing fields in the copy constructor * - Refactoring the exileTokensCreated function to exile all tokens as a single trigger. - Changed Mirage Phalanx to use the new exileTokensCreated function - changed ’ to '
This commit is contained in:
parent
c68c7699c0
commit
5611f41949
36 changed files with 250 additions and 74 deletions
|
@ -112,7 +112,7 @@ class ArcaneArtisanCreateTokenEffect extends OneShotEffect {
|
|||
} else {
|
||||
tokensCreated = new HashSet<>();
|
||||
}
|
||||
for (Permanent perm : effect.getAddedPermanent()) {
|
||||
for (Permanent perm : effect.getAddedPermanents()) {
|
||||
if (perm != null) {
|
||||
tokensCreated.add(perm.getId());
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ class CogworkAssemblerCreateTokenEffect extends OneShotEffect {
|
|||
if (copiedPermanent != null) {
|
||||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, CardType.ARTIFACT, true);
|
||||
if (effect.apply(game, source)) {
|
||||
for (Permanent copyPermanent : effect.getAddedPermanent()) {
|
||||
for (Permanent copyPermanent : effect.getAddedPermanents()) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(copyPermanent, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
|
|
|
@ -93,8 +93,8 @@ class DanceOfManyCreateTokenCopyEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect();
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
effect.apply(game, source);
|
||||
game.getState().setValue(source.getSourceId() + "_token", effect.getAddedPermanent());
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
game.getState().setValue(source.getSourceId() + "_token", effect.getAddedPermanents());
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
Effect sacrificeEffect = new SacrificeTargetEffect("sacrifice Dance of Many");
|
||||
sacrificeEffect.setTargetPointer(new FixedTarget(sourceObject, game));
|
||||
LeavesBattlefieldTriggeredAbility triggerAbility = new LeavesBattlefieldTriggeredAbility(sacrificeEffect, false);
|
||||
|
|
|
@ -94,7 +94,7 @@ class DollhouseOfHorrorsEffect extends OneShotEffect {
|
|||
effect.apply(game, source);
|
||||
game.addEffect(new GainAbilityTargetEffect(
|
||||
HasteAbility.getInstance(), Duration.EndOfTurn
|
||||
).setTargetPointer(new FixedTargets(effect.getAddedPermanent(), game)), source);
|
||||
).setTargetPointer(new FixedTargets(effect.getAddedPermanents(), game)), source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ class DualNatureCreateTokenEffect extends OneShotEffect {
|
|||
} else {
|
||||
tokensCreated = new HashSet<>();
|
||||
}
|
||||
for (Permanent perm : effect.getAddedPermanent()) {
|
||||
for (Permanent perm : effect.getAddedPermanents()) {
|
||||
if (perm != null) {
|
||||
tokensCreated.add(perm.getId());
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ class EchoChamberCreateTokenEffect extends OneShotEffect {
|
|||
if (copiedPermanent != null) {
|
||||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, CardType.CREATURE, true);
|
||||
if (effect.apply(game, source)) {
|
||||
for (Permanent copyPermanent : effect.getAddedPermanent()) {
|
||||
for (Permanent copyPermanent : effect.getAddedPermanents()) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(copyPermanent, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
|
|
|
@ -86,7 +86,7 @@ class FaerieArtisansEffect extends OneShotEffect {
|
|||
if (effect.apply(game, source)) {
|
||||
String oldTokens = (String) game.getState().getValue(source.getSourceId().toString() + source.getSourceObjectZoneChangeCounter());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Permanent permanent : effect.getAddedPermanent()) {
|
||||
for (Permanent permanent : effect.getAddedPermanents()) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(';');
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ class FeldonOfTheThirdPathEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), CardType.ARTIFACT, true);
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId())));
|
||||
effect.apply(game, source);
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect("Sacrifice the token at the beginning of the next end step", source.getControllerId());
|
||||
sacrificeEffect.setTargetPointer(new FixedTarget(addedToken, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(sacrificeEffect);
|
||||
|
|
|
@ -83,7 +83,7 @@ class FelhideSpiritbinderEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, CardType.ENCHANTMENT, true);
|
||||
effect.setTargetPointer(getTargetPointer());
|
||||
if (effect.apply(game, source)) {
|
||||
for (Permanent tokenPermanent : effect.getAddedPermanent()) {
|
||||
for (Permanent tokenPermanent : effect.getAddedPermanents()) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(tokenPermanent, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
|
|
|
@ -89,7 +89,7 @@ class FlamerushRiderEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true, 1, true, true);
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
effect.apply(game, source);
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
Effect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(addedToken, game));
|
||||
new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(exileEffect), false).apply(game, source);
|
||||
|
|
|
@ -81,7 +81,7 @@ class FlameshadowConjuringEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, null, true);
|
||||
effect.setTargetPointer(getTargetPointer());
|
||||
if (effect.apply(game, source)) {
|
||||
for (Permanent tokenPermanent : effect.getAddedPermanent()) {
|
||||
for (Permanent tokenPermanent : effect.getAddedPermanents()) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(tokenPermanent, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
|
|
|
@ -80,7 +80,7 @@ class ForceProjectionEffect extends OneShotEffect {
|
|||
|
||||
// and gains "When this creature becomes the target of a spell, sacrifice it."
|
||||
Effect sacrificeEffect = new SacrificeSourceEffect();
|
||||
sacrificeEffect.setTargetPointer(new FixedTarget(effect.getAddedPermanent().get(0), game));
|
||||
sacrificeEffect.setTargetPointer(new FixedTarget(effect.getAddedPermanents().get(0), game));
|
||||
TriggeredAbility ability = new BecomesTargetTriggeredAbility(sacrificeEffect, new FilterSpell());
|
||||
game.addTriggeredAbility(ability, null);
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ class GyrusWakerOfCorpsesEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true, 1, true, true);
|
||||
effect.setTargetPointer(new FixedTarget(card, game));
|
||||
effect.apply(game, source);
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
Effect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(addedToken, game));
|
||||
new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(exileEffect), false).apply(game, source);
|
||||
|
|
|
@ -68,7 +68,7 @@ class HeatShimmerEffect extends OneShotEffect {
|
|||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
effect.apply(game, source);
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(effect.getAddedPermanent().get(0), game));
|
||||
exileEffect.setTargetPointer(new FixedTarget(effect.getAddedPermanents().get(0), game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||
return true;
|
||||
|
|
|
@ -114,7 +114,7 @@ class InallaArchmageRitualistEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, null, true);
|
||||
effect.setTargetPointer(getTargetPointer());
|
||||
if (effect.apply(game, source)) {
|
||||
for (Permanent tokenPermanent : effect.getAddedPermanent()) {
|
||||
for (Permanent tokenPermanent : effect.getAddedPermanents()) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(tokenPermanent, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
|
|
|
@ -88,7 +88,7 @@ class KikiJikiMirrorBreakerEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true);
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
effect.apply(game, source);
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect("Sacrifice the token at the beginning of the next end step", source.getControllerId());
|
||||
sacrificeEffect.setTargetPointer(new FixedTarget(addedToken.getId()));
|
||||
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(sacrificeEffect), source);
|
||||
|
|
|
@ -77,7 +77,7 @@ class KindredChargeEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true);
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
effect.apply(game, source);
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
Effect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(addedToken, game));
|
||||
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect), source);
|
||||
|
|
|
@ -77,7 +77,7 @@ class LittjaraMirrorlakeEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect();
|
||||
effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game));
|
||||
effect.apply(game, source);
|
||||
for (Permanent permanent : effect.getAddedPermanent()) {
|
||||
for (Permanent permanent : effect.getAddedPermanents()) {
|
||||
if (permanent == null) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ class MimicVatCreateTokenEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true);
|
||||
effect.setTargetPointer(new FixedTarget(card, game));
|
||||
effect.apply(game, source);
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(addedToken, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
|
|
|
@ -83,7 +83,7 @@ class MinionReflectorEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true);
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
effect.apply(game, source);
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
ContinuousEffect continuousEffect = new GainAbilityTargetEffect(new BeginningOfEndStepTriggeredAbility(new SacrificeSourceEffect(), TargetController.ANY, false), Duration.Custom);
|
||||
continuousEffect.setTargetPointer(new FixedTarget(addedToken.getId()));
|
||||
game.addEffect(continuousEffect, source);
|
||||
|
|
91
Mage.Sets/src/mage/cards/m/MiragePhalanx.java
Normal file
91
Mage.Sets/src/mage/cards/m/MiragePhalanx.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfCombatTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityPairedEffect;
|
||||
import mage.abilities.keyword.SoulbondAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Alex-Vasile
|
||||
*/
|
||||
public class MiragePhalanx extends CardImpl {
|
||||
|
||||
private static final String ruleText =
|
||||
"As long as {this} is paired with another creature, each of those creatures has " +
|
||||
"\"At the beginning of combat on your turn, create a token that's a copy of this creature, " +
|
||||
"except it has haste and loses soulbond. " +
|
||||
"Exile it at end of combat.\"";
|
||||
|
||||
public MiragePhalanx(UUID ownderId, CardSetInfo setInfo) {
|
||||
super(ownderId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}");
|
||||
|
||||
this.addSubType(SubType.HUMAN);
|
||||
this.addSubType(SubType.SOLDIER);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Mirage Phalanx is paired with another creature, each of those creatures has
|
||||
// “At the beginning of combat on your turn, create a token that's a copy of this creature,
|
||||
// except it has haste and loses soulbond.
|
||||
// Exile it at end of combat.”
|
||||
Ability ability = new BeginningOfCombatTriggeredAbility(new MiragePhalanxEffect(), TargetController.YOU, false);
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(ability, ruleText)));
|
||||
}
|
||||
|
||||
private MiragePhalanx(final MiragePhalanx card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MiragePhalanx copy() {
|
||||
return new MiragePhalanx(this);
|
||||
}
|
||||
}
|
||||
|
||||
class MiragePhalanxEffect extends OneShotEffect {
|
||||
MiragePhalanxEffect() {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
this.staticText = "create a token that's a copy of this creature, " +
|
||||
"except it has haste and loses soulbond. " +
|
||||
"Exile it at end of combat.";
|
||||
}
|
||||
|
||||
private MiragePhalanxEffect(final MiragePhalanxEffect effect) { super(effect); }
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = source.getSourcePermanentOrLKI(game);
|
||||
if (permanent == null) { return false; }
|
||||
|
||||
// It has haste
|
||||
CreateTokenCopyTargetEffect tokenCopyEffect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true);
|
||||
tokenCopyEffect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
// It loses soulbond
|
||||
tokenCopyEffect.addAbilityClassesToRemoveFromTokens(SoulbondAbility.class);
|
||||
// Create the token(s)
|
||||
tokenCopyEffect.apply(game, source);
|
||||
// Exile it at the end of combat
|
||||
tokenCopyEffect.exileTokensCreatedAtEndOfCombat(game, source);
|
||||
|
||||
return !tokenCopyEffect.getAddedPermanents().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Effect copy() { return new MiragePhalanxEffect(this); }
|
||||
}
|
|
@ -77,14 +77,14 @@ class MirrorMatchEffect extends OneShotEffect {
|
|||
CombatGroup group = game.getCombat().findGroup(attacker.getId());
|
||||
boolean isCreature = false;
|
||||
if (group != null) {
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
if (addedToken.isCreature(game)) {
|
||||
group.addBlockerToGroup(addedToken.getId(), attackerId, game);
|
||||
isCreature = true;
|
||||
}
|
||||
}
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect("Exile those tokens at end of combat");
|
||||
exileEffect.setTargetPointer(new FixedTargets(effect.getAddedPermanent(), game));
|
||||
exileEffect.setTargetPointer(new FixedTargets(effect.getAddedPermanents(), game));
|
||||
game.addDelayedTriggeredAbility(new AtTheEndOfCombatDelayedTriggeredAbility(exileEffect), source);
|
||||
if (isCreature) {
|
||||
group.pickBlockerOrder(attacker.getControllerId(), game);
|
||||
|
|
|
@ -85,7 +85,7 @@ class MirrorMockeryEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect();
|
||||
effect.setTargetPointer(new FixedTarget(enchanted, game));
|
||||
effect.apply(game, source);
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
if (addedToken != null) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(addedToken, game));
|
||||
|
|
|
@ -82,7 +82,7 @@ class MoltenEchoesEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, null, true);
|
||||
effect.setTargetPointer(getTargetPointer());
|
||||
if (effect.apply(game, source)) {
|
||||
for (Permanent tokenPermanent : effect.getAddedPermanent()) {
|
||||
for (Permanent tokenPermanent : effect.getAddedPermanents()) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(tokenPermanent, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
|
|
|
@ -105,7 +105,7 @@ class NacatlWarPrideEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(controller.getId(), null, false, count, true, true);
|
||||
effect.setTargetPointer(new FixedTarget(origNactalWarPride, game));
|
||||
effect.apply(game, source);
|
||||
copies.addAll(effect.getAddedPermanent());
|
||||
copies.addAll(effect.getAddedPermanents());
|
||||
|
||||
if (!copies.isEmpty()) {
|
||||
FixedTargets fixedTargets = new FixedTargets(copies, game);
|
||||
|
|
|
@ -88,7 +88,7 @@ class NemesisTrapEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect();
|
||||
effect.setTargetPointer(new FixedTarget(targetedCreature, game));
|
||||
effect.apply(game, source);
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
Effect exileEffect = new ExileTargetEffect("Exile " + addedToken.getName() + " at the beginning of the next end step");
|
||||
exileEffect.setTargetPointer(new FixedTarget(addedToken, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
|
|
|
@ -91,7 +91,7 @@ class OffspringsRevengeEffect extends OneShotEffect {
|
|||
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game) + 1));
|
||||
player.moveCards(card, Zone.EXILED, source, game);
|
||||
effect.apply(game, source);
|
||||
effect.getAddedPermanent().stream().forEach(permanent -> {
|
||||
effect.getAddedPermanents().stream().forEach(permanent -> {
|
||||
ContinuousEffect continuousEffect = new GainAbilityTargetEffect(
|
||||
HasteAbility.getInstance(), Duration.UntilYourNextTurn
|
||||
);
|
||||
|
|
|
@ -87,7 +87,7 @@ class SaheeliRaiCreateTokenEffect extends OneShotEffect {
|
|||
if (copiedPermanent != null) {
|
||||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, CardType.ARTIFACT, true);
|
||||
if (effect.apply(game, source)) {
|
||||
for (Permanent copyPermanent : effect.getAddedPermanent()) {
|
||||
for (Permanent copyPermanent : effect.getAddedPermanents()) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(copyPermanent, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
|
|
|
@ -75,7 +75,7 @@ class SeanceEffect extends OneShotEffect {
|
|||
effect.setAdditionalSubType(SubType.SPIRIT);
|
||||
effect.apply(game, source);
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTargets(effect.getAddedPermanent(), game));
|
||||
exileEffect.setTargetPointer(new FixedTargets(effect.getAddedPermanents(), game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||
return true;
|
||||
|
|
|
@ -81,7 +81,7 @@ class SplinterTwinEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true);
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
effect.apply(game, source);
|
||||
for (Permanent addedToken : effect.getAddedPermanent()) {
|
||||
for (Permanent addedToken : effect.getAddedPermanents()) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
exileEffect.setTargetPointer(new FixedTarget(addedToken, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
|
|
|
@ -77,7 +77,7 @@ class TwinflameCopyEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true);
|
||||
effect.setTargetPointer(new FixedTarget(creature, game));
|
||||
effect.apply(game, source);
|
||||
toExile.addAll(effect.getAddedPermanent());
|
||||
toExile.addAll(effect.getAddedPermanents());
|
||||
}
|
||||
}
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||
|
|
|
@ -99,6 +99,7 @@ public final class CrimsonVowCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Midnight Arsonist", 27, Rarity.RARE, mage.cards.m.MidnightArsonist.class));
|
||||
cards.add(new SetCardInfo("Midnight Clock", 108, Rarity.RARE, mage.cards.m.MidnightClock.class));
|
||||
cards.add(new SetCardInfo("Millicent, Restless Revenant", 1, Rarity.MYTHIC, mage.cards.m.MillicentRestlessRevenant.class));
|
||||
cards.add(new SetCardInfo("Mirage Phalanx", 35, Rarity.RARE, mage.cards.m.MiragePhalanx.class));
|
||||
cards.add(new SetCardInfo("Mirror Entity", 94, Rarity.RARE, mage.cards.m.MirrorEntity.class));
|
||||
cards.add(new SetCardInfo("Mob Rule", 147, Rarity.RARE, mage.cards.m.MobRule.class));
|
||||
cards.add(new SetCardInfo("Molten Echoes", 148, Rarity.RARE, mage.cards.m.MoltenEchoes.class));
|
||||
|
|
|
@ -3,10 +3,14 @@ package mage.abilities.effects.common;
|
|||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.EffectImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
|
@ -16,43 +20,44 @@ import mage.counters.CounterType;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.EmptyToken;
|
||||
import mage.game.turn.Step;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.target.targetpointer.FixedTargets;
|
||||
import mage.util.CardUtil;
|
||||
import mage.util.functions.CopyApplier;
|
||||
import mage.util.functions.EmptyCopyApplier;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CreateTokenCopyTargetEffect extends OneShotEffect {
|
||||
|
||||
private final UUID playerId;
|
||||
private final CardType additionalCardType;
|
||||
private boolean hasHaste;
|
||||
private int number;
|
||||
private final Set<Class<? extends Ability>> abilityClazzesToRemove;
|
||||
private final List<Permanent> addedTokenPermanents;
|
||||
private final List<Ability> additionalAbilities;
|
||||
private final CardType additionalCardType;
|
||||
private SubType additionalSubType;
|
||||
private SubType onlySubType;
|
||||
private final boolean tapped;
|
||||
private final boolean attacking;
|
||||
private final UUID attackedPlayer;
|
||||
private final int tokenPower;
|
||||
private final int tokenToughness;
|
||||
private final boolean gainsFlying;
|
||||
private final boolean attacking;
|
||||
private boolean becomesArtifact;
|
||||
private ObjectColor color;
|
||||
private boolean useLKI = false;
|
||||
private boolean isntLegendary = false;
|
||||
private int startingLoyalty = -1;
|
||||
private final List<Ability> additionalAbilities = new ArrayList();
|
||||
private Permanent savedPermanent = null;
|
||||
private CounterType counter;
|
||||
private final boolean gainsFlying;
|
||||
private boolean hasHaste;
|
||||
private boolean isntLegendary = false;
|
||||
private int number;
|
||||
private int numberOfCounters;
|
||||
private SubType onlySubType;
|
||||
private final UUID playerId;
|
||||
private final boolean tapped;
|
||||
private Permanent savedPermanent = null;
|
||||
private int startingLoyalty = -1;
|
||||
private final int tokenPower;
|
||||
private final int tokenToughness;
|
||||
private boolean useLKI = false;
|
||||
|
||||
|
||||
public CreateTokenCopyTargetEffect(boolean useLKI) {
|
||||
this();
|
||||
|
@ -111,27 +116,37 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
|
|||
this.tokenPower = power;
|
||||
this.tokenToughness = toughness;
|
||||
this.gainsFlying = gainsFlying;
|
||||
|
||||
this.abilityClazzesToRemove = new HashSet<>();
|
||||
this.additionalAbilities = new ArrayList<>();
|
||||
}
|
||||
|
||||
public CreateTokenCopyTargetEffect(final CreateTokenCopyTargetEffect effect) {
|
||||
super(effect);
|
||||
this.playerId = effect.playerId;
|
||||
this.additionalCardType = effect.additionalCardType;
|
||||
this.hasHaste = effect.hasHaste;
|
||||
|
||||
this.abilityClazzesToRemove = new HashSet<>(effect.abilityClazzesToRemove);
|
||||
this.addedTokenPermanents = new ArrayList<>(effect.addedTokenPermanents);
|
||||
this.number = effect.number;
|
||||
this.additionalAbilities = new ArrayList<>(effect.additionalAbilities);
|
||||
this.additionalCardType = effect.additionalCardType;
|
||||
this.additionalSubType = effect.additionalSubType;
|
||||
this.onlySubType = effect.onlySubType;
|
||||
this.tapped = effect.tapped;
|
||||
this.attacking = effect.attacking;
|
||||
this.attackedPlayer = effect.attackedPlayer;
|
||||
this.tokenPower = effect.tokenPower;
|
||||
this.tokenToughness = effect.tokenToughness;
|
||||
this.gainsFlying = effect.gainsFlying;
|
||||
this.attacking = effect.attacking;
|
||||
this.becomesArtifact = effect.becomesArtifact;
|
||||
this.color = effect.color;
|
||||
this.useLKI = effect.useLKI;
|
||||
this.counter = effect.counter;
|
||||
this.gainsFlying = effect.gainsFlying;
|
||||
this.hasHaste = effect.hasHaste;
|
||||
this.isntLegendary = effect.isntLegendary;
|
||||
this.number = effect.number;
|
||||
this.numberOfCounters = effect.numberOfCounters;
|
||||
this.onlySubType = effect.onlySubType;
|
||||
this.playerId = effect.playerId;
|
||||
this.savedPermanent = effect.savedPermanent;
|
||||
this.startingLoyalty = effect.startingLoyalty;
|
||||
this.tapped = effect.tapped;
|
||||
this.tokenPower = effect.tokenPower;
|
||||
this.tokenToughness = effect.tokenToughness;
|
||||
this.useLKI = effect.useLKI;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -224,6 +239,25 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
|
|||
}
|
||||
additionalAbilities.stream().forEach(token::addAbility);
|
||||
|
||||
if (!this.abilityClazzesToRemove.isEmpty()) {
|
||||
List<Ability> abilitiesToRemoveTmp = new ArrayList<>();
|
||||
|
||||
// Find the ones to remove
|
||||
for (Ability ability : token.getAbilities()) {
|
||||
if (this.abilityClazzesToRemove.contains(ability.getClass())) {
|
||||
abilitiesToRemoveTmp.add(ability);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove them
|
||||
for (Ability ability : abilitiesToRemoveTmp) {
|
||||
// Remove subabilities
|
||||
token.removeAbilities(ability.getSubAbilities());
|
||||
// Remove the ability
|
||||
token.removeAbility(ability);
|
||||
}
|
||||
}
|
||||
|
||||
token.putOntoBattlefield(number, game, source, playerId == null ? source.getControllerId() : playerId, tapped, attacking, attackedPlayer);
|
||||
for (UUID tokenId : token.getLastAddedTokenIds()) { // by cards like Doubling Season multiple tokens can be added to the battlefield
|
||||
Permanent tokenPermanent = game.getPermanent(tokenId);
|
||||
|
@ -280,7 +314,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
public List<Permanent> getAddedPermanent() {
|
||||
public List<Permanent> getAddedPermanents() {
|
||||
return addedTokenPermanents;
|
||||
}
|
||||
|
||||
|
@ -321,26 +355,43 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
|
|||
}
|
||||
|
||||
public void exileTokensCreatedAtNextEndStep(Game game, Ability source) {
|
||||
for (Permanent tokenPermanent : addedTokenPermanents) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect(null, "", Zone.BATTLEFIELD);
|
||||
exileEffect.setTargetPointer(new FixedTarget(tokenPermanent, game));
|
||||
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect), source);
|
||||
}
|
||||
this.exileTokensCreatedAtEndOf(game, source, PhaseStep.END_TURN);
|
||||
}
|
||||
|
||||
public void exileTokensCreatedAtEndOfCombat(Game game, Ability source) {
|
||||
for (Permanent tokenPermanent : addedTokenPermanents) {
|
||||
this.exileTokensCreatedAtEndOf(game, source, PhaseStep.END_COMBAT);
|
||||
}
|
||||
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect(null, "", Zone.BATTLEFIELD);
|
||||
exileEffect.setTargetPointer(new FixedTarget(tokenPermanent, game));
|
||||
game.addDelayedTriggeredAbility(new AtTheEndOfCombatDelayedTriggeredAbility(exileEffect), source);
|
||||
private void exileTokensCreatedAtEndOf(Game game, Ability source, PhaseStep phaseStepToExileCards) {
|
||||
ExileTargetEffect exileEffect = new ExileTargetEffect(null, "", Zone.BATTLEFIELD);
|
||||
exileEffect.setText("exile the token copies");
|
||||
exileEffect.setTargetPointer(new FixedTargets(addedTokenPermanents, game));
|
||||
|
||||
DelayedTriggeredAbility exileAbility;
|
||||
|
||||
switch (phaseStepToExileCards) {
|
||||
case END_TURN:
|
||||
exileAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
|
||||
break;
|
||||
case END_COMBAT:
|
||||
exileAbility = new AtTheEndOfCombatDelayedTriggeredAbility(exileEffect);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
game.addDelayedTriggeredAbility(exileAbility, source);
|
||||
}
|
||||
|
||||
public void addAbilityClassesToRemoveFromTokens(Class<? extends Ability> clazz) {
|
||||
this.abilityClazzesToRemove.add(clazz);
|
||||
}
|
||||
|
||||
public void addAdditionalAbilities(Ability... abilities) {
|
||||
Arrays.stream(abilities).forEach(this.additionalAbilities::add);
|
||||
this.additionalAbilities.addAll(Arrays.asList(abilities));
|
||||
}
|
||||
|
||||
|
||||
public CreateTokenCopyTargetEffect setSavedPermanent(Permanent savedPermanent) {
|
||||
this.savedPermanent = savedPermanent;
|
||||
return this;
|
||||
|
|
|
@ -79,7 +79,7 @@ class MyriadEffect extends OneShotEffect {
|
|||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(controller.getId(), null, false, 1, true, true, playerId);
|
||||
effect.setTargetPointer(new FixedTarget(sourceObject, game));
|
||||
effect.apply(game, source);
|
||||
tokens.addAll(effect.getAddedPermanent());
|
||||
tokens.addAll(effect.getAddedPermanents());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@ public interface Token extends MageObject {
|
|||
|
||||
void addAbility(Ability ability);
|
||||
|
||||
void removeAbility(Ability abilityToRemove);
|
||||
|
||||
void removeAbilities(List<Ability> abilitiesToRemove);
|
||||
|
||||
boolean putOntoBattlefield(int amount, Game game, Ability source);
|
||||
|
||||
boolean putOntoBattlefield(int amount, Game game, Ability source, UUID controllerId);
|
||||
|
|
|
@ -130,6 +130,35 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
|||
abilities.addAll(ability.getSubAbilities());
|
||||
}
|
||||
|
||||
// Directly from PermanentImpl
|
||||
@Override
|
||||
public void removeAbility(Ability abilityToRemove) {
|
||||
if (abilityToRemove == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 112.10b Effects that remove an ability remove all instances of it.
|
||||
List<Ability> toRemove = new ArrayList<>();
|
||||
abilities.forEach(a -> {
|
||||
if (a.isSameInstance(abilityToRemove)) {
|
||||
toRemove.add(a);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: what about triggered abilities? See addAbility above -- triggers adds to GameState
|
||||
toRemove.forEach(r -> abilities.remove(r));
|
||||
}
|
||||
|
||||
// Directly from PermanentImpl
|
||||
@Override
|
||||
public void removeAbilities(List<Ability> abilitiesToRemove) {
|
||||
if (abilitiesToRemove == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
abilitiesToRemove.forEach(a -> removeAbility(a));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(int amount, Game game, Ability source) {
|
||||
return this.putOntoBattlefield(amount, game, source, source.getControllerId());
|
||||
|
|
Loading…
Reference in a new issue