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();
}
// intensity is perpetual
if (c.hasIntensity()) {
copied.setIntensity(c.getIntensity(false));
}
// update state for view
copied.updateStateForView();

View File

@@ -2066,6 +2066,10 @@ public class AbilityUtils {
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")) {
// CardCounters.ALL to be used for Kinsbaile Borderguard and anything that cares about all counters
int count = 0;

View File

@@ -96,6 +96,7 @@ public enum ApiType {
Goad (GoadEffect.class),
Haunt (HauntEffect.class),
Investigate (InvestigateEffect.class),
Intensify (IntensifyEffect.class),
ImmediateTrigger (ImmediateTriggerEffect.class),
Learn (LearnEffect.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);
for (Card c : newLibrary) {
if (c.getIntensity(false) > 0) {
c.setIntensity(0);
}
action.moveToLibrary(c, 0, sa);
}
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")) {
final String[] k = keyword.split(":");
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")) {
sb.append("\r\nHaunt (");
if (isCreature()) {
@@ -2541,6 +2543,8 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
} else if (keyword.startsWith("Dredge")) {
sbAfter.append(TextUtil.fastReplace(keyword, ":", " ")).append(" (").append(inst.getReminderText()).append(")");
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")
|| keyword.startsWith("Prowl")) {
final String[] k = keyword.split(":");
@@ -4081,6 +4085,23 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
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;
public final void addMultiKickerMagnitude(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());
}
public int getIntensity() {
return get (TrackableProperty.Intensity);
}
void updateIntensity(Card c) {
set(TrackableProperty.Intensity, c.getIntensity(true));
}
public boolean wasDestroyed() {
if (get(TrackableProperty.WasDestroyed) == null)
return false;
@@ -867,6 +874,10 @@ public class CardView extends GameEntityView {
updateZoneText(c);
updateDamage(c);
if (c.getIntensity(false) > 0) {
updateIntensity(c);
}
if (getBackup() == null && !c.isFaceDown() && (c.hasBackSide()||c.isFlipCard()||c.isAdventureCard())) {
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."),
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."),
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."),
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."),

View File

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