mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
Copy Permanent Spell turns into token
This commit is contained in:
@@ -103,7 +103,7 @@ public class GameAction {
|
||||
boolean wasFacedown = c.isFaceDown();
|
||||
|
||||
//Rule 110.5g: A token that has left the battlefield can't move to another zone
|
||||
if (c.isToken() && zoneFrom != null && !fromBattlefield) {
|
||||
if (c.isToken() && zoneFrom != null && !fromBattlefield && !zoneFrom.is(ZoneType.Stack)) {
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect {
|
||||
String prompt = Localizer.getInstance().getMessage("lblSelectMultiSpellCopyToStack", Lang.getOrdinal(multi + 1));
|
||||
SpellAbility chosen = controller.getController().chooseSingleSpellForEffect(tgtSpells, sa, prompt,
|
||||
ImmutableMap.of());
|
||||
SpellAbility copiedSpell = CardFactory.copySpellAbilityAndPossiblyHost(card, chosen.getHostCard(), chosen, true);
|
||||
SpellAbility copiedSpell = CardFactory.copySpellAbilityAndPossiblyHost(sa, chosen);
|
||||
copiedSpell.getHostCard().setController(card.getController(), card.getGame().getNextTimestamp());
|
||||
copiedSpell.setActivatingPlayer(controller);
|
||||
copies.add(copiedSpell);
|
||||
@@ -120,7 +120,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect {
|
||||
|
||||
mayChooseNewTargets = false;
|
||||
for (GameEntity o : candidates) {
|
||||
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true);
|
||||
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(sa, chosenSA);
|
||||
resetFirstTargetOnCopy(copy, o, targetedSA);
|
||||
copies.add(copy);
|
||||
}
|
||||
@@ -147,18 +147,18 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect {
|
||||
mayChooseNewTargets = false;
|
||||
if (sa.hasParam("ChooseOnlyOne")) {
|
||||
Card choice = controller.getController().chooseSingleEntityForEffect(valid, sa, Localizer.getInstance().getMessage("lblChooseOne"), null);
|
||||
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true);
|
||||
resetFirstTargetOnCopy(copy, choice, targetedSA);
|
||||
if (choice != null) {
|
||||
valid = new CardCollection(choice);
|
||||
}
|
||||
}
|
||||
|
||||
for (final Card c : valid) {
|
||||
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(sa, chosenSA);
|
||||
resetFirstTargetOnCopy(copy, c, targetedSA);
|
||||
copies.add(copy);
|
||||
} else {
|
||||
for (final Card c : valid) {
|
||||
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true);
|
||||
resetFirstTargetOnCopy(copy, c, targetedSA);
|
||||
copies.add(copy);
|
||||
}
|
||||
}
|
||||
for (final Player p : players) {
|
||||
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true);
|
||||
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(sa, chosenSA);
|
||||
resetFirstTargetOnCopy(copy, p, targetedSA);
|
||||
copies.add(copy);
|
||||
}
|
||||
@@ -169,8 +169,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect {
|
||||
Localizer.getInstance().getMessage("lblSelectASpellCopy"), ImmutableMap.of());
|
||||
chosenSA.setActivatingPlayer(controller);
|
||||
for (int i = 0; i < amount; i++) {
|
||||
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(
|
||||
card, chosenSA.getHostCard(), chosenSA, true);
|
||||
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(sa, chosenSA);
|
||||
|
||||
// extra case for Epic to remove the keyword and the last part of the SpellAbility
|
||||
if (sa.hasParam("Epic")) {
|
||||
|
||||
@@ -22,6 +22,16 @@ public class PermanentEffect extends SpellAbilityEffect {
|
||||
sa.getHostCard().setController(p, 0);
|
||||
final Card host = sa.getHostCard();
|
||||
|
||||
// 111.11. A copy of a permanent spell becomes a token as it resolves.
|
||||
// The token has the characteristics of the spell that became that token.
|
||||
// The token is not “created” for the purposes of any replacement effects or triggered abilities that refer to creating a token.
|
||||
if (host.isCopiedSpell()) {
|
||||
host.setCopiedSpell(false);
|
||||
host.setToken(true);
|
||||
// for replacement Effects, need to add the previous copied spell to the Stack Zone
|
||||
host.getGame().getStackZone().add(host);
|
||||
}
|
||||
|
||||
final Card c = p.getGame().getAction().moveToPlay(host, p, sa);
|
||||
sa.setHostCard(c);
|
||||
|
||||
|
||||
@@ -125,12 +125,13 @@ public class CardFactory {
|
||||
* which wouldn't ordinarily get set during a simple Card.copy() call.
|
||||
* </p>
|
||||
* */
|
||||
private final static Card copySpellHost(final Card source, final Card original, final SpellAbility sa, final boolean bCopyDetails){
|
||||
Player controller = sa.getActivatingPlayer();
|
||||
private final static Card copySpellHost(final SpellAbility sourceSA, final SpellAbility targetSA){
|
||||
final Card source = sourceSA.getHostCard();
|
||||
final Card original = targetSA.getHostCard();
|
||||
Player controller = sourceSA.getActivatingPlayer();
|
||||
final Card c = copyCard(original, true);
|
||||
|
||||
// change the color of the copy (eg: Fork)
|
||||
final SpellAbility sourceSA = source.getFirstSpellAbility();
|
||||
if (null != sourceSA && sourceSA.hasParam("CopyIsColor")) {
|
||||
String tmp = "";
|
||||
final String newColor = sourceSA.getParam("CopyIsColor");
|
||||
@@ -148,13 +149,11 @@ public class CardFactory {
|
||||
c.setOwner(controller);
|
||||
c.setCopiedSpell(true);
|
||||
|
||||
if (bCopyDetails) {
|
||||
c.setXManaCostPaidByColor(original.getXManaCostPaidByColor());
|
||||
c.setKickerMagnitude(original.getKickerMagnitude());
|
||||
c.setXManaCostPaidByColor(original.getXManaCostPaidByColor());
|
||||
c.setKickerMagnitude(original.getKickerMagnitude());
|
||||
|
||||
for (OptionalCost cost : original.getOptionalCostsPaid()) {
|
||||
c.addOptionalCostPaid(cost);
|
||||
}
|
||||
for (OptionalCost cost : original.getOptionalCostsPaid()) {
|
||||
c.addOptionalCostPaid(cost);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
@@ -174,44 +173,27 @@ public class CardFactory {
|
||||
* @param bCopyDetails
|
||||
* a boolean.
|
||||
*/
|
||||
public final static SpellAbility copySpellAbilityAndPossiblyHost(final Card source, final Card original, final SpellAbility sa, final boolean bCopyDetails) {
|
||||
Player controller = sa.getActivatingPlayer();
|
||||
public final static SpellAbility copySpellAbilityAndPossiblyHost(final SpellAbility sourceSA, final SpellAbility targetSA) {
|
||||
Player controller = sourceSA.getActivatingPlayer();
|
||||
|
||||
//it is only necessary to copy the host card if the SpellAbility is a spell, not an ability
|
||||
final Card c;
|
||||
if (sa.isSpell()){
|
||||
c = copySpellHost(source, original, sa, bCopyDetails);
|
||||
}
|
||||
else {
|
||||
c = original;
|
||||
}
|
||||
final Card c = targetSA.isSpell() ? copySpellHost(sourceSA, targetSA) : targetSA.getHostCard();
|
||||
|
||||
final SpellAbility copySA;
|
||||
if (sa.isTrigger() && sa.isWrapper()) {
|
||||
copySA = getCopiedTriggeredAbility((WrappedAbility)sa, c);
|
||||
if (targetSA.isTrigger() && targetSA.isWrapper()) {
|
||||
copySA = getCopiedTriggeredAbility((WrappedAbility)targetSA, c);
|
||||
} else {
|
||||
copySA = sa.copy(c, false);
|
||||
}
|
||||
|
||||
if (sa.isSpell()){
|
||||
//only update c's abilities if c is a copy.
|
||||
//(it would be nice to move this into `copySpellHost`,
|
||||
// so all the c-mutating code is together in one place.
|
||||
// but copySA doesn't exist until after `copySpellHost` finishes executing,
|
||||
// so it's hard to resolve that dependency.)
|
||||
c.getCurrentState().setNonManaAbilities(copySA);
|
||||
copySA = targetSA.copy(c, false);
|
||||
}
|
||||
|
||||
copySA.setCopied(true);
|
||||
//remove all costs
|
||||
if (!copySA.isTrigger()) {
|
||||
copySA.setPayCosts(new Cost("", sa.isAbility()));
|
||||
copySA.setPayCosts(new Cost("", targetSA.isAbility()));
|
||||
}
|
||||
copySA.setActivatingPlayer(controller);
|
||||
|
||||
if (bCopyDetails) {
|
||||
copySA.setPaidHash(sa.getPaidHash());
|
||||
}
|
||||
copySA.setPaidHash(targetSA.getPaidHash());
|
||||
return copySA;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ public class Zone implements java.io.Serializable, Iterable<Card> {
|
||||
|
||||
// Do not add Tokens to other zones than the battlefield.
|
||||
// But Effects/Emblems count as Tokens too, so allow Command too.
|
||||
if (zoneType == ZoneType.Battlefield || !c.isToken()) {
|
||||
if (zoneType == ZoneType.Battlefield || zoneType == ZoneType.Stack || !c.isToken()) {
|
||||
c.setZone(this);
|
||||
|
||||
if (index == null) {
|
||||
|
||||
8
forge-gui/res/cardsfolder/l/lithoform_engine.txt
Normal file
8
forge-gui/res/cardsfolder/l/lithoform_engine.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
Name:Lithoform Engine
|
||||
ManaCost:4
|
||||
Types:Legendary Artifact
|
||||
A:AB$ CopySpellAbility | Cost$ 2 T | TgtPrompt$ Select target activated or triggered ability you control | TargetType$ Activated.YouCtrl,Triggered.YouCtrl | ValidTgts$ Card | StackDescription$ SpellDescription | SpellDescription$ Copy target activated or triggered ability you control. You may choose new targets for the copy.
|
||||
A:AB$ CopySpellAbility | Cost$ 3 T | TgtPrompt$ Select target instant or sorcery spell you control | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TargetType$ Spell | SpellDescription$ Copy target instant or sorcery spell you control. You may choose new targets for the copy.
|
||||
A:AB$ CopySpellAbility | Cost$ 4 T | TgtPrompt$ Select target permanent spell you control | ValidTgts$ Permanent.YouCtrl | TargetType$ Spell | SpellDescription$ Copy target permanent spell you control. (The copy becomes a token.)
|
||||
Oracle:{2}, {T}: Copy target activated or triggered ability you control. You may choose new targets for the copy.\n{3}, {T}: Copy target instant or sorcery spell you control. You may choose new targets for the copy.\n{4}, {T}: Copy target permanent spell you control. (The copy becomes a token.)
|
||||
|
||||
15
forge-gui/res/cardsfolder/v/verazol_the_split_current.txt
Normal file
15
forge-gui/res/cardsfolder/v/verazol_the_split_current.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
Name:Verazol, the Split Current
|
||||
ManaCost:X G U
|
||||
Types:Legendary Creature Serpent
|
||||
PT:0/0
|
||||
K:etbCounter:P1P1:Y:no Condition:CARDNAME enters the battlefield with a +1/+1 counter on it for each mana spent to cast it.
|
||||
SVar:X:Count$xPaid
|
||||
SVar:Y:Count$FirstSpellTotalManaSpent
|
||||
T:Mode$ SpellCast | ValidSA$ Spell.Kicked | ValidActivatingPlayer$ You | Execute$ DBRemoveCounters | TriggerZones$ Battlefield | OptionalDecider$ You | TriggerDescription$ Whenever you cast a kicked spell, you may remove two +1/+1 counters from CARDNAME.
|
||||
SVar:DBRemoveCounters:DB$ RemoveCounter | CounterType$ P1P1 | CounterNum$ 2 | RememberRemoved$ True | SubAbility$ DBCopy
|
||||
SVar:DBCopy:DB$ CopySpellAbility | ConditionCheckSVar$ Z | ConditionSVarCompare$ GE1 | References$ Z | SubAbility$ DBCleanup | Defined$ TriggeredSpellAbility | AILogic$ Always | SpellDescription$ If you do, copy that spell. You may choose new targets for that copy. (A copy of a permanent spell becomes a token.)
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
SVar:Z:Count$RememberedSize
|
||||
DeckHas:Ability$Counters
|
||||
Oracle:Verazol, the Split Current enters the battlefield with a +1/+1 counter on it for each mana spent to cast it.\nWhenever you cast a kicked spell, you may remove two +1/+1 counters from Verazol, the Split Current. If you do, copy that spell. You may choose new targets for that copy. (A copy of a permanent spell becomes a token.)
|
||||
|
||||
Reference in New Issue
Block a user