add loop functionality to CloneEffect / refactor some cards! (#3966)

This commit is contained in:
Northmoc
2023-10-28 07:43:20 -04:00
committed by GitHub
parent 8796170480
commit 45fb4003bf
9 changed files with 111 additions and 122 deletions

View File

@@ -1,21 +1,13 @@
package forge.game.ability.effects;
import java.util.Arrays;
import java.util.List;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.GameCommand;
import forge.StaticData;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardFactory;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.*;
import forge.game.event.GameEventCardStatsChanged;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
@@ -24,6 +16,10 @@ import forge.util.CardTranslation;
import forge.util.Localizer;
import forge.util.collect.FCollection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CloneEffect extends SpellAbilityEffect {
// TODO update this method
@@ -58,7 +54,7 @@ public class CloneEffect extends SpellAbilityEffect {
public void resolve(SpellAbility sa) {
final Card host = sa.getHostCard();
final Player activator = sa.getActivatingPlayer();
Card tgtCard = host;
List<Card> cloneTargets = new ArrayList<>();
final Game game = activator.getGame();
final List<String> pumpKeywords = Lists.newArrayList();
@@ -89,9 +85,11 @@ public class CloneEffect extends SpellAbilityEffect {
}
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, host, sa);
boolean choiceOpt = sa.hasParam("ChoiceOptional");
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : Localizer.getInstance().getMessage("lblChooseaCard") + " ";
cardToCopy = activator.getController().chooseSingleEntityForEffect(choices, sa, title, false, null);
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") :
Localizer.getInstance().getMessage("lblChooseaCard") + " ";
cardToCopy = activator.getController().chooseSingleEntityForEffect(choices, sa, title, choiceOpt, null);
} else if (sa.hasParam("Defined")) {
List<Card> cloneSources = AbilityUtils.getDefinedCards(host, sa.getParam("Defined"), sa);
if (!cloneSources.isEmpty()) {
@@ -114,89 +112,94 @@ public class CloneEffect extends SpellAbilityEffect {
// find target of cloning i.e. card becoming a clone
if (sa.hasParam("CloneTarget")) {
final List<Card> cloneTargets = AbilityUtils.getDefinedCards(host, sa.getParam("CloneTarget"), sa);
if (!cloneTargets.isEmpty()) {
tgtCard = cloneTargets.get(0);
game.getTriggerHandler().clearActiveTriggers(tgtCard, null);
} else {
cloneTargets = AbilityUtils.getDefinedCards(host, sa.getParam("CloneTarget"), sa);
if (cloneTargets.isEmpty()) {
return;
}
} else if (sa.hasParam("Choices") && sa.usesTargeting()) {
tgtCard = sa.getTargetCard();
cloneTargets.add(sa.getTargetCard());
} else {
cloneTargets.add(host);
}
if (cloneTargets.contains(cardToCopy) && sa.hasParam("ExcludeChosen")) {
cloneTargets.remove(cardToCopy);
}
for (Card tgtCard : cloneTargets) {
game.getTriggerHandler().clearActiveTriggers(tgtCard, null);
}
if (sa.hasParam("CloneZone")) {
if (!tgtCard.isInZone(ZoneType.smartValueOf(sa.getParam("CloneZone")))) {
return;
}
}
if (tgtCard.isPhasedOut()) {
return;
}
if ("UntilTargetedUntaps".equals(sa.getParam("Duration")) && !cardToCopy.isTapped()) {
return;
}
final Long ts = game.getNextTimestamp();
tgtCard.addCloneState(CardFactory.getCloneStates(cardToCopy, tgtCard, sa), ts);
// set ETB tapped of clone
if (sa.hasParam("IntoPlayTapped")) {
tgtCard.setTapped(true);
}
if (!pumpKeywords.isEmpty()) {
tgtCard.addChangedCardKeywords(pumpKeywords, Lists.newArrayList(), false, ts, 0);
}
tgtCard.updateStateForView();
// when clone is itself, cleanup from old abilities
if (host.equals(tgtCard) && !sa.hasParam("ImprintRememberedNoCleanup")) {
tgtCard.clearImprintedCards();
tgtCard.clearRemembered();
}
if (sa.hasParam("Duration")) {
final Card cloneCard = tgtCard;
// if clone is temporary, target needs old values back after (keep Death-Mask Duplicant working)
final Iterable<Card> clonedImprinted = new CardCollection(tgtCard.getImprintedCards());
final Iterable<Object> clonedRemembered = new FCollection<>(tgtCard.getRemembered());
final GameCommand unclone = new GameCommand() {
private static final long serialVersionUID = -78375985476256279L;
@Override
public void run() {
if (cloneCard.removeCloneState(ts)) {
// remove values gained while being cloned
cloneCard.clearImprintedCards();
cloneCard.clearRemembered();
// restore original Remembered and Imprinted, ignore cards from players who lost
cloneCard.addImprintedCards(Iterables.filter(clonedImprinted, CardPredicates.ownerLives()));
cloneCard.addRemembered(Iterables.filter(clonedRemembered, Player.class));
cloneCard.addRemembered(Iterables.filter(Iterables.filter(clonedRemembered, Card.class), CardPredicates.ownerLives()));
cloneCard.updateStateForView();
game.fireEvent(new GameEventCardStatsChanged(cloneCard));
}
if (sa.hasParam("CloneZone")) {
if (!tgtCard.isInZone(ZoneType.smartValueOf(sa.getParam("CloneZone")))) {
continue;
}
};
}
addUntilCommand(sa, unclone);
if (tgtCard.isPhasedOut()) {
continue;
}
if ("UntilTargetedUntaps".equals(sa.getParam("Duration")) && !cardToCopy.isTapped()) {
continue;
}
final Long ts = game.getNextTimestamp();
tgtCard.addCloneState(CardFactory.getCloneStates(cardToCopy, tgtCard, sa), ts);
// set ETB tapped of clone
if (sa.hasParam("IntoPlayTapped")) {
tgtCard.setTapped(true);
}
if (!pumpKeywords.isEmpty()) {
tgtCard.addChangedCardKeywords(pumpKeywords, Lists.newArrayList(), false, ts, 0);
}
tgtCard.updateStateForView();
// when clone is itself, cleanup from old abilities
if (host.equals(tgtCard) && !sa.hasParam("ImprintRememberedNoCleanup")) {
tgtCard.clearImprintedCards();
tgtCard.clearRemembered();
}
if (sa.hasParam("Duration")) {
final Card cloneCard = tgtCard;
// if clone is temporary, target needs old values back after (keep Death-Mask Duplicant working)
final Iterable<Card> clonedImprinted = new CardCollection(tgtCard.getImprintedCards());
final Iterable<Object> clonedRemembered = new FCollection<>(tgtCard.getRemembered());
final GameCommand unclone = new GameCommand() {
private static final long serialVersionUID = -78375985476256279L;
@Override
public void run() {
if (cloneCard.removeCloneState(ts)) {
// remove values gained while being cloned
cloneCard.clearImprintedCards();
cloneCard.clearRemembered();
// restore original Remembered and Imprinted, ignore cards from players who lost
cloneCard.addImprintedCards(Iterables.filter(clonedImprinted, CardPredicates.ownerLives()));
cloneCard.addRemembered(Iterables.filter(clonedRemembered, Player.class));
cloneCard.addRemembered(Iterables.filter(Iterables.filter(clonedRemembered, Card.class), CardPredicates.ownerLives()));
cloneCard.updateStateForView();
game.fireEvent(new GameEventCardStatsChanged(cloneCard));
}
}
};
addUntilCommand(sa, unclone);
}
// now we can also cleanup in case target was another card
tgtCard.clearRemembered();
tgtCard.clearImprintedCards();
if (sa.hasParam("RememberCloneOrigin")) {
tgtCard.addRemembered(cardToCopy);
}
game.fireEvent(new GameEventCardStatsChanged(tgtCard));
}
// now we can also cleanup in case target was another card
tgtCard.clearRemembered();
tgtCard.clearImprintedCards();
if (sa.hasParam("RememberCloneOrigin")) {
tgtCard.addRemembered(cardToCopy);
}
game.fireEvent(new GameEventCardStatsChanged(tgtCard));
}
}

View File

@@ -12,7 +12,5 @@ ALTERNATE
Name:Echoing Equation
ManaCost:3 U U
Types:Sorcery
A:SP$ Pump | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Choose target creature you control | SubAbility$ DBRepeatEach | StackDescription$ Each other creature {p:You} controls becomes a copy of {c:Targeted} until end of turn, except those creatures aren't legendary if {c:Targeted} is legendary. | SpellDescription$ Choose target creature you control. Each other creature you control becomes a copy of it until end of turn, except those creatures aren't legendary if the chosen creature is legendary.
SVar:DBRepeatEach:DB$ RepeatEach | RepeatCards$ Creature.YouCtrl+NotDefinedTargeted | RepeatSubAbility$ DBClone
SVar:DBClone:DB$ Clone | Defined$ Targeted | CloneTarget$ Imprinted | NonLegendary$ True | Duration$ UntilEndOfTurn
A:SP$ Clone | Defined$ Targeted | CloneTarget$ Valid Creature.YouCtrl+NotDefinedTargeted | NonLegendary$ True | Duration$ UntilEndOfTurn | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Choose target creature you control | StackDescription$ Each other creature {p:You} controls becomes a copy of {c:Targeted} until end of turn, except those creatures aren't legendary. | SpellDescription$ Choose target creature you control. Each other creature you control becomes a copy of it until end of turn, except those creatures aren't legendary if the chosen creature is legendary.
Oracle:Choose target creature you control. Each other creature you control becomes a copy of it until end of turn, except those creatures aren't legendary if the chosen creature is legendary.

View File

@@ -5,11 +5,8 @@ PT:4/4
S:Mode$ Continuous | Affected$ Creature.token+YouCtrl | AddKeyword$ Haste | Description$ Creature tokens you control have haste.
SVar:PlayMain1:TRUE
T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ At the beginning of combat on your turn, create a 2/1 blue Phyrexian Myr artifact creature token. Then you may choose a token you control. If you do, each other token you control becomes a copy of that token.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ u_2_1_a_phyrexian_myr | TokenOwner$ You | SubAbility$ DBImprint
SVar:DBImprint:DB$ ChooseCard | Defined$ You | Amount$ 1 | Choices$ Card.token+YouCtrl | ChoiceTitle$ Choose token you control | SubAbility$ MassClone | StackDescription$ None | SpellDescription$ Each other token becomes a copy of target token.
SVar:MassClone:DB$ RepeatEach | UseImprinted$ True | RepeatCards$ Card.token+nonChosenCard+YouCtrl | RepeatSubAbility$ DBCopy | SubAbility$ DBCleanup
SVar:DBCopy:DB$ Clone | Defined$ ChosenCard | CloneTarget$ Imprinted
SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True
SVar:TrigToken:DB$ Token | TokenScript$ u_2_1_a_phyrexian_myr | SubAbility$ DBClone
SVar:DBClone:DB$ Clone | Choices$ Card.token+YouCtrl | ChoiceTitle$ You may choose a token you control | ChoiceOptional$ True | ExcludeChosen$ True | CloneTarget$ Valid Card.token+YouCtrl
DeckHints:Type$Token
DeckHas:Type$Token
DeckHas:Type$Token & Type$Artifact|Myr
Oracle:Creature tokens you control have haste.\nAt the beginning of combat on your turn, create a 2/1 blue Phyrexian Myr artifact creature token. Then you may choose a token you control. If you do, each other token you control becomes a copy of that token.

View File

@@ -1,7 +1,7 @@
Name:Crack Open
ManaCost:2 G
Types:Sorcery
A:SP$ Destroy | Cost$ 2 G | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | SubAbility$ DBToken | SpellDescription$ Destroy target artifact or enchantment. Create a Treasure token. (It's an artifact with "{T}, Sacrifice this artifact: Add one mana of any color.")
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_treasure_sac | TokenOwner$ You
DeckHas:Ability$Token
A:SP$ Destroy | Cost$ 2 G | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | SubAbility$ DBToken | SpellDescription$ Destroy target artifact or enchantment.
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_treasure_sac | TokenOwner$ You | SpellDescription$ Create a Treasure token. (It's an artifact with "{T}, Sacrifice this artifact: Add one mana of any color.")
DeckHas:Ability$Token|Sacrifice & Type$Artifact|Treasure
Oracle:Destroy target artifact or enchantment. Create a Treasure token. (It's an artifact with "{T}, Sacrifice this artifact: Add one mana of any color.")

View File

@@ -2,12 +2,11 @@ Name:Infinite Reflection
ManaCost:5 U
Types:Enchantment Aura
K:Enchant creature
A:SP$ Attach | Cost$ 5 U | ValidTgts$ Creature | AILogic$ HighestEvaluation
A:SP$ Attach | ValidTgts$ Creature | AILogic$ HighestEvaluation
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self+AttachedTo Card | Execute$ RememberInitialAttach | Static$ True
SVar:RememberInitialAttach:DB$ Pump | RememberObjects$ Valid Card.AttachedBy
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self+AttachedTo Card | Execute$ FirstReflections | TriggerZones$ Battlefield | TriggerDescription$ When CARDNAME enters the battlefield attached to a creature, each other nontoken creature you control becomes a copy of that creature.
SVar:FirstReflections:DB$ RepeatEach | RepeatCards$ Creature.nonToken+YouCtrl+IsNotRemembered | UseImprinted$ True | Zone$ Battlefield | RepeatSubAbility$ Reflect | SubAbility$ DBCleanup
SVar:Reflect:DB$ Clone | Defined$ Remembered | CloneTarget$ Imprinted
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self+AttachedTo Card | Execute$ TrigClone | TriggerZones$ Battlefield | TriggerDescription$ When CARDNAME enters the battlefield attached to a creature, each other nontoken creature you control becomes a copy of that creature.
SVar:TrigClone:DB$ Clone | Defined$ Remembered | CloneTarget$ Valid Creature.nonToken+YouCtrl+IsNotRemembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
K:ETBReplacement:Copy:Reflections:Mandatory:Battlefield:Creature.nonToken+YouCtrl
SVar:Reflections:DB$ Clone | Defined$ Enchanted | CloneTarget$ ReplacedCard | SpellDescription$ Nontoken creatures you control enter the battlefield as a copy of enchanted creature.

View File

@@ -1,11 +1,10 @@
Name:Masterful Replication
ManaCost:5 U
Types:Instant
A:SP$ Charm | Cost$ 5 U | Choices$ DBToken,DBCopy
A:SP$ Charm | Choices$ DBToken,DBClone
SVar:DBToken:DB$ Token | TokenAmount$ 2 | TokenScript$ c_3_3_a_golem | TokenOwner$ You | SpellDescription$ Create two 3/3 colorless Golem artifact creature tokens.
SVar:DBCopy:DB$ Pump | ValidTgts$ Artifact.YouCtrl | SubAbility$ DBRepeat | SpellDescription$ Choose target artifact you control. Each other artifact you control becomes a copy of that artifact until end of turn.
SVar:DBRepeat:DB$ RepeatEach | RepeatCards$ Artifact.YouCtrl+NotDefinedTargeted | RepeatSubAbility$ DBClone
SVar:DBClone:DB$ Clone | Defined$ Targeted | CloneTarget$ Remembered | Duration$ UntilEndOfTurn
SVar:DBClone:DB$ Clone | Defined$ Targeted | CloneTarget$ Valid Artifact.YouCtrl+NotDefinedTargeted | Duration$ UntilEndOfTurn | ValidTgts$ Artifact.YouCtrl | TgtPrompt$ Choose target artifact you control | StackDescription$ Each other artifact {p:You} controls becomes a copy of {c:Targeted} until end of turn. | SpellDescription$ Choose target artifact you control. Each other artifact you control becomes a copy of that artifact until end of turn.
AI:RemoveDeck:All
DeckHas:Ability$Token
DeckHas:Ability$Token & Type$Artifact|Golem
DeckHints:Type$Artifact
Oracle:Choose one —\n• Create two 3/3 colorless Golem artifact creature tokens.\n• Choose target artifact you control. Each other artifact you control becomes a copy of that artifact until end of turn.

View File

@@ -1,7 +1,5 @@
Name:Mirrorweave
ManaCost:2 WU WU
Types:Instant
A:SP$ Pump | Cost$ 2 WU WU | ValidTgts$ Creature.nonLegendary | TgtPrompt$ Choose target nonlegendary creature | AILogic$ Pump | SubAbility$ MirrorweaveClone | StackDescription$ None | SpellDescription$ Each other creature becomes a copy of target nonlegendary creature until end of turn.
SVar:MirrorweaveClone:DB$ RepeatEach | RepeatCards$ Creature.NotDefinedTargeted | RepeatSubAbility$ DBCopy
SVar:DBCopy:DB$ Clone | Defined$ Targeted | CloneTarget$ Remembered | Duration$ UntilEndOfTurn
A:SP$ Clone | Defined$ Targeted | CloneTarget$ Valid Creature.NotDefinedTargeted | Duration$ UntilEndOfTurn | ValidTgts$ Creature.nonLegendary | TgtPrompt$ Select target nonlegendary creature | StackDescription$ REP target nonlegendary creature_{c:Targeted} | SpellDescription$ Each other creature becomes a copy of target nonlegendary creature until end of turn.
Oracle:Each other creature becomes a copy of target nonlegendary creature until end of turn.

View File

@@ -1,13 +1,10 @@
Name:Sakashima's Will
ManaCost:3 U
Types:Sorcery
A:SP$ Charm | Cost$ 3 U | MinCharmNum$ 1 | CharmNum$ X | Choices$ DBControl,DBImprint | AdditionalDescription$ . If you control a commander as you cast this spell, you may choose both.
SVar:DBControl:DB$ ChooseCard | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | Mandatory$ True | Choices$ Creature.TargetedPlayerCtrl | ChoiceTitle$ Choose a creature you control | SubAbility$ DBGainControl | AILogic$ WorstCard | SpellDescription$ Target opponent chooses a creature they control. You gain control of it.
A:SP$ Charm | MinCharmNum$ 1 | CharmNum$ X | Choices$ DBControl,DBClone | AdditionalDescription$ . If you control a commander as you cast this spell, you may choose both.
SVar:DBControl:DB$ ChooseCard | ValidTgts$ Opponent | Mandatory$ True | Choices$ Creature.TargetedPlayerCtrl | ChoiceTitle$ Choose a creature you control | SubAbility$ DBGainControl | AILogic$ WorstCard | SpellDescription$ Target opponent chooses a creature they control. You gain control of it.
SVar:DBGainControl:DB$ GainControl | Defined$ ChosenCard | NewController$ You
SVar:DBImprint:DB$ ChooseCard | Defined$ You | Mandatory$ True | Choices$ Creature.YouCtrl | ChoiceTitle$ Choose a creature you control | SubAbility$ MassClone | SpellDescription$ Choose a creature you control. Each other creature you control becomes a copy of that creature until end of turn.
SVar:MassClone:DB$ RepeatEach | RepeatCards$ Card.Creature+nonChosenCard+YouCtrl | RepeatSubAbility$ DBCopy
SVar:DBCopy:DB$ Clone | Defined$ ChosenCard | CloneTarget$ Remembered | Duration$ UntilEndOfTurn
SVar:X:Count$Compare Y GE1.2.1
SVar:Y:Count$Valid Card.IsCommander+YouCtrl
SVar:DBClone:DB$ Clone | Choices$ Creature.YouCtrl | ChoiceTitle$ Choose a creature you control | ExcludeChosen$ True | CloneTarget$ Valid Creature.YouCtrl | Duration$ UntilEndOfTurn
SVar:X:Count$Compare Count$Valid Card.IsCommander+YouCtrl GE1.2.1
SVar:PlayMain1:TRUE
Oracle:Choose one. If you control a commander as you cast this spell, you may choose both.\n• Target opponent chooses a creature they control. You gain control of it.\n• Choose a creature you control. Each other creature you control becomes a copy of that creature until end of turn.

View File

@@ -1,7 +1,5 @@
Name:Nanogene Conversion
ManaCost:3 U
Types:Sorcery
A:SP$ Pump | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Choose target creature you control | SubAbility$ DBRepeatEach | StackDescription$ Each other creature becomes a copy of {c:Targeted} until end of turn, except those creatures aren't legendary | SpellDescription$ Choose target creature you control. Each other creature becomes a copy of that creature until end of turn, except it isn't legendary.
SVar:DBRepeatEach:DB$ RepeatEach | RepeatCards$ Creature.NotDefinedTargeted | RepeatSubAbility$ DBClone
SVar:DBClone:DB$ Clone | Defined$ Targeted | CloneTarget$ Remembered | NonLegendary$ True | Duration$ UntilEndOfTurn
A:SP$ Clone | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Choose target creature you control | Defined$ Targeted | CloneTarget$ Valid Creature.NotDefinedTargeted | NonLegendary$ True | Duration$ UntilEndOfTurn | StackDescription$ Each other creature becomes a copy of {c:Targeted} until end of turn, except those creatures aren't legendary. | SpellDescription$ Choose target creature you control. Each other creature becomes a copy of that creature until end of turn, except it isn't legendary.
Oracle:Choose target creature you control. Each other creature becomes a copy of that creature until end of turn, except it isn't legendary.