From f859bd951a8886a9156931bc12ad2b81786d3705 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Wed, 27 Apr 2022 13:44:43 -0400 Subject: [PATCH 1/6] Card > keywordsToText "AlternativeAdditionalCost" refactor to support more than two possible costs --- .../src/main/java/forge/game/card/Card.java | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) 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 e7ba212a4e8..d5fe263bc67 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -2011,15 +2011,17 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } else if (keyword.startsWith("Alternative Cost")) { sbLong.append("Has alternative cost."); } else if (keyword.startsWith("AlternateAdditionalCost")) { - final String costString1 = keyword.split(":")[1]; - final String costString2 = keyword.split(":")[2]; - final Cost cost1 = new Cost(costString1, false); - final Cost cost2 = new Cost(costString2, false); - sbLong.append("As an additional cost to cast this spell, ") - .append(StringUtils.uncapitalize(cost1.toSimpleString())) - .append(" or pay ") - .append(StringUtils.uncapitalize(cost2.toSimpleString())) - .append(".\r\n\r\n"); + final String[] costs = (keyword.split(":", 2)[1]).split(":"); + sbLong.append("As an additional cost to cast this spell, "); + for (int n = 0; n < costs.length; n++) { + final Cost cost = new Cost(costs[n], false); + if (cost.isOnlyManaCost()) { + sbLong.append(" pay "); + } + sbLong.append(StringUtils.uncapitalize(cost.toSimpleString())); + sbLong.append(n + 1 == costs.length ? ".\r\n\r\n" : n + 2 == costs.length && costs.length > 2 + ? ", or " : n + 2 == costs.length ? " or " : ", "); + } } else if (keyword.startsWith("Multikicker")) { if (!keyword.endsWith("Generic")) { final String[] n = keyword.split(":"); @@ -2632,14 +2634,17 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } sbBefore.append(sbx).append("\r\n"); } else if (keyword.startsWith("AlternateAdditionalCost")) { - final String[] k = keyword.split(":"); - final Cost cost1 = new Cost(k[1], false); - final Cost cost2 = new Cost(k[2], false); - sbBefore.append("As an additional cost to cast this spell, ") - .append(StringUtils.uncapitalize(cost1.toSimpleString())) - .append(" or pay ") - .append(StringUtils.uncapitalize(cost2.toSimpleString())) - .append(".\r\n\r\n"); + final String[] costs = (keyword.split(":", 2)[1]).split(":"); + sbBefore.append("As an additional cost to cast this spell, "); + for (int n = 0; n < costs.length; n++) { + final Cost cost = new Cost(costs[n], false); + if (cost.isOnlyManaCost()) { + sbBefore.append(" pay "); + } + sbBefore.append(StringUtils.uncapitalize(cost.toSimpleString())); + sbBefore.append(n + 1 == costs.length ? ".\r\n\r\n" : n + 2 == costs.length && costs.length > 2 + ? ", or " : n + 2 == costs.length ? " or " : ", "); + } } else if (keyword.startsWith("Presence") || keyword.startsWith("MayFlash")) { // Pseudo keywords, only print Reminder sbBefore.append(inst.getReminderText()); From 86d1f548300fcd0d27a346112ec44c94c9793f0b Mon Sep 17 00:00:00 2001 From: Northmoc Date: Wed, 27 Apr 2022 13:45:18 -0400 Subject: [PATCH 2/6] Cost > IsOnlyManaCost() clarify comment --- forge-game/src/main/java/forge/game/cost/Cost.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-game/src/main/java/forge/game/cost/Cost.java b/forge-game/src/main/java/forge/game/cost/Cost.java index bb744d6e2b5..4b2fe9d1475 100644 --- a/forge-game/src/main/java/forge/game/cost/Cost.java +++ b/forge-game/src/main/java/forge/game/cost/Cost.java @@ -155,7 +155,7 @@ public class Cost implements Serializable { * @return a boolean. */ public final boolean isOnlyManaCost() { - // Only used by Morph and Equip... why do we need this? + // used by Morph, Equip and some string builders for (final CostPart part : this.costParts) { if (!(part instanceof CostPartMana)) { return false; From b6f15cf1d743008e92caa19f5b3fd8ab2721035b Mon Sep 17 00:00:00 2001 From: Northmoc Date: Wed, 27 Apr 2022 13:46:02 -0400 Subject: [PATCH 3/6] GameActionUtil > getAdditionalCostSpell() "AlternativeAdditionalCost" refactor to support more than two possible costs --- .../main/java/forge/game/GameActionUtil.java | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index c6ce66f4d5b..bb09976f183 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -487,27 +487,18 @@ public final class GameActionUtil { final String keyword = inst.getOriginal(); if (keyword.startsWith("AlternateAdditionalCost")) { final List newAbilities = Lists.newArrayList(); - String[] costs = TextUtil.split(keyword, ':'); + final String[] costs = (keyword.split(":", 2)[1]).split(":"); - final SpellAbility newSA = sa.copy(); - newSA.setBasicSpell(false); + for (String s : costs) { + final SpellAbility newSA = sa.copy(); + newSA.setBasicSpell(false); - final Cost cost1 = new Cost(costs[1], false); - newSA.setDescription(sa.getDescription() + " (Additional cost " + cost1.toSimpleString() + ")"); - newSA.setPayCosts(cost1.add(sa.getPayCosts())); - if (newSA.canPlay()) { - newAbilities.add(newSA); - } - - //second option - final SpellAbility newSA2 = sa.copy(); - newSA2.setBasicSpell(false); - - final Cost cost2 = new Cost(costs[2], false); - newSA2.setDescription(sa.getDescription() + " (Additional cost " + cost2.toSimpleString() + ")"); - newSA2.setPayCosts(cost2.add(sa.getPayCosts())); - if (newSA2.canPlay()) { - newAbilities.add(newSA2); + final Cost cost = new Cost(s, false); + newSA.setDescription(sa.getDescription() + " (Additional cost: " + cost.toSimpleString() + ")"); + newSA.setPayCosts(cost.add(sa.getPayCosts())); + if (newSA.canPlay()) { + newAbilities.add(newSA); + } } abilities.clear(); From 7e61af3dcaa4d1d44671b0efe6e4034b492547d0 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Wed, 27 Apr 2022 13:46:17 -0400 Subject: [PATCH 4/6] dusk_mangler.txt --- forge-gui/res/cardsfolder/upcoming/dusk_mangler.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/dusk_mangler.txt diff --git a/forge-gui/res/cardsfolder/upcoming/dusk_mangler.txt b/forge-gui/res/cardsfolder/upcoming/dusk_mangler.txt new file mode 100644 index 00000000000..d65ff385ba7 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/dusk_mangler.txt @@ -0,0 +1,12 @@ +Name:Dusk Mangler +ManaCost:5 B B +Types:Creature Horror +PT:5/4 +K:AlternateAdditionalCost:Sac<1/Creature>:Discard<1/Card>:PayLife<4> +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSac | TriggerDescription$ When CARDNAME enters the battlefield, each opponent sacrifices a creature, discards a card, and loses 4 life. +SVar:TrigSac:DB$ Sacrifice | Defined$ Opponent | SacValid$ Creature | SubAbility$ DBDiscard +SVar:DBDiscard:DB$ Discard | Mode$ TgtChoose | Defined$ Opponent | SubAbility$ DBLoseLife +SVar:DBLoseLife:DB$ LoseLife | Defined$ Opponent | LifeAmount$ 4 +DeckHas:Ability$Sacrifice|Discard +SVar:AIPreference:SacCost$Creature.token,Creature.cmcLE3 +Oracle:As an additional cost to cast this spell, sacrifice a creature, discard a card, or pay 4 life.\nWhen Dusk Mangler enters the battlefield, each opponent sacrifices a creature, discards a card, and loses 4 life. From 1ce726b8ef09edfd4ecb0d7b6694e8a73c24b864 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Thu, 28 Apr 2022 10:06:38 -0400 Subject: [PATCH 5/6] GameActionUtil streamline more --- forge-game/src/main/java/forge/game/GameActionUtil.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index bb09976f183..7bdb0ff4497 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -487,9 +487,8 @@ public final class GameActionUtil { final String keyword = inst.getOriginal(); if (keyword.startsWith("AlternateAdditionalCost")) { final List newAbilities = Lists.newArrayList(); - final String[] costs = (keyword.split(":", 2)[1]).split(":"); - for (String s : costs) { + for (String s : keyword.split(":", 2)[1].split(":")) { final SpellAbility newSA = sa.copy(); newSA.setBasicSpell(false); From ce28f04bc6aa58b00da5e12a80d0b08c87f522ef Mon Sep 17 00:00:00 2001 From: Northmoc Date: Thu, 28 Apr 2022 10:06:59 -0400 Subject: [PATCH 6/6] Card.java remove unneeded () --- forge-game/src/main/java/forge/game/card/Card.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 d5fe263bc67..31162c4d59e 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -2011,7 +2011,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } else if (keyword.startsWith("Alternative Cost")) { sbLong.append("Has alternative cost."); } else if (keyword.startsWith("AlternateAdditionalCost")) { - final String[] costs = (keyword.split(":", 2)[1]).split(":"); + final String[] costs = keyword.split(":", 2)[1].split(":"); sbLong.append("As an additional cost to cast this spell, "); for (int n = 0; n < costs.length; n++) { final Cost cost = new Cost(costs[n], false); @@ -2634,7 +2634,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } sbBefore.append(sbx).append("\r\n"); } else if (keyword.startsWith("AlternateAdditionalCost")) { - final String[] costs = (keyword.split(":", 2)[1]).split(":"); + final String[] costs = keyword.split(":", 2)[1].split(":"); sbBefore.append("As an additional cost to cast this spell, "); for (int n = 0; n < costs.length; n++) { final Cost cost = new Cost(costs[n], false);