diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 16c872b967e..ff7fee3cea0 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -2781,6 +2781,22 @@ public static int xCount(Card c, final String s, final CardTraitBase ctb) { someCards = CardUtil.getLastTurnCast(validFilter, c, ctb, player); } } + + // Count$DifferentManaValuesAmongSpellsAndLandsThisTurn -- distinct mana values among cards matching + // cast this turn, combined with lands you've played this turn. Built for the Coststorm keyword. + if (sq[0].startsWith("DifferentManaValuesAmongSpellsAndLandsThisTurn")) { + final String[] workingCopy = paidparts[0].split("_"); + final String validFilter = workingCopy[1]; + final Set manaValues = Sets.newHashSet(); + for (final Card castCard : CardUtil.getThisTurnCast(validFilter, c, ctb, player)) { + manaValues.add(castCard.getCMC()); + } + for (final Card landCard : player.getLandsPlayedThisTurnCards()) { + manaValues.add(landCard.getCMC()); + } + return doXMath(manaValues.size(), expr, c, ctb); + } + if (sq[0].startsWith("ThisTurnActivated")) { final String[] workingCopy = paidparts[0].split("_"); final String validFilter = workingCopy[1]; 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 63dbe17256c..78e466999fc 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -3266,6 +3266,16 @@ private StringBuilder abilityTextInstantSorcery(CardState state) { sbAfter.append(" You may choose new targets for the copies."); } + sbAfter.append(")"); + sbAfter.append("\r\n"); + } else if (keyword.equals("Coststorm")) { + sbAfter.append("Coststorm ("); + sbAfter.append("When you cast this spell, copy it for each different mana value among other spells and lands you've played this turn."); + + if (strSpell.contains("Target") || strSpell.contains("target")) { + sbAfter.append(" You may choose new targets for the copies."); + } + sbAfter.append(")"); sbAfter.append("\r\n"); } else if (keyword.startsWith("Replicate")) { 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 02740d7007f..7a73b8b7cd0 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -1181,6 +1181,20 @@ public void resolve() { trigger.setOverridingAbility(copySa); inst.addTrigger(trigger); + } else if (keyword.equals("Coststorm")) { + final String actualTrigger = "Mode$ SpellCast | ValidCard$ Card.Self | TriggerZones$ Stack | Secondary$ True" + + "| TriggerDescription$ Coststorm (" + inst.getReminderText() + ")"; + + String effect = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ CoststormCount | MayChooseTarget$ True"; + + final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, card, intrinsic); + + final SpellAbility sa = AbilityFactory.getAbility(effect, card); + sa.setSVar("CoststormCount", "Count$DifferentManaValuesAmongSpellsAndLandsThisTurn_Card.YouCtrl+!CastSaSource"); + + parsedTrigger.setOverridingAbility(sa); + + inst.addTrigger(parsedTrigger); } else if (keyword.startsWith("Haunt")) { final String[] k = keyword.split(":"); final String hauntSVarName = k[1]; 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 646f3131b54..237a30c6d0d 100644 --- a/forge-game/src/main/java/forge/game/keyword/Keyword.java +++ b/forge-game/src/main/java/forge/game/keyword/Keyword.java @@ -40,6 +40,7 @@ public enum Keyword { COMPLEATED("Compleated", Compleated.class, true, "This planeswalker enters with two fewer loyalty counters for each Phyrexian mana symbol life was paid for."), CONSPIRE("Conspire", SimpleKeyword.class, false, "As an additional cost to cast this spell, you may tap two untapped creatures you control that each share a color with it. If you do, copy it."), CONVOKE("Convoke", SimpleKeyword.class, true, "Your creatures can help cast this spell. Each creature you tap while playing this spell reduces its cost by {1} or by one mana of that creature's color."), + COSTSTORM("Coststorm", SimpleKeyword.class, false, "When you cast this spell, copy it for each different mana value among other spells and lands you've played this turn."), CRAFT("Craft", Craft.class, false, "%s, Exile this artifact, %s: Return this card transformed under its owner's control. Craft only as a sorcery."), CREW("Crew", KeywordWithAmount.class, false, "Tap any number of creatures you control with total power %1$d or more: This Vehicle becomes an artifact creature until end of turn."), CUMULATIVE_UPKEEP("Cumulative upkeep", KeywordWithCost.class, false, "At the beginning of your upkeep, put an age counter on this permanent, then sacrifice it unless you pay its upkeep cost for each age counter on it."), 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 8ff89446517..57de823147d 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -100,6 +100,7 @@ public class Player extends GameEntity implements Comparable { private int numForetoldThisTurn; private int landsPlayedThisTurn; private int landsPlayedLastTurn; + private final CardCollection landsPlayedThisTurnCards = new CardCollection(); //Used for Coststorm. Needed because a land's mana value isn't always 0 (Glade of the Pump Spells) private int numPowerSurgeLands; private int spellsCastThisGame; private int spellsCastLastTurn; @@ -1651,6 +1652,7 @@ public final Card playLand(final Card land, SpellAbility cause) { game.getStack().unfreezeStack(); addLandPlayedThisTurn(); + landsPlayedThisTurnCards.add(c); // play a sound game.fireEvent(new GameEventLandPlayed(PlayerView.get(this), CardView.get(c))); @@ -2235,6 +2237,9 @@ public final int getLandsPlayedThisTurn() { public final int getLandsPlayedLastTurn() { return landsPlayedLastTurn; } + public final List getLandsPlayedThisTurnCards() { + return landsPlayedThisTurnCards; + } public final void addLandPlayedThisTurn() { landsPlayedThisTurn++; achievementTracker.landsPlayed++; @@ -2479,6 +2484,7 @@ public void onCleanupPhase() { setTappedLandForManaThisTurn(false); setLandsPlayedLastTurn(getLandsPlayedThisTurn()); resetLandsPlayedThisTurn(); + landsPlayedThisTurnCards.clear(); resetInvestigatedThisTurn(); resetSurveilThisTurn(); resetDiscardedThisTurn(); diff --git a/forge-gui/res/cardsfolder/f/friarball.txt b/forge-gui/res/cardsfolder/f/friarball.txt new file mode 100644 index 00000000000..b666b852d4a --- /dev/null +++ b/forge-gui/res/cardsfolder/f/friarball.txt @@ -0,0 +1,6 @@ +Name:Friarball +ManaCost:3 W +Types:Sorcery +K:Coststorm +A:SP$ Token | TokenScript$ w_2_2_monk | TokenOwner$ You | SpellDescription$ Create a 2/2 white Monk creature token. +Oracle:Create a 2/2 white Monk creature token.\nCoststorm (When you cast this spell, copy it for each different mana value among other spells and lands you've played this turn.) diff --git a/forge-gui/res/tokenscripts/w_2_2_monk.txt b/forge-gui/res/tokenscripts/w_2_2_monk.txt new file mode 100644 index 00000000000..0795496e00c --- /dev/null +++ b/forge-gui/res/tokenscripts/w_2_2_monk.txt @@ -0,0 +1,6 @@ +Name:Monk Token +ManaCost:no cost +Colors:white +Types:Creature Monk +PT:2/2 +Oracle: