Skip to content

Commit

Permalink
Card: add Table for ChangedSVars (Card-Forge#426)
Browse files Browse the repository at this point in the history
* Card: add Table for ChangedSVars
Hanmac authored Jun 12, 2022
1 parent 783b58d commit c654234
Showing 60 changed files with 162 additions and 156 deletions.
4 changes: 2 additions & 2 deletions forge-ai/src/main/java/forge/ai/AiController.java
Original file line number Diff line number Diff line change
@@ -1925,8 +1925,8 @@ public int chooseNumber(SpellAbility sa, String title, int min, int max) {
return Math.min(player.getLife() -1,MyRandom.getRandom().nextInt(Math.max(player.getLife() / 3, player.getWeakestOpponent().getLife())) + 1);
} else if ("HighestGetCounter".equals(logic)) {
return MyRandom.getRandom().nextInt(3);
} else if (source.hasSVar("EnergyToPay")) {
return AbilityUtils.calculateAmount(source, source.getSVar("EnergyToPay"), sa);
} else if (sa.hasSVar("EnergyToPay")) {
return AbilityUtils.calculateAmount(source, sa.getSVar("EnergyToPay"), sa);
} else if ("Vermin".equals(logic)) {
return MyRandom.getRandom().nextInt(Math.max(player.getLife() - 5, 0));
} else if ("SweepCreatures".equals(logic)) {
10 changes: 6 additions & 4 deletions forge-ai/src/main/java/forge/ai/ability/AnimateAi.java
Original file line number Diff line number Diff line change
@@ -500,17 +500,19 @@ public static void becomeAnimated(final Card card, final boolean hasOriginalCard
}

// give sVars
if (sVars.size() > 0) {
for (final String s : sVars) {
String actualsVar = source.getSVar(s);
if (sa.hasParam("sVars")) {
Map<String, String> sVarsMap = Maps.newHashMap();
for (final String s : sa.getParam("sVars").split(",")) {
String actualsVar = AbilityUtils.getSVar(sa, s);
String name = s;
if (actualsVar.startsWith("SVar:")) {
actualsVar = actualsVar.split("SVar:")[1];
name = actualsVar.split(":")[0];
actualsVar = actualsVar.split(":")[1];
}
card.setSVar(name, actualsVar);
sVarsMap.put(name, actualsVar);
}
card.addChangedSVars(sVarsMap, timestamp, 0);
}
ComputerUtilCard.applyStaticContPT(game, card, null);
}
3 changes: 2 additions & 1 deletion forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java
Original file line number Diff line number Diff line change
@@ -53,6 +53,7 @@
public class DamageDealAi extends DamageAiBase {
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
final SpellAbility root = sa.getRootAbility();
final String damage = sa.getParam("NumDmg");
Card source = sa.getHostCard();
int dmg = AbilityUtils.calculateAmount(source, damage, sa);
@@ -76,7 +77,7 @@ public boolean chkAIDrawback(SpellAbility sa, Player ai) {
if (dmg > energy || dmg < 1) {
continue; // in case the calculation gets messed up somewhere
}
source.setSVar("EnergyToPay", "Number$" + dmg);
root.setSVar("EnergyToPay", "Number$" + dmg);
return true;
}
}
2 changes: 1 addition & 1 deletion forge-ai/src/main/java/forge/ai/ability/PumpAi.java
Original file line number Diff line number Diff line change
@@ -731,7 +731,7 @@ public boolean chkAIDrawback(SpellAbility sa, Player ai) {
if (minus > energy || minus < 1) {
continue; // in case the calculation gets messed up somewhere
}
source.setSVar("EnergyToPay", "Number$" + minus);
root.setSVar("EnergyToPay", "Number$" + minus);
return true;
}
}
11 changes: 2 additions & 9 deletions forge-game/src/main/java/forge/game/CardTraitBase.java
Original file line number Diff line number Diff line change
@@ -55,15 +55,13 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView,
/** Keys of descriptive (text) parameters. */
private static final ImmutableList<String> descriptiveKeys = ImmutableList.<String>builder()
.add("Description", "SpellDescription", "StackDescription", "TriggerDescription").build();
/** Keys to be followed as SVar names when changing text. */
private static final ImmutableList<String> mutableKeys = ImmutableList.<String>builder()
.add("AddAbility").build();

/**
* Keys that should not changed
*/
private static final ImmutableList<String> noChangeKeys = ImmutableList.<String>builder()
.add("TokenScript", "LegacyImage", "TokenImage", "NewName", "ChooseFromList").build();
.add("TokenScript", "LegacyImage", "TokenImage", "NewName", "ChooseFromList")
.add("AddAbility").build();

/**
* <p>
@@ -511,11 +509,6 @@ public void changeText() {
} else if (descriptiveKeys.contains(key)) {
// change descriptions differently
newValue = AbilityUtils.applyDescriptionTextChangeEffects(value, this);
} else if (mutableKeys.contains(key)) {
// follow SVar and change it
final String originalSVarValue = hostCard.getSVar(value);
hostCard.changeSVar(value, AbilityUtils.applyAbilityTextChangeEffects(originalSVarValue, this));
newValue = null;
} else if (this.getHostCard().hasSVar(value)) {
// don't change literal SVar names!
newValue = null;
9 changes: 1 addition & 8 deletions forge-game/src/main/java/forge/game/GameAction.java
Original file line number Diff line number Diff line change
@@ -233,13 +233,6 @@ else if (Iterables.any((CardCollectionView) params.get(AbilityKey.LastStateGrave
}
}

// Clean up the temporary Dash/Blitz SVar when the card leaves the battlefield
// Clean up the temporary AtEOT SVar
String endofTurn = c.getSVar("EndOfTurnLeavePlay");
if (fromBattlefield && (endofTurn.equals("Dash") || endofTurn.equals("Blitz") || endofTurn.equals("AtEOT"))) {
c.removeSVar("EndOfTurnLeavePlay");
}

if (fromBattlefield && !toBattlefield) {
c.getController().setRevolt(true);
}
@@ -337,7 +330,7 @@ else if (Iterables.any((CardCollectionView) params.get(AbilityKey.LastStateGrave
CardCollectionView comCards = c.getOwner().getCardsIn(ZoneType.Command);
for (final Card effCard : comCards) {
for (final ReplacementEffect re : effCard.getReplacementEffects()) {
if (re.hasSVar("CommanderMoveReplacement") && effCard.getEffectSource().getName().equals(c.getRealCommander().getName())) {
if (re.hasParam("CommanderMoveReplacement") && effCard.getEffectSource().getName().equals(c.getRealCommander().getName())) {
commanderEffect = effCard;
break;
}
2 changes: 2 additions & 0 deletions forge-game/src/main/java/forge/game/StaticEffect.java
Original file line number Diff line number Diff line change
@@ -288,6 +288,8 @@ final CardCollectionView remove() {
affectedCard.removeCanBlockAdditional(getTimestamp());
}

affectedCard.removeChangedSVars(getTimestamp(), ability.getId());

affectedCard.updateAbilityTextForView(); // only update keywords and text for view to avoid flickering
}
return affectedCards;
Original file line number Diff line number Diff line change
@@ -300,13 +300,12 @@ protected static void registerDelayedTrigger(final SpellAbility sa, String locat
delTrig.append("| TriggerDescription$ ").append(desc);

final Trigger trig = TriggerHandler.parseTrigger(delTrig.toString(), CardUtil.getLKICopy(sa.getHostCard()), intrinsic);
long ts = sa.getHostCard().getGame().getNextTimestamp();
for (final Card c : crds) {
trig.addRemembered(c);

// Svar for AI
if (!c.hasSVar("EndOfTurnLeavePlay")) {
c.setSVar("EndOfTurnLeavePlay", "AtEOT");
}
c.addChangedSVars(Collections.singletonMap("EndOfTurnLeavePlay", "AtEOT"), ts, 0);
}
String trigSA = "";
if (location.equals("Hand")) {
@@ -346,9 +345,7 @@ protected static void addSelfTrigger(final SpellAbility sa, String location, fin
card.addTrigger(trig);

// Svar for AI
if (!card.hasSVar("EndOfTurnLeavePlay")) {
card.setSVar("EndOfTurnLeavePlay", "AtEOT");
}
card.addChangedSVars(Collections.singletonMap("EndOfTurnLeavePlay", "AtEOT"), card.getGame().getNextTimestamp(), 0);
}

protected static SpellAbility getForgetSpellAbility(final Card card) {
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package forge.game.ability.effects;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import forge.GameCommand;
import forge.card.CardType;
@@ -64,17 +66,17 @@ public void resolve(final SpellAbility sa) {
types.add(host.getChosenType2());
}

final List<String> keywords = new ArrayList<>();
final List<String> keywords = Lists.newArrayList();
if (sa.hasParam("Keywords")) {
keywords.addAll(Arrays.asList(sa.getParam("Keywords").split(" & ")));
}

final List<String> removeKeywords = new ArrayList<>();
final List<String> removeKeywords = Lists.newArrayList();
if (sa.hasParam("RemoveKeywords")) {
removeKeywords.addAll(Arrays.asList(sa.getParam("RemoveKeywords").split(" & ")));
}

final List<String> hiddenKeywords = new ArrayList<>();
final List<String> hiddenKeywords = Lists.newArrayList();
if (sa.hasParam("HiddenKeywords")) {
hiddenKeywords.addAll(Arrays.asList(sa.getParam("HiddenKeywords").split(" & ")));
}
@@ -99,27 +101,32 @@ public void resolve(final SpellAbility sa) {
}

// abilities to add to the animated being
final List<String> abilities = new ArrayList<>();
final List<String> abilities = Lists.newArrayList();
if (sa.hasParam("Abilities")) {
abilities.addAll(Arrays.asList(sa.getParam("Abilities").split(",")));
}
// replacement effects to add to the animated being
final List<String> replacements = new ArrayList<>();
final List<String> replacements = Lists.newArrayList();
if (sa.hasParam("Replacements")) {
replacements.addAll(Arrays.asList(sa.getParam("Replacements").split(",")));
}
// triggers to add to the animated being
final List<String> triggers = new ArrayList<>();
final List<String> triggers = Lists.newArrayList();
if (sa.hasParam("Triggers")) {
triggers.addAll(Arrays.asList(sa.getParam("Triggers").split(",")));
}

// sVars to add to the animated being
final List<String> sVars = new ArrayList<>();
final List<String> sVars = Lists.newArrayList();
if (sa.hasParam("sVars")) {
sVars.addAll(Arrays.asList(sa.getParam("sVars").split(",")));
}

Map<String, String> sVarsMap = Maps.newHashMap();
for (final String s : sVars) {
sVarsMap.put(s, AbilityUtils.getSVar(sa, s));
}

final String valid = sa.getParamOrDefault("ValidCards", "");

CardCollectionView list;
@@ -139,9 +146,10 @@ public void resolve(final SpellAbility sa) {
timestamp);

// give sVars
for (final String s : sVars) {
c.setSVar(s, AbilityUtils.getSVar(sa, s));
if (!sVarsMap.isEmpty() ) {
c.addChangedSVars(sVarsMap, timestamp, 0);
}

game.fireEvent(new GameEventCardStatsChanged(c));

final GameCommand unanimate = new GameCommand() {
Original file line number Diff line number Diff line change
@@ -2,7 +2,9 @@

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import com.google.common.collect.Maps;
import com.google.common.collect.Lists;

import forge.card.CardType;
@@ -138,11 +140,22 @@ public void resolve(final SpellAbility sa) {
}

// sVars to add to the animated being
final List<String> sVars = Lists.newArrayList();
Map<String, String> sVarsMap = Maps.newHashMap();
if (sa.hasParam("sVars")) {
sVars.addAll(Arrays.asList(sa.getParam("sVars").split(",")));
for (final String s : sa.getParam("sVars").split(",")) {
String actualsVar = AbilityUtils.getSVar(sa, s);
String name = s;
if (actualsVar.startsWith("SVar:")) {
actualsVar = actualsVar.split("SVar:")[1];
name = actualsVar.split(":")[0];
actualsVar = actualsVar.split(":")[1];
}
sVarsMap.put(name, actualsVar);
}
}



List<Card> tgts = getCardsfromTargets(sa);

if (sa.hasParam("Optional")) {
@@ -166,15 +179,8 @@ public void resolve(final SpellAbility sa) {
}

// give sVars
for (final String s : sVars) {
String actualsVar = AbilityUtils.getSVar(sa, s);
String name = s;
if (actualsVar.startsWith("SVar:")) {
actualsVar = actualsVar.split("SVar:")[1];
name = actualsVar.split(":")[0];
actualsVar = actualsVar.split(":")[1];
}
c.setSVar(name, actualsVar);
if (!sVarsMap.isEmpty()) {
c.addChangedSVars(sVarsMap, timestamp, 0);
}

// give Remembered
Original file line number Diff line number Diff line change
@@ -137,6 +137,7 @@ public static void doAnimate(final Card c, final SpellAbility sa, final Integer
public void run() {
doUnanimate(c, timestamp);

c.removeChangedSVars(timestamp, 0);
c.removeChangedName(timestamp, 0);
c.updateStateForView();

Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package forge.game.ability.effects;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.google.common.collect.Lists;

import forge.GameCommand;
@@ -16,9 +20,6 @@
import forge.game.zone.ZoneType;
import forge.util.Localizer;

import java.util.Arrays;
import java.util.List;

public class ControlGainEffect extends SpellAbilityEffect {

@Override
@@ -210,11 +211,11 @@ public void resolve(SpellAbility sa) {
}
if (lose.contains("EOT")) {
game.getEndOfTurn().addUntil(loseControl);
tgtC.setSVar("SacMe", "6");
tgtC.addChangedSVars(Collections.singletonMap("SacMe", "6"), tStamp, 0);
}
if (lose.contains("EndOfCombat")) {
game.getEndOfCombat().addUntil(loseControl);
tgtC.setSVar("SacMe", "6");
tgtC.addChangedSVars(Collections.singletonMap("SacMe", "6"), tStamp, 0);
}
if (lose.contains("StaticCommandCheck")) {
String leftVar = sa.getSVar(sa.getParam("StaticCommandCheckSVar"));
@@ -276,7 +277,7 @@ private static GameCommand getLoseControlCommand(final Card c,
@Override
public void run() {
doLoseControl(c, hostCard, bTapOnLose, tStamp);
c.removeSVar("SacMe");
c.removeChangedSVars(tStamp, 0);
}
};

Original file line number Diff line number Diff line change
@@ -299,7 +299,7 @@ protected void internalDamageDeal(SpellAbility sa, Card sourceLKI, Card c, int d
} else {
damageMap.put(sourceLKI, c, dmg);
if (sa.hasParam("ExcessSVar")) {
hostCard.setSVar(sa.getParam("ExcessSVar"), Integer.toString(excess));
sa.setSVar(sa.getParam("ExcessSVar"), Integer.toString(excess));
}
}
}
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@


import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.ability.SpellAbilityEffect;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
@@ -41,14 +40,7 @@ public void resolve(SpellAbility sa) {
lifeLost += p.loseLife(lifeAmount, false, false);
}
}
sa.getHostCard().setSVar("AFLifeLost", "Number$" + lifeLost);

// Exceptional case for Extort: must propagate the amount of life lost to subability,
// otherwise the first Extort trigger per game won't work
if (sa.getSubAbility() != null && ApiType.GainLife.equals(sa.getSubAbility().getApi())) {
sa.getSubAbility().setSVar("AFLifeLost", "Number$" + lifeLost);
}

sa.setSVar("AFLifeLost", "Number$" + lifeLost);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package forge.game.ability.effects;

import java.util.Collections;
import java.util.Map;

import com.google.common.collect.Lists;
@@ -42,12 +43,12 @@ public void resolve(SpellAbility sa) {

// some extra for Dashing
if (sa.isDash() && c.isInPlay()) {
c.setSVar("EndOfTurnLeavePlay", "Dash");
c.addChangedSVars(Collections.singletonMap("EndOfTurnLeavePlay", "Dash"), c.getGame().getNextTimestamp(), 0);
registerDelayedTrigger(sa, "Hand", Lists.newArrayList(c));
}
// similar for Blitz keyword
if (sa.isBlitz() && c.isInPlay()) {
c.setSVar("EndOfTurnLeavePlay", "Blitz");
c.addChangedSVars(Collections.singletonMap("EndOfTurnLeavePlay", "Blitz"), c.getGame().getNextTimestamp(), 0);
registerDelayedTrigger(sa, "Sacrifice", Lists.newArrayList(c));
}

Loading

0 comments on commit c654234

Please sign in to comment.