Y22/J21: Implement Intensity mechanic

This commit is contained in:
Tim Mocny
2022-03-18 10:43:06 +00:00
committed by Michael Kamensky
parent 352649b0a8
commit a280a46ffd
13 changed files with 129 additions and 0 deletions

View File

@@ -565,6 +565,11 @@ public class GameAction {
copied.clearEtbCounters(); copied.clearEtbCounters();
} }
// intensity is perpetual
if (c.hasIntensity()) {
copied.setIntensity(c.getIntensity(false));
}
// update state for view // update state for view
copied.updateStateForView(); copied.updateStateForView();

View File

@@ -2066,6 +2066,10 @@ public class AbilityUtils {
return doXMath(c.getDamageHistory().getCreatureAttacksThisTurn(), expr, c, ctb); return doXMath(c.getDamageHistory().getCreatureAttacksThisTurn(), expr, c, ctb);
} }
if (sq[0].contains("Intensity")) {
return doXMath(c.getIntensity(true), expr, c, ctb);
}
if (sq[0].contains("CardCounters")) { if (sq[0].contains("CardCounters")) {
// CardCounters.ALL to be used for Kinsbaile Borderguard and anything that cares about all counters // CardCounters.ALL to be used for Kinsbaile Borderguard and anything that cares about all counters
int count = 0; int count = 0;

View File

@@ -96,6 +96,7 @@ public enum ApiType {
Goad (GoadEffect.class), Goad (GoadEffect.class),
Haunt (HauntEffect.class), Haunt (HauntEffect.class),
Investigate (InvestigateEffect.class), Investigate (InvestigateEffect.class),
Intensify (IntensifyEffect.class),
ImmediateTrigger (ImmediateTriggerEffect.class), ImmediateTrigger (ImmediateTriggerEffect.class),
Learn (LearnEffect.class), Learn (LearnEffect.class),
LookAt (LookAtEffect.class), LookAt (LookAtEffect.class),

View File

@@ -0,0 +1,44 @@
package forge.game.ability.effects;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.spellability.SpellAbility;
import forge.util.Lang;
public class IntensifyEffect extends SpellAbilityEffect {
@Override
protected String getStackDescription(SpellAbility sa) {
final StringBuilder sb = new StringBuilder();
String these = sa.hasParam("DefinedDesc") ? sa.getParam("DefinedDesc") :
Lang.joinHomogenous(getDefinedCardsOrTargeted(sa));
final int amount = AbilityUtils.calculateAmount(sa.getHostCard(),
sa.getParamOrDefault("Amount", "1"), sa);
sb.append(sa.getActivatingPlayer()).append(" perpetually increases the intensity of ").append(these);
sb.append(" by ").append(amount).append(".");
return sb.toString();
}
@Override
public void resolve(SpellAbility sa) {
final Card host = sa.getHostCard();
final int amount = AbilityUtils.calculateAmount(sa.getHostCard(),
sa.getParamOrDefault("Amount", "1"), sa);
CardCollectionView toIntensify;
if (sa.hasParam("AllDefined")) {
toIntensify = CardLists.getValidCards(host.getGame().getCardsInGame(), sa.getParam("AllDefined"),
sa.getActivatingPlayer(), host, sa);
} else {
toIntensify = getDefinedCardsOrTargeted(sa);
}
for (final Card tgtC : toIntensify) {
tgtC.addIntensity(amount);
}
}
}

View File

@@ -91,6 +91,9 @@ public class RestartGameEffect extends SpellAbilityEffect {
p.getZone(ZoneType.Command).removeAllCards(true); p.getZone(ZoneType.Command).removeAllCards(true);
for (Card c : newLibrary) { for (Card c : newLibrary) {
if (c.getIntensity(false) > 0) {
c.setIntensity(0);
}
action.moveToLibrary(c, 0, sa); action.moveToLibrary(c, 0, sa);
} }
p.initVariantsZones(p.getRegisteredPlayer()); p.initVariantsZones(p.getRegisteredPlayer());

View File

@@ -2090,6 +2090,8 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|| keyword.startsWith("Renown") || keyword.startsWith("Annihilator") || keyword.startsWith("Devour")) { || keyword.startsWith("Renown") || keyword.startsWith("Annihilator") || keyword.startsWith("Devour")) {
final String[] k = keyword.split(":"); final String[] k = keyword.split(":");
sbLong.append(k[0]).append(" ").append(k[1]).append(" (").append(inst.getReminderText()).append(")"); sbLong.append(k[0]).append(" ").append(k[1]).append(" (").append(inst.getReminderText()).append(")");
} else if (keyword.startsWith("Starting intensity")) {
sbLong.append(TextUtil.fastReplace(keyword, ":", " "));
} else if (keyword.contains("Haunt")) { } else if (keyword.contains("Haunt")) {
sb.append("\r\nHaunt ("); sb.append("\r\nHaunt (");
if (isCreature()) { if (isCreature()) {
@@ -2541,6 +2543,8 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
} else if (keyword.startsWith("Dredge")) { } else if (keyword.startsWith("Dredge")) {
sbAfter.append(TextUtil.fastReplace(keyword, ":", " ")).append(" (").append(inst.getReminderText()).append(")"); sbAfter.append(TextUtil.fastReplace(keyword, ":", " ")).append(" (").append(inst.getReminderText()).append(")");
sbAfter.append("\r\n"); sbAfter.append("\r\n");
} else if (keyword.startsWith("Starting intensity")) {
sbAfter.append(TextUtil.fastReplace(keyword, ":", " ")).append("\r\n");
} else if (keyword.startsWith("Escalate") || keyword.startsWith("Buyback") } else if (keyword.startsWith("Escalate") || keyword.startsWith("Buyback")
|| keyword.startsWith("Prowl")) { || keyword.startsWith("Prowl")) {
final String[] k = keyword.split(":"); final String[] k = keyword.split(":");
@@ -4081,6 +4085,23 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
return getNetCombatDamageBreakdown().getTotal(); return getNetCombatDamageBreakdown().getTotal();
} }
private int intensity = 0;
public final void addIntensity(final int n) {
intensity = intensity + n;
view.updateIntensity(this);
}
public final int getIntensity(boolean total) {
if (total && hasKeyword(Keyword.STARTING_INTENSITY)) {
return getKeywordMagnitude(Keyword.STARTING_INTENSITY) + intensity;
} else {
return intensity;
}
}
public final void setIntensity(final int n) { intensity = n; }
public final boolean hasIntensity() {
return intensity > 0;
}
private int multiKickerMagnitude = 0; private int multiKickerMagnitude = 0;
public final void addMultiKickerMagnitude(final int n) { multiKickerMagnitude += n; } public final void addMultiKickerMagnitude(final int n) { multiKickerMagnitude += n; }
public final void setKickerMagnitude(final int n) { multiKickerMagnitude = n; } public final void setKickerMagnitude(final int n) { multiKickerMagnitude = n; }

View File

@@ -415,6 +415,13 @@ public class CardView extends GameEntityView {
set(TrackableProperty.CurrentRoom, c.getCurrentRoom()); set(TrackableProperty.CurrentRoom, c.getCurrentRoom());
} }
public int getIntensity() {
return get (TrackableProperty.Intensity);
}
void updateIntensity(Card c) {
set(TrackableProperty.Intensity, c.getIntensity(true));
}
public boolean wasDestroyed() { public boolean wasDestroyed() {
if (get(TrackableProperty.WasDestroyed) == null) if (get(TrackableProperty.WasDestroyed) == null)
return false; return false;
@@ -867,6 +874,10 @@ public class CardView extends GameEntityView {
updateZoneText(c); updateZoneText(c);
updateDamage(c); updateDamage(c);
if (c.getIntensity(false) > 0) {
updateIntensity(c);
}
if (getBackup() == null && !c.isFaceDown() && (c.hasBackSide()||c.isFlipCard()||c.isAdventureCard())) { if (getBackup() == null && !c.isFaceDown() && (c.hasBackSide()||c.isFlipCard()||c.isAdventureCard())) {
set(TrackableProperty.PaperCardBackup, c.getPaperCard()); set(TrackableProperty.PaperCardBackup, c.getPaperCard());
} }

View File

@@ -153,6 +153,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."),
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."),
STRIVE("Strive", KeywordWithCost.class, false, "CARDNAME costs %s more to cast for each target beyond the first."), STRIVE("Strive", KeywordWithCost.class, false, "CARDNAME costs %s more to cast for each target beyond the first."),
SUNBURST("Sunburst", SimpleKeyword.class, false, "This enters the battlefield with either a +1/+1 or charge counter on it for each color of mana spent to cast it based on whether it's a creature."), SUNBURST("Sunburst", SimpleKeyword.class, false, "This enters the battlefield with either a +1/+1 or charge counter on it for each color of mana spent to cast it based on whether it's a creature."),

View File

@@ -68,6 +68,7 @@ public enum TrackableProperty {
ChosenMode(TrackableTypes.StringType), ChosenMode(TrackableTypes.StringType),
ClassLevel(TrackableTypes.IntegerType), ClassLevel(TrackableTypes.IntegerType),
CurrentRoom(TrackableTypes.StringType), CurrentRoom(TrackableTypes.StringType),
Intensity(TrackableTypes.IntegerType),
Remembered(TrackableTypes.StringType), Remembered(TrackableTypes.StringType),
NamedCard(TrackableTypes.StringType), NamedCard(TrackableTypes.StringType),
NamedCard2(TrackableTypes.StringType), NamedCard2(TrackableTypes.StringType),

View File

@@ -0,0 +1,8 @@
Name:Static Discharge
ManaCost:1 R
Types:Sorcery
K:Starting intensity:3
A:SP$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | SubAbility$ DBIntensify | SpellDescription$ CARDNAME deals damage equal to its intensity to any target, then perpetually increase the intensity of all cards you own named Static Discharge by 1.
SVar:DBIntensify:DB$ Intensify | AllDefined$ Card.YouOwn+namedStatic Discharge | DefinedDesc$ all cards they own named Static Discharge
SVar:X:Count$Intensity
Oracle:Starting intensity 3\nStatic Discharge deals damage equal to its intensity to any target, then perpetually increase the intensity of all cards you own named Static Discharge by 1.

View File

@@ -0,0 +1,11 @@
Name:Bellowsbreath Ogre
ManaCost:2 R
Types:Artifact Creature Ogre Shaman
PT:3/3
K:Starting intensity:1
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigDamage | TriggerDescription$ Whenever CARDNAME attacks, it deals damage equal to its intensity to any target, then perpetually increase its intensity by 1.
SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | SubAbility$ DBIntensify
SVar:DBIntensify:DB$ Intensify
SVar:X:Count$Intensity
SVar:HasAttackEffect:TRUE
Oracle:Starting intensity 1\nWhenever Bellowsbreath Ogre attacks, it deals damage equal to its intensity to any target, then perpetually increase its intensity by 1.

View File

@@ -0,0 +1,11 @@
Name:Runaway Growth
ManaCost:3 G
Types:Enchantment Aura
K:Starting intensity:1
K:Enchant land
A:SP$ Attach | ValidTgts$ Land | TgtPrompt$ Select target land | AILogic$ Pump
T:Mode$ TapsForMana | ValidCard$ Card.EnchantedBy | TriggerZones$ Battlefield | Execute$ TrigMana | TriggerDescription$ Whenever enchanted land is tapped for mana, its controller adds an additional amount of {G} equal to CARDNAME's intensity, then perpetually increase its intensity by 1.
SVar:TrigMana:DB$ Mana | Produced$ G | Amount$ X | Defined$ TriggeredCardController | SubAbility$ DBIntensify
SVar:DBIntensify:DB$ Intensify
SVar:X:Count$Intensity
Oracle:Starting intensity 1\nEnchant land\nWhenever enchanted land is tapped for mana, its controller adds an additional amount of {G} equal to Runaway Growth's intensity, then perpetually increase its intensity by 1.

View File

@@ -349,6 +349,14 @@ public class CardDetailUtil {
} }
} }
final int intensity = card.getIntensity();
if (intensity > 0) {
if (area.length() != 0) {
area.append("\n");
}
area.append("Intensity: ").append(intensity);
}
// counter text // counter text
if (card.getCounters() != null) { if (card.getCounters() != null) {
for (final Entry<CounterType, Integer> c : card.getCounters().entrySet()) { for (final Entry<CounterType, Integer> c : card.getCounters().entrySet()) {