mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
Add code allowing text-changing effects (+some cleanup).
This commit is contained in:
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -307,6 +307,7 @@ forge-game/src/main/java/forge/game/ability/effects/BecomesBlockedEffect.java -t
|
|||||||
forge-game/src/main/java/forge/game/ability/effects/BidLifeEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/BidLifeEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/BondEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/BondEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/ChangeTargetsEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ChangeTargetsEffect.java -text
|
||||||
|
forge-game/src/main/java/forge/game/ability/effects/ChangeTextEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java -text
|
||||||
@@ -422,6 +423,8 @@ forge-game/src/main/java/forge/game/ability/effects/VoteEffect.java -text
|
|||||||
forge-game/src/main/java/forge/game/ability/effects/ZoneExchangeEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ZoneExchangeEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/package-info.java svneol=native#text/plain
|
forge-game/src/main/java/forge/game/ability/package-info.java svneol=native#text/plain
|
||||||
forge-game/src/main/java/forge/game/card/Card.java svneol=native#text/plain
|
forge-game/src/main/java/forge/game/card/Card.java svneol=native#text/plain
|
||||||
|
forge-game/src/main/java/forge/game/card/CardChangedWord.java -text
|
||||||
|
forge-game/src/main/java/forge/game/card/CardChangedWords.java -text
|
||||||
forge-game/src/main/java/forge/game/card/CardCharacteristics.java -text
|
forge-game/src/main/java/forge/game/card/CardCharacteristics.java -text
|
||||||
forge-game/src/main/java/forge/game/card/CardColor.java svneol=native#text/plain
|
forge-game/src/main/java/forge/game/card/CardColor.java svneol=native#text/plain
|
||||||
forge-game/src/main/java/forge/game/card/CardDamageHistory.java -text
|
forge-game/src/main/java/forge/game/card/CardDamageHistory.java -text
|
||||||
|
|||||||
@@ -481,7 +481,7 @@ public class AiController {
|
|||||||
|
|
||||||
// don't play the land if it has cycling and enough lands are
|
// don't play the land if it has cycling and enough lands are
|
||||||
// available
|
// available
|
||||||
final ArrayList<SpellAbility> spellAbilities = c.getSpellAbilities();
|
final List<SpellAbility> spellAbilities = c.getSpellAbilities();
|
||||||
|
|
||||||
final List<Card> hand = player.getCardsIn(ZoneType.Hand);
|
final List<Card> hand = player.getCardsIn(ZoneType.Hand);
|
||||||
List<Card> lands = player.getCardsIn(ZoneType.Battlefield);
|
List<Card> lands = player.getCardsIn(ZoneType.Battlefield);
|
||||||
|
|||||||
@@ -178,4 +178,9 @@ public class TextUtil {
|
|||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String capitalize(final String s) {
|
||||||
|
return s.substring(0, 1).toUpperCase()
|
||||||
|
+ s.substring(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import forge.util.Expressions;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for Triggers,ReplacementEffects and StaticAbilities.
|
* Base class for Triggers,ReplacementEffects and StaticAbilities.
|
||||||
*
|
*
|
||||||
@@ -22,7 +24,8 @@ public abstract class CardTraitBase extends GameObject {
|
|||||||
protected Card hostCard;
|
protected Card hostCard;
|
||||||
|
|
||||||
/** The map params. */
|
/** The map params. */
|
||||||
protected final Map<String, String> mapParams = new HashMap<String, String>();
|
protected final Map<String, String> originalMapParams = Maps.newHashMap(),
|
||||||
|
mapParams = Maps.newHashMap();
|
||||||
|
|
||||||
/** The is intrinsic. */
|
/** The is intrinsic. */
|
||||||
protected boolean intrinsic;
|
protected boolean intrinsic;
|
||||||
@@ -66,11 +69,6 @@ public abstract class CardTraitBase extends GameObject {
|
|||||||
return this.mapParams;
|
return this.mapParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setMapParams(Map<String,String> params) {
|
|
||||||
this.mapParams.clear();
|
|
||||||
this.mapParams.putAll(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if is intrinsic.
|
* Checks if is intrinsic.
|
||||||
*
|
*
|
||||||
@@ -350,4 +348,15 @@ public abstract class CardTraitBase extends GameObject {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void changeText() {
|
||||||
|
for (final String key : this.mapParams.keySet()) {
|
||||||
|
// don't change literal SVar names!
|
||||||
|
if (!this.getHostCard().hasSVar(key)) {
|
||||||
|
final String value = this.originalMapParams.get(key),
|
||||||
|
newValue = AbilityUtils.applyTextChangeEffects(value, this.getHostCard());
|
||||||
|
this.mapParams.put(key, newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public class AbilityApiBased extends AbilityActivated {
|
|||||||
|
|
||||||
public AbilityApiBased(ApiType api0, Card sourceCard, Cost abCost, TargetRestrictions tgt, Map<String, String> params0) {
|
public AbilityApiBased(ApiType api0, Card sourceCard, Cost abCost, TargetRestrictions tgt, Map<String, String> params0) {
|
||||||
super(sourceCard, abCost, tgt);
|
super(sourceCard, abCost, tgt);
|
||||||
|
originalMapParams.putAll(params0);
|
||||||
mapParams.putAll(params0);
|
mapParams.putAll(params0);
|
||||||
api = api0;
|
api = api0;
|
||||||
effect = api.getSpellEffect();
|
effect = api.getSpellEffect();
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.apache.commons.lang3.text.WordUtils;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -79,7 +80,7 @@ public class AbilityUtils {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static List<Card> getDefinedCards(final Card hostCard, final String def, final SpellAbility sa) {
|
public static List<Card> getDefinedCards(final Card hostCard, final String def, final SpellAbility sa) {
|
||||||
final List<Card> cards = new ArrayList<Card>();
|
final List<Card> cards = new ArrayList<Card>();
|
||||||
final String defined = (def == null) ? "Self" : def; // default to Self
|
final String defined = (def == null) ? "Self" : applyTextChangeEffects(def, hostCard); // default to Self
|
||||||
final Game game = hostCard.getGame();
|
final Game game = hostCard.getGame();
|
||||||
|
|
||||||
Card c = null;
|
Card c = null;
|
||||||
@@ -351,34 +352,37 @@ public class AbilityUtils {
|
|||||||
// return result soon for plain numbers
|
// return result soon for plain numbers
|
||||||
if (StringUtils.isNumeric(amount)) { return Integer.parseInt(amount) * multiplier; }
|
if (StringUtils.isNumeric(amount)) { return Integer.parseInt(amount) * multiplier; }
|
||||||
|
|
||||||
|
// modify amount string for text changes
|
||||||
|
final String amount2 = AbilityUtils.applyTextChangeEffects(amount, card);
|
||||||
|
|
||||||
// Try to fetch variable, try ability first, then card.
|
// Try to fetch variable, try ability first, then card.
|
||||||
String svarval = null;
|
String svarval = null;
|
||||||
if (amount.indexOf('$') > 0) { // when there is a dollar sign, it's not a reference, it's a raw value!
|
if (amount2.indexOf('$') > 0) { // when there is a dollar sign, it's not a reference, it's a raw value!
|
||||||
svarval = amount;
|
svarval = amount2;
|
||||||
}
|
}
|
||||||
else if (ability != null) {
|
else if (ability != null) {
|
||||||
svarval = ability.getSVar(amount);
|
svarval = ability.getSVar(amount2);
|
||||||
}
|
}
|
||||||
if (StringUtils.isBlank(svarval)) {
|
if (StringUtils.isBlank(svarval)) {
|
||||||
if (ability != null) {
|
if (ability != null) {
|
||||||
System.err.printf("SVar '%s' not found in ability, fallback to Card (%s). Ability is (%s)%n", amount, card.getName(), ability);
|
System.err.printf("SVar '%s' not found in ability, fallback to Card (%s). Ability is (%s)%n", amount2, card.getName(), ability);
|
||||||
}
|
}
|
||||||
svarval = card.getSVar(amount);
|
svarval = card.getSVar(amount2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isBlank(svarval)) {
|
if (StringUtils.isBlank(svarval)) {
|
||||||
// Some variables may be not chosen yet at this moment
|
// Some variables may be not chosen yet at this moment
|
||||||
// So return 0 and don't issue an error.
|
// So return 0 and don't issue an error.
|
||||||
if (amount.equals("ChosenX")) {
|
if (amount2.equals("ChosenX")) {
|
||||||
// isn't made yet
|
// isn't made yet
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// cost hasn't been paid yet
|
// cost hasn't been paid yet
|
||||||
if (amount.startsWith("Cost")) {
|
if (amount2.startsWith("Cost")) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Nothing to do here if value is missing or blank
|
// Nothing to do here if value is missing or blank
|
||||||
System.err.printf("SVar '%s' not defined in Card (%s)%n", amount, card.getName());
|
System.err.printf("SVar '%s' not defined in Card (%s)%n", amount2, card.getName());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,6 +399,9 @@ public class AbilityUtils {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// modify amount string for text changes
|
||||||
|
calcX[1] = AbilityUtils.applyTextChangeEffects(calcX[1], card);
|
||||||
|
|
||||||
if (calcX[0].startsWith("Count")) {
|
if (calcX[0].startsWith("Count")) {
|
||||||
return AbilityUtils.xCount(card, calcX[1], ability) * multiplier;
|
return AbilityUtils.xCount(card, calcX[1], ability) * multiplier;
|
||||||
}
|
}
|
||||||
@@ -806,7 +813,7 @@ public class AbilityUtils {
|
|||||||
*/
|
*/
|
||||||
public static List<Player> getDefinedPlayers(final Card card, final String def, final SpellAbility sa) {
|
public static List<Player> getDefinedPlayers(final Card card, final String def, final SpellAbility sa) {
|
||||||
final List<Player> players = new ArrayList<Player>();
|
final List<Player> players = new ArrayList<Player>();
|
||||||
final String defined = (def == null) ? "You" : def;
|
final String defined = (def == null) ? "You" : applyTextChangeEffects(def, card);
|
||||||
final Game game = card == null ? null : card.getGame();
|
final Game game = card == null ? null : card.getGame();
|
||||||
|
|
||||||
if (defined.equals("Targeted") || defined.equals("TargetedPlayer")) {
|
if (defined.equals("Targeted") || defined.equals("TargetedPlayer")) {
|
||||||
@@ -1125,7 +1132,7 @@ public class AbilityUtils {
|
|||||||
public static ArrayList<SpellAbility> getDefinedSpellAbilities(final Card card, final String def,
|
public static ArrayList<SpellAbility> getDefinedSpellAbilities(final Card card, final String def,
|
||||||
final SpellAbility sa) {
|
final SpellAbility sa) {
|
||||||
final ArrayList<SpellAbility> sas = new ArrayList<SpellAbility>();
|
final ArrayList<SpellAbility> sas = new ArrayList<SpellAbility>();
|
||||||
final String defined = (def == null) ? "Self" : def; // default to Self
|
final String defined = (def == null) ? "Self" : applyTextChangeEffects(def, card); // default to Self
|
||||||
final Game game = sa.getActivatingPlayer().getGame();
|
final Game game = sa.getActivatingPlayer().getGame();
|
||||||
|
|
||||||
SpellAbility s = null;
|
SpellAbility s = null;
|
||||||
@@ -1398,9 +1405,9 @@ public class AbilityUtils {
|
|||||||
* @return a int.
|
* @return a int.
|
||||||
*/
|
*/
|
||||||
public static int xCount(final Card c, final String s, final SpellAbility sa) {
|
public static int xCount(final Card c, final String s, final SpellAbility sa) {
|
||||||
|
final String s2 = AbilityUtils.applyTextChangeEffects(s, c);
|
||||||
final String[] l = s.split("/");
|
final String[] l = s2.split("/");
|
||||||
final String expr = CardFactoryUtil.extractOperators(s);
|
final String expr = CardFactoryUtil.extractOperators(s2);
|
||||||
|
|
||||||
final String[] sq;
|
final String[] sq;
|
||||||
sq = l[0].split("\\.");
|
sq = l[0].split("\\.");
|
||||||
@@ -1459,7 +1466,7 @@ public class AbilityUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CardFactoryUtil.xCount(c, s);
|
return CardFactoryUtil.xCount(c, s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final void applyManaColorConversion(final Player p, final Map<String, String> params) {
|
public static final void applyManaColorConversion(final Player p, final Map<String, String> params) {
|
||||||
@@ -1506,4 +1513,15 @@ public class AbilityUtils {
|
|||||||
}
|
}
|
||||||
return sas;
|
return sas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final String applyTextChangeEffects(final String def, final Card hostCard) {
|
||||||
|
String replaced = def;
|
||||||
|
for (final Entry<String, String> e : hostCard.getChangedTextColorWords().entrySet()) {
|
||||||
|
replaced = replaced.replace(e.getKey(), e.getValue());
|
||||||
|
}
|
||||||
|
for (final Entry<String, String> e : hostCard.getChangedTextTypeWords().entrySet()) {
|
||||||
|
replaced = replaced.replace(e.getKey(), e.getValue());
|
||||||
|
}
|
||||||
|
return replaced;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ public enum ApiType {
|
|||||||
BidLife (BidLifeEffect.class),
|
BidLife (BidLifeEffect.class),
|
||||||
Bond (BondEffect.class),
|
Bond (BondEffect.class),
|
||||||
ChangeTargets (ChangeTargetsEffect.class),
|
ChangeTargets (ChangeTargetsEffect.class),
|
||||||
|
ChangeText (ChangeTextEffect.class),
|
||||||
ChangeZone (ChangeZoneEffect.class),
|
ChangeZone (ChangeZoneEffect.class),
|
||||||
ChangeZoneAll (ChangeZoneAllEffect.class),
|
ChangeZoneAll (ChangeZoneAllEffect.class),
|
||||||
|
|
||||||
Charm (CharmEffect.class),
|
Charm (CharmEffect.class),
|
||||||
ChooseCard (ChooseCardEffect.class),
|
ChooseCard (ChooseCardEffect.class),
|
||||||
ChooseColor (ChooseColorEffect.class),
|
ChooseColor (ChooseColorEffect.class),
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public class SpellApiBased extends Spell {
|
|||||||
super(sourceCard, abCost);
|
super(sourceCard, abCost);
|
||||||
this.setTargetRestrictions(tgt);
|
this.setTargetRestrictions(tgt);
|
||||||
|
|
||||||
|
originalMapParams.putAll(params0);
|
||||||
mapParams.putAll(params0);
|
mapParams.putAll(params0);
|
||||||
api = api0;
|
api = api0;
|
||||||
effect = api.getSpellEffect();
|
effect = api.getSpellEffect();
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ public class StaticAbilityApiBased extends AbilityStatic {
|
|||||||
|
|
||||||
public StaticAbilityApiBased(ApiType api0, Card sourceCard, Cost abCost, TargetRestrictions tgt, Map<String, String> params0) {
|
public StaticAbilityApiBased(ApiType api0, Card sourceCard, Cost abCost, TargetRestrictions tgt, Map<String, String> params0) {
|
||||||
super(sourceCard, abCost, tgt);
|
super(sourceCard, abCost, tgt);
|
||||||
|
originalMapParams.putAll(params0);
|
||||||
mapParams.putAll(params0);
|
mapParams.putAll(params0);
|
||||||
api = api0;
|
api = api0;
|
||||||
effect = api.getSpellEffect();
|
effect = api.getSpellEffect();
|
||||||
|
|||||||
@@ -0,0 +1,235 @@
|
|||||||
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import forge.GameCommand;
|
||||||
|
import forge.card.CardType;
|
||||||
|
import forge.card.ColorSet;
|
||||||
|
import forge.card.MagicColor;
|
||||||
|
import forge.game.Game;
|
||||||
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.event.GameEventCardStatsChanged;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.util.TextUtil;
|
||||||
|
|
||||||
|
public class ChangeTextEffect extends SpellAbilityEffect {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.abilityfactory.SpellEffect#resolve(forge.card.spellability.SpellAbility)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void resolve(final SpellAbility sa) {
|
||||||
|
final Card source = sa.getHostCard();
|
||||||
|
final Game game = source.getGame();
|
||||||
|
final boolean permanent = sa.hasParam("Permanent");
|
||||||
|
|
||||||
|
final String changedColorWordOriginal, changedColorWordNew;
|
||||||
|
if (sa.hasParam("ChangeColorWord")) {
|
||||||
|
byte originalColor = 0;
|
||||||
|
final String[] changedColorWordsArray = sa.getParam("ChangeColorWord").split(" ");
|
||||||
|
if (changedColorWordsArray[0].equals("Choose")) {
|
||||||
|
originalColor = sa.getActivatingPlayer().getController().chooseColor(
|
||||||
|
"Choose a color word to replace", sa, ColorSet.fromMask(MagicColor.ALL_COLORS));
|
||||||
|
changedColorWordOriginal = TextUtil.capitalize(MagicColor.toLongString(originalColor));
|
||||||
|
} else {
|
||||||
|
changedColorWordOriginal = changedColorWordsArray[0];
|
||||||
|
originalColor = MagicColor.fromName(changedColorWordOriginal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changedColorWordsArray[1].equals("Choose")) {
|
||||||
|
final ColorSet possibleNewColors;
|
||||||
|
if (originalColor == 0) { // no original color (ie. any or absent)
|
||||||
|
possibleNewColors = ColorSet.fromMask(MagicColor.ALL_COLORS);
|
||||||
|
} else { // may choose any except original color
|
||||||
|
possibleNewColors = ColorSet.fromMask(originalColor).inverse();
|
||||||
|
}
|
||||||
|
final byte newColor = sa.getActivatingPlayer().getController().chooseColor(
|
||||||
|
"Choose a new color word", sa, possibleNewColors);
|
||||||
|
changedColorWordNew = TextUtil.capitalize(MagicColor.toLongString(newColor));
|
||||||
|
} else {
|
||||||
|
changedColorWordNew = changedColorWordsArray[1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
changedColorWordOriginal = null;
|
||||||
|
changedColorWordNew = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String changedTypeWordOriginal, changedTypeWordNew;
|
||||||
|
if (sa.hasParam("ChangeTypeWord")) {
|
||||||
|
String kindOfType = "";
|
||||||
|
final List<String> validTypes = Lists.newArrayList();
|
||||||
|
final String[] changedTypeWordsArray = sa.getParam("ChangeTypeWord").split(" ");
|
||||||
|
if (changedTypeWordsArray[0].equals("ChooseBasicLandType") || changedTypeWordsArray[0].equals("ChooseCreatureType")) {
|
||||||
|
if (changedTypeWordsArray[0].equals("ChooseBasicLandType")) {
|
||||||
|
validTypes.addAll(CardType.getBasicTypes());
|
||||||
|
kindOfType = "basic land";
|
||||||
|
} else if (changedTypeWordsArray[0].equals("ChooseCreatureType")) {
|
||||||
|
validTypes.addAll(CardType.getCreatureTypes());
|
||||||
|
kindOfType = "creature";
|
||||||
|
}
|
||||||
|
changedTypeWordOriginal = sa.getActivatingPlayer().getController().chooseSomeType(kindOfType, sa, validTypes, Lists.<String>newArrayList());
|
||||||
|
} else {
|
||||||
|
changedTypeWordOriginal = changedTypeWordsArray[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
validTypes.clear();
|
||||||
|
final List<String> forbiddenTypes = sa.hasParam("ForbiddenNewTypes") ? Lists.newArrayList(sa.getParam("ForbiddenNewTypes").split(",")) : Lists.<String>newArrayList();
|
||||||
|
forbiddenTypes.add(changedTypeWordOriginal);
|
||||||
|
if (changedTypeWordsArray[0].startsWith("Choose")) {
|
||||||
|
if (changedTypeWordsArray[0].equals("ChooseBasicLandType")) {
|
||||||
|
validTypes.addAll(CardType.getBasicTypes());
|
||||||
|
kindOfType = "basic land";
|
||||||
|
} else if (changedTypeWordsArray[0].equals("ChooseCreatureType")) {
|
||||||
|
validTypes.addAll(CardType.getCreatureTypes());
|
||||||
|
kindOfType = "creature";
|
||||||
|
}
|
||||||
|
changedTypeWordNew = sa.getActivatingPlayer().getController().chooseSomeType(kindOfType, sa, validTypes, forbiddenTypes);
|
||||||
|
} else {
|
||||||
|
changedTypeWordNew = changedTypeWordsArray[1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
changedTypeWordOriginal = null;
|
||||||
|
changedTypeWordNew = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Card> tgts = getTargetCards(sa);
|
||||||
|
for (final Card c : tgts) {
|
||||||
|
final Long colorTimestamp;
|
||||||
|
if (changedColorWordNew != null) {
|
||||||
|
colorTimestamp = c.addChangedTextColorWord(changedColorWordOriginal, changedColorWordNew);
|
||||||
|
} else {
|
||||||
|
colorTimestamp = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Long typeTimestamp;
|
||||||
|
if (changedTypeWordNew != null) {
|
||||||
|
typeTimestamp = c.addChangedTextTypeWord(changedTypeWordOriginal, changedTypeWordNew);
|
||||||
|
} else {
|
||||||
|
typeTimestamp = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!permanent) {
|
||||||
|
final GameCommand revert = new GameCommand() {
|
||||||
|
private static final long serialVersionUID = -7802388880114360593L;
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (changedColorWordNew != null) {
|
||||||
|
c.removeChangedTextColorWord(colorTimestamp);
|
||||||
|
}
|
||||||
|
if (changedTypeWordNew != null) {
|
||||||
|
c.removeChangedTextTypeWord(typeTimestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
game.getEndOfTurn().addUntil(revert);
|
||||||
|
}
|
||||||
|
|
||||||
|
game.fireEvent(new GameEventCardStatsChanged(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getStackDescription(SpellAbility sa) {
|
||||||
|
final String changedColorWordOriginal, changedColorWordNew;
|
||||||
|
if (sa.hasParam("ChangeColorWord")) {
|
||||||
|
final String[] changedColorWordsArray = sa.getParam("ChangeColorWord").split(" ");
|
||||||
|
changedColorWordOriginal = changedColorWordsArray[0];
|
||||||
|
changedColorWordNew = changedColorWordsArray[1];
|
||||||
|
} else {
|
||||||
|
changedColorWordOriginal = null;
|
||||||
|
changedColorWordNew = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String changedTypeWordOriginal, changedTypeWordNew;
|
||||||
|
if (sa.hasParam("ChangeTypeWord")) {
|
||||||
|
final String[] changedTypeWordsArray = sa.getParam("ChangeTypeWord").split(" ");
|
||||||
|
changedTypeWordOriginal = changedTypeWordsArray[0];
|
||||||
|
changedTypeWordNew = changedTypeWordsArray[1];
|
||||||
|
} else {
|
||||||
|
changedTypeWordOriginal = null;
|
||||||
|
changedTypeWordNew = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean permanent = sa.hasParam("Permanent");
|
||||||
|
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Change the text of ");
|
||||||
|
|
||||||
|
final List<Card> tgts = getTargetCards(sa);
|
||||||
|
for (final Card c : tgts) {
|
||||||
|
sb.append(c).append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changedColorWordOriginal != null) {
|
||||||
|
sb.append(" by replacing all instances of ");
|
||||||
|
if (changedColorWordOriginal.equals("Choose")) {
|
||||||
|
sb.append("one color word");
|
||||||
|
} else if (changedColorWordOriginal.equals("Any")) {
|
||||||
|
sb.append("each color word");
|
||||||
|
} else {
|
||||||
|
sb.append(changedColorWordOriginal);
|
||||||
|
}
|
||||||
|
sb.append(" with ");
|
||||||
|
if (changedColorWordNew.equals("Choose")) {
|
||||||
|
if (changedColorWordOriginal.equals("Choose")) {
|
||||||
|
sb.append("another");
|
||||||
|
} else {
|
||||||
|
sb.append("a color word of your choice");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append(changedColorWordNew);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changedTypeWordOriginal != null) {
|
||||||
|
sb.append(" by replacing all instances of ");
|
||||||
|
if (changedTypeWordOriginal.equals("ChooseBasicLandType")) {
|
||||||
|
sb.append("one basic land type");
|
||||||
|
} else if (changedTypeWordOriginal.equals("ChooseCreatureType")) {
|
||||||
|
sb.append("one creature type");
|
||||||
|
} else {
|
||||||
|
sb.append(changedTypeWordOriginal);
|
||||||
|
}
|
||||||
|
sb.append(" with ");
|
||||||
|
if (changedTypeWordNew.equals("ChooseBasicLandType")) {
|
||||||
|
if (changedTypeWordOriginal.equals("ChooseBasicLandType")) {
|
||||||
|
sb.append("another");
|
||||||
|
} else {
|
||||||
|
sb.append("a basic land type of your choice");
|
||||||
|
}
|
||||||
|
} else if (changedTypeWordNew.equals("ChooseCreatureType")) {
|
||||||
|
if (changedTypeWordOriginal.equals("ChooseCreatureType")) {
|
||||||
|
sb.append("another");
|
||||||
|
} else {
|
||||||
|
sb.append("a creature type of your choice");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append(changedTypeWordNew);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!permanent) {
|
||||||
|
sb.append(" until end of turn");
|
||||||
|
}
|
||||||
|
sb.append('.');
|
||||||
|
|
||||||
|
if (sa.hasParam("ForbiddenNewTypes")) {
|
||||||
|
sb.append(" The new creature type can't be ");
|
||||||
|
sb.append(sa.getParam("ForbiddenNewTypes"));
|
||||||
|
sb.append('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (permanent) {
|
||||||
|
sb.append(" (This effect lasts indefinitely.)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -518,7 +518,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
movedCard = game.getAction().moveTo(destination, tgtC);
|
movedCard = game.getAction().moveTo(destination, tgtC);
|
||||||
// If a card is Exiled from the stack, remove its spells from the stack
|
// If a card is Exiled from the stack, remove its spells from the stack
|
||||||
if (sa.hasParam("Fizzle")) {
|
if (sa.hasParam("Fizzle")) {
|
||||||
ArrayList<SpellAbility> spells = tgtC.getSpellAbilities();
|
final List<SpellAbility> spells = tgtC.getSpellAbilities();
|
||||||
for (SpellAbility spell : spells) {
|
for (SpellAbility spell : spells) {
|
||||||
if (tgtC.isInZone(ZoneType.Exile) || tgtC.isInZone(ZoneType.Hand)) {
|
if (tgtC.isInZone(ZoneType.Exile) || tgtC.isInZone(ZoneType.Hand)) {
|
||||||
final SpellAbilityStackInstance si = game.getStack().getInstanceFromSpellAbility(spell);
|
final SpellAbilityStackInstance si = game.getStack().getInstanceFromSpellAbility(spell);
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ package forge.game.card;
|
|||||||
import com.esotericsoftware.minlog.Log;
|
import com.esotericsoftware.minlog.Log;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import forge.GameCommand;
|
import forge.GameCommand;
|
||||||
import forge.StaticData;
|
import forge.StaticData;
|
||||||
@@ -118,6 +120,12 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private Map<Long, CardType> changedCardTypes = new ConcurrentSkipListMap<Long, CardType>();
|
private Map<Long, CardType> changedCardTypes = new ConcurrentSkipListMap<Long, CardType>();
|
||||||
private Map<Long, CardKeywords> changedCardKeywords = new ConcurrentSkipListMap<Long, CardKeywords>();
|
private Map<Long, CardKeywords> changedCardKeywords = new ConcurrentSkipListMap<Long, CardKeywords>();
|
||||||
|
|
||||||
|
// changes that say "replace each instance of one [color,type] by another - timestamp is the key of maps
|
||||||
|
private final CardChangedWords changedTextColors = new CardChangedWords();
|
||||||
|
private final CardChangedWords changedTextTypes = new CardChangedWords();
|
||||||
|
/** List of the keywords that have been added by text changes. */
|
||||||
|
private final List<String> keywordsGrantedByTextChanges = Lists.newArrayList();
|
||||||
|
|
||||||
private final ArrayList<Object> rememberedObjects = new ArrayList<Object>();
|
private final ArrayList<Object> rememberedObjects = new ArrayList<Object>();
|
||||||
private final MapOfLists<GameEntity, Object> rememberMap = new HashMapOfLists<GameEntity, Object>(CollectionSuppliers.<Object>arrayLists());
|
private final MapOfLists<GameEntity, Object> rememberMap = new HashMapOfLists<GameEntity, Object>(CollectionSuppliers.<Object>arrayLists());
|
||||||
private final ArrayList<Card> imprintedCards = new ArrayList<Card>();
|
private final ArrayList<Card> imprintedCards = new ArrayList<Card>();
|
||||||
@@ -2389,6 +2397,18 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (final Entry<String, String> e : Sets.union(this.changedTextColors.toMap().entrySet(),
|
||||||
|
this.changedTextTypes.toMap().entrySet())) {
|
||||||
|
// only the upper case ones, to avoid duplicity
|
||||||
|
if (Character.isUpperCase(e.getKey().charAt(0))) {
|
||||||
|
sb.append("Text changed: all instances of ");
|
||||||
|
sb.append(e.getKey());
|
||||||
|
sb.append(" are replaced by ");
|
||||||
|
sb.append(e.getValue());
|
||||||
|
sb.append(".\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE:
|
// NOTE:
|
||||||
if (sb.toString().contains(" (NOTE: ")) {
|
if (sb.toString().contains(" (NOTE: ")) {
|
||||||
sb.insert(sb.indexOf("(NOTE: "), "\r\n");
|
sb.insert(sb.indexOf("(NOTE: "), "\r\n");
|
||||||
@@ -2594,7 +2614,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return Collections.unmodifiableList(this.getCharacteristics().getManaAbility());
|
return Collections.unmodifiableList(this.getCharacteristics().getManaAbility());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public final boolean canProduceSameManaTypeWith(final Card c) {
|
public final boolean canProduceSameManaTypeWith(final Card c) {
|
||||||
final List<SpellAbility> manaAb = this.getManaAbility();
|
final List<SpellAbility> manaAb = this.getManaAbility();
|
||||||
if (manaAb.isEmpty()) {
|
if (manaAb.isEmpty()) {
|
||||||
@@ -2691,7 +2710,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
* a {@link forge.game.spellability.SpellAbility} object.
|
* a {@link forge.game.spellability.SpellAbility} object.
|
||||||
*/
|
*/
|
||||||
public final void addSpellAbility(final SpellAbility a) {
|
public final void addSpellAbility(final SpellAbility a) {
|
||||||
|
|
||||||
a.setHostCard(this);
|
a.setHostCard(this);
|
||||||
if (a.isManaAbility()) {
|
if (a.isManaAbility()) {
|
||||||
this.getCharacteristics().getManaAbility().add(a);
|
this.getCharacteristics().getManaAbility().add(a);
|
||||||
@@ -2700,7 +2718,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* removeSpellAbility.
|
* removeSpellAbility.
|
||||||
@@ -2726,7 +2743,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
*
|
*
|
||||||
* @return a {@link java.util.ArrayList} object.
|
* @return a {@link java.util.ArrayList} object.
|
||||||
*/
|
*/
|
||||||
public final ArrayList<SpellAbility> getSpellAbilities() {
|
public final List<SpellAbility> getSpellAbilities() {
|
||||||
final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>(this.getManaAbility());
|
final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>(this.getManaAbility());
|
||||||
res.addAll(this.getCharacteristics().getSpellAbility());
|
res.addAll(this.getCharacteristics().getSpellAbility());
|
||||||
return res;
|
return res;
|
||||||
@@ -4483,9 +4500,10 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
*
|
*
|
||||||
* @param timestamp
|
* @param timestamp
|
||||||
* the timestamp
|
* the timestamp
|
||||||
|
* @return the removed {@link CardKeywords}.
|
||||||
*/
|
*/
|
||||||
public final void removeChangedCardKeywords(final long timestamp) {
|
public final CardKeywords removeChangedCardKeywords(final long timestamp) {
|
||||||
changedCardKeywords.remove(Long.valueOf(timestamp));
|
return changedCardKeywords.remove(Long.valueOf(timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hidden keywords will be left out
|
// Hidden keywords will be left out
|
||||||
@@ -4518,6 +4536,97 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return keywords;
|
return keywords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace all instances of one color word in this card's text by another.
|
||||||
|
* @param originalWord the original color word.
|
||||||
|
* @param newWord the new color word.
|
||||||
|
* @return the timestamp.
|
||||||
|
* @throws RuntimeException if either of the strings is not a valid Magic
|
||||||
|
* color.
|
||||||
|
*/
|
||||||
|
public final Long addChangedTextColorWord(final String originalWord, final String newWord) {
|
||||||
|
if (MagicColor.fromName(newWord) == 0) {
|
||||||
|
throw new RuntimeException("Not a color: " + newWord);
|
||||||
|
}
|
||||||
|
final Long timestamp = this.changedTextColors.add(this.getGame().getNextTimestamp(), originalWord, newWord);
|
||||||
|
this.updateKeywordsChangedText(originalWord, newWord, timestamp);
|
||||||
|
this.updateChangedText();
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void removeChangedTextColorWord(final Long timestamp) {
|
||||||
|
this.changedTextColors.remove(timestamp);
|
||||||
|
this.updateKeywordsOnRemoveChangedText(
|
||||||
|
this.removeChangedCardKeywords(timestamp.longValue()));
|
||||||
|
this.updateChangedText();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace all instances of one type in this card's text by another.
|
||||||
|
* @param originalWord the original type word.
|
||||||
|
* @param newWord the new type word.
|
||||||
|
*/
|
||||||
|
public final Long addChangedTextTypeWord(final String originalWord, final String newWord) {
|
||||||
|
final Long timestamp = this.changedTextTypes.add(this.getGame().getNextTimestamp(), originalWord, newWord);
|
||||||
|
if (this.getType().contains(originalWord)) {
|
||||||
|
this.addChangedCardTypes(Lists.newArrayList(newWord), Lists.newArrayList(originalWord), false, false, false, false, timestamp);
|
||||||
|
}
|
||||||
|
this.updateKeywordsChangedText(originalWord, newWord, timestamp);
|
||||||
|
this.updateChangedText();
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void removeChangedTextTypeWord(final Long timestamp) {
|
||||||
|
this.changedTextTypes.remove(timestamp);
|
||||||
|
this.removeChangedCardTypes(timestamp);
|
||||||
|
this.updateKeywordsOnRemoveChangedText(
|
||||||
|
this.removeChangedCardKeywords(timestamp.longValue()));
|
||||||
|
this.updateChangedText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final void updateKeywordsChangedText(final String originalWord, final String newWord, final Long timestamp) {
|
||||||
|
final List<String> addKeywords = Lists.newArrayList(),
|
||||||
|
removeKeywords = Lists.newArrayList(this.keywordsGrantedByTextChanges);
|
||||||
|
|
||||||
|
for (final String kw : this.getIntrinsicKeyword()) {
|
||||||
|
final String newKw = AbilityUtils.applyTextChangeEffects(kw, this);
|
||||||
|
if (!newKw.equals(kw)) {
|
||||||
|
addKeywords.add(newKw);
|
||||||
|
removeKeywords.add(kw);
|
||||||
|
this.keywordsGrantedByTextChanges.add(newKw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.addChangedCardKeywords(addKeywords, removeKeywords, false, timestamp.longValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private final void updateKeywordsOnRemoveChangedText(final CardKeywords k) {
|
||||||
|
this.keywordsGrantedByTextChanges.removeAll(k.getKeywords());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the changed text of the intrinsic spell abilities and keywords.
|
||||||
|
*/
|
||||||
|
private final void updateChangedText() {
|
||||||
|
final List<CardTraitBase> allAbs = Lists.newLinkedList();
|
||||||
|
allAbs.addAll(this.getSpellAbilities());
|
||||||
|
allAbs.addAll(this.getStaticAbilities());
|
||||||
|
allAbs.addAll(this.getReplacementEffects());
|
||||||
|
allAbs.addAll(this.getTriggers());
|
||||||
|
for (final CardTraitBase ctb : allAbs) {
|
||||||
|
if (ctb.isIntrinsic()) {
|
||||||
|
ctb.changeText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ImmutableMap<String, String> getChangedTextColorWords() {
|
||||||
|
return ImmutableMap.copyOf(changedTextColors.toMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ImmutableMap<String, String> getChangedTextTypeWords() {
|
||||||
|
return ImmutableMap.copyOf(changedTextTypes.toMap());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* getIntrinsicAbilities.
|
* getIntrinsicAbilities.
|
||||||
@@ -4542,19 +4651,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return this.getCharacteristics().getIntrinsicKeyword();
|
return this.getCharacteristics().getIntrinsicKeyword();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Setter for the field <code>intrinsicKeyword</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param a
|
|
||||||
* a {@link java.util.ArrayList} object.
|
|
||||||
*/
|
|
||||||
public final void setIntrinsicKeyword(final List<String> a) {
|
|
||||||
this.getCharacteristics().setIntrinsicKeyword(new ArrayList<String>(a));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* setIntrinsicAbilities.
|
* setIntrinsicAbilities.
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package forge.game.card;
|
||||||
|
|
||||||
|
public class CardChangedWord {
|
||||||
|
|
||||||
|
private final String originalWord,
|
||||||
|
newWord;
|
||||||
|
|
||||||
|
public CardChangedWord(final String originalWord, final String newWord) {
|
||||||
|
this.originalWord = originalWord;
|
||||||
|
this.newWord = newWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOriginalWord() {
|
||||||
|
return originalWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNewWord() {
|
||||||
|
return newWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package forge.game.card;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
public final class CardChangedWords {
|
||||||
|
|
||||||
|
private final SortedMap<Long, CardChangedWord> map = Maps.newTreeMap();
|
||||||
|
|
||||||
|
private boolean isDirty = false;
|
||||||
|
private Map<String, String> resultCache = Maps.newHashMap();
|
||||||
|
|
||||||
|
public CardChangedWords() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long add(final long timestamp, final String originalWord, final String newWord) {
|
||||||
|
final Long stamp = Long.valueOf(timestamp);
|
||||||
|
map.put(stamp, new CardChangedWord(originalWord, newWord));
|
||||||
|
isDirty = true;
|
||||||
|
return stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(final Long timestamp) {
|
||||||
|
map.remove(timestamp);
|
||||||
|
isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this object to a {@link Map}.
|
||||||
|
*
|
||||||
|
* @return a map of strings to strings, where each changed word in this
|
||||||
|
* object is mapped to its corresponding replacement word.
|
||||||
|
*/
|
||||||
|
public Map<String, String> toMap() {
|
||||||
|
refreshCache();
|
||||||
|
return resultCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshCache() {
|
||||||
|
if (isDirty) {
|
||||||
|
resultCache = Maps.newHashMap();
|
||||||
|
for (final CardChangedWord ccw : this.map.values()) {
|
||||||
|
for (final Entry<String, String> e : resultCache.entrySet()) {
|
||||||
|
if (e.getValue().equals(ccw.getOriginalWord())) {
|
||||||
|
e.setValue(ccw.getNewWord());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resultCache.put(ccw.getOriginalWord(), ccw.getNewWord());
|
||||||
|
}
|
||||||
|
for (final String key : ImmutableList.copyOf(resultCache.keySet())) {
|
||||||
|
resultCache.put(key.toLowerCase(), resultCache.get(key).toLowerCase());
|
||||||
|
}
|
||||||
|
isDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@ import forge.game.cost.Cost;
|
|||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.replacement.ReplacementHandler;
|
import forge.game.replacement.ReplacementHandler;
|
||||||
import forge.game.spellability.*;
|
import forge.game.spellability.*;
|
||||||
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
import forge.game.trigger.TriggerHandler;
|
import forge.game.trigger.TriggerHandler;
|
||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
@@ -288,10 +289,10 @@ public class CardFactory {
|
|||||||
card.setState(state);
|
card.setState(state);
|
||||||
CardFactoryUtil.addAbilityFactoryAbilities(card);
|
CardFactoryUtil.addAbilityFactoryAbilities(card);
|
||||||
for (String stAb : card.getStaticAbilityStrings()) {
|
for (String stAb : card.getStaticAbilityStrings()) {
|
||||||
card.addStaticAbility(stAb);
|
final StaticAbility s = card.addStaticAbility(stAb);
|
||||||
|
s.setIntrinsic(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (state == CardCharacteristicName.LeftSplit || state == CardCharacteristicName.RightSplit)
|
if (state == CardCharacteristicName.LeftSplit || state == CardCharacteristicName.RightSplit)
|
||||||
{
|
{
|
||||||
CardCharacteristics original = card.getState(CardCharacteristicName.Original);
|
CardCharacteristics original = card.getState(CardCharacteristicName.Original);
|
||||||
|
|||||||
@@ -682,7 +682,7 @@ public class CardFactoryUtil {
|
|||||||
return doXMath(n, m, source);
|
return doXMath(n, m, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int playerXProperty(Player player, String s, Card source) {
|
public static int playerXProperty(final Player player, final String s, final Card source) {
|
||||||
final String[] l = s.split("/");
|
final String[] l = s.split("/");
|
||||||
final String m = extractOperators(s);
|
final String m = extractOperators(s);
|
||||||
|
|
||||||
@@ -1975,7 +1975,9 @@ public class CardFactoryUtil {
|
|||||||
// **************************************************
|
// **************************************************
|
||||||
// AbilityFactory cards
|
// AbilityFactory cards
|
||||||
for (String rawAbility : card.getUnparsedAbilities()) {
|
for (String rawAbility : card.getUnparsedAbilities()) {
|
||||||
card.addSpellAbility(AbilityFactory.getAbility(rawAbility, card));
|
final SpellAbility intrinsicAbility = AbilityFactory.getAbility(rawAbility, card);
|
||||||
|
card.addSpellAbility(intrinsicAbility);
|
||||||
|
intrinsicAbility.setIntrinsic(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
|
|||||||
*/
|
*/
|
||||||
public ReplacementEffect(final Map<String, String> map, final Card host, final boolean intrinsic) {
|
public ReplacementEffect(final Map<String, String> map, final Card host, final boolean intrinsic) {
|
||||||
this.intrinsic = intrinsic;
|
this.intrinsic = intrinsic;
|
||||||
|
originalMapParams.putAll(map);
|
||||||
mapParams.putAll(map);
|
mapParams.putAll(map);
|
||||||
this.setHostCard(host);
|
this.setHostCard(host);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,6 +192,10 @@ public class ReplacementHandler implements IGameStateObject {
|
|||||||
} while(tailend != null);
|
} while(tailend != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (effectSA.isIntrinsic()) {
|
||||||
|
effectSA.changeText();
|
||||||
|
}
|
||||||
|
|
||||||
// Decider gets to choose whether or not to apply the replacement.
|
// Decider gets to choose whether or not to apply the replacement.
|
||||||
if (replacementEffect.getMapParams().containsKey("Optional")) {
|
if (replacementEffect.getMapParams().containsKey("Optional")) {
|
||||||
Player optDecider = decider;
|
Player optDecider = decider;
|
||||||
|
|||||||
@@ -86,8 +86,11 @@ public final class AbilitySub extends SpellAbility implements java.io.Serializab
|
|||||||
this.setTargetRestrictions(tgt);
|
this.setTargetRestrictions(tgt);
|
||||||
|
|
||||||
api = api0;
|
api = api0;
|
||||||
if (params0 != null)
|
if (params0 != null) {
|
||||||
|
originalMapParams.putAll(params0);
|
||||||
mapParams.putAll(params0);
|
mapParams.putAll(params0);
|
||||||
|
}
|
||||||
|
|
||||||
effect = api.getSpellEffect();
|
effect = api.getSpellEffect();
|
||||||
|
|
||||||
if (effect instanceof ManaEffect || effect instanceof ManaReflectedEffect) {
|
if (effect instanceof ManaEffect || effect instanceof ManaReflectedEffect) {
|
||||||
|
|||||||
@@ -1773,4 +1773,17 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
public void setChosenList(List<AbilitySub> choices) {
|
public void setChosenList(List<AbilitySub> choices) {
|
||||||
this.chosenList = choices;
|
this.chosenList = choices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changeText() {
|
||||||
|
super.changeText();
|
||||||
|
|
||||||
|
if (this.targetRestricions != null) {
|
||||||
|
this.targetRestricions.applyTargetTextChanges(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.subAbility != null) {
|
||||||
|
this.subAbility.changeText();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -24,6 +24,7 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -47,7 +48,8 @@ public class TargetRestrictions {
|
|||||||
|
|
||||||
// What this Object is restricted to targeting
|
// What this Object is restricted to targeting
|
||||||
private boolean tgtValid = false;
|
private boolean tgtValid = false;
|
||||||
private String[] validTgts;
|
private String[] originalValidTgts,
|
||||||
|
validTgts;
|
||||||
private String uiPrompt = "";
|
private String uiPrompt = "";
|
||||||
private List<ZoneType> tgtZone = Arrays.asList(ZoneType.Battlefield);
|
private List<ZoneType> tgtZone = Arrays.asList(ZoneType.Battlefield);
|
||||||
|
|
||||||
@@ -86,7 +88,8 @@ public class TargetRestrictions {
|
|||||||
public TargetRestrictions(final TargetRestrictions target) {
|
public TargetRestrictions(final TargetRestrictions target) {
|
||||||
this.tgtValid = true;
|
this.tgtValid = true;
|
||||||
this.uiPrompt = target.getVTSelection();
|
this.uiPrompt = target.getVTSelection();
|
||||||
this.validTgts = target.getValidTgts();
|
this.originalValidTgts = target.getValidTgts();
|
||||||
|
this.validTgts = this.originalValidTgts.clone();
|
||||||
this.minTargets = target.getMinTargets();
|
this.minTargets = target.getMinTargets();
|
||||||
this.maxTargets = target.getMaxTargets();
|
this.maxTargets = target.getMaxTargets();
|
||||||
this.tgtZone = target.getZone();
|
this.tgtZone = target.getZone();
|
||||||
@@ -120,7 +123,8 @@ public class TargetRestrictions {
|
|||||||
public TargetRestrictions(final String prompt, final String[] valid, final String min, final String max) {
|
public TargetRestrictions(final String prompt, final String[] valid, final String min, final String max) {
|
||||||
this.tgtValid = true;
|
this.tgtValid = true;
|
||||||
this.uiPrompt = prompt;
|
this.uiPrompt = prompt;
|
||||||
this.validTgts = valid;
|
this.originalValidTgts = valid;
|
||||||
|
this.validTgts = this.originalValidTgts.clone();
|
||||||
this.minTargets = min;
|
this.minTargets = min;
|
||||||
this.maxTargets = max;
|
this.maxTargets = max;
|
||||||
}
|
}
|
||||||
@@ -419,6 +423,8 @@ public class TargetRestrictions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.applyTargetTextChanges(sa);
|
||||||
|
|
||||||
final Card srcCard = sa.getHostCard(); // should there be OrginalHost at any moment?
|
final Card srcCard = sa.getHostCard(); // should there be OrginalHost at any moment?
|
||||||
if (this.tgtZone.contains(ZoneType.Stack)) {
|
if (this.tgtZone.contains(ZoneType.Stack)) {
|
||||||
// Stack Zone targets are considered later
|
// Stack Zone targets are considered later
|
||||||
@@ -476,6 +482,8 @@ public class TargetRestrictions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.applyTargetTextChanges(sa);
|
||||||
|
|
||||||
final Card srcCard = sa.getHostCard(); // should there be OrginalHost at any moment?
|
final Card srcCard = sa.getHostCard(); // should there be OrginalHost at any moment?
|
||||||
if (this.tgtZone.contains(ZoneType.Stack)) {
|
if (this.tgtZone.contains(ZoneType.Stack)) {
|
||||||
for (final Card c : game.getStackZone().getCards()) {
|
for (final Card c : game.getStackZone().getCards()) {
|
||||||
@@ -698,4 +706,10 @@ public class TargetRestrictions {
|
|||||||
return this.dividedMap;
|
return this.dividedMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final void applyTargetTextChanges(final SpellAbility sa) {
|
||||||
|
for (int i = 0; i < validTgts.length; i++) {
|
||||||
|
validTgts[i] = AbilityUtils.applyTextChangeEffects(originalValidTgts[i], sa.getHostCard());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,10 @@ public class StaticAbility extends CardTraitBase {
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.mapParams.containsKey("ChangeText")) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.mapParams.containsKey("AddType") || this.mapParams.containsKey("RemoveType")
|
if (this.mapParams.containsKey("AddType") || this.mapParams.containsKey("RemoveType")
|
||||||
|| this.mapParams.containsKey("RemoveCardTypes") || this.mapParams.containsKey("RemoveSubTypes")
|
|| this.mapParams.containsKey("RemoveCardTypes") || this.mapParams.containsKey("RemoveSubTypes")
|
||||||
|| this.mapParams.containsKey("RemoveSuperTypes") || this.mapParams.containsKey("RemoveCreatureTypes")) {
|
|| this.mapParams.containsKey("RemoveSuperTypes") || this.mapParams.containsKey("RemoveCreatureTypes")) {
|
||||||
@@ -170,7 +174,9 @@ public class StaticAbility extends CardTraitBase {
|
|||||||
* the host
|
* the host
|
||||||
*/
|
*/
|
||||||
public StaticAbility(final String params, final Card host) {
|
public StaticAbility(final String params, final Card host) {
|
||||||
this.mapParams.putAll(this.parseParams(params, host));
|
final Map<String, String> parsedParams = this.parseParams(params, host);
|
||||||
|
this.originalMapParams.putAll(parsedParams);
|
||||||
|
this.mapParams.putAll(parsedParams);
|
||||||
this.hostCard = host;
|
this.hostCard = host;
|
||||||
this.layer = this.generateLayer();
|
this.layer = this.generateLayer();
|
||||||
}
|
}
|
||||||
@@ -183,10 +189,9 @@ public class StaticAbility extends CardTraitBase {
|
|||||||
* @param host
|
* @param host
|
||||||
* the host
|
* the host
|
||||||
*/
|
*/
|
||||||
public StaticAbility(final HashMap<String, String> params, final Card host) {
|
public StaticAbility(final Map<String, String> params, final Card host) {
|
||||||
for (final Map.Entry<String, String> entry : params.entrySet()) {
|
this.originalMapParams.putAll(params);
|
||||||
this.mapParams.put(entry.getKey(), entry.getValue());
|
this.mapParams.putAll(params);
|
||||||
}
|
|
||||||
this.layer = this.generateLayer();
|
this.layer = this.generateLayer();
|
||||||
this.hostCard = host;
|
this.hostCard = host;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ public abstract class Trigger extends TriggerReplacementBase {
|
|||||||
this.intrinsic = intrinsic;
|
this.intrinsic = intrinsic;
|
||||||
|
|
||||||
this.setRunParams(new HashMap<String, Object>());
|
this.setRunParams(new HashMap<String, Object>());
|
||||||
|
this.originalMapParams.putAll(params);
|
||||||
this.mapParams.putAll(params);
|
this.mapParams.putAll(params);
|
||||||
this.setHostCard(host);
|
this.setHostCard(host);
|
||||||
}
|
}
|
||||||
@@ -441,8 +442,8 @@ public abstract class Trigger extends TriggerReplacementBase {
|
|||||||
|
|
||||||
|
|
||||||
public final Trigger getCopyForHostCard(Card newHost) {
|
public final Trigger getCopyForHostCard(Card newHost) {
|
||||||
TriggerType tt = TriggerType.getTypeFor(this);
|
final TriggerType tt = TriggerType.getTypeFor(this);
|
||||||
Trigger copy = tt.createTrigger(mapParams, newHost, intrinsic);
|
final Trigger copy = tt.createTrigger(originalMapParams, newHost, intrinsic);
|
||||||
|
|
||||||
if (this.getOverridingAbility() != null) {
|
if (this.getOverridingAbility() != null) {
|
||||||
copy.setOverridingAbility(this.getOverridingAbility());
|
copy.setOverridingAbility(this.getOverridingAbility());
|
||||||
|
|||||||
@@ -390,6 +390,10 @@ public class TriggerHandler implements IGameStateObject {
|
|||||||
host.addRemembered(sa.getActivatingPlayer());
|
host.addRemembered(sa.getActivatingPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (regtrig.isIntrinsic()) {
|
||||||
|
sa.changeText();
|
||||||
|
}
|
||||||
|
|
||||||
sa.setStackDescription(sa.toString());
|
sa.setStackDescription(sa.toString());
|
||||||
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
||||||
CharmEffect.makeChoices(sa);
|
CharmEffect.makeChoices(sa);
|
||||||
|
|||||||
Reference in New Issue
Block a user