From bcaadd0765a0692d79c056caa0e260d4288f24df Mon Sep 17 00:00:00 2001 From: tool4ever Date: Tue, 16 Apr 2024 16:00:16 +0200 Subject: [PATCH] Remove Alternative Cost KW (#5050) --- .../src/main/java/forge/game/card/Card.java | 3 +-- .../java/forge/game/card/CardFactoryUtil.java | 18 +---------------- .../StaticAbilityAlternativeCost.java | 20 ++++++++++++------- .../cardsfolder/k/kentaro_the_smiling_cat.txt | 3 ++- .../cardsfolder/m/marshland_bloodcaster.txt | 5 +++-- .../forge/player/HumanPlaySpellAbility.java | 5 ++++- 6 files changed, 24 insertions(+), 30 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 7e6cfb819de..ba4db6ea0ec 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -2495,8 +2495,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { || keyword.startsWith("Class") || keyword.startsWith("Blitz") || keyword.startsWith("Specialize") || keyword.equals("Ravenous") || keyword.equals("For Mirrodin") || keyword.startsWith("Craft") - || keyword.startsWith("Landwalk") - || keyword.startsWith("Alternative Cost")) { + || keyword.startsWith("Landwalk")) { // keyword parsing takes care of adding a proper description } else if (keyword.equals("Read ahead")) { sb.append(Localizer.getInstance().getMessage("lblReadAhead")).append(" (").append(Localizer.getInstance().getMessage("lblReadAheadDesc")); 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 a18fcd1273f..378d5a4ee5b 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -2607,23 +2607,7 @@ public class CardFactoryUtil { public static void addSpellAbility(final KeywordInterface inst, final CardState card, final boolean intrinsic) { String keyword = inst.getOriginal(); Card host = card.getCard(); - if (keyword.startsWith("Alternative Cost") && !host.isLand()) { - final String[] kw = keyword.split(":"); - String costStr = kw[1]; - for (SpellAbility sa : host.getBasicSpells()) { - if (costStr.equals("ConvertedManaCost")) { - costStr = Integer.toString(host.getCMC()); - } - final Cost cost = new Cost(costStr, false).add(sa.getPayCosts().copyWithNoMana()); - final SpellAbility newSA = sa.copyWithDefinedCost(cost); - newSA.setBasicSpell(false); - newSA.putParam("Secondary", "True"); - newSA.setDescription(sa.getDescription() + " (by paying " + cost.toSimpleString() + " instead of its mana cost)"); - newSA.setIntrinsic(intrinsic); - - inst.addSpellAbility(newSA); - } - } else if (keyword.startsWith("Adapt")) { + if (keyword.startsWith("Adapt")) { final String[] k = keyword.split(":"); final String magnitude = k[1]; final String manacost = k[2]; diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityAlternativeCost.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityAlternativeCost.java index 08ecfca12fc..994aeb7fadc 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityAlternativeCost.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityAlternativeCost.java @@ -18,8 +18,9 @@ public class StaticAbilityAlternativeCost { public static List alternativeCosts(final SpellAbility sa, final Card source, final Player pl) { List result = Lists.newArrayList(); - CardCollection list = new CardCollection(source.getGame().getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)); - list.add(source); + // add source first in case it's LKI (alternate host) + CardCollection list = new CardCollection(source); + list.addAll(source.getGame().getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)); for (final Card ca : list) { for (final StaticAbility stAb : ca.getStaticAbilities()) { if (!stAb.checkConditions(MODE)) { @@ -36,18 +37,23 @@ public class StaticAbilityAlternativeCost { newSA.setActivatingPlayer(pl); newSA.setBasicSpell(false); - // CostDesc only for ManaCost? - if (sa.isAbility()) { - newSA.putParam("CostDesc", stAb.hasParam("CostDesc") ? ManaCostParser.parse(stAb.getParam("CostDesc")) : cost.toSimpleString()); + if (cost.hasXInAnyCostPart()) { + newSA.setSVar("X", stAb.getSVar("X")); } // makes new SpellDescription final StringBuilder sb = new StringBuilder(); - sb.append(newSA.getCostDescription()); + + // CostDesc only for ManaCost? + if (sa.isAbility()) { + newSA.putParam("CostDesc", stAb.hasParam("CostDesc") ? ManaCostParser.parse(stAb.getParam("CostDesc")) : cost.toSimpleString()); + sb.append(newSA.getCostDescription()); + } + // skip reminder text for now, Keywords might be too complicated //sb.append("(").append(newKi.getReminderText()).append(")"); if (sa.isSpell()) { - sb.append(" ").append(sa.getDescription()).append(" (by paying " + cost.toSimpleString() + " instead of its mana cost)"); + sb.append(sa.getDescription()).append(" (by paying " + cost.toSimpleString() + " instead of its mana cost)"); } newSA.setDescription(sb.toString()); diff --git a/forge-gui/res/cardsfolder/k/kentaro_the_smiling_cat.txt b/forge-gui/res/cardsfolder/k/kentaro_the_smiling_cat.txt index 7e38aff201b..9fccad9c7e8 100644 --- a/forge-gui/res/cardsfolder/k/kentaro_the_smiling_cat.txt +++ b/forge-gui/res/cardsfolder/k/kentaro_the_smiling_cat.txt @@ -3,5 +3,6 @@ ManaCost:1 W Types:Legendary Creature Human Samurai PT:2/1 K:Bushido:1 -S:Mode$ Continuous | Affected$ Card.Samurai+YouCtrl | AddKeyword$ Alternative Cost:ConvertedManaCost | AffectedZone$ Hand,Graveyard,Exile,Library,Command | Description$ You may pay {X} rather than pay the mana cost for Samurai spells you cast, where X is that spell's mana value. +S:Mode$ AlternativeCost | ValidSA$ Spell.Samurai | ValidPlayer$ You | Cost$ X | Description$ You may pay {X} rather than pay the mana cost for Samurai spells you cast, where X is that spell's mana value. +SVar:X:Count$CardManaCost Oracle:Bushido 1 (Whenever this creature blocks or becomes blocked, it gets +1/+1 until end of turn.)\nYou may pay {X} rather than pay the mana cost for Samurai spells you cast, where X is that spell's mana value. diff --git a/forge-gui/res/cardsfolder/m/marshland_bloodcaster.txt b/forge-gui/res/cardsfolder/m/marshland_bloodcaster.txt index 68eb3d0870b..e23afcdab44 100644 --- a/forge-gui/res/cardsfolder/m/marshland_bloodcaster.txt +++ b/forge-gui/res/cardsfolder/m/marshland_bloodcaster.txt @@ -3,8 +3,9 @@ ManaCost:4 B Types:Creature Vampire Warlock PT:3/5 K:Flying -A:AB$ Effect | Cost$ 1 B T | StaticAbilities$ ReduceCost | Triggers$ TrigCastSpell -SVar:ReduceCost:Mode$ Continuous | Affected$ Card.nonLand+YouCtrl | AddKeyword$ Alternative Cost:PayLife | AffectedZone$ Hand,Graveyard,Exile,Library,Command | EffectZone$ Command | Description$ Rather than pay the mana cost of the next spell you cast this turn, you may pay life equal to that spell's mana value. +A:AB$ Effect | Cost$ 1 B T | StaticAbilities$ ReduceCost | Triggers$ TrigCastSpell | SpellDescription$ Rather than pay the mana cost of the next spell you cast this turn, you may pay life equal to that spell's mana value. +SVar:ReduceCost:Mode$ AlternativeCost | ValidSA$ Spell | ValidPlayer$ You | Cost$ PayLife | Description$ Rather than pay the mana cost of the next spell you cast this turn, you may pay life equal to that spell's mana value. SVar:TrigCastSpell:Mode$ SpellCast | ValidActivatingPlayer$ You | TriggerZones$ Command | Execute$ RemoveEffect | Static$ True SVar:RemoveEffect:DB$ ChangeZone | Origin$ Command | Destination$ Exile +SVar:X:Count$CardManaCost Oracle:Flying\n{1}{B}, {T}: Rather than pay the mana cost of the next spell you cast this turn, you may pay life equal to that spell's mana value. diff --git a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java index aeee2ea51eb..ec524c5ee98 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java +++ b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java @@ -264,7 +264,10 @@ public class HumanPlaySpellAbility { if (needX) { if (cost.hasXInAnyCostPart()) { final String sVar = ability.getSVar("X"); //only prompt for new X value if card doesn't determine it another way - if ("Count$xPaid".equals(sVar) || sVar.isEmpty()) { + // check if X != 0 is even allowed or the X shard got removed + boolean replacedXshard = ability.isSpell() && ability.getHostCard().getManaCost().countX() > 0 && + (cost.hasNoManaCost() || cost.getCostMana().getAmountOfX() == 0); + if (("Count$xPaid".equals(sVar) && !replacedXshard) || sVar.isEmpty()) { final Integer value = controller.announceRequirements(ability, "X"); if (value == null) { return false;