From bbac9c4dedbfc2b601ee2949b7e6ac9ab4266571 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Wed, 19 Jun 2024 14:25:37 +0200 Subject: [PATCH] Keyword: Freerunning (#5439) * Keyword: Freerunning * Update Player.java --- .../src/main/java/forge/game/card/Card.java | 4 ++-- .../java/forge/game/card/CardFactoryUtil.java | 21 +++++++++++++++++++ .../main/java/forge/game/card/CardUtil.java | 2 +- .../main/java/forge/game/keyword/Keyword.java | 1 + .../main/java/forge/game/player/Player.java | 4 ++++ .../game/spellability/AlternativeCost.java | 1 + .../forge/game/spellability/SpellAbility.java | 4 ++++ .../spellability/SpellAbilityRestriction.java | 5 +++++ .../upcoming/achilles_davenport.txt | 8 +++++++ 9 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 forge-gui/res/cardsfolder/upcoming/achilles_davenport.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 ba7e4a9ed9e..dabdf7352d4 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -2495,7 +2495,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { || keyword.equals("Undaunted") || keyword.startsWith("Monstrosity") || keyword.startsWith("Embalm") || keyword.equals("Prowess") || keyword.startsWith("Eternalize") || keyword.startsWith("Reinforce") - || keyword.startsWith("Champion") || keyword.startsWith("Prowl") || keyword.startsWith("Adapt") + || keyword.startsWith("Champion") || keyword.startsWith("Freerunning") || keyword.startsWith("Prowl") || keyword.startsWith("Adapt") || keyword.startsWith("Amplify") || keyword.startsWith("Ninjutsu") || keyword.startsWith("Chapter") || keyword.startsWith("Transfigure") || keyword.startsWith("Aura swap") || keyword.startsWith("Cycling") || keyword.startsWith("TypeCycling") @@ -3013,7 +3013,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } else if (keyword.startsWith("Starting intensity")) { sbAfter.append(TextUtil.fastReplace(keyword, ":", " ")).append("\r\n"); } else if (keyword.startsWith("Escalate") || keyword.startsWith("Buyback") - || keyword.startsWith("Prowl")) { + || keyword.startsWith("Freerunning") || keyword.startsWith("Prowl")) { final String[] k = keyword.split(":"); final String manacost = k[1]; final Cost cost = new Cost(manacost, false); 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 a725e7b9907..3763075cc9b 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -3086,6 +3086,27 @@ public class CardFactoryUtil { // instantiate attach ability final SpellAbility sa = AbilityFactory.getAbility(abilityStr.toString(), card); inst.addSpellAbility(sa); + } else if (keyword.startsWith("Freerunning")) { + final String[] k = keyword.split(":"); + final Cost freerunningCost = new Cost(k[1], false); + final SpellAbility newSA = card.getFirstSpellAbility().copyWithDefinedCost(freerunningCost); + + if (host.isInstant() || host.isSorcery()) { + newSA.putParam("Secondary", "True"); + } + newSA.putParam("PrecostDesc", "Freerunning"); + newSA.putParam("CostDesc", ManaCostParser.parse(k[1])); + + // makes new SpellDescription + final StringBuilder sb = new StringBuilder(); + sb.append(newSA.getCostDescription()); + sb.append("(").append(inst.getReminderText()).append(")"); + newSA.setDescription(sb.toString()); + + newSA.setAlternativeCost(AlternativeCost.Freerunning); + + newSA.setIntrinsic(intrinsic); + inst.addSpellAbility(newSA); } else if (keyword.startsWith("Fuse") && card.getStateName().equals(CardStateName.Original)) { final SpellAbility sa = AbilityFactory.buildFusedAbility(card.getCard()); card.addSpellAbility(sa); 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 dd39808343b..019a64e389e 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -57,7 +57,7 @@ public final class CardUtil { "Cycling", "Echo", "Kicker", "Flashback", "Madness", "Morph", "Affinity", "Entwine", "Splice", "Ninjutsu", "Transmute", "Replicate", "Recover", "Squad", "Suspend", "Aura swap", - "Fortify", "Transfigure", "Champion", "Evoke", "Prowl", + "Fortify", "Transfigure", "Champion", "Evoke", "Prowl", "Freerunning", "Reinforce", "Unearth", "Level up", "Miracle", "Overload", "Cleave", "Scavenge", "Encore", "Bestow", "Outlast", "Dash", "Surge", "Emerge", "Hexproof:", "etbCounter", "Reflect", "Ward").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 c52a2728ebb..efbffabba9c 100644 --- a/forge-game/src/main/java/forge/game/keyword/Keyword.java +++ b/forge-game/src/main/java/forge/game/keyword/Keyword.java @@ -95,6 +95,7 @@ public enum Keyword { FOR_MIRRODIN("For Mirrodin", SimpleKeyword.class, false, "When this Equipment enters the battlefield, create a 2/2 red Rebel creature token, then attach this to it."), FORETELL("Foretell", KeywordWithCost.class, false, "During your turn, you may pay {2} and exile this card from your hand face down. Cast it on a later turn for its foretell cost."), FORTIFY("Fortify", KeywordWithCost.class, false, "%s: Attach to target land you control. Fortify only as a sorcery."), + FREERUNNING("Freerunning", KeywordWithCost.class, false, "You may cast this spell for its freerunning cost if you dealt combat damage to a player this turn with an Assassin or commander."), FRENZY("Frenzy", KeywordWithAmount.class, false, "Whenever this creature attacks and isn't blocked, it gets +%d/+0 until end of turn."), FRIENDS_FOREVER("Friends forever", Partner.class, true, "You can have two commanders if both have friends forever."), FUSE("Fuse", SimpleKeyword.class, true, "You may cast one or both halves of this card from your hand."), diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 63301767915..42908ea4965 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -2140,6 +2140,10 @@ public class Player extends GameEntity implements Comparable { return !game.getDamageDoneThisTurn(true, true, sb.toString(), "Player", null, this, null).isEmpty(); } + public final boolean hasFreerunning() { + return !game.getDamageDoneThisTurn(true, true, "Card.Assassin+YouCtrl,Card.IsCommander+YouCtrl", "Player", null, this, null).isEmpty(); + } + public final void setLibrarySearched(final int l) { numLibrarySearchedOwn = l; } diff --git a/forge-game/src/main/java/forge/game/spellability/AlternativeCost.java b/forge-game/src/main/java/forge/game/spellability/AlternativeCost.java index 32710b509e6..71aeccd3f95 100644 --- a/forge-game/src/main/java/forge/game/spellability/AlternativeCost.java +++ b/forge-game/src/main/java/forge/game/spellability/AlternativeCost.java @@ -11,6 +11,7 @@ public enum AlternativeCost { Evoke, Flashback, Foretold, + Freerunning, Madness, MTMtE, // More Than Meets the Eye (Transformers Universes Beyond) Mutate, diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 0d05b5d116f..744adafe626 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -1549,6 +1549,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit return isAlternativeCost(AlternativeCost.Evoke); } + public final boolean isFreerunning() { + return isAlternativeCost(AlternativeCost.Freerunning); + } + public final boolean isMadness() { return isAlternativeCost(AlternativeCost.Madness); } diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java index 9a2e75566a3..a1c2876bb62 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java @@ -444,6 +444,11 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { return false; } } + if (sa.isFreerunning()) { + if (!activator.hasFreerunning()) { + return false; + } + } if (this.getIsPresent() != null) { FCollection list; if (getPresentDefined() != null) { diff --git a/forge-gui/res/cardsfolder/upcoming/achilles_davenport.txt b/forge-gui/res/cardsfolder/upcoming/achilles_davenport.txt new file mode 100644 index 00000000000..9fecde456df --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/achilles_davenport.txt @@ -0,0 +1,8 @@ +Name:Achilles Davenport +ManaCost:2 U B +Types:Legendary Creature Human Assassin +PT:3/3 +K:Freerunning:U B +K:Menace +S:Mode$ Continuous | Affected$ Assassin.Other+YouCtrl | AddPower$ 1 | AddToughness$ 1 | Description$ Other Assassins you control get +1/+1. +Oracle:Freerunning {U}{B} (You may cast this spell for its freerunning cost if you dealt combat damage to a player this turn with an Assassin or commander.)\nMenace\nOther Assassins you control get +1/+1.