mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
Y22/J21: Implement Intensity mechanic
This commit is contained in:
committed by
Michael Kamensky
parent
352649b0a8
commit
a280a46ffd
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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());
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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."),
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
8
forge-gui/res/cardsfolder/s/static_discharge.txt
Normal file
8
forge-gui/res/cardsfolder/s/static_discharge.txt
Normal 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.
|
||||||
11
forge-gui/res/cardsfolder/upcoming/bellowsbreath_ogre.txt
Normal file
11
forge-gui/res/cardsfolder/upcoming/bellowsbreath_ogre.txt
Normal 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.
|
||||||
11
forge-gui/res/cardsfolder/upcoming/runaway_growth.txt
Normal file
11
forge-gui/res/cardsfolder/upcoming/runaway_growth.txt
Normal 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.
|
||||||
@@ -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()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user