From 9db11ce690b671c7ed57162907f27d168166e718 Mon Sep 17 00:00:00 2001 From: Hythonia Date: Wed, 24 Mar 2021 20:14:41 +0100 Subject: [PATCH 1/4] ManaEffect rework --- .../java/forge/game/ability/effects/ManaEffect.java | 12 ++++++------ forge-gui/res/cardsfolder/e/elemental_resonance.txt | 3 +-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java index a39274131d2..7feecdb23f0 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java @@ -125,17 +125,17 @@ public class ManaEffect extends SpellAbilityEffect { String type = abMana.getOrigProduced().split("Special ")[1]; - if (type.equals("EnchantedManaCost")) { - Card enchanted = card.getEnchantingCard(); - if (enchanted == null ) + if (type.equals("DefinedManaCost")) { + Card defined = AbilityUtils.getDefinedCards(card, sa.getParam("ManaCostOf"), sa).get(0); + if (defined == null) continue; StringBuilder sb = new StringBuilder(); - int generic = enchanted.getManaCost().getGenericCost(); - if( generic > 0 ) + int generic = defined.getManaCost().getGenericCost(); + if(generic > 0) sb.append(generic); - for (ManaCostShard s : enchanted.getManaCost()) { + for (ManaCostShard s : defined.getManaCost()) { ColorSet cs = ColorSet.fromMask(s.getColorMask()); if(cs.isColorless()) continue; diff --git a/forge-gui/res/cardsfolder/e/elemental_resonance.txt b/forge-gui/res/cardsfolder/e/elemental_resonance.txt index 41c5ddca734..03cdc90a077 100644 --- a/forge-gui/res/cardsfolder/e/elemental_resonance.txt +++ b/forge-gui/res/cardsfolder/e/elemental_resonance.txt @@ -4,6 +4,5 @@ Types:Enchantment Aura K:Enchant permanent A:SP$ Attach | Cost$ 2 G G | ValidTgts$ Permanent | AILogic$ Pump T:Mode$ Phase | PreCombatMain$ True | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigMana | TriggerDescription$ At the beginning of your precombat main phase, add mana equal to enchanted permanent's mana cost. (Mana cost includes color. If a mana symbol has multiple colors, choose one.) -SVar:TrigMana:DB$ Mana | Produced$ Special EnchantedManaCost -SVar:Picture:http://www.wizards.com/global/images/magic/general/elemental_resonance.jpg +SVar:TrigMana:DB$ Mana | Produced$ Special DefinedManaCost | ManaCostOf$ Enchanted Oracle:Enchant permanent\nAt the beginning of your precombat main phase, add mana equal to enchanted permanent's mana cost. (Mana cost includes color. If a mana symbol has multiple colors, choose one.) From 7952bdcb48fcd26798a172c7f2fb3ea70580b413 Mon Sep 17 00:00:00 2001 From: Hythonia Date: Fri, 26 Mar 2021 11:37:57 +0100 Subject: [PATCH 2/4] Revert "ManaEffect rework" This reverts commit 9db11ce6 --- .../java/forge/game/ability/effects/ManaEffect.java | 12 ++++++------ forge-gui/res/cardsfolder/e/elemental_resonance.txt | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java index 0b55085cf2e..e63f3f8d6a7 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java @@ -125,17 +125,17 @@ public class ManaEffect extends SpellAbilityEffect { String type = abMana.getOrigProduced().split("Special ")[1]; - if (type.equals("DefinedManaCost")) { - Card defined = AbilityUtils.getDefinedCards(card, sa.getParam("ManaCostOf"), sa).get(0); - if (defined == null) + if (type.equals("EnchantedManaCost")) { + Card enchanted = card.getEnchantingCard(); + if (enchanted == null ) continue; StringBuilder sb = new StringBuilder(); - int generic = defined.getManaCost().getGenericCost(); - if(generic > 0) + int generic = enchanted.getManaCost().getGenericCost(); + if( generic > 0 ) sb.append(generic); - for (ManaCostShard s : defined.getManaCost()) { + for (ManaCostShard s : enchanted.getManaCost()) { ColorSet cs = ColorSet.fromMask(s.getColorMask()); if(cs.isColorless()) continue; diff --git a/forge-gui/res/cardsfolder/e/elemental_resonance.txt b/forge-gui/res/cardsfolder/e/elemental_resonance.txt index 03cdc90a077..41c5ddca734 100644 --- a/forge-gui/res/cardsfolder/e/elemental_resonance.txt +++ b/forge-gui/res/cardsfolder/e/elemental_resonance.txt @@ -4,5 +4,6 @@ Types:Enchantment Aura K:Enchant permanent A:SP$ Attach | Cost$ 2 G G | ValidTgts$ Permanent | AILogic$ Pump T:Mode$ Phase | PreCombatMain$ True | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigMana | TriggerDescription$ At the beginning of your precombat main phase, add mana equal to enchanted permanent's mana cost. (Mana cost includes color. If a mana symbol has multiple colors, choose one.) -SVar:TrigMana:DB$ Mana | Produced$ Special DefinedManaCost | ManaCostOf$ Enchanted +SVar:TrigMana:DB$ Mana | Produced$ Special EnchantedManaCost +SVar:Picture:http://www.wizards.com/global/images/magic/general/elemental_resonance.jpg Oracle:Enchant permanent\nAt the beginning of your precombat main phase, add mana equal to enchanted permanent's mana cost. (Mana cost includes color. If a mana symbol has multiple colors, choose one.) From b0380443475a438c766304141b2600009e43b496 Mon Sep 17 00:00:00 2001 From: Hythonia Date: Fri, 26 Mar 2021 15:01:59 +0100 Subject: [PATCH 3/4] STX: One Ward, two card --- .../src/main/java/forge/game/card/Card.java | 13 ++++++++++ .../java/forge/game/card/CardFactoryUtil.java | 15 ++++++++++- .../main/java/forge/game/card/CardUtil.java | 2 +- .../main/java/forge/game/keyword/Keyword.java | 1 + .../torrent_sculptor_flamethrower_sonata.txt | 25 +++++++++++++++++++ .../upcoming/waterfall_aerialist.txt | 7 ++++++ 6 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 forge-gui/res/cardsfolder/upcoming/torrent_sculptor_flamethrower_sonata.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/waterfall_aerialist.txt 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 8a35eee03e2..e8faae14813 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -2072,6 +2072,19 @@ public class Card extends GameEntity implements Comparable, IHasSVars { sb.append(" (").append(inst.getReminderText()).append(")"); printedKW.add(keyword); } + } else if (keyword.startsWith("Ward")) { + final String[] k = keyword.split(":"); + final Cost cost = new Cost(k[1], false); + + StringBuilder sbCost = new StringBuilder(k[0]); + if (!cost.isOnlyManaCost()) { + sbCost.append("—"); + } else { + sbCost.append(" "); + } + sbCost.append(cost.toSimpleString()); + sbLong.append(sbCost).append(" (").append(inst.getReminderText()).append(")"); + sbLong.append("\r\n"); } else if (keyword.endsWith(" offering")) { String offeringType = keyword.split(" ")[0]; if (sb.length() != 0) { 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 4a40fbd06ae..340d523a8f1 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -3331,7 +3331,7 @@ public class CardFactoryUtil { // sacrifice trigger final StringBuilder sacTrig = new StringBuilder("Mode$ CounterRemoved | TriggerZones$ Battlefield" + - " | ValidCard$ Card.Self | NewCounterAmount$ 0 | CounterType$ TIME"); + " | ValidCard$ Card.Self | NewCounterAmount$ 0 | CounterType$ TIME"); if (keyword.contains(":")) { sacTrig.append("| Secondary$ True"); } @@ -3343,6 +3343,19 @@ public class CardFactoryUtil { inst.addTrigger(parsedUpkeepTrig); inst.addTrigger(parsedSacTrigger); + } else if (keyword.startsWith("Ward")) { + final String[] k = keyword.split(":"); + final String cost = k[1]; + + String strTrig = "Mode$ BecomesTarget | ValidSource$ Card.OppCtrl | ValidTarget$ Card.Self " + + " | Secondary$ True | TriggerDescription$ " + inst.getReminderText(); + String effect = "DB$ Counter | Defined$ TriggeredSourceSA | UnlessCost$ " + cost + + " | UnlessPayer$ TriggeredSourceSAController"; + + final Trigger trigger = TriggerHandler.parseTrigger(strTrig, card, intrinsic); + trigger.setOverridingAbility(AbilityFactory.getAbility(effect, card)); + + inst.addTrigger(trigger); } else if (keyword.equals("MayFlashSac")) { String strTrig = "Mode$ SpellCast | ValidCard$ Card.Self | ValidSA$ Spell.MayPlaySource | Static$ True | Secondary$ True " + " | TriggerDescription$ If you cast it any time a sorcery couldn't have been cast, " diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java index 9c3027fc6ba..aa5c7ca0195 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -65,7 +65,7 @@ public final class CardUtil { "Fortify", "Transfigure", "Champion", "Evoke", "Prowl", "IfReach", "Reinforce", "Unearth", "Level up", "Miracle", "Overload", "Scavenge", "Encore", "Bestow", "Outlast", "Dash", "Surge", "Emerge", "Hexproof:", - "etbCounter", "Reflect").build(); + "etbCounter", "Reflect", "Ward").build(); /** List of keyword endings of keywords that could be modified by text changes. */ public static final ImmutableList modifiableKeywordEndings = ImmutableList.builder().add( "walk", "cycling", "offering").build(); 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 f27e0dfc56b..fea88ec24ff 100644 --- a/forge-game/src/main/java/forge/game/keyword/Keyword.java +++ b/forge-game/src/main/java/forge/game/keyword/Keyword.java @@ -161,6 +161,7 @@ public enum Keyword { UNLEASH("Unleash", SimpleKeyword.class, false, "You may have this creature enter the battlefield with a +1/+1 counter on it. It can't block as long as it has a +1/+1 counter on it."), VANISHING("Vanishing", KeywordWithAmount.class, false, "This permanent enters the battlefield with {%d:time counter} on it. At the beginning of your upkeep, remove a time counter from it. When the last is removed, sacrifice it."), VIGILANCE("Vigilance", SimpleKeyword.class, true, "Attacking doesn't cause this creature to tap."), + WARD("Ward", KeywordWithCost.class, false, "Whenever this permanent becomes the target of a spell or ability an opponent controls, counter it unless that player pays %s."), WITHER("Wither", SimpleKeyword.class, true, "This deals damage to creatures in the form of -1/-1 counters."), // mayflash additional cast diff --git a/forge-gui/res/cardsfolder/upcoming/torrent_sculptor_flamethrower_sonata.txt b/forge-gui/res/cardsfolder/upcoming/torrent_sculptor_flamethrower_sonata.txt new file mode 100644 index 00000000000..8b395a7f328 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/torrent_sculptor_flamethrower_sonata.txt @@ -0,0 +1,25 @@ +Name:Torrent Sculptor +ManaCost:2 U U +Types:Creature Merfolk Wizard +PT:2/2 +K:Ward:2 +T:Mode$ ChangesZone | ValidCard$ Card.Self | Destination$ Battlefield | Execute$ TrigChangeZone | TriggerDescription$ When CARDNAME enters the battlefield, exile an instant or sorcery card from your graveyard. Put a number of +1/+1 counters on Torrent Sculptor equal to half that card's mana value, rounded up. +SVar:TrigChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | ChangeType$ Instant.YouCtrl,Sorcery.YouCtrl | ChangeNum$ 1 | RememberChanged$ True | Hidden$ True | Mandatory$ True | SubAbility$ DBPutCounter +SVar:DBPutCounter:DB$ PutCounter | CounterType$ P1P1 | CounterNum$ X | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:X:Remembered$CardManaCost/HalfUp +AlternateMode:Modal +Oracle:Ward {2} (Whenever this creature becomes the target of a spell or ability an opponent controls, counter it unless that player pays {2}.)\nWhen Torrent Sculptor enters the battlefield, exile an instant or sorcery card from your graveyard. Put a number of +1/+1 counters on Torrent Sculptor equal to half that card's mana value, rounded up. + +ALTERNATE + +Name:Flamethrower Sonata +ManaCost:1 R +Types:Sorcery +A:SP$ Discard | Cost$ 1 R | Mode$ TgtChoose | SubAbility$ DBDraw | RememberDiscarded$ True | SpellDescription$ Discard a card, then draw a card. When you discard an instant or sorcery card this way, CARDNAME deals damage equal to that card's mana value to target creature or planeswalker you don't control. +SVar:DBDraw:DB$ Draw | SubAbility$ DBImmediateTrigger +SVar:DBImmediateTrigger:DB$ ImmediateTrigger | ConditionDefined$ Remembered | ConditionPresent$ Instant,Sorcery | Execute$ TrigDealDamage | RememberObjects$ RememberedCard | SubAbility$ DBCleanup | TriggerDescription$ When you discard an instant or sorcery card this way, CARDNAME deals damage equal to that card's mana value to target creature or planeswalker you don't control. +SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Creature.YouDontCtrl,Planeswalker.YouDontCtrl | TgtPrompt$ Select target creature or planeswalker you don't control | NumDmg$ X +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:X:Remembered$CardManaCost +Oracle:Discard a card, then draw a card. When you discard an instant or sorcery card this way, Flamethrower Sonata deals damage equal to that card's mana value to target creature or planeswalker you don't control. diff --git a/forge-gui/res/cardsfolder/upcoming/waterfall_aerialist.txt b/forge-gui/res/cardsfolder/upcoming/waterfall_aerialist.txt new file mode 100644 index 00000000000..dec50e0fc46 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/waterfall_aerialist.txt @@ -0,0 +1,7 @@ +Name:Waterfall Aerialist +ManaCost:3 U +Types:Creature Djinn Wizard +PT:3/1 +K:Flying +K:Ward:2 +Oracle:Flying\nWard {2} (Whenever this creature becomes the target of a spell or ability an opponent controls, counter it unless that player pays {2}.) From 351f9c1976e9de2953a97c8865e4b140711b5fce Mon Sep 17 00:00:00 2001 From: Hythonia Date: Fri, 26 Mar 2021 18:14:27 +0100 Subject: [PATCH 4/4] STX: Ward's TriggerDescription --- .../src/main/java/forge/game/card/CardFactoryUtil.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 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 340d523a8f1..3465e014479 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -3345,11 +3345,13 @@ public class CardFactoryUtil { inst.addTrigger(parsedSacTrigger); } else if (keyword.startsWith("Ward")) { final String[] k = keyword.split(":"); - final String cost = k[1]; + final Cost cost = new Cost(k[1], false); + String costDesc = cost.toSimpleString(); String strTrig = "Mode$ BecomesTarget | ValidSource$ Card.OppCtrl | ValidTarget$ Card.Self " - + " | Secondary$ True | TriggerDescription$ " + inst.getReminderText(); - String effect = "DB$ Counter | Defined$ TriggeredSourceSA | UnlessCost$ " + cost + + " | Secondary$ True | TriggerDescription$ Ward " + costDesc + " (" + + inst.getReminderText() + ")"; + String effect = "DB$ Counter | Defined$ TriggeredSourceSA | UnlessCost$ " + k[1] + " | UnlessPayer$ TriggeredSourceSAController"; final Trigger trigger = TriggerHandler.parseTrigger(strTrig, card, intrinsic);