mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
Merge branch 'tokenCardText' into 'master'
Token card text Closes #716 See merge request core-developers/forge!961
This commit is contained in:
@@ -188,6 +188,21 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
|
||||
return supertypes.remove(st);
|
||||
}
|
||||
|
||||
public boolean remove(final String str) {
|
||||
boolean changed = false;
|
||||
if (CardType.isASupertype(str) && supertypes.remove(stringToSupertype.get(str))) {
|
||||
changed = true;
|
||||
} else if (CardType.isACardType(str) && coreTypes.remove(stringToCoreType.get(str))) {
|
||||
changed = true;
|
||||
} else if (subtypes.remove(str)) {
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
calculatedType = null;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public boolean setCreatureTypes(Collection<String> ctypes) {
|
||||
// if it isn't a creature then this has no effect
|
||||
if (!isCreature() && !isTribal()) {
|
||||
|
||||
@@ -46,6 +46,11 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView {
|
||||
|
||||
protected Map<String, String> sVars = Maps.newHashMap();
|
||||
|
||||
protected Map<String, String> intrinsicChangedTextColors = Maps.newHashMap();
|
||||
protected Map<String, String> intrinsicChangedTextTypes = Maps.newHashMap();
|
||||
protected Map<String, String> changedTextColors = Maps.newHashMap();
|
||||
protected Map<String, String> changedTextTypes = Maps.newHashMap();
|
||||
|
||||
/** Keys of descriptive (text) parameters. */
|
||||
private static final ImmutableList<String> descriptiveKeys = ImmutableList.<String>builder()
|
||||
.add("Description", "SpellDescription", "StackDescription", "TriggerDescription").build();
|
||||
@@ -53,6 +58,11 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView {
|
||||
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").build();
|
||||
/**
|
||||
* Sets the temporary.
|
||||
*
|
||||
@@ -449,9 +459,15 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView {
|
||||
}
|
||||
|
||||
public void changeText() {
|
||||
// copy changed text words into card trait there
|
||||
this.changedTextColors = getHostCard().getChangedTextColorWords();
|
||||
this.changedTextTypes = getHostCard().getChangedTextTypeWords();
|
||||
|
||||
for (final String key : this.mapParams.keySet()) {
|
||||
final String value = this.originalMapParams.get(key), newValue;
|
||||
if (descriptiveKeys.contains(key)) {
|
||||
if (noChangeKeys.contains(key)) {
|
||||
continue;
|
||||
} else if (descriptiveKeys.contains(key)) {
|
||||
// change descriptions differently
|
||||
newValue = AbilityUtils.applyDescriptionTextChangeEffects(value, this);
|
||||
} else if (mutableKeys.contains(key)) {
|
||||
@@ -515,4 +531,53 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView {
|
||||
public Set<String> getSVars() {
|
||||
return sVars.keySet();
|
||||
}
|
||||
|
||||
public Map<String, String> getChangedTextColors() {
|
||||
return _combineChangedMap(intrinsicChangedTextColors, changedTextColors);
|
||||
}
|
||||
public Map<String, String> getChangedTextTypes() {
|
||||
return _combineChangedMap(intrinsicChangedTextTypes, changedTextTypes);
|
||||
}
|
||||
|
||||
private Map<String, String> _combineChangedMap(Map<String, String> input, Map<String, String> output) {
|
||||
// no need to do something, just return hash
|
||||
if (input.isEmpty()) {
|
||||
return output;
|
||||
}
|
||||
if (output.isEmpty()) {
|
||||
return input;
|
||||
}
|
||||
// magic combine them
|
||||
Map<String, String> result = Maps.newHashMap(output);
|
||||
for (Map.Entry<String, String> e : input.entrySet()) {
|
||||
String value = e.getValue();
|
||||
result.put(e.getKey(), output.containsKey(value) ? output.get(value) : value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void changeTextIntrinsic(Map<String,String> colorMap, Map<String,String> typeMap) {
|
||||
intrinsicChangedTextColors = colorMap;
|
||||
intrinsicChangedTextTypes = typeMap;
|
||||
for (final String key : this.mapParams.keySet()) {
|
||||
final String value = this.originalMapParams.get(key), newValue;
|
||||
if (noChangeKeys.contains(key)) {
|
||||
continue;
|
||||
} else if (descriptiveKeys.contains(key)) {
|
||||
// change descriptions differently
|
||||
newValue = AbilityUtils.applyTextChangeEffects(value, true, colorMap, typeMap);
|
||||
}else if (this.getHostCard().hasSVar(value)) {
|
||||
// don't change literal SVar names!
|
||||
continue;
|
||||
} else {
|
||||
newValue = AbilityUtils.applyTextChangeEffects(value, false, colorMap, typeMap);
|
||||
}
|
||||
|
||||
if (newValue != null) {
|
||||
this.mapParams.put(key, newValue);
|
||||
}
|
||||
}
|
||||
// this does overwrite the original MapParams
|
||||
this.originalMapParams = Maps.newHashMap(this.mapParams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1724,12 +1724,18 @@ public class AbilityUtils {
|
||||
}
|
||||
|
||||
private static final String applyTextChangeEffects(final String def, final Card card, final boolean isDescriptive) {
|
||||
return applyTextChangeEffects(def, isDescriptive,
|
||||
card.getChangedTextColorWords(), card.getChangedTextTypeWords());
|
||||
}
|
||||
|
||||
public static final String applyTextChangeEffects(final String def, final boolean isDescriptive,
|
||||
Map<String,String> colorMap, Map<String,String> typeMap) {
|
||||
if (StringUtils.isEmpty(def)) {
|
||||
return def;
|
||||
}
|
||||
|
||||
String replaced = def;
|
||||
for (final Entry<String, String> e : card.getChangedTextColorWords().entrySet()) {
|
||||
for (final Entry<String, String> e : colorMap.entrySet()) {
|
||||
final String key = e.getKey();
|
||||
String value;
|
||||
if (key.equals("Any")) {
|
||||
@@ -1750,7 +1756,7 @@ public class AbilityUtils {
|
||||
replaced = replaced.replaceAll("(?<!>)" + key, value);
|
||||
}
|
||||
}
|
||||
for (final Entry<String, String> e : card.getChangedTextTypeWords().entrySet()) {
|
||||
for (final Entry<String, String> e : typeMap.entrySet()) {
|
||||
final String key = e.getKey();
|
||||
final String pkey = CardType.getPluralType(key);
|
||||
final String pvalue = getReplacedText(pkey, CardType.getPluralType(e.getValue()), isDescriptive);
|
||||
|
||||
@@ -3640,6 +3640,12 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
}
|
||||
|
||||
public final void removeIntrinsicKeyword(final KeywordInterface s) {
|
||||
if (currentState.removeIntrinsicKeyword(s)) {
|
||||
currentState.getView().updateKeywords(this, currentState);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<KeywordInterface> getExtrinsicKeyword() {
|
||||
return extrinsicKeyword.getValues();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import java.util.SortedMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.card.CardType;
|
||||
|
||||
public final class CardChangedWords {
|
||||
|
||||
private final SortedMap<Long, CardChangedWord> map = Maps.newTreeMap();
|
||||
@@ -68,14 +66,9 @@ public final class CardChangedWords {
|
||||
|
||||
// the actual change (b->c)
|
||||
resultCache.put(ccw.getOriginalWord(), ccw.getNewWord());
|
||||
|
||||
// possible plural form
|
||||
final String singular = CardType.getPluralType(ccw.getOriginalWord());
|
||||
if (!singular.equals(ccw.getOriginalWord())) {
|
||||
resultCache.put(singular, ccw.getNewWord());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO should that be removed?
|
||||
for (final String key : ImmutableList.copyOf(resultCache.keySet())) {
|
||||
if (!key.equals("Any")) {
|
||||
resultCache.put(key.toLowerCase(), resultCache.get(key).toLowerCase());
|
||||
|
||||
@@ -231,6 +231,9 @@ public class CardState extends GameObject {
|
||||
public final boolean removeIntrinsicKeyword(final String s) {
|
||||
return intrinsicKeywords.remove(s);
|
||||
}
|
||||
public final boolean removeIntrinsicKeyword(final KeywordInterface s) {
|
||||
return intrinsicKeywords.remove(s);
|
||||
}
|
||||
|
||||
public final FCollectionView<SpellAbility> getSpellAbilities() {
|
||||
FCollection<SpellAbility> newCol = new FCollection<SpellAbility>(manaAbilities);
|
||||
@@ -554,4 +557,19 @@ public class CardState extends GameObject {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void changeTextIntrinsic(Map<String,String> colorMap, Map<String,String> typeMap) {
|
||||
final List<CardTraitBase> allAbs = ImmutableList.<CardTraitBase>builder()
|
||||
.addAll(manaAbilities)
|
||||
.addAll(nonManaAbilities)
|
||||
.addAll(triggers)
|
||||
.addAll(replacementEffects)
|
||||
.addAll(staticAbilities)
|
||||
.build();
|
||||
for (final CardTraitBase ctb : allAbs) {
|
||||
if (ctb.isIntrinsic()) {
|
||||
ctb.changeTextIntrinsic(colorMap, typeMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,6 +281,8 @@ public final class CardUtil {
|
||||
newCopy.setChangedCardKeywords(in.getChangedCardKeywords());
|
||||
newCopy.setChangedCardTypes(in.getChangedCardTypesMap());
|
||||
|
||||
newCopy.copyChangedTextFrom(in);
|
||||
|
||||
newCopy.setMeldedWith(in.getMeldedWith());
|
||||
|
||||
newCopy.setTimestamp(in.getTimestamp());
|
||||
|
||||
@@ -12,6 +12,7 @@ import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardFactory;
|
||||
import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.keyword.KeywordInterface;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
@@ -20,6 +21,8 @@ import forge.item.PaperToken;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class TokenInfo {
|
||||
final String name;
|
||||
final String imageName;
|
||||
@@ -229,10 +232,121 @@ public class TokenInfo {
|
||||
String edition = host.getSetCode();
|
||||
PaperToken token = StaticData.instance().getAllTokens().getToken(script, edition);
|
||||
|
||||
// TODO add Card Text Change from SpellAbility
|
||||
|
||||
if (token != null) {
|
||||
return Card.fromPaperCard(token, null, game);
|
||||
final Card result = Card.fromPaperCard(token, null, game);
|
||||
|
||||
// update Token with CardTextChanges
|
||||
Map<String, String> colorMap = sa.getChangedTextColors();
|
||||
Map<String, String> typeMap = sa.getChangedTextTypes();
|
||||
if (!colorMap.isEmpty()) {
|
||||
if (!result.isColorless()) {
|
||||
// change Token Colors
|
||||
byte color = CardUtil.getColors(result).getColor();
|
||||
|
||||
for (final Map.Entry<String, String> e : colorMap.entrySet()) {
|
||||
byte v = MagicColor.fromName(e.getValue());
|
||||
// Any used by Swirl the Mists
|
||||
if ("Any".equals(e.getKey())) {
|
||||
for (final byte c : MagicColor.WUBRG) {
|
||||
// try to replace color flips
|
||||
if ((color & c) != 0) {
|
||||
color &= ~c;
|
||||
color |= v;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
byte c = MagicColor.fromName(e.getKey());
|
||||
// try to replace color flips
|
||||
if ((color & c) != 0) {
|
||||
color &= ~c;
|
||||
color |= v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.setColor(color);
|
||||
}
|
||||
}
|
||||
if (!typeMap.isEmpty()) {
|
||||
String oldName = result.getName();
|
||||
|
||||
CardType type = new CardType(result.getType());
|
||||
String joinedName = StringUtils.join(type.getSubtypes(), " ");
|
||||
final boolean nameGenerated = oldName.equals(joinedName);
|
||||
boolean typeChanged = false;
|
||||
|
||||
if (!Iterables.isEmpty(type.getSubtypes())) {
|
||||
for (final Map.Entry<String, String> e : typeMap.entrySet()) {
|
||||
if (type.hasSubtype(e.getKey())) {
|
||||
type.remove(e.getKey());
|
||||
type.add(e.getValue());
|
||||
typeChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeChanged) {
|
||||
result.setType(type);
|
||||
|
||||
// update generated Name
|
||||
if (nameGenerated) {
|
||||
result.setName(StringUtils.join(type.getSubtypes(), " "));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// replace Intrinsic Keyword
|
||||
List<KeywordInterface> toRemove = Lists.newArrayList();
|
||||
List<String> toAdd = Lists.newArrayList();
|
||||
for (final KeywordInterface k : result.getCurrentState().getIntrinsicKeywords()) {
|
||||
final String o = k.getOriginal();
|
||||
// only Modifiable should go there
|
||||
if (!CardUtil.isKeywordModifiable(o)) {
|
||||
continue;
|
||||
}
|
||||
String r = new String(o);
|
||||
// replace types
|
||||
for (final Map.Entry<String, String> e : typeMap.entrySet()) {
|
||||
final String key = e.getKey();
|
||||
final String pkey = CardType.getPluralType(key);
|
||||
final String value = e.getValue();
|
||||
final String pvalue = CardType.getPluralType(e.getValue());
|
||||
r = r.replaceAll(pkey, pvalue);
|
||||
r = r.replaceAll(key, value);
|
||||
}
|
||||
// replace color words
|
||||
for (final Map.Entry<String, String> e : colorMap.entrySet()) {
|
||||
final String vName = e.getValue();
|
||||
final String vCaps = StringUtils.capitalize(vName);
|
||||
final String vLow = vName.toLowerCase();
|
||||
if ("Any".equals(e.getKey())) {
|
||||
for (final byte c : MagicColor.WUBRG) {
|
||||
final String cName = MagicColor.toLongString(c);
|
||||
final String cNameCaps = StringUtils.capitalize(cName);
|
||||
final String cNameLow = cName.toLowerCase();
|
||||
r = r.replaceAll(cNameCaps, vCaps);
|
||||
r = r.replaceAll(cNameLow, vLow);
|
||||
}
|
||||
} else {
|
||||
final String cName = e.getKey();
|
||||
final String cNameCaps = StringUtils.capitalize(cName);
|
||||
final String cNameLow = cName.toLowerCase();
|
||||
r = r.replaceAll(cNameCaps, vCaps);
|
||||
r = r.replaceAll(cNameLow, vLow);
|
||||
}
|
||||
}
|
||||
if (!r.equals(o)) {
|
||||
toRemove.add(k);
|
||||
toAdd.add(r);
|
||||
}
|
||||
}
|
||||
for (final KeywordInterface k : toRemove) {
|
||||
result.getCurrentState().removeIntrinsicKeyword(k);
|
||||
}
|
||||
result.addIntrinsicKeywords(toAdd);
|
||||
|
||||
result.getCurrentState().changeTextIntrinsic(colorMap, typeMap);
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -96,6 +96,10 @@ public class KeywordCollection implements Iterable<String>, Serializable {
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean remove(KeywordInterface keyword) {
|
||||
return map.remove(keyword.getKeyword(), keyword);
|
||||
}
|
||||
|
||||
public boolean removeAll(Iterable<String> keywords) {
|
||||
boolean result = false;
|
||||
for (String k : keywords) {
|
||||
|
||||
@@ -1709,6 +1709,31 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.CardTraitBase#changeTextIntrinsic(java.util.Map, java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public void changeTextIntrinsic(Map<String, String> colorMap, Map<String, String> typeMap) {
|
||||
super.changeTextIntrinsic(colorMap, typeMap);
|
||||
|
||||
if (subAbility != null) {
|
||||
// if the parent of the subability is not this,
|
||||
// then there might be a loop
|
||||
if (subAbility.getParent() == this) {
|
||||
subAbility.changeTextIntrinsic(colorMap, typeMap);
|
||||
}
|
||||
}
|
||||
for (AbilitySub sa : additionalAbilities.values()) {
|
||||
sa.changeTextIntrinsic(colorMap, typeMap);
|
||||
}
|
||||
|
||||
for (List<AbilitySub> list : additionalAbilityLists.values()) {
|
||||
for (AbilitySub sa : list) {
|
||||
sa.changeTextIntrinsic(colorMap, typeMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIntrinsic(boolean i) {
|
||||
super.setIntrinsic(i);
|
||||
|
||||
@@ -169,11 +169,7 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
if (!desc.contains("ABILITY")) {
|
||||
return desc;
|
||||
}
|
||||
SpellAbility sa = getOverridingAbility();
|
||||
if (sa == null && this.mapParams.containsKey("Execute")) {
|
||||
sa = AbilityFactory.getAbility(state, this.mapParams.get("Execute"));
|
||||
setOverridingAbility(sa);
|
||||
}
|
||||
SpellAbility sa = ensureAbility();
|
||||
|
||||
return replaceAbilityText(desc, sa);
|
||||
|
||||
@@ -583,4 +579,48 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
throw new RuntimeException("Trigger : clone() error, " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.CardTraitBase#changeText()
|
||||
*/
|
||||
@Override
|
||||
public void changeText() {
|
||||
if (!isIntrinsic()) {
|
||||
return;
|
||||
}
|
||||
super.changeText();
|
||||
|
||||
ensureAbility();
|
||||
|
||||
if (getOverridingAbility() != null) {
|
||||
getOverridingAbility().changeText();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.CardTraitBase#changeTextIntrinsic(java.util.Map, java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public void changeTextIntrinsic(Map<String, String> colorMap, Map<String, String> typeMap) {
|
||||
if (!isIntrinsic()) {
|
||||
return;
|
||||
}
|
||||
super.changeTextIntrinsic(colorMap, typeMap);
|
||||
|
||||
ensureAbility();
|
||||
|
||||
if (getOverridingAbility() != null) {
|
||||
getOverridingAbility().changeTextIntrinsic(colorMap, typeMap);
|
||||
}
|
||||
}
|
||||
|
||||
private SpellAbility ensureAbility() {
|
||||
SpellAbility sa = getOverridingAbility();
|
||||
if (sa == null && hasParam("Execute")) {
|
||||
sa = AbilityFactory.getAbility(getHostCard(), getParam("Execute"));
|
||||
setOverridingAbility(sa);
|
||||
}
|
||||
return sa;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@ ManaCost:3 R
|
||||
Types:Creature Human Shaman
|
||||
PT:2/3
|
||||
T:Mode$ Attached | ValidSource$ Aura | ValidTarget$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever an Aura becomes attached to CARDNAME, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn."
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenName$ Dragon | TokenTypes$ Creature,Dragon | TokenOwner$ You | TokenColors$ Red | TokenPower$ 2 | TokenToughness$ 2 | TokenImage$ r 2 2 dragon M15 | TokenKeywords$ Flying | TokenAbilities$ BroodPump
|
||||
SVar:BroodPump:AB$ Pump | Cost$ R | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn.
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | LegacyImage$ r 2 2 dragon M15 | TokenScript$ r_2_2_dragon_flying_firebreathing
|
||||
SVar:EnchantMe:Multiple
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/brood_keeper.jpg
|
||||
Oracle:Whenever an Aura becomes attached to Brood Keeper, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn."
|
||||
|
||||
@@ -4,8 +4,7 @@ Types:Creature Dragon Egg
|
||||
PT:0/2
|
||||
K:Defender
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn".
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenName$ Dragon | TokenTypes$ Creature,Dragon | TokenOwner$ You | TokenColors$ Red | TokenPower$ 2 | TokenToughness$ 2 | TokenImage$ r 2 2 dragon M14 | TokenKeywords$ Flying | TokenAbilities$ DragonPump
|
||||
SVar:DragonPump:AB$ Pump | Cost$ R | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn.
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | LegacyImage$ r 2 2 dragon M14 | TokenScript$ r_2_2_dragon_flying_firebreathing
|
||||
SVar:SacMe:4
|
||||
DeckHas:Ability$Token
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/dragon_egg.jpg
|
||||
|
||||
@@ -4,6 +4,6 @@ Types:Creature Horror
|
||||
PT:7/7
|
||||
K:Trample
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, target opponent creates two 3/3 green Centaur creature tokens with protection from black.
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenName$ Centaur | TokenImage$ g 3 3 centaur pro black | TokenTypes$ Creature,Centaur | ValidTgts$ Opponent | TokenOwner$ Targeted | TokenColors$ Green | TokenPower$ 3 | TokenToughness$ 3 | TokenKeywords$ Protection from black
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ g_3_3_centaur_pro_black | ValidTgts$ Opponent | TokenOwner$ Targeted | LegacyImage$ g 3 3 centaur pro black
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/hunted_horror.jpg
|
||||
Oracle:Trample\nWhen Hunted Horror enters the battlefield, target opponent creates two 3/3 green Centaur creature tokens with protection from black.
|
||||
@@ -5,7 +5,7 @@ PT:5/5
|
||||
K:Forestwalk
|
||||
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME attacks or blocks, create a 2/2 green Cat Warrior creature token with forestwalk.
|
||||
T:Mode$ Blocks | ValidCard$ Card.Self | Execute$ TrigToken | Secondary$ True | TriggerDescription$ Whenever CARDNAME attacks or blocks, create a 2/2 green Cat Warrior creature token with forestwalk.
|
||||
SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenName$ Cat Warrior | TokenTypes$ Creature,Cat,Warrior | TokenOwner$ You | TokenColors$ Green | TokenPower$ 2 | TokenToughness$ 2 | TokenKeywords$ Forestwalk
|
||||
SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ g_2_2_cat_warrior_forestwalk
|
||||
SVar:HasAttackEffect:TRUE
|
||||
SVar:HasBlockEffect:TRUE
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/jedit_ojanen_of_efrava.jpg
|
||||
|
||||
@@ -5,8 +5,7 @@ PT:*/*
|
||||
S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | SetToughness$ X | Description$ CARDNAMEs power and toughness are each equal to the number of Forests you control.
|
||||
SVar:X:Count$Valid Forest.YouCtrl
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a green Treefolk Warrior creature token with "This creature's power and toughness are each equal to the number of Forests you control."
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenName$ Treefolk Warrior | TokenTypes$ Creature,Treefolk,Warrior | TokenOwner$ You | TokenColors$ Green | TokenPower$ X | TokenToughness$ X | TokenStaticAbilities$ TokenPT | TokenSVars$ X | References$ X | TokenImage$ g x x treefolk warrior
|
||||
SVar:TokenPT:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | SetToughness$ X | Description$ CARDNAME's power and toughness are each equal to the number of Forests you control.
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ g_x_x_treefolk_warrior | LegacyImage$ g x x treefolk warrior
|
||||
SVar:BuffedBy:Forest
|
||||
SVar:NeedsToPlayVar:X GE3
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/kalonian_twingrove.jpg
|
||||
|
||||
@@ -8,6 +8,6 @@ SVar:DBDraw2:DB$ Draw | NumCards$ 1 | ConditionDefined$ Remembered | ConditionPr
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
A:AB$ ChangeZone | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | Origin$ Graveyard | Destination$ Battlefield | TargetMin$ 0 | TargetMax$ 2 | TgtPrompt$ Choose target land card in your graveyard | ValidTgts$ Land.YouCtrl | SpellDescription$ Return up to two target land cards from your graveyard to the battlefield.
|
||||
A:AB$ Destroy | Cost$ SubCounter<11/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | TargetMin$ 0 | TargetMax$ 6 | SubAbility$ DBToken | SpellDescription$ Destroy up to six target nonland permanents, then create six 2/2 green Cat Warrior creature tokens with forestwalk.
|
||||
SVar:DBToken:DB$ Token | TokenAmount$ 6 | TokenName$ Cat Warrior | TokenTypes$ Creature,Cat,Warrior | TokenOwner$ You | TokenColors$ Green | TokenPower$ 2 | TokenToughness$ 2 | TokenKeywords$ Forestwalk | TokenImage$ g 2 2 cat warrior c18
|
||||
SVar:DBToken:DB$ Token | TokenAmount$ 6 | TokenOwner$ You | TokenScript$ g_2_2_cat_warrior_forestwalk | LegacyImage$ g 2 2 cat warrior c18
|
||||
K:CARDNAME can be your commander.
|
||||
Oracle:[+2]: Discard a card, then draw a card. If a land card is discarded this way, draw an additional card.\n[-3]: Return up to two target land cards from your graveyard to the battlefield.\n[-11]: Destroy up to six target nonland permanents, then create six 2/2 green Cat Warrior creature tokens with forestwalk.\nLord Windgrace can be your commander.
|
||||
|
||||
@@ -3,8 +3,6 @@ ManaCost:4 G
|
||||
Types:Creature Ooze
|
||||
PT:4/4
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenSenior | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create two 2/2 green Ooze creature tokens. They have "When this creature dies, create two 1/1 green Ooze creature tokens."
|
||||
SVar:TrigTokenSenior:DB$Token | TokenImage$ g 2 2 ooze | TokenName$ Ooze | TokenTypes$ Creature,Ooze | TokenColors$ Green | TokenOwner$ You | TokenPower$ 2 | TokenToughness$ 2 | TokenAmount$ 2 | TokenTriggers$ TriggerJunior | TokenSVars$ TrigTokenJunior
|
||||
SVar:TriggerJunior:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenJunior | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create two 1/1 green Ooze creature tokens.
|
||||
SVar:TrigTokenJunior:DB$Token | TokenImage$ g 1 1 ooze | TokenName$ Ooze | TokenTypes$ Creature,Ooze | TokenColors$ Green | TokenOwner$ You | TokenPower$ 1 | TokenToughness$ 1 | TokenAmount$ 2
|
||||
SVar:TrigTokenSenior:DB$Token | LegacyImage$ g 2 2 ooze | TokenScript$ g_2_2_ooze_mitotic | TokenOwner$ You | TokenAmount$ 2
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/mitotic_slime.jpg
|
||||
Oracle:When Mitotic Slime dies, create two 2/2 green Ooze creature tokens. They have "When this creature dies, create two 1/1 green Ooze creature tokens."
|
||||
|
||||
@@ -4,8 +4,5 @@ Types:Creature Dragon
|
||||
PT:5/4
|
||||
K:Flying
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Landfall Whenever a land enters the battlefield under your control, create a 0/2 red Dragon creature token with defender and "When this creature dies, create a 2/2 red Dragon creature token with flying and '{R}: This creature gets +1/+0 until end of turn.'"
|
||||
SVar:TrigToken:DB$ Token | TokenImage$ r 0 2 dragon egg | TokenAmount$ 1 | TokenName$ Dragon Egg | TokenTypes$ Creature,Dragon,Egg | TokenOwner$ You | TokenColors$ Red | TokenPower$ 0 | TokenToughness$ 2 | TokenKeywords$ Defender | TokenTriggers$ TriggerDies | TokenSVars$ TrigToken2,DragonPump
|
||||
SVar:TriggerDies:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken2 | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create a 2/2 red Dragon creature token with flying and "{R}: This creature gets +1/+0 until end of turn."
|
||||
SVar:TrigToken2:DB$Token | TokenImage$ r 2 2 dragon c18 | TokenAmount$ 1 | TokenName$ Dragon | TokenTypes$ Creature,Dragon | TokenOwner$ You | TokenColors$ Red | TokenPower$ 2 | TokenToughness$ 2 | TokenKeywords$ Flying | TokenAbilities$ DragonPump
|
||||
SVar:DragonPump:AB$ Pump | Cost$ R | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn.
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | LegacyImage$ r 0 2 dragon egg | TokenScript$ r_0_2_dragon_egg_defender_hatches_dragon
|
||||
Oracle:Flying\nLandfall — Whenever a land enters the battlefield under your control, create a 0/2 red Dragon Egg creature token with defender and "When this creature dies, create a 2/2 red Dragon creature token with flying and '{R}: This creature gets +1/+0 until end of turn.'"
|
||||
@@ -2,11 +2,7 @@ Name:Reef Worm
|
||||
ManaCost:3 U
|
||||
Types:Creature Worm
|
||||
PT:0/1
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenFish | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create a 3/3 blue Fish creature token with "When this creature dies, create a 6/6 blue Whale creature token with 'When this creature dies, create a 9/9 blue Kraken creature token.'"
|
||||
SVar:TrigTokenFish:DB$Token | TokenImage$ u 3 3 fish | TokenName$ Fish | TokenTypes$ Creature,Fish | TokenColors$ Blue | TokenOwner$ You | TokenPower$ 3 | TokenToughness$ 3 | TokenAmount$ 1 | TokenTriggers$ TriggerWhale | TokenSVars$ TrigTokenWhale,TriggerKraken,TrigTokenKraken
|
||||
SVar:TriggerWhale:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenWhale | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create a 6/6 blue Whale creature token with "When this creature dies, create a 9/9 blue Kraken creature token."
|
||||
SVar:TrigTokenWhale:DB$Token | TokenImage$ u 6 6 whale | TokenName$ Whale | TokenTypes$ Creature,Whale | TokenColors$ Blue | TokenOwner$ You | TokenPower$ 6 | TokenToughness$ 6 | TokenAmount$ 1 | TokenTriggers$ TriggerKraken | TokenSVars$ TrigTokenKraken
|
||||
SVar:TriggerKraken:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenKraken | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create a 9/9 blue Kraken creature token.
|
||||
SVar:TrigTokenKraken:DB$Token | TokenImage$ u 9 9 kraken c14 | TokenName$ Kraken | TokenTypes$ Creature,Kraken | TokenColors$ Blue | TokenOwner$ You | TokenPower$ 9 | TokenToughness$ 9 | TokenAmount$ 1
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create a 3/3 blue Fish creature token with "When this creature dies, create a 6/6 blue Whale creature token with 'When this creature dies, create a 9/9 blue Kraken creature token.'"
|
||||
SVar:TrigToken:DB$Token | LegacyImage$ u 3 3 fish | TokenScript$ u_3_3_fish_hatches_whale | TokenOwner$ You | TokenAmount$ 1
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/reef_worm.jpg
|
||||
Oracle:When Reef Worm dies, create a 3/3 blue Fish creature token with "When this creature dies, create a 6/6 blue Whale creature token with 'When this creature dies, create a 9/9 blue Kraken creature token.'"
|
||||
@@ -6,6 +6,6 @@ K:Flanking
|
||||
K:Protection from black
|
||||
K:Suspend:3:1 W W
|
||||
T:Mode$ CounterRemoved | ValidCard$ Card.Self | TriggerZones$ Exile | CounterType$ TIME | Execute$ TrigToken | IsPresent$ Card.Self+counters_GE1_TIME | PresentZone$ Exile | PresentCompare$ EQ0 | TriggerDescription$ When the last time counter is removed from CARDNAME while it's exiled, create a 2/2 black Knight creature token with flanking, protection from white, and haste.
|
||||
SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenName$ Knight | TokenTypes$ Creature,Knight | TokenOwner$ You | TokenColors$ Black | TokenPower$ 2 | TokenToughness$ 2 | TokenKeywords$ Flanking<>Protection from white<>Haste
|
||||
SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ b_2_2_knight_flanking_pro_white_haste
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/riftmarked_knight.jpg
|
||||
Oracle:Protection from black, flanking (Whenever a creature without flanking blocks this creature, the blocking creature gets -1/-1 until end of turn.)\nSuspend 3—{1}{W}{W} (Rather than cast this card from your hand, you may pay {1}{W}{W} and exile it with three time counters on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost. It has haste.)\nWhen the last time counter is removed from Riftmarked Knight while it's exiled, create a 2/2 black Knight creature token with flanking, protection from white, and haste.
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
Name:Knight
|
||||
ManaCost:no cost
|
||||
Types:Creature Knight
|
||||
Colors:black
|
||||
PT:2/2
|
||||
K:Flanking
|
||||
K:Protection from white
|
||||
K:Haste
|
||||
Oracle:Flanking\nProtection from white\nHaste
|
||||
6
forge-gui/res/tokenscripts/g_1_1_ooze.txt
Normal file
6
forge-gui/res/tokenscripts/g_1_1_ooze.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Name:Ooze
|
||||
ManaCost:no cost
|
||||
Types:Creature Ooze
|
||||
Colors:green
|
||||
PT:1/1
|
||||
Oracle:
|
||||
@@ -0,0 +1,7 @@
|
||||
Name:Cat Warrior
|
||||
ManaCost:no cost
|
||||
Types:Creature Cat Warrior
|
||||
Colors:green
|
||||
PT:2/2
|
||||
K:Forestwalk
|
||||
Oracle:Forestwalk
|
||||
8
forge-gui/res/tokenscripts/g_2_2_ooze_mitotic.txt
Normal file
8
forge-gui/res/tokenscripts/g_2_2_ooze_mitotic.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
Name:Ooze
|
||||
ManaCost:no cost
|
||||
Types:Creature Ooze
|
||||
Colors:green
|
||||
PT:2/2
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenJunior | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create two 1/1 green Ooze creature tokens.
|
||||
SVar:TrigTokenJunior:DB$Token | LegacyImage$ g 1 1 ooze | TokenScript$ g_1_1_ooze | TokenOwner$ You | TokenAmount$ 2
|
||||
Oracle:When this creature dies, create two 1/1 green Ooze creature tokens.
|
||||
7
forge-gui/res/tokenscripts/g_3_3_centaur_pro_black.txt
Normal file
7
forge-gui/res/tokenscripts/g_3_3_centaur_pro_black.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
Name:Centaur
|
||||
ManaCost:no cost
|
||||
Types:Creature Centaur
|
||||
Colors:green
|
||||
PT:3/3
|
||||
K:Protection from black
|
||||
Oracle:Protection from black
|
||||
9
forge-gui/res/tokenscripts/g_x_x_treefolk_warrior.txt
Normal file
9
forge-gui/res/tokenscripts/g_x_x_treefolk_warrior.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
Name:Treefolk Warrior
|
||||
ManaCost:no cost
|
||||
Types:Creature Treefolk Warrior
|
||||
Colors:green
|
||||
PT:*/*
|
||||
S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | SetToughness$ X | Description$ CARDNAMEs power and toughness are each equal to the number of Forests you control.
|
||||
SVar:X:Count$Valid Forest.YouCtrl
|
||||
SVar:BuffedBy:Forest
|
||||
Oracle:CARDNAMEs power and toughness are each equal to the number of Forests you control.
|
||||
@@ -0,0 +1,10 @@
|
||||
Name:Dragon Egg
|
||||
ManaCost:no cost
|
||||
Types:Creature Dragon Egg
|
||||
Colors:red
|
||||
PT:0/2
|
||||
K:Defender
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn".
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | LegacyImage$ r 2 2 dragon c18 | TokenScript$ r_2_2_dragon_flying_firebreathing
|
||||
SVar:SacMe:4
|
||||
Oracle:Defender\nWhen Dragon Egg dies, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn."
|
||||
@@ -0,0 +1,8 @@
|
||||
Name:Dragon
|
||||
ManaCost:no cost
|
||||
Types:Creature Dragon
|
||||
Colors:red
|
||||
PT:2/2
|
||||
K:Flying
|
||||
A:AB$ Pump | Cost$ R | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn.
|
||||
Oracle:Flying\n{R}: This creature gets +1/+0 until end of turn.
|
||||
8
forge-gui/res/tokenscripts/u_3_3_fish_hatches_whale.txt
Normal file
8
forge-gui/res/tokenscripts/u_3_3_fish_hatches_whale.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
Name:Fish
|
||||
ManaCost:no cost
|
||||
Types:Creature Fish
|
||||
Colors:blue
|
||||
PT:3/3
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create a 6/6 blue Whale creature token with "When this creature dies, create a 9/9 blue Kraken creature token."
|
||||
SVar:TrigToken:DB$Token | LegacyImage$ u 6 6 whale | TokenScript$ u_6_6_whale_hatches_kraken | TokenOwner$ You | TokenAmount$ 1
|
||||
Oracle:When this creature dies, create a 6/6 blue Whale creature token with "When this creature dies, create a 9/9 blue Kraken creature token.".
|
||||
@@ -0,0 +1,8 @@
|
||||
Name:Whale
|
||||
ManaCost:no cost
|
||||
Types:Creature Whale
|
||||
Colors:blue
|
||||
PT:6/6
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerController$ TriggeredCardController | TriggerDescription$ When this creature dies, create a 9/9 blue Kraken creature token.
|
||||
SVar:TrigToken:DB$Token | LegacyImage$ u 9 9 kraken | TokenScript$ u_9_9_kraken | TokenOwner$ You | TokenAmount$ 1
|
||||
Oracle:When this creature dies, create a 9/9 blue Kraken creature token.
|
||||
6
forge-gui/res/tokenscripts/u_9_9_kraken.txt
Normal file
6
forge-gui/res/tokenscripts/u_9_9_kraken.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Name:Kraken
|
||||
ManaCost:no cost
|
||||
Types:Creature Kraken
|
||||
Colors:blue
|
||||
PT:9/9
|
||||
Oracle:
|
||||
Reference in New Issue
Block a user