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 78d32d576f7..539125293db 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -2170,6 +2170,9 @@ public class CardFactoryUtil { else if (keyword.startsWith("Awaken")) { card.addSpellAbility(makeAwakenSpell(card, keyword)); } + else if (keyword.startsWith("Surge")) { + card.addSpellAbility(makeSurgeSpell(card, keyword)); + } else if (keyword.startsWith("Monstrosity")) { final String[] k = keyword.split(":"); final String magnitude = k[0].substring(12); @@ -3167,6 +3170,32 @@ public class CardFactoryUtil { return awakenSpell; } + /** + * make Surge keyword + * @param card + * @param surgeKeyword + * @return + */ + private static SpellAbility makeSurgeSpell(final Card card, final String surgeKeyword) { + final String[] k = surgeKeyword.split(":"); + final Cost surgeCost = new Cost(k[1], false); + card.removeIntrinsicKeyword(surgeKeyword); + final SpellAbility surgeSpell = card.getFirstSpellAbility().copy(); + + surgeSpell.setPayCosts(surgeCost); + surgeSpell.setBasicSpell(false); + surgeSpell.addOptionalCost(OptionalCost.Surge); + + final SpellAbilityRestriction restriction = new SpellAbilityRestriction(); + restriction.setVariables(card.getFirstSpellAbility().getRestrictions()); + restriction.setSurge(true); + surgeSpell.setRestrictions(restriction); + String desc = "Surge " + surgeCost.toSimpleString() + " (You may cast this spell for its " + + "surge cost if you or a teammate has cast another spell this turn.)"; + surgeSpell.setDescription(desc); + return surgeSpell; + } + /** *

* hasKeyword. 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 b3c354c01e1..61f39558d36 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -60,7 +60,7 @@ public final class CardUtil { "Transmute", "Replicate", "Recover", "Suspend", "Aura swap", "Fortify", "Transfigure", "Champion", "Evoke", "Prowl", "Reinforce", "Unearth", "Level up", "Miracle", "Overload", - "Scavenge", "Bestow", "Outlast", "Dash", "Renown").build(); + "Scavenge", "Bestow", "Outlast", "Dash", "Renown", "Surge").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/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index d9ca1dd1f4e..e0c6e9d2fab 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -1867,6 +1867,12 @@ public class Player extends GameEntity implements Comparable { return blood; } + public final boolean hasSurge() { + FCollection list = getAllies(); + list.add(this); + return !CardLists.filterControlledBy(game.getStack().getSpellsCastThisTurn(), list).isEmpty(); + } + public final boolean hasProwl(final String type) { if (prowl.contains("AllCreatureTypes")) { return true; diff --git a/forge-game/src/main/java/forge/game/spellability/OptionalCost.java b/forge-game/src/main/java/forge/game/spellability/OptionalCost.java index 0c274373fbd..604f1b5e703 100644 --- a/forge-game/src/main/java/forge/game/spellability/OptionalCost.java +++ b/forge-game/src/main/java/forge/game/spellability/OptionalCost.java @@ -9,7 +9,8 @@ public enum OptionalCost { Buyback, Entwine, Kicker1, - Kicker2, + Kicker2, + Surge, AltCost, // used by prowl Generic, // used by "Dragon Presence" and pseudo-kicker cards } 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 3f51f16a431..023cf0049e3 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -417,6 +417,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit return isOptionalCostPaid(OptionalCost.Kicker1) || isOptionalCostPaid(OptionalCost.Kicker2); } + public boolean isSurged() { + return isOptionalCostPaid(OptionalCost.Surge); + } + public boolean isOptionalCostPaid(OptionalCost cost) { SpellAbility saRoot = getRootAbility(); return saRoot.optionalCosts.contains(cost); diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java index 14ed36c367c..84eae6a79b1 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java @@ -95,7 +95,10 @@ public class SpellAbilityCondition extends SpellAbilityVariables { } if (value.equals("Kicked 2")) { this.kicked2 = true; - } + } + if (value.equals("Surge")) { + this.surgeCostPaid = true; + } if (value.equals("AllTargetsLegal")) { this.setAllTargetsLegal(true); } @@ -223,6 +226,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables { if (this.kicked1 && !sa.isOptionalCostPaid(OptionalCost.Kicker1)) return false; if (this.kicked2 && !sa.isOptionalCostPaid(OptionalCost.Kicker2)) return false; if (this.altCostPaid && !sa.isOptionalCostPaid(OptionalCost.AltCost)) return false; + if (this.surgeCostPaid && !sa.isSurged()) return false; if (this.optionalCostPaid && this.optionalBoolean && !sa.isOptionalCostPaid(OptionalCost.Generic)) return false; if (this.optionalCostPaid && !this.optionalBoolean && sa.isOptionalCostPaid(OptionalCost.Generic)) return false; 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 0886f1ac989..114dd8c2ee7 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java @@ -332,6 +332,11 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { return false; } } + if (this.isSurge()) { + if (!activator.hasSurge()) { + return false; + } + } if (this.getProwlTypes() != null && !this.getProwlTypes().isEmpty()) { // only true if the activating player has damaged the opponent with // one of the specified types diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java index 65d2e12ab7e..6e2c1dd8db5 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java @@ -70,6 +70,7 @@ public class SpellAbilityVariables { this.cardsInHand = sav.getCardsInHand(); this.chosenColors = sav.getColorToCheck(); this.threshold = sav.isThreshold(); + this.surge = sav.isSurge(); this.metalcraft = sav.isThreshold(); this.hellbent = sav.isHellbent(); this.allTargetsLegal = sav.isAllTargetsLegal(); @@ -153,6 +154,9 @@ public class SpellAbilityVariables { /** The hellbent. */ private boolean hellbent = false; + /** The surge. */ + private boolean surge = false; + private boolean allTargetsLegal = false; /** The prowl. */ @@ -486,6 +490,18 @@ public class SpellAbilityVariables { this.metalcraft = bMetalcraft; } + /** + *

+ * Setter for the field surge. + *

+ * + * @param bSurge + * a boolean. + */ + public final void setSurge(final boolean bSurge) { + this.surge = bSurge; + } + /** Optional Costs */ protected boolean kicked = false; protected boolean kicked1 = false; // http://magiccards.info/query?q=o%3A%22kicker%22+not+o%3A%22multikicker%22+o%3A%22and%2For+{%22 @@ -494,6 +510,7 @@ public class SpellAbilityVariables { protected boolean optionalCostPaid = false; // Undergrowth other Pseudo-kickers protected boolean optionalBoolean = true; // Just in case you need to check if something wasn't kicked, etc protected boolean dragonPresence = false; + protected boolean surgeCostPaid = false; /** * @return the allTargetsLegal @@ -709,6 +726,15 @@ public class SpellAbilityVariables { return this.hellbent; } + /** + * Checks if is surge. + * + * @return the surge + */ + public final boolean isSurge() { + return this.surge; + } + public String getShareAllColors() { return shareAllColors; }