From 347dfa05bf5668732863f449bd7ce118d15d5374 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Fri, 30 Oct 2020 14:22:25 -0400 Subject: [PATCH 1/8] amphin_mutineer.txt and token --- forge-gui/res/cardsfolder/upcoming/amphin_mutineer.txt | 10 ++++++++++ .../res/tokenscripts/u_4_3_salamander_warrior.txt | 6 ++++++ 2 files changed, 16 insertions(+) create mode 100755 forge-gui/res/cardsfolder/upcoming/amphin_mutineer.txt create mode 100644 forge-gui/res/tokenscripts/u_4_3_salamander_warrior.txt diff --git a/forge-gui/res/cardsfolder/upcoming/amphin_mutineer.txt b/forge-gui/res/cardsfolder/upcoming/amphin_mutineer.txt new file mode 100755 index 00000000000..f76d12c38a9 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/amphin_mutineer.txt @@ -0,0 +1,10 @@ +Name:Amphin Mutineer +ManaCost:3 U +Types:Creature Salamander Pirate +PT:3/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, exile up to one target non-flying creature. That creature's controller creates a 4/3 blue Salamander Warrior creature token. +SVar:TrigExile:DB$ ChangeZone | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature.nonSalamander | TgtPrompt$ Select up to one target non-Salamander creature | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBToken +SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ u_4_3_salamander_warrior | TokenOwner$ TargetedController +K:Encore:4 U U +SVar:X:Count$Valid Card.IsRemembered+OppOwn +Oracle:When Amphin Mutineer enters the battlefield, exile up to one target non-Salamander creature. That creature's controller creates a 4/3 blue Salamander Warrior creature token.\nEncore {4}{U}{U} ({4}{U}{U}, Exile this card from your graveyard: For each opponent, create a token copy that attacks that opponent this turn if able. They gain haste. Sacrifice them at the beginning of the next end step. Activate only as a sorcery.) diff --git a/forge-gui/res/tokenscripts/u_4_3_salamander_warrior.txt b/forge-gui/res/tokenscripts/u_4_3_salamander_warrior.txt new file mode 100644 index 00000000000..df0586f6a6d --- /dev/null +++ b/forge-gui/res/tokenscripts/u_4_3_salamander_warrior.txt @@ -0,0 +1,6 @@ +Name:Salamander Warrior +ManaCost:no cost +Types:Creature Salamander Warrior +Colors:blue +PT:4/3 +Oracle: From fa619ee16e6d07a9dcc38081633b87d2532b6082 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Fri, 30 Oct 2020 18:39:36 -0400 Subject: [PATCH 2/8] - small typo --- forge-gui/res/cardsfolder/upcoming/amphin_mutineer.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/amphin_mutineer.txt b/forge-gui/res/cardsfolder/upcoming/amphin_mutineer.txt index f76d12c38a9..05d110dee5f 100755 --- a/forge-gui/res/cardsfolder/upcoming/amphin_mutineer.txt +++ b/forge-gui/res/cardsfolder/upcoming/amphin_mutineer.txt @@ -2,9 +2,8 @@ Name:Amphin Mutineer ManaCost:3 U Types:Creature Salamander Pirate PT:3/3 -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, exile up to one target non-flying creature. That creature's controller creates a 4/3 blue Salamander Warrior creature token. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, exile up to one target non-Salamander creature. That creature's controller creates a 4/3 blue Salamander Warrior creature token. SVar:TrigExile:DB$ ChangeZone | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature.nonSalamander | TgtPrompt$ Select up to one target non-Salamander creature | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBToken SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ u_4_3_salamander_warrior | TokenOwner$ TargetedController K:Encore:4 U U -SVar:X:Count$Valid Card.IsRemembered+OppOwn Oracle:When Amphin Mutineer enters the battlefield, exile up to one target non-Salamander creature. That creature's controller creates a 4/3 blue Salamander Warrior creature token.\nEncore {4}{U}{U} ({4}{U}{U}, Exile this card from your graveyard: For each opponent, create a token copy that attacks that opponent this turn if able. They gain haste. Sacrifice them at the beginning of the next end step. Activate only as a sorcery.) From dc8be8c0a0aca02bb151cb3e2ebc3c374378542e Mon Sep 17 00:00:00 2001 From: Northmoc Date: Fri, 30 Oct 2020 18:40:35 -0400 Subject: [PATCH 3/8] Encore mechanic --- forge-game/src/main/java/forge/game/card/Card.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 3d3d6b7379e..1ecff58ab29 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1823,7 +1823,8 @@ public class Card extends GameEntity implements Comparable { || keyword.startsWith("Reinforce") || keyword.startsWith("Champion") || keyword.startsWith("Prowl") || keyword.startsWith("Amplify") || keyword.startsWith("Ninjutsu") || keyword.startsWith("Adapt") || keyword.startsWith("Transfigure") || keyword.startsWith("Aura swap") - || keyword.startsWith("Cycling") || keyword.startsWith("TypeCycling")) { + || keyword.startsWith("Cycling") || keyword.startsWith("TypeCycling") + || keyword.startsWith("Encore")) { // keyword parsing takes care of adding a proper description } else if (keyword.startsWith("CantBeBlockedByAmount")) { sbLong.append(getName()).append(" can't be blocked "); From ea908ce5ad2ccf216227dc7d598d5d0a992b40a7 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Fri, 30 Oct 2020 18:43:45 -0400 Subject: [PATCH 4/8] rest of Encore mechanic --- .../java/forge/game/card/CardFactoryUtil.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 44fbf4c2899..1e746804488 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -4347,6 +4347,48 @@ public class CardFactoryUtil { sa.setIntrinsic(intrinsic); inst.addSpellAbility(sa); + } else if (keyword.startsWith("Encore")) { + final String[] k = keyword.split(":"); + final String manacost = k[1]; + + String effect = "AB$ RepeatEach | Cost$ " + manacost + " ExileFromGrave<1/CARDNAME> " + + "| ActivationZone$ Graveyard | RepeatPlayers$ Opponent" + + "| PrecostDesc$ Encore | CostDesc$ " + ManaCostParser.parse(manacost) + + "| SpellDescription$ (" + inst.getReminderText() + ")"; + + final String copyStr = "DB$ CopyPermanent | Defined$ Self | ImprintTokens$ True " + + "| AddKeywords$ Haste | TokenRemembered$ Player.IsRemembered"; + + final String pumpStr = "DB$ Pump | Defined$ Imprinted | Permanent$ True " + + "| KW$ HIDDEN CARDNAME attacks specific player each combat if able:Remembered"; + + final String delTrigStr = "DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | RememberObjects$ Imprinted " + + "| TriggerDescription$ Sacrifice them at the beginning of the next end step."; + + final String sacStr = "DB$ SacrificeAll | Defined$ DelayTriggerRemembered"; + + final String cleanupStr = "DB$ Cleanup | ClearImprinted$ True"; + + final SpellAbility sa = AbilityFactory.getAbility(effect, card); + sa.setIntrinsic(intrinsic); + inst.addSpellAbility(sa); + + AbilitySub copySA = (AbilitySub) AbilityFactory.getAbility(copyStr, card); + sa.setAdditionalAbility("RepeatSubAbility", copySA); + + AbilitySub pumpSA = (AbilitySub) AbilityFactory.getAbility(pumpStr, card); + copySA.setSubAbility(pumpSA); + + AbilitySub delTrigSA = (AbilitySub) AbilityFactory.getAbility(delTrigStr, card); + sa.setSubAbility(delTrigSA); + + AbilitySub sacSA = (AbilitySub) AbilityFactory.getAbility(sacStr, card); + delTrigSA.setAdditionalAbility("Execute", sacSA); + + AbilitySub cleanupSA = (AbilitySub) AbilityFactory.getAbility(cleanupStr, card); + delTrigSA.setSubAbility(cleanupSA); + + } else if (keyword.startsWith("Spectacle")) { final String[] k = keyword.split(":"); final Cost cost = new Cost(k[1], false); From 64131f15e56cc7c470764a34e7d3258e987f1dcc Mon Sep 17 00:00:00 2001 From: Northmoc Date: Fri, 30 Oct 2020 18:44:09 -0400 Subject: [PATCH 5/8] Encore keyword/reminder text --- forge-game/src/main/java/forge/game/keyword/Keyword.java | 1 + 1 file changed, 1 insertion(+) diff --git a/forge-game/src/main/java/forge/game/keyword/Keyword.java b/forge-game/src/main/java/forge/game/keyword/Keyword.java index d810408411c..bcf60c0a504 100644 --- a/forge-game/src/main/java/forge/game/keyword/Keyword.java +++ b/forge-game/src/main/java/forge/game/keyword/Keyword.java @@ -49,6 +49,7 @@ public enum Keyword { EMBALM("Embalm", KeywordWithCost.class, false, "%s, Exile this card from your graveyard: Create a token that's a copy of this card, except it's white, it has no mana cost, and it's a Zombie in addition to its other types. Embalm only as a sorcery."), EMERGE("Emerge", KeywordWithCost.class, false, "You may cast this spell by sacrificing a creature and paying the emerge cost reduced by that creature's converted mana cost."), ENCHANT("Enchant", KeywordWithType.class, false, "Target a %s as you cast this. This card enters the battlefield attached to that %s."), + ENCORE("Encore", KeywordWithCost.class, false, "%s, Exile this card from your graveyard: For each opponent, create a token copy that attacks that opponent this turn if able. They gain haste. Sacrifice them at the beginning of the next end step. Activate only as a sorcery."), ENTWINE("Entwine", KeywordWithCost.class, true, "You may choose all modes of this spell instead of just one. If you do, you pay an additional %s."), EPIC("Epic", SimpleKeyword.class, true, "For the rest of the game, you can't cast spells. At the beginning of each of your upkeeps for the rest of the game, copy this spell except for its epic ability. If the spell has any targets, you may choose new targets for the copy."), EQUIP("Equip", Equip.class, false, "%s: Attach to target %s you control. Equip only as a sorcery."), From be6d633763a22e9d4b492a1be1c1ca9196e1e8cc Mon Sep 17 00:00:00 2001 From: Northmoc Date: Fri, 30 Oct 2020 19:48:13 -0400 Subject: [PATCH 6/8] Clean up card detail mess --- .../main/java/forge/game/card/CardFactoryUtil.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 1e746804488..534dc7e2d54 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -4357,13 +4357,15 @@ public class CardFactoryUtil { "| SpellDescription$ (" + inst.getReminderText() + ")"; final String copyStr = "DB$ CopyPermanent | Defined$ Self | ImprintTokens$ True " + - "| AddKeywords$ Haste | TokenRemembered$ Player.IsRemembered"; + "| AddKeywords$ Haste | RememberTokens$ True | TokenRemembered$ Player.IsRemembered"; - final String pumpStr = "DB$ Pump | Defined$ Imprinted | Permanent$ True " + - "| KW$ HIDDEN CARDNAME attacks specific player each combat if able:Remembered"; + final String pumpStr = "DB$ Animate | Defined$ Remembered " + + "| HiddenKeywords$ CARDNAME attacks specific player each combat if able:Remembered"; + + final String pumpcleanStr = "DB$ Cleanup | ForgetDefined$ RememberedCard"; final String delTrigStr = "DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | RememberObjects$ Imprinted " + - "| TriggerDescription$ Sacrifice them at the beginning of the next end step."; + "| StackDescription$ None | TriggerDescription$ Sacrifice them at the beginning of the next end step."; final String sacStr = "DB$ SacrificeAll | Defined$ DelayTriggerRemembered"; @@ -4379,6 +4381,9 @@ public class CardFactoryUtil { AbilitySub pumpSA = (AbilitySub) AbilityFactory.getAbility(pumpStr, card); copySA.setSubAbility(pumpSA); + AbilitySub pumpcleanSA = (AbilitySub) AbilityFactory.getAbility(pumpcleanStr, card); + pumpSA.setSubAbility(pumpcleanSA); + AbilitySub delTrigSA = (AbilitySub) AbilityFactory.getAbility(delTrigStr, card); sa.setSubAbility(delTrigSA); From 8ee13d7abe0e79b69526112477457e82d4c730c9 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Fri, 30 Oct 2020 23:46:09 -0400 Subject: [PATCH 7/8] few more little tweaks --- .../src/main/java/forge/game/card/CardFactoryUtil.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 534dc7e2d54..535506dd4f2 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -2909,7 +2909,7 @@ public class CardFactoryUtil { final String repeatStr = "DB$ RepeatEach | RepeatPlayers$ OpponentsOtherThanDefendingPlayer | ChangeZoneTable$ True"; final String copyStr = "DB$ CopyPermanent | Defined$ Self | TokenTapped$ True | Optional$ True | TokenAttacking$ Remembered" - + " | ChoosePlayerOrPlaneswalker$ True | ImprintTokens$ True"; + + " | ChoosePlayerOrPlaneswalker$ True | ImprintTokens$ True"; final String delTrigStr = "DB$ DelayedTrigger | Mode$ Phase | Phase$ EndCombat | RememberObjects$ Imprinted" + " | TriggerDescription$ Exile the tokens at end of combat."; @@ -4359,8 +4359,8 @@ public class CardFactoryUtil { final String copyStr = "DB$ CopyPermanent | Defined$ Self | ImprintTokens$ True " + "| AddKeywords$ Haste | RememberTokens$ True | TokenRemembered$ Player.IsRemembered"; - final String pumpStr = "DB$ Animate | Defined$ Remembered " + - "| HiddenKeywords$ CARDNAME attacks specific player each combat if able:Remembered"; + final String pumpStr = "DB$ PumpAll | Defined$ Creature.IsRemembered " + + "| KW$ HIDDEN CARDNAME attacks specific player each combat if able:Remembered"; final String pumpcleanStr = "DB$ Cleanup | ForgetDefined$ RememberedCard"; @@ -4393,7 +4393,6 @@ public class CardFactoryUtil { AbilitySub cleanupSA = (AbilitySub) AbilityFactory.getAbility(cleanupStr, card); delTrigSA.setSubAbility(cleanupSA); - } else if (keyword.startsWith("Spectacle")) { final String[] k = keyword.split(":"); final Cost cost = new Cost(k[1], false); From 9bb425c2ab291d35e2203501a54086d5e4d651ec Mon Sep 17 00:00:00 2001 From: Northmoc Date: Sat, 31 Oct 2020 00:28:03 -0400 Subject: [PATCH 8/8] ValidCards > Defined --- forge-game/src/main/java/forge/game/card/CardFactoryUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 535506dd4f2..866b53e1564 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -4359,7 +4359,7 @@ public class CardFactoryUtil { final String copyStr = "DB$ CopyPermanent | Defined$ Self | ImprintTokens$ True " + "| AddKeywords$ Haste | RememberTokens$ True | TokenRemembered$ Player.IsRemembered"; - final String pumpStr = "DB$ PumpAll | Defined$ Creature.IsRemembered " + + final String pumpStr = "DB$ PumpAll | ValidCards$ Creature.IsRemembered " + "| KW$ HIDDEN CARDNAME attacks specific player each combat if able:Remembered"; final String pumpcleanStr = "DB$ Cleanup | ForgetDefined$ RememberedCard";