* Copy spells - improved combo support with other abilities like Kicker or Entwine (#7192):

* Now ZCC of copied spells syncs with source card or coping spell (allows to keep ability settings that depends on ZCC);
  * Fixed bug that allows to lost kicked status in copied spells after counter the original spell or moves the original card (see #7192);
  * Test framework: improved support of targeting copy or non copy spells on stack;
This commit is contained in:
Oleg Agafonov 2020-12-15 20:06:53 +04:00
parent 936be75a66
commit 4d362d7edc
32 changed files with 522 additions and 302 deletions

View file

@ -11,7 +11,6 @@ import mage.filter.FilterInPlay;
import mage.filter.predicate.mageobject.FromSetPredicate;
import mage.game.Game;
import mage.game.events.CopiedStackObjectEvent;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.Target;
@ -82,7 +81,7 @@ public abstract class CopySpellForEachItCouldTargetEffect<T extends MageItem> ex
}
// collect objects that can be targeted
Spell copy = spell.copySpell(source.getControllerId());
Spell copy = spell.copySpell(source.getControllerId(), game);
modifyCopy(copy, game, source);
Target sampleTarget = targetsToBeChanged.iterator().next().getTarget(copy);
sampleTarget.setNotTarget(true);
@ -94,7 +93,7 @@ public abstract class CopySpellForEachItCouldTargetEffect<T extends MageItem> ex
obj = game.getPlayer(objId);
}
if (obj != null) {
copy = spell.copySpell(source.getControllerId());
copy = spell.copySpell(source.getControllerId(), game);
try {
modifyCopy(copy, (T) obj, game, source);
if (!filter.match((T) obj, source.getSourceId(), actingPlayer.getId(), game)) {

View file

@ -34,15 +34,15 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
private final CardType additionalCardType;
private boolean hasHaste;
private final int number;
private List<Permanent> addedTokenPermanents;
private final List<Permanent> addedTokenPermanents;
private SubType additionalSubType;
private SubType onlySubType;
private boolean tapped;
private boolean attacking;
private UUID attackedPlayer;
private final boolean tapped;
private final boolean attacking;
private final UUID attackedPlayer;
private final int tokenPower;
private final int tokenToughness;
private boolean gainsFlying;
private final boolean gainsFlying;
private boolean becomesArtifact;
private ObjectColor color;
private boolean useLKI = false;
@ -170,7 +170,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
}
EmptyToken token = new EmptyToken();
CardUtil.copyTo(token).from(copyFrom); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
CardUtil.copyTo(token).from(copyFrom, game); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
applier.apply(game, token, source, targetId);
if (becomesArtifact) {
token.addCardType(CardType.ARTIFACT);

View file

@ -4,7 +4,6 @@
*/
package mage.abilities.effects.common;
import java.util.Objects;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
@ -20,10 +19,11 @@ import mage.game.stack.Spell;
import mage.game.stack.StackObject;
import mage.players.Player;
import java.util.Objects;
/**
*
* @author jeffwadsworth
*
* <p>
* 702.49. Epic 702.49a Epic represents two spell abilities, one of which
* creates a delayed triggered ability. Epic means For the rest of the game,
* you can't cast spells, and At the beginning of each of your upkeeps for the
@ -55,7 +55,7 @@ public class EpicEffect extends OneShotEffect {
if (spell == null) {
return false;
}
spell = spell.copySpell(source.getControllerId());
spell = spell.copySpell(source.getControllerId(), game);
// Remove Epic effect from the spell
Effect epicEffect = null;
for (Effect effect : spell.getSpellAbility().getEffects()) {
@ -118,9 +118,7 @@ class EpicReplacementEffect extends ContinuousRuleModifyingEffectImpl {
public boolean applies(GameEvent event, Ability source, Game game) {
if (Objects.equals(source.getControllerId(), event.getPlayerId())) {
MageObject object = game.getObject(event.getSourceId());
if (object != null) {
return true;
}
return object != null;
}
return false;
}