Keyword: Spree (#4815)

* Keyword: Spree

---------

Co-authored-by: tool4EvEr <tool4EvEr@192.168.0.59>
This commit is contained in:
Hans Mackowiak
2024-03-13 09:39:14 +01:00
committed by GitHub
parent 9c2986e3c4
commit 25a620c6cd
6 changed files with 45 additions and 16 deletions

View File

@@ -8,6 +8,7 @@ import com.google.common.collect.Lists;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.cost.Cost;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.AbilitySub; import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -83,11 +84,13 @@ public class CharmEffect extends SpellAbilityEffect {
boolean limit = sa.hasParam("ActivationLimit"); boolean limit = sa.hasParam("ActivationLimit");
boolean gameLimit = sa.hasParam("GameActivationLimit"); boolean gameLimit = sa.hasParam("GameActivationLimit");
boolean oppChooses = "Opponent".equals(sa.getParam("Chooser")); boolean oppChooses = "Opponent".equals(sa.getParam("Chooser"));
boolean spree = sa.hasParam("Spree");
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(sa.getCostDescription()); sb.append(sa.getCostDescription());
sb.append(oppChooses ? "An opponent chooses " : "Choose ");
if (!spree) {
sb.append(oppChooses ? "An opponent chooses " : "Choose ");
if (isX) { if (isX) {
sb.append("X"); sb.append("X");
} else if (num == min || num == Integer.MAX_VALUE) { } else if (num == min || num == Integer.MAX_VALUE) {
@@ -99,6 +102,7 @@ public class CharmEffect extends SpellAbilityEffect {
} else { } else {
sb.append(Lang.getNumeral(min)).append(" or ").append(list.size() == 2 ? "both" : "more"); sb.append(Lang.getNumeral(min)).append(" or ").append(list.size() == 2 ? "both" : "more");
} }
}
if (sa.hasParam("ChoiceRestriction")) { if (sa.hasParam("ChoiceRestriction")) {
String rest = sa.getParam("ChoiceRestriction"); String rest = sa.getParam("ChoiceRestriction");
@@ -148,12 +152,14 @@ public class CharmEffect extends SpellAbilityEffect {
if (!includeChosen) { if (!includeChosen) {
sb.append(num == 1 ? " mode." : " modes."); sb.append(num == 1 ? " mode." : " modes.");
} else if (!list.isEmpty()) { } else if (!list.isEmpty()) {
if (!spree) {
if (!repeat && !additionalDesc && !limit && !gameLimit) { if (!repeat && !additionalDesc && !limit && !gameLimit) {
sb.append(" \u2014"); sb.append(" \u2014");
} }
sb.append("\r\n"); sb.append("\r\n");
}
for (AbilitySub sub : list) { for (AbilitySub sub : list) {
sb.append("\u2022 ").append(sub.getParam("SpellDescription")); sb.append(spree ? "+" + new Cost(sub.getParam("SpreeCost"), false).toSimpleString() + " \u2014" : "\u2022 ").append(sub.getParam("SpellDescription"));
sb.append("\r\n"); sb.append("\r\n");
} }
sb.append("\r\n"); sb.append("\r\n");

View File

@@ -2929,7 +2929,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|| keyword.equals("Improvise") || keyword.equals("Retrace") || keyword.equals("Improvise") || keyword.equals("Retrace")
|| keyword.equals("Undaunted") || keyword.equals("Cascade") || keyword.equals("Undaunted") || keyword.equals("Cascade")
|| keyword.equals("Devoid") || keyword.equals("Lifelink") || keyword.equals("Devoid") || keyword.equals("Lifelink")
|| keyword.equals("Bargain") || keyword.equals("Bargain")|| keyword.equals("Spree")
|| keyword.equals("Split second")) { || keyword.equals("Split second")) {
sbBefore.append(keyword).append(" (").append(inst.getReminderText()).append(")"); sbBefore.append(keyword).append(" (").append(inst.getReminderText()).append(")");
sbBefore.append("\r\n\r\n"); sbBefore.append("\r\n\r\n");

View File

@@ -3893,6 +3893,10 @@ public class CardFactoryUtil {
StaticAbility st = StaticAbility.create(effect, state.getCard(), state, intrinsic); StaticAbility st = StaticAbility.create(effect, state.getCard(), state, intrinsic);
st.setSVar("X", "Count$CardPower"); st.setSVar("X", "Count$CardPower");
inst.addStaticAbility(st); inst.addStaticAbility(st);
} else if (keyword.equals("Spree")) {
String effect = "Mode$ RaiseCost | ValidCard$ Card.Self | Type$ Spell | Secondary$ True | Amount$ Spree | EffectZone$ All"
+ " | Description$ Spree (" + inst.getReminderText() + ")";
inst.addStaticAbility(StaticAbility.create(effect, state.getCard(), state, intrinsic));
} else if (keyword.startsWith("Strive")) { } else if (keyword.startsWith("Strive")) {
final String[] k = keyword.split(":"); final String[] k = keyword.split(":");
final String manacost = k[1]; final String manacost = k[1];

View File

@@ -147,6 +147,15 @@ public class CostAdjustment {
count += tc.size(); count += tc.size();
} }
--count; --count;
} else if ("Spree".equals(amount)) {
SpellAbility sub = sa;
while (sub != null) {
if (sub.hasParam("SpreeCost")) {
Cost part = new Cost(sub.getParam("SpreeCost"), sa.isAbility(), sa.getHostCard().equals(hostCard));
cost.mergeTo(part, count, sa);
}
sub = sub.getSubAbility();
}
} else { } else {
if (StringUtils.isNumeric(amount)) { if (StringUtils.isNumeric(amount)) {
count = Integer.parseInt(amount); count = Integer.parseInt(amount);

View File

@@ -170,6 +170,7 @@ public enum Keyword {
SPECTACLE("Spectacle", KeywordWithCost.class, false, "You may cast this spell for its spectacle cost rather than its mana cost if an opponent lost life this turn."), SPECTACLE("Spectacle", KeywordWithCost.class, false, "You may cast this spell for its spectacle cost rather than its mana cost if an opponent lost life this turn."),
SPLICE("Splice", KeywordWithCostAndType.class, false, "As you cast an %2$s spell, you may reveal this card from your hand and pay its splice cost. If you do, add this card's effects to that spell."), SPLICE("Splice", KeywordWithCostAndType.class, false, "As you cast an %2$s spell, you may reveal this card from your hand and pay its splice cost. If you do, add this card's effects to that spell."),
SPLIT_SECOND("Split second", SimpleKeyword.class, true, "As long as this spell is on the stack, players can't cast other spells or activate abilities that aren't mana abilities."), SPLIT_SECOND("Split second", SimpleKeyword.class, true, "As long as this spell is on the stack, players can't cast other spells or activate abilities that aren't mana abilities."),
SPREE("Spree", SimpleKeyword.class, true, "Choose one or more additional costs."),
SQUAD("Squad", KeywordWithCost.class, false, "As an additional cost to cast this spell, you may pay %s any number of times. When this creature enters the battlefield, create that many tokens that are copies of it."), SQUAD("Squad", KeywordWithCost.class, false, "As an additional cost to cast this spell, you may pay %s any number of times. When this creature enters the battlefield, create that many tokens that are copies of it."),
STARTING_INTENSITY("Starting intensity", KeywordWithAmount.class, true, null), STARTING_INTENSITY("Starting intensity", KeywordWithAmount.class, true, null),
STORM("Storm", SimpleKeyword.class, false, "When you cast this spell, copy it for each other spell that was cast before it this turn. You may choose new targets for the copies."), STORM("Storm", SimpleKeyword.class, false, "When you cast this spell, copy it for each other spell that was cast before it this turn. You may choose new targets for the copies."),

View File

@@ -0,0 +1,9 @@
Name:Shifting Grift
ManaCost:U U
Types:Sorcery
K:Spree
A:SP$ Charm | Choices$ DBCreature,DBArtifact,DBEnchantment | MinCharmNum$ 1 | CharmNum$ 3 | Spree$ True
SVar:DBCreature:DB$ ExchangeControl | SpreeCost$ 2 | ValidTgts$ Creature | TgtPrompt$ Select target creature | TargetMin$ 2 | TargetMax$ 2 | SpellDescription$ Exchange control of two target creatures
SVar:DBArtifact:DB$ ExchangeControl | SpreeCost$ 1 | ValidTgts$ Artifact | TgtPrompt$ Select target artifact | TargetMin$ 2 | TargetMax$ 2 | SpellDescription$ Exchange control of two target artifacts
SVar:DBEnchantment:DB$ ExchangeControl | SpreeCost$ 1 | ValidTgts$ Enchantment | TgtPrompt$ Select target enchantment | TargetMin$ 2 | TargetMax$ 2 | SpellDescription$ Exchange control of two target enchantments
Oracle:Spree (Choose one or more additional costs.)\n+{2} —Exchange control of two target creatures\n+{1} —Exchange control of two target artifacts\n+{1} —Exchange control of two target enchantments