Compare commits

..

21 Commits

Author SHA1 Message Date
Hans Mackowiak
8f5276d10d HiddenStaticAbilities: add Statics without the need for Effect objects 2025-11-15 10:57:12 +01:00
tool4ever
c226ec5b1e Update momo_friendly_flier.txt
Closes #9165
2025-11-15 08:37:55 +00:00
Fulgur14
89dfb252e8 Changed Planetarium of Wan Shi Ton's static trigger 2025-11-14 18:40:48 +01:00
Fulgur14
940264c537 Update planetarium_of_wan_shi_tong.txt
I realized that it does need ChangesZone to handle the case where it's blinked or something.
2025-11-14 17:55:21 +01:00
Hans Mackowiak
95dcd8984e StaticAbility: add getTimestamp using getLayerTimestamp (#9160)
* StaticAbility: add getTimestamp using getLayerTimestamp
2025-11-14 17:28:18 +01:00
Fulgur14
37b5503e77 Planetarium of Wan Shi Tong (TLA) 2025-11-14 16:03:13 +01:00
aryst0krat
70b6ae1461 Fix invalid item slot #9149 2025-11-14 15:58:43 +01:00
tool4ever
78f4b13744 Update Unblockable ability source in giant_koi.txt 2025-11-14 12:32:43 +01:00
tool4ever
dff971e9e8 Update true_ancestry.txt 2025-11-14 12:29:47 +01:00
tool4ever
c049d3c905 Update tolls_of_war.txt 2025-11-14 10:19:14 +01:00
tool4ever
1dbdd49a99 Update regex for fixing markdown links
hyperlink support
2025-11-13 16:30:42 +00:00
Jetz72
b6c775eec5 Merge pull request #9155 from Jetz72/fixes20251112
Automatically swap flavor names into oracle text
2025-11-13 08:33:01 -06:00
Hans Mackowiak
164d1573e0 Update squall_gunblade_duelist.txt 2025-11-12 21:25:17 +01:00
Hans Mackowiak
80ef4c2d19 Update the_legend_of_kuruk_avatar_kuruk.txt 2025-11-12 20:46:26 +01:00
tool4ever
e114819cc4 Change mana production from U to R in fire_nation_palace 2025-11-12 16:38:14 +01:00
Jetz
cdfe5ee18b Make that failsafe not break oracle text 2025-11-12 09:50:54 -05:00
Jetz
f2feb5edf8 Failsafe in case Android decides to explode due to complicated regex syntax again. 2025-11-12 09:41:29 -05:00
Jetz
22a9b173a5 Replace flavor names into oracle text. 2025-11-12 09:28:51 -05:00
Paul Hammerton
435af883c5 update tla.rnk 2025-11-12 07:36:06 -05:00
Chris H
154b40b24d Fix typo 2025-11-12 07:36:06 -05:00
Chris H
cd09193924 Add TLA Booster info and Rankins 2025-11-12 07:36:06 -05:00
35 changed files with 733 additions and 136 deletions

View File

@@ -18,7 +18,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: fix md links for Gollum
run: find ${{ github.workspace }}/docs/ -type f -name "*.md" -exec sed -i -E 's|(\[[^]]+]\()([^)]+\/)*([^).]+).md\)|\1\3)|g' '{}' \;
run: find ${{ github.workspace }}/docs/ -type f -name "*.md" -exec sed -i -E 's|(\[[^]]+]\()([^)]+\/)*([^).]+).md(#)*([[:alnum:]]*)\)|\1\3\4\5)|g' '{}' \;
- name: fix image links for Gollum
run: find ${{ github.workspace }}/docs/ -type f -name "*.png" -exec mv '{}' ${{ github.workspace }}/docs/ \;
- uses: Andrew-Chen-Wang/github-wiki-action@v5

View File

@@ -241,8 +241,7 @@ public class PlayerControllerAi extends PlayerController {
public Map<Byte, Integer> specifyManaCombo(SpellAbility sa, ColorSet colorSet, int manaAmount, boolean different) {
Map<Byte, Integer> result = new HashMap<>();
for (int i = 0; i < manaAmount; ++i) {
MagicColor.Color chosenColor = chooseColor("", sa, colorSet);
Byte chosen = chosenColor == null ? (byte)0 : chosenColor.getColorMask();
Byte chosen = chooseColor("", sa, colorSet);
if (result.containsKey(chosen)) {
result.put(chosen, result.get(chosen) + 1);
} else {
@@ -1023,22 +1022,19 @@ public class PlayerControllerAi extends PlayerController {
}
@Override
public MagicColor.Color chooseColorAllowColorless(String message, Card card, ColorSet colors) {
public byte chooseColorAllowColorless(String message, Card card, ColorSet colors) {
final String c = ComputerUtilCard.getMostProminentColor(player.getCardsIn(ZoneType.Hand));
byte chosenColorMask = MagicColor.fromName(c);
if ((colors.getColor() & chosenColorMask) != 0) {
return MagicColor.Color.fromByte(chosenColorMask);
return chosenColorMask;
}
return Iterables.getFirst(colors, MagicColor.Color.COLORLESS);
return Iterables.getFirst(colors, MagicColor.Color.COLORLESS).getColorMask();
}
@Override
public MagicColor.Color chooseColor(String message, SpellAbility sa, ColorSet colors) {
if (colors.countColors() == 0) {
return null;
}
public byte chooseColor(String message, SpellAbility sa, ColorSet colors) {
if (colors.countColors() < 2) {
return Iterables.getFirst(colors, MagicColor.Color.WHITE);
return Iterables.getFirst(colors, MagicColor.Color.WHITE).getColorMask();
}
// You may switch on sa.getApi() here and use sa.getParam("AILogic")
CardCollectionView hand = player.getCardsIn(ZoneType.Hand);
@@ -1049,9 +1045,9 @@ public class PlayerControllerAi extends PlayerController {
byte chosenColorMask = MagicColor.fromName(c);
if ((colors.getColor() & chosenColorMask) != 0) {
return MagicColor.Color.fromByte(chosenColorMask);
return chosenColorMask;
}
return Iterables.getFirst(colors, MagicColor.Color.WHITE);
return Iterables.getFirst(colors, MagicColor.Color.WHITE).getColorMask();
}
@Override

View File

@@ -1,10 +1,12 @@
package forge.card;
import forge.card.mana.ManaCost;
import forge.util.Lang;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;
//
@@ -185,7 +187,25 @@ final class CardFace implements ICardFace, Cloneable {
}
void assignMissingFieldsToVariant(CardFace variant) {
if(variant.oracleText == null) variant.oracleText = this.oracleText;
if(variant.oracleText == null) {
if(variant.flavorName != null && this.oracleText != null) {
try {
Lang lang = Lang.getInstance();
//Rudimentary name replacement. Can't do pronouns, ability words, or flavored keywords. Need to define variant text manually for that.
//Regex here checks for the name following either a word boundary or a literal "\n" string, since those haven't yet been converted to line breaks.
String flavoredText = this.oracleText.replaceAll("(?<=\\b|\\\\n)" + this.name + "\\b", variant.flavorName);
flavoredText = flavoredText.replaceAll("(?<=\\b|\\\\n)" + lang.getNickName(this.name) + "\\b", lang.getNickName(variant.flavorName));
variant.oracleText = flavoredText;
}
catch (PatternSyntaxException ignored) {
// Old versions of Android are weird about patterns sometimes. I don't *think* this is such a case but
// the documentation is unreliable. May be worth removing this once we're sure it's not a problem.
variant.oracleText = this.oracleText;
}
}
else
variant.oracleText = this.oracleText;
}
if(variant.manaCost == null) variant.manaCost = this.manaCost;
if(variant.color == null) variant.color = ColorSet.fromManaCost(variant.manaCost);

View File

@@ -504,16 +504,11 @@ public final class CardRules implements ICardCharacteristics {
CardFace variantMain = ((CardFace) mainPart).getOrCreateFunctionalVariant(variantName);
variantMain.setFlavorName(nameParts[0]);
//Rudimentary name replacement. Can't do nicknames, pronouns, ability words, or flavored keywords. Need to define variants manually for that.
if(mainPart.getOracleText().contains(mainPart.getName()))
variantMain.setOracleText(mainPart.getOracleText().replace(mainPart.getName(), nameParts[0]));
((CardFace) mainPart).assignMissingFieldsToVariant(variantMain);
if(otherPart != null) {
CardFace variantOther = ((CardFace) otherPart).getOrCreateFunctionalVariant(variantName);
variantOther.setFlavorName(nameParts[1]);
if(otherPart.getOracleText().contains(otherPart.getName()))
variantMain.setOracleText(otherPart.getOracleText().replace(otherPart.getName(), nameParts[1]));
((CardFace) otherPart).assignMissingFieldsToVariant(variantOther);
}

View File

@@ -1027,6 +1027,22 @@ public class DeckRecognizer {
};
}
/**
* Get the magic color by the localised/translated name.
* @param localisedName String of localised color name.
* @return The string of the magic color.
*/
public static String getColorNameByLocalisedName(String localisedName) {
Localizer localizer = Localizer.getInstance();
if(localisedName.equals(localizer.getMessage("lblWhite"))) return MagicColor.Constant.WHITE;
if(localisedName.equals(localizer.getMessage("lblBlue"))) return MagicColor.Constant.BLUE;
if(localisedName.equals(localizer.getMessage("lblBlack"))) return MagicColor.Constant.BLACK;
if(localisedName.equals(localizer.getMessage("lblRed"))) return MagicColor.Constant.RED;
if(localisedName.equals(localizer.getMessage("lblGreen"))) return MagicColor.Constant.GREEN;
return "";
}
public static boolean isDeckName(final String lineAsIs) {
if (lineAsIs == null)
return false;

View File

@@ -78,7 +78,7 @@ public class GameAction {
private boolean holdCheckingStaticAbilities = false;
private final static Comparator<StaticAbility> effectOrder = Comparator.comparing(StaticAbility::isCharacteristicDefining).reversed()
.thenComparing(s -> s.getHostCard().getLayerTimestamp());
.thenComparing(StaticAbility::getTimestamp);
public GameAction(Game game0) {
game = game0;
@@ -1103,11 +1103,16 @@ public class GameAction {
if (stAb.checkMode(StaticAbilityMode.Continuous) && stAb.zonesCheck()) {
staticAbilities.add(stAb);
}
}
if (!co.getStaticCommandList().isEmpty()) {
staticList.add(co);
}
return true;
}
if (!co.getStaticCommandList().isEmpty()) {
staticList.add(co);
}
for (StaticAbility stAb : co.getHiddenStaticAbilities()) {
if (stAb.checkMode(StaticAbilityMode.Continuous) && stAb.zonesCheck()) {
staticAbilities.add(stAb);
}
}
return true;
}
}, true);
@@ -1333,7 +1338,7 @@ public class GameAction {
// now the earliest one left is the correct choice
List<StaticAbility> statics = Lists.newArrayList(dependencyGraph.vertexSet());
statics.sort(Comparator.comparing(s -> s.getHostCard().getLayerTimestamp()));
statics.sort(Comparator.comparing(StaticAbility::getTimestamp));
return statics.get(0);
}

View File

@@ -30,28 +30,27 @@ public class ChangeTextEffect extends SpellAbilityEffect {
final String changedColorWordOriginal, changedColorWordNew;
if (sa.hasParam("ChangeColorWord")) {
// all instances are Choose Choose
MagicColor.Color originalColor = null;
byte originalColor = 0;
final String[] changedColorWordsArray = sa.getParam("ChangeColorWord").split(" ");
if (changedColorWordsArray[0].equals("Choose")) {
originalColor = sa.getActivatingPlayer().getController().chooseColor(
Localizer.getInstance().getMessage("lblChooseColorReplace"), sa, ColorSet.WUBRG);
changedColorWordOriginal = TextUtil.capitalize(originalColor.getName());
changedColorWordOriginal = TextUtil.capitalize(MagicColor.toLongString(originalColor));
} else {
changedColorWordOriginal = changedColorWordsArray[0];
originalColor = MagicColor.Color.fromByte(MagicColor.fromName(changedColorWordOriginal));
originalColor = MagicColor.fromName(changedColorWordOriginal);
}
if (changedColorWordsArray[1].equals("Choose")) {
final ColorSet possibleNewColors;
if (originalColor == null) { // no original color (ie. any or absent)
if (originalColor == 0) { // no original color (ie. any or absent)
possibleNewColors = ColorSet.WUBRG;
} else { // may choose any except original color
possibleNewColors = ColorSet.fromEnums(originalColor).inverse();
possibleNewColors = ColorSet.fromMask(originalColor).inverse();
}
MagicColor.Color newColor = sa.getActivatingPlayer().getController().chooseColor(
final byte newColor = sa.getActivatingPlayer().getController().chooseColor(
Localizer.getInstance().getMessage("lblChooseNewColor"), sa, possibleNewColors);
changedColorWordNew = TextUtil.capitalize(newColor.getName());
changedColorWordNew = TextUtil.capitalize(MagicColor.toLongString(newColor));
} else {
changedColorWordNew = changedColorWordsArray[1];
}

View File

@@ -114,15 +114,15 @@ public class ManaEffect extends SpellAbilityEffect {
// just use the first possible color.
choice = colorsProduced[differentChoice ? nMana : 0];
} else {
MagicColor.Color chosenColor = chooser.getController().chooseColor(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa,
byte chosenColor = chooser.getController().chooseColor(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa,
differentChoice && (colorsNeeded == null || colorsNeeded.length <= nMana) ? fullOptions : colorOptions);
if (chosenColor == null)
if (chosenColor == 0)
throw new RuntimeException("ManaEffect::resolve() /*combo mana*/ - " + p + " color mana choice is empty for " + card.getName());
if (differentChoice) {
fullOptions = ColorSet.fromMask(fullOptions.getColor() - chosenColor.getColorMask());
fullOptions = ColorSet.fromMask(fullOptions.getColor() - chosenColor);
}
choice = chosenColor.getShortName();
choice = MagicColor.toShortString(chosenColor);
}
if (nMana > 0) {
@@ -157,13 +157,13 @@ public class ManaEffect extends SpellAbilityEffect {
mask |= MagicColor.fromName(colorsNeeded.charAt(nChar));
}
colorMenu = mask == 0 ? ColorSet.WUBRG : ColorSet.fromMask(mask);
MagicColor.Color val = chooser.getController().chooseColor(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa, colorMenu);
if (val == null) {
byte val = chooser.getController().chooseColor(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa, colorMenu);
if (0 == val) {
throw new RuntimeException("ManaEffect::resolve() /*any mana*/ - " + p + " color mana choice is empty for " + card.getName());
}
game.getAction().notifyOfValue(sa, card, val.getSymbol(), p);
abMana.setExpressChoice(val.getShortName());
game.getAction().notifyOfValue(sa, card, MagicColor.toSymbol(val), p);
abMana.setExpressChoice(MagicColor.toShortString(val));
}
else if (abMana.isSpecialMana()) {
String type = abMana.getOrigProduced().split("Special ")[1];
@@ -178,22 +178,22 @@ public class ManaEffect extends SpellAbilityEffect {
for (ManaCostShard s : enchanted.getManaCost()) {
ColorSet cs = ColorSet.fromMask(s.getColorMask());
MagicColor.Color chosenColor;
byte chosenColor;
if (cs.isColorless())
continue;
if (s.isOr2Generic()) { // CR 106.8
chosenColor = chooser.getController().chooseColorAllowColorless(Localizer.getInstance().getMessage("lblChooseSingleColorFromTarget", s.toString()), card, cs);
if (chosenColor == MagicColor.Color.COLORLESS) {
if (chosenColor == MagicColor.COLORLESS) {
generic += 2;
continue;
}
}
else if (cs.isMonoColor())
chosenColor = MagicColor.Color.fromByte(s.getColorMask());
chosenColor = s.getColorMask();
else /* (cs.isMulticolor()) */ {
chosenColor = chooser.getController().chooseColor(Localizer.getInstance().getMessage("lblChooseSingleColorFromTarget", s.toString()), sa, cs);
}
sb.append(chosenColor.getShortName());
sb.append(MagicColor.toShortString(chosenColor));
sb.append(' ');
}
if (generic > 0) {
@@ -239,8 +239,8 @@ public class ManaEffect extends SpellAbilityEffect {
if (cs.isMonoColor())
sb.append(MagicColor.toShortString(s.getColorMask()));
else /* (cs.isMulticolor()) */ {
MagicColor.Color chosenColor = chooser.getController().chooseColor(Localizer.getInstance().getMessage("lblChooseSingleColorFromTarget", s.toString()), sa, cs);
sb.append(chosenColor.getShortName());
byte chosenColor = chooser.getController().chooseColor(Localizer.getInstance().getMessage("lblChooseSingleColorFromTarget", s.toString()), sa, cs);
sb.append(MagicColor.toShortString(chosenColor));
}
}
}

View File

@@ -95,7 +95,7 @@ public class ManaReflectedEffect extends SpellAbilityEffect {
}
if (mask == 0 && !expressChoiceColors.isEmpty() && colors.contains("colorless")) {
baseMana = player.getController().chooseColorAllowColorless(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa.getHostCard(), ColorSet.fromMask(mask)).getShortName();
baseMana = MagicColor.toShortString(player.getController().chooseColorAllowColorless(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa.getHostCard(), ColorSet.fromMask(mask)));
} else {
// Nothing set previously so ask player if needed
if (mask == 0) {
@@ -104,17 +104,17 @@ public class ManaReflectedEffect extends SpellAbilityEffect {
} else if (colors.size() == 1) {
baseMana = MagicColor.toShortString(colors.iterator().next());
} else if (colors.contains("colorless")) {
baseMana = player.getController().chooseColorAllowColorless(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa.getHostCard(), ColorSet.fromNames(colors)).getShortName();
baseMana = MagicColor.toShortString(player.getController().chooseColorAllowColorless(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa.getHostCard(), ColorSet.fromNames(colors)));
} else {
baseMana = player.getController().chooseColor(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa, ColorSet.fromNames(colors)).getShortName();
baseMana = MagicColor.toShortString(player.getController().chooseColor(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa, ColorSet.fromNames(colors)));
}
} else {
colorMenu = ColorSet.fromMask(mask);
MagicColor.Color color = sa.getActivatingPlayer().getController().chooseColor(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa, colorMenu);
if (color == null) {
byte color = sa.getActivatingPlayer().getController().chooseColor(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa, colorMenu);
if (color == 0) {
System.err.println("Unexpected behavior in ManaReflectedEffect: " + sa.getActivatingPlayer() + " - color mana choice is empty for " + sa.getHostCard().getName());
}
baseMana = color.getShortName();
baseMana = MagicColor.toShortString(color);
}
}

View File

@@ -34,15 +34,15 @@ public class ReplaceManaEffect extends SpellAbilityEffect {
// replace type and amount
replaced = sa.getParam("ReplaceMana");
if ("Any".equals(replaced)) {
MagicColor.Color rs = player.getController().chooseColor("Choose a color", sa, ColorSet.WUBRG);
replaced = rs.getShortName();
byte rs = player.getController().chooseColor("Choose a color", sa, ColorSet.WUBRG);
replaced = MagicColor.toShortString(rs);
}
} else if (sa.hasParam("ReplaceType")) {
// replace color and colorless
String color = sa.getParam("ReplaceType");
if ("Any".equals(color)) {
MagicColor.Color rs = player.getController().chooseColor("Choose a color", sa, ColorSet.WUBRG);
color = rs.getShortName();
byte rs = player.getController().chooseColor("Choose a color", sa, ColorSet.WUBRG);
color = MagicColor.toShortString(rs);
} else {
// convert in case Color Word used
color = MagicColor.toShortString(color);

View File

@@ -209,7 +209,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
private boolean renowned;
private boolean solved;
private boolean tributed;
private Card suspectedEffect = null;
private StaticAbility suspectedStatic = null;
private SpellAbility manifestedSA;
private SpellAbility cloakedSA;
@@ -6758,15 +6758,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
return true;
}
public Card getSuspectedEffect() {
return this.suspectedEffect;
public StaticAbility getSuspectedStatic() {
return this.suspectedStatic;
}
public void setSuspectedEffect(Card effect) {
this.suspectedEffect = effect;
public void setSuspectedStatic(StaticAbility stAb) {
this.suspectedStatic = stAb;
}
public final boolean isSuspected() {
return suspectedEffect != null;
return suspectedStatic != null;
}
public final boolean setSuspected(final boolean suspected) {
@@ -6779,23 +6779,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
return true;
}
suspectedEffect = SpellAbilityEffect.createEffect(null, this, this.getController(), "Suspected Effect", getImageKey(), getGame().getNextTimestamp());
suspectedEffect.setRenderForUI(false);
suspectedEffect.addRemembered(this);
String s = "Mode$ Continuous | AffectedDefined$ Self | AddKeyword$ Menace | AddStaticAbility$ SuspectedCantBlockBy";
suspectedStatic = StaticAbility.create(s, this, currentState, true);
suspectedStatic.putParam("Timestamp", String.valueOf(getGame().getNextTimestamp()));
String s = "Mode$ Continuous | AffectedDefined$ RememberedCard | EffectZone$ Command | AddKeyword$ Menace | AddStaticAbility$ SuspectedCantBlockBy";
StaticAbility suspectedStatic = suspectedEffect.addStaticAbility(s);
String effect = "Mode$ CantBlock | ValidCard$ Creature.Self | Description$ CARDNAME can't block.";
suspectedStatic.setSVar("SuspectedCantBlockBy", effect);
GameCommand until = SpellAbilityEffect.exileEffectCommand(getGame(), suspectedEffect);
addLeavesPlayCommand(until);
getGame().getAction().moveToCommand(suspectedEffect, null);
} else {
if (isSuspected()) {
getGame().getAction().exileEffect(suspectedEffect);
suspectedEffect = null;
}
suspectedStatic = null;
}
return true;
}
@@ -7293,6 +7285,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
}
}
public final FCollectionView<StaticAbility> getHiddenStaticAbilities() {
FCollection<StaticAbility> result = new FCollection<>();
// Suspected
if (this.isInPlay() && this.isSuspected()) {
result.add(suspectedStatic);
}
return result;
}
public final FCollectionView<Trigger> getTriggers() {
return currentState.getTriggers();
}

View File

@@ -315,7 +315,7 @@ public class CardCopyService {
newCopy.setSaddled(copyFrom.isSaddled());
if (newCopy.isSaddled()) newCopy.setSaddledByThisTurn(copyFrom.getSaddledByThisTurn());
if (copyFrom.isSuspected()) {
newCopy.setSuspectedEffect(getLKICopy(copyFrom.getSuspectedEffect(), cachedMap));
newCopy.setSuspectedStatic(copyFrom.getSuspectedStatic().copy(newCopy, true));
}
newCopy.setDamageHistory(copyFrom.getDamageHistory());

View File

@@ -3100,10 +3100,10 @@ public class Player extends GameEntity implements Comparable<Player> {
Player p = cmd.getController();
String prompt = Localizer.getInstance().getMessage("lblChooseAColorFor", cmd.getName());
SpellAbility cmdColorsa = new SpellAbility.EmptySa(ApiType.ChooseColor, cmd, p);
MagicColor.Color chosenColor = p.getController().chooseColor(prompt, cmdColorsa, ColorSet.WUBRG);
cmd.setChosenColors(List.of(chosenColor.getName()));
byte chosenColor = p.getController().chooseColor(prompt, cmdColorsa, ColorSet.WUBRG);
cmd.setChosenColors(List.of(MagicColor.toLongString(chosenColor)));
p.getGame().getAction().notifyOfValue(cmdColorsa, cmd,
Localizer.getInstance().getMessage("lblPlayerPickedChosen", p.getName(), chosenColor.getName()), p);
Localizer.getInstance().getMessage("lblPlayerPickedChosen", p.getName(), MagicColor.toLongString(chosenColor)), p);
}
}

View File

@@ -6,7 +6,6 @@ import com.google.common.collect.Multimap;
import forge.LobbyPlayer;
import forge.card.ColorSet;
import forge.card.ICardFace;
import forge.card.MagicColor;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostShard;
import forge.deck.Deck;
@@ -266,8 +265,8 @@ public abstract class PlayerController {
public abstract boolean chooseFlipResult(SpellAbility sa, Player flipper, boolean[] results, boolean call);
public abstract MagicColor.Color chooseColor(String message, SpellAbility sa, ColorSet colors);
public abstract MagicColor.Color chooseColorAllowColorless(String message, Card c, ColorSet colors);
public abstract byte chooseColor(String message, SpellAbility sa, ColorSet colors);
public abstract byte chooseColorAllowColorless(String message, Card c, ColorSet colors);
public abstract List<String> chooseColors(String message, SpellAbility sa, int min, int max, List<String> options);
public abstract ICardFace chooseSingleCardFace(SpellAbility sa, String message, Predicate<ICardFace> cpp, String name);

View File

@@ -297,7 +297,9 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
* conditions are fulfilled.
*/
private boolean shouldApplyContinuousAbility(final StaticAbilityLayer layer, final boolean previousRun) {
return layers.contains(layer) && checkConditions(StaticAbilityMode.Continuous) && (previousRun || getHostCard().getStaticAbilities().contains(this));
return layers.contains(layer) && checkConditions(StaticAbilityMode.Continuous) && ( previousRun ||
getHostCard().getStaticAbilities().contains(this) ||
getHostCard().getHiddenStaticAbilities().contains(this));
}
public final Cost getAttackCost(final Card attacker, final GameEntity target, final List<Card> attackersWithOptionalCost) {
@@ -583,6 +585,13 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
.result();
}
public long getTimestamp() {
if (hasParam("Timestamp")) {
return Long.valueOf(getParam("Timestamp"));
}
return getHostCard().getLayerTimestamp();
}
@Override
public void setHostCard(Card host) {
super.setHostCard(host);

View File

@@ -25,7 +25,6 @@ import forge.GameCommand;
import forge.card.*;
import forge.game.Game;
import forge.game.StaticEffect;
import forge.game.StaticEffects;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.card.*;
@@ -93,12 +92,11 @@ public final class StaticAbilityContinuous {
final List<Player> affectedPlayers = StaticAbilityContinuous.getAffectedPlayers(stAb);
final Game game = hostCard.getGame();
final StaticEffects effects = game.getStaticEffects();
final StaticEffect se = effects.getStaticEffect(stAb);
final StaticEffect se = game.getStaticEffects().getStaticEffect(stAb);
se.setAffectedCards(affectedCards);
se.setAffectedPlayers(affectedPlayers);
se.setParams(params);
se.setTimestamp(hostCard.getLayerTimestamp());
se.setTimestamp(stAb.getTimestamp());
// nothing more to do
if (stAb.hasParam("Affected") && affectedPlayers.isEmpty() && affectedCards.isEmpty()) {

View File

@@ -470,16 +470,13 @@ public class PlayerControllerForTests extends PlayerController {
}
@Override
public MagicColor.Color chooseColor(String message, SpellAbility sa, ColorSet colors) {
if (colors.countColors() == 0) {
return null;
}
return Iterables.getFirst(colors, MagicColor.Color.WHITE);
public byte chooseColor(String message, SpellAbility sa, ColorSet colors) {
return Iterables.getFirst(colors, MagicColor.Color.WHITE).getColorMask();
}
@Override
public MagicColor.Color chooseColorAllowColorless(String message, Card card, ColorSet colors) {
return Iterables.getFirst(colors, MagicColor.Color.COLORLESS);
public byte chooseColorAllowColorless(String message, Card card, ColorSet colors) {
return Iterables.getFirst(colors, MagicColor.Color.COLORLESS).getColorMask();
}
private CardCollection chooseItems(CardCollectionView items, int amount) {

View File

@@ -1556,7 +1556,7 @@
},
{
"name": "Amulet of the Deceiver",
"equipmentSlot": "Head",
"equipmentSlot": "Neck",
"iconName": "MoxJet",
"effect": {
"lifeModifier": -1,

View File

@@ -1343,7 +1343,7 @@
},
{
"name": "Helm of Obedience",
"equipmentSlot": "Head",
"equipmentSlot": "Neck",
"iconName": "MoxJet",
"effect": {
"lifeModifier": -1,

View File

@@ -1556,7 +1556,7 @@
},
{
"name": "Amulet of the Deceiver",
"equipmentSlot": "Head",
"equipmentSlot": "Neck",
"iconName": "MoxJet",
"effect": {
"lifeModifier": -1,

View File

@@ -145,3 +145,4 @@ Final Fantasy, 3/6/FIN, FIN
Alchemy: Innistrad, 3/6/ISD, YMID
Edge of Eternities, 3/6/EOE, EOE
Marvel's Spider-Man, 3/6/SPM, SPM
Avatar: The Last Airbender, 3/6/TLA, TLA

View File

@@ -3,8 +3,8 @@ ManaCost:W
Types:Legendary Creature Lemur Bat Ally
PT:1/1
K:Flying
S:Mode$ ReduceCost | ValidCard$ Creature.nonLemur+hasFlying+YouCtrl | Type$ Spell | Activator$ You | Amount$ 1 | Condition$ PlayerTurn | CheckSVar$ X | SVarCompare$ EQ0 | Description$ The first non-Lemur creature spell with flying you cast during each of your turns costs {1} less to cast.
S:Mode$ ReduceCost | ValidCard$ Creature.nonLemur+withFlying+YouCtrl | Type$ Spell | Activator$ You | Amount$ 1 | Condition$ PlayerTurn | CheckSVar$ X | SVarCompare$ EQ0 | Description$ The first non-Lemur creature spell with flying you cast during each of your turns costs {1} less to cast.
T:Mode$ ChangesZone | ValidCard$ Creature.Other+YouCtrl+withFlying | Origin$ Any | Destination$ Battlefield | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ Whenever another creature you control with flying enters, NICKNAME gets +1/+1 until end of turn.
SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ +1 | NumDef$ +1
SVar:X:Count$ThisTurnCast_Creature.nonLemur+hasFlying+YouCtrl
SVar:X:Count$ThisTurnCast_Creature.nonLemur+withFlying+YouCtrl
Oracle:Flying\nThe first non-Lemur creature spell with flying you cast during each of your turns costs {1} less to cast.\nWhenever another creature you control with flying enters, Momo gets +1/+1 until end of turn.

View File

@@ -3,6 +3,6 @@ ManaCost:no cost
Types:Land
R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ LandTapped | ReplacementResult$ Updated | Description$ This land enters tapped unless you control a basic land.
SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Land.Basic+YouCtrl | ConditionCompare$ EQ0
A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {R}.
A:AB$ Mana | Cost$ T | Produced$ R | SpellDescription$ Add {R}.
A:AB$ Pump | Cost$ 1 R T | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | KW$ Firebending:4 | SpellDescription$ Target creature you control gains firebending 4 until end of turn. (Whenever it attacks, add {R}{R}{R}{R}. This mana lasts until end of combat.)
Oracle:This land enters tapped unless you control a basic land.\n{T}: Add {R}.\n{1}{R}, {T}: Target creature you control gains firebending 4 until end of turn. (Whenever it attacks, add {R}{R}{R}{R}. This mana lasts until end of combat.)

View File

@@ -4,5 +4,5 @@ Types:Creature Fish
PT:5/7
K:TypeCycling:Island:2
A:AB$ Effect | Cost$ Waterbend<3> | Defined$ Self | StaticAbilities$ Unblockable | AILogic$ Pump | SpellDescription$ This creature can't be blocked this turn.
SVar:Unblockable:Mode$ CantBlockBy | ValidAttacker$ Card.Self | Description$ This creature can't be blocked this turn.
SVar:Unblockable:Mode$ CantBlockBy | ValidAttacker$ Card.EffectSource | Description$ This creature can't be blocked this turn.
Oracle:Waterbend {3}: This creature can't be blocked this turn. (While paying a waterbend cost, you can tap your artifacts and creatures to help. Each one pays for {1}.)\nIslandcycling {2} ({2}, Discard this card: Search your library for an Island card, reveal it, put it into your hand, then shuffle.)

View File

@@ -0,0 +1,12 @@
Name:Planetarium of Wan Shi Tong
ManaCost:6
Types:Legendary Artifact
A:AB$ Scry | Cost$ 1 T | ScryNum$ 2 | SpellDescription$ Scry 2.
T:Mode$ Scry | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPeek | PresentDefined$ Remembered | IsPresent$ Card | PresentCompare$ EQ0 | TriggerDescription$ Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn. (Look at the card after you scry or surveil.)
T:Mode$ Surveil | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPeek | Secondary$ True | PresentDefined$ Remembered | IsPresent$ Card | PresentCompare$ EQ0 | TriggerDescription$ Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn. (Look at the card after you scry or surveil.)
SVar:TrigPeek:DB$ PeekAndReveal | NoReveal$ True | SubAbility$ TrigPlay
SVar:TrigPlay:DB$ Play | Defined$ TopOfLibrary | WithoutManaCost$ True | ValidSA$ Spell | Optional$ True | RememberPlayed$ True | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ DBCleanup | Static$ True
T:Mode$ TurnBegin | ValidPlayer$ Player | Execute$ DBCleanup | Static$ True
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
Oracle:{1}, {T}: Scry 2.\nWhenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn. (Look at the card after you scry or surveil.)

View File

@@ -5,7 +5,7 @@ PT:3/2
K:First Strike
K:ETBReplacement:Other:ChooseNumber
SVar:ChooseNumber:DB$ ChooseNumber | Defined$ You | SpellDescription$ As NICKNAME enters, choose a number.
T:Mode$ AttackersDeclaredOneTarget | AttackedTarget$ Opponent | ValidAttackers$ Creature.powerEQChosen,Creature.toughnessEQChosen | TriggerZones$ Battlefield | Execute$ TrigDamage | TriggerDescription$ Whenever one or more creatures attack one of your opponents, if any of those creatures have power or toughness equal to the chosen number, NICKNAME deals damage equal to its power to defending player.
T:Mode$ AttackersDeclaredOneTarget | AttackedTarget$ Opponent | ValidAttackers$ Creature.powerEQChosen,Creature.toughnessEQChosen | TriggerZones$ Battlefield | Execute$ TrigDealDamage | TriggerDescription$ Whenever one or more creatures attack one of your opponents, if any of those creatures have power or toughness equal to the chosen number, NICKNAME deals damage equal to its power to defending player.
SVar:TrigDealDamage:DB$ DealDamage | Defined$ TriggeredAttackedTarget | NumDmg$ X | ConditionCheckSVar$ Y | ConditionSVarCompare$ GE1
SVar:X:Count$CardPower
SVar:Y:Count$Valid Creature.TriggeredAttackers+powerEQChosen,Creature.TriggeredAttackers+toughnessEQChosen

View File

@@ -18,6 +18,6 @@ ManaCost:no cost
Types:Legendary Creature Avatar
PT:4/3
T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | SpellDescription$ Whenever you cast a spell, create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures."
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_1_1_spirit_spiritshadow | TokenOwner$ You
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_1_1_spirit_spiritshadow | TokenOwner$ You
A:AB$ AddTurn | Cost$ Waterbend<20> | NumTurns$ 1 | Exhaust$ True | SpellDescription$ Take an extra turn after this one.
Oracle:Whenever you cast a spell, create a 1/1 colorless Spirit creature token with "This token cant block or be blocked by non-Spirit creatures."\nExhaust — Waterbend {20}: Take an extra turn after this one. (While paying a waterbend cost, you can tap your artifacts and creatures to help. Each one pays for {1}. Activate each exhaust ability only once.)

View File

@@ -1,8 +1,8 @@
Name:Tolls of War
ManaCost:W B
Types:Enchantment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When this enchantment enters, create a Clue token. (It's an artifact with "{2}, Sacrifice this token: Draw a card.")
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_clue_draw | TokenOwner$ You
T:Mode$ Sacrificed | ValidCard$ Permanent.YouCtrl | Execute$ TrigToken | TriggerZones$ Battlefield | ValidPlayer$ You | PlayerTurn$ True | ActivationLimit$ 1 | TriggerDescription$ Whenever you sacrifice a permanent during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn.
SVar:TrigToken:DB$ Token | TokenScript$ w_1_1_ally
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigClue | TriggerDescription$ When this enchantment enters, create a Clue token. (It's an artifact with "{2}, Sacrifice this token: Draw a card.")
SVar:TrigClue:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_clue_draw | TokenOwner$ You
T:Mode$ Sacrificed | ValidCard$ Permanent.YouCtrl | Execute$ TrigAlly | TriggerZones$ Battlefield | ValidPlayer$ You | PlayerTurn$ True | ActivationLimit$ 1 | TriggerDescription$ Whenever you sacrifice a permanent during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn.
SVar:TrigAlly:DB$ Token | TokenScript$ w_1_1_ally
Oracle:When this enchantment enters, create a Clue token. (It's an artifact with "{2}, Sacrifice this token: Draw a card.")\nWhenever you sacrifice a permanent during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn.

View File

@@ -1,7 +1,7 @@
Name:True Ancestry
ManaCost:1 G
Types:Sorcery Lesson
A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Permanent.YouOwn | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Choose up to one target creature card in your graveyard | SubAbility$ DBToken | SpellDescription$ Return up to one target permanent card from your graveyard to your hand. Create a Clue token. (It's an artifact with "{2}, Sacrifice this token: Draw a card.")
A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Hand | ValidTgts$ Permanent.YouOwn | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Choose up to one target creature card in your graveyard | SubAbility$ DBToken | SpellDescription$ Return up to one target permanent card from your graveyard to your hand. Create a Clue token. (It's an artifact with "{2}, Sacrifice this token: Draw a card.")
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_clue_draw | TokenOwner$ You
DeckHints:Ability$Graveyard|Token
Oracle:Return up to one target permanent card from your graveyard to your hand.\nCreate a Clue token. (It's an artifact with "{2}, Sacrifice this token: Draw a card.")

View File

@@ -0,0 +1,348 @@
//Rank|Name|Rarity|Set
#1|Day of Black Sun|R|TLA
#2|Phoenix Fleet Airship|M|TLA
#3|The Rise of Sozin|M|TLA
#4|Ran and Shaw|R|TLA
#5|Azula, Cunning Usurper|R|TLA
#6|Sokka, Tenacious Tactician|R|TLA
#7|Black Sun's Zenith|M|TLE
#8|Koma, Cosmos Serpent|M|TLE
#9|Hakoda, Selfless Commander|R|TLA
#10|United Front|M|TLA
#11|Iroh, Grand Lotus|R|TLA
#12|Agent of Treachery|M|TLE
#13|Noxious Gearhulk|M|TLE
#14|Appa, Steadfast Guardian|M|TLA
#15|Avatar's Wrath|R|TLA
#16|Suki, Courageous Rescuer|R|TLA
#17|Wan Shi Tong, Librarian|M|TLA
#18|The Fire Nation Drill|R|TLA
#19|Wartime Protestors|R|TLA
#20|The Earth King|R|TLA
#21|Aang, at the Crossroads|R|TLA
#22|Bumi, Unleashed|M|TLA
#23|Iroh, Tea Master|R|TLA
#24|Katara, Water Tribe's Hope|R|TLA
#25|Ozai, the Phoenix King|M|TLA
#26|Abandoned Air Temple|R|TLA
#27|Jasmine Dragon Tea Shop|R|TLA
#28|South Pole Voyager|R|TLA
#29|Fire Lord Azula|R|TLA
#30|Return of the Wildspeaker|M|TLE
#31|The Legend of Kuruk|M|TLA
#32|Spirit Water Revival|R|TLA
#33|The Unagi of Kyoshi Island|R|TLA
#34|Koh, the Face Stealer|M|TLA
#35|Diligent Zookeeper|R|TLA
#36|The Legend of Kyoshi|M|TLA
#37|Aang, Swift Savior|R|TLA
#38|Earth King's Lieutenant|R|TLA
#39|Sandbender Scavengers|R|TLA
#40|Toph, the First Metalbender|R|TLA
#41|Planetarium of Wan Shi Tong|M|TLA
#42|Mirrorwing Dragon|M|TLE
#43|Warstorm Surge|M|TLE
#44|Cityscape Leveler|M|TLE
#45|Obsessive Pursuit|R|TLA
#46|Toph, Hardheaded Teacher|R|TLA
#47|Realm of Koh|R|TLA
#48|Airbender Ascension|R|TLA
#49|The Legend of Yangchen|M|TLA
#50|Momo, Friendly Flier|R|TLA
#51|The Mechanist, Aerial Artisan|R|TLA
#52|Ty Lee, Chi Blocker|R|TLA
#53|Waterbender Ascension|R|TLA
#54|Yue, the Moon Spirit|R|TLA
#55|Boiling Rock Rioter|R|TLA
#56|Mai, Scornful Striker|R|TLA
#57|Raven Eagle|R|TLA
#58|Fated Firepower|M|TLA
#59|The Legend of Roku|M|TLA
#60|Badgermole Cub|M|TLA
#61|Great Divide Guide|R|TLA
#62|Avatar Aang|M|TLA
#63|Beifong's Bounty Hunters|R|TLA
#64|Fire Lord Zuko|R|TLA
#65|Agna Qel'a|R|TLA
#66|Ba Sing Se|R|TLA
#67|Drannith Magistrate|M|TLE
#68|Bribery|M|TLE
#69|Blasphemous Act|M|TLE
#70|Insurrection|M|TLE
#71|Beastmaster Ascension|M|TLE
#72|The Great Henge|M|TLE
#73|Rhys the Redeemed|M|TLE
#74|Treetop Village|M|TLE
#75|Earth Kingdom Jailer|U|TLA
#76|Water Tribe Rallier|U|TLA
#77|Accumulate Wisdom|U|TLA
#78|Master Pakku|U|TLA
#79|Joo Dee, One of Many|U|TLA
#80|June, Bounty Hunter|U|TLA
#81|Firebending Student|R|TLA
#82|Haru, Hidden Talent|U|TLA
#83|Invasion Tactics|U|TLA
#84|Leaves from the Vine|U|TLA
#85|Ostrich-Horse|C|TLA
#86|Bitter Work|U|TLA
#87|Dragonfly Swarm|U|TLA
#88|Sokka, Bold Boomeranger|R|TLA
#89|Sokka, Lateral Strategist|U|TLA
#90|White Lotus Reinforcements|U|TLA
#91|Aang, the Last Airbender|U|TLA
#92|Aang's Iceberg|R|TLA
#93|Team Avatar|U|TLA
#94|Crashing Wave|U|TLA
#95|Forecasting Fortune Teller|C|TLA
#96|Katara, Bending Prodigy|U|TLA
#97|Knowledge Seeker|U|TLA
#98|The Cave of Two Lovers|U|TLA
#99|Combustion Technique|U|TLA
#100|Iroh's Demonstration|U|TLA
#101|The Last Agni Kai|R|TLA
#102|Lightning Strike|C|TLA
#103|Earth Rumble|U|TLA
#104|Air Nomad Legacy|U|TLA
#105|Cruel Administrator|U|TLA
#106|Hama, the Bloodbender|U|TLA
#107|Hei Bai, Spirit of Balance|U|TLA
#108|Hermitic Herbalist|U|TLA
#109|Katara, the Fearless|R|TLA
#110|The Lion-Turtle|R|TLA
#111|Suki, Kyoshi Warrior|U|TLA
#112|Tolls of War|U|TLA
#113|Lightning Bolt|M|TLE
#114|Enter the Avatar State|U|TLA
#115|Invasion Reinforcements|U|TLA
#116|Master Piandao|U|TLA
#117|Momo, Playful Pet|U|TLA
#118|Sold Out|C|TLA
#119|Swampsnare Trap|C|TLA
#120|Fire Nation Attacks|U|TLA
#121|Firebender Ascension|R|TLA
#122|Allies at Last|U|TLA
#123|Earth Kingdom General|U|TLA
#124|Earthbender Ascension|R|TLA
#125|Rocky Rebuke|C|TLA
#126|Toph, the Blind Bandit|U|TLA
#127|True Ancestry|U|TLA
#128|Guru Pathik|U|TLA
#129|Jet, Freedom Fighter|U|TLA
#130|Long Feng, Grand Secretariat|U|TLA
#131|Messenger Hawk|C|TLA
#132|Sun Warriors|U|TLA
#133|Uncle Iroh|U|TLA
#134|Vindictive Warden|C|TLA
#135|Zhao, Ruthless Admiral|U|TLA
#136|Lita, Mechanical Engineer|M|TLE
#137|Release to Memory|M|TLE
#138|Searing Blood|M|TLE
#139|Elemental Bond|M|TLE
#140|Appa, Loyal Sky Bison|U|TLA
#141|Earth Kingdom Protectors|U|TLA
#142|Glider Staff|U|TLA
#143|Path to Redemption|C|TLA
#144|Southern Air Temple|U|TLA
#145|Vengeful Villagers|U|TLA
#146|Benevolent River Spirit|U|TLA
#147|Boomerang Basics|U|TLA
#148|Invasion Submersible|U|TLA
#149|Lost Days|C|TLA
#150|Octopus Form|C|TLA
#151|The Spirit Oasis|U|TLA
#152|Azula, On the Hunt|U|TLA
#153|Buzzard-Wasp Colony|U|TLA
#154|Epic Downfall|U|TLA
#155|Heartless Act|U|TLA
#156|Lo and Li, Twin Tutors|U|TLA
#157|Combustion Man|U|TLA
#158|Crescent Island Temple|U|TLA
#159|Fire Sages|U|TLA
#160|Firebending Lesson|C|TLA
#161|Jeong Jeong, the Deserter|U|TLA
#162|Mai, Jaded Edge|U|TLA
#163|Zhao, the Moon Slayer|R|TLA
#164|Avatar Destiny|R|TLA
#165|Bumi, King of Three Trials|U|TLA
#166|Earthen Ally|R|TLA
#167|Flopsie, Bumi's Buddy|U|TLA
#168|Unlucky Cabbage Merchant|U|TLA
#169|Dai Li Agents|U|TLA
#170|Foggy Swamp Spirit Keeper|U|TLA
#171|Three Dreams|M|TLE
#172|Sakashima of a Thousand Faces|M|TLE
#173|Standstill|M|TLE
#174|Heroic Intervention|M|TLE
#175|Captain Sisay|M|TLE
#176|Join the Dance|M|TLE
#177|Aang's Journey|C|TLA
#178|Avatar Enthusiasts|C|TLA
#179|Gather the White Lotus|U|TLA
#180|Ember Island Production|U|TLA
#181|Honest Work|U|TLA
#182|Serpent of the Pass|U|TLA
#183|Teo, Spirited Glider|U|TLA
#184|Waterbending Scroll|U|TLA
#185|Watery Grasp|C|TLA
#186|Callous Inspector|C|TLA
#187|Cat-Gator|U|TLA
#188|Corrupt Court Official|C|TLA
#189|Fire Nation Engineer|U|TLA
#190|Fire Navy Trebuchet|U|TLA
#191|Tundra Tank|U|TLA
#192|Wolfbat|U|TLA
#193|Zuko's Conviction|U|TLA
#194|Twin Blades|U|TLA
#195|Ty Lee, Artful Acrobat|U|TLA
#196|War Balloon|U|TLA
#197|Zuko, Exiled Prince|U|TLA
#198|The Boulder, Ready to Rumble|U|TLA
#199|Origin of Metalbending|C|TLA
#200|Fire Nation Warship|U|TLA
#201|Meteor Sword|U|TLA
#202|Fervor|M|TLE
#203|Meteorite|M|TLE
#204|Zuko's Exile|C|TLA
#205|Airbender's Reversal|U|TLA
#206|Airbending Lesson|C|TLA
#207|Compassionate Healer|C|TLA
#208|Fancy Footwork|U|TLA
#209|Glider Kids|C|TLA
#210|Jeong Jeong's Deserters|C|TLA
#211|Kyoshi Warriors|C|TLA
#212|Rabaroo Troop|C|TLA
#213|Sandbenders' Storm|C|TLA
#214|Water Tribe Captain|C|TLA
#215|Yip Yip!|C|TLA
#216|First-Time Flyer|C|TLA
#217|Giant Koi|C|TLA
#218|Gran-Gran|U|TLA
#219|Iguana Parrot|C|TLA
#220|Otter-Penguin|C|TLA
#221|Rowdy Snowballers|C|TLA
#222|Waterbending Lesson|C|TLA
#223|Canyon Crawler|C|TLA
#224|Deadly Precision|C|TLA
#225|Pirate Peddlers|C|TLA
#226|Bumi Bash|C|TLA
#227|Cunning Maneuver|C|TLA
#228|Fire Nation Raider|C|TLA
#229|Mongoose Lizard|C|TLA
#230|Treetop Freedom Fighters|C|TLA
#231|Yuyan Archers|C|TLA
#232|Badgermole|C|TLA
#233|Foggy Swamp Vinebender|C|TLA
#234|Pillar Launch|C|TLA
#235|Raucous Audience|C|TLA
#236|Rebellious Captives|C|TLA
#237|Rockalanche|U|TLA
#238|Saber-Tooth Moose-Lion|C|TLA
#239|Cat-Owl|C|TLA
#240|Earth Kingdom Soldier|C|TLA
#241|Platypus-Bear|C|TLA
#242|Pretending Poxbearers|C|TLA
#243|Professor Zei, Anthropologist|U|TLA
#244|Wandering Musicians|C|TLA
#245|Kyoshi Battle Fan|C|TLA
#246|Airship Engine Room|C|TLA
#247|Boiling Rock Prison|C|TLA
#248|Foggy Bottom Swamp|C|TLA
#249|Kyoshi Village|C|TLA
#250|Meditation Pools|C|TLA
#251|Misty Palms Oasis|C|TLA
#252|North Pole Gates|C|TLA
#253|Omashu City|C|TLA
#254|Serpent's Pass|C|TLA
#255|Sun-Blessed Peak|C|TLA
#256|White Lotus Hideout|U|TLA
#257|Imprisoned in the Moon|M|TLE
#258|Visions of Beyond|M|TLE
#259|Fabled Passage|M|TLE
#260|Energybending|U|TLA
#261|Curious Farm Animals|C|TLA
#262|Razor Rings|C|TLA
#263|Flexible Waterbender|C|TLA
#264|Geyser Leaper|C|TLA
#265|It'll Quench Ya!|C|TLA
#266|North Pole Patrol|U|TLA
#267|Sokka's Haiku|U|TLA
#268|Azula Always Lies|C|TLA
#269|Beetle-Headed Merchants|C|TLA
#270|Dai Li Indoctrination|C|TLA
#271|Fatal Fissure|U|TLA
#272|Foggy Swamp Hunters|C|TLA
#273|Hog-Monkey|C|TLA
#274|Merchant of Many Hats|C|TLA
#275|Ozai's Cruelty|U|TLA
#276|Boar-q-pine|C|TLA
#277|Deserter's Disciple|C|TLA
#278|Fire Nation Cadets|C|TLA
#279|How to Start a Riot|C|TLA
#280|Jet's Brainwashing|U|TLA
#281|Price of Freedom|U|TLA
#282|Rough Rhino Cavalry|C|TLA
#283|Cycle of Renewal|C|TLA
#284|Earthbending Lesson|C|TLA
#285|Kyoshi Island Plaza|U|TLA
#286|Seismic Sense|U|TLA
#287|Shared Roots|U|TLA
#288|Sparring Dummy|U|TLA
#289|Turtle-Duck|C|TLA
#290|Walltop Sentries|C|TLA
#291|Abandon Attachments|C|TLA
#292|Earth Rumble Wrestlers|C|TLA
#293|Earth Village Ruffians|C|TLA
#294|Barrels of Blasting Jelly|C|TLA
#295|Bender's Waterskin|C|TLA
#296|Fire Nation Palace|R|TLA
#297|Rumble Arena|C|TLA
#298|Secret Tunnel|R|TLA
#299|Clone|M|TLE
#300|Dockside Extortionist|M|TLE
#301|Ruinous Waterbending|U|TLA
#302|Tiger-Dillo|U|TLA
#303|Northern Air Temple|U|TLA
#304|Zuko, Conflicted|R|TLA
#305|Trusty Boomerang|U|TLA
#306|The Walls of Ba Sing Se|M|TLA
#307|Brought Back|M|TLE
#308|Force of Negation|M|TLE
#309|Humble Defector|M|TLE
#310|Rending Volley|M|TLE
#311|Eladamri's Call|M|TLE
#312|Sunbaked Canyon|M|TLE
#313|Valakut, the Molten Pinnacle|M|TLE
#314|Clone Legion|M|TLE
#315|Destined Confrontation|U|TLA
#316|Tiger-Seal|R|TLA
#317|Solstice Revelations|U|TLA
#318|Elemental Teachings|R|TLA
#319|Scout's Warning|M|TLE
#320|Teferi's Protection|M|TLE
#321|Prosperity|M|TLE
#322|Diaochan, Artful Beauty|M|TLE
#323|Shattering Spree|M|TLE
#324|Volcanic Torrent|M|TLE
#325|Taunting Challenge|M|TLE
#326|Fevered Visions|M|TLE
#327|Secret of Bloodbending|M|TLA
#328|Foggy Swamp Visions|R|TLA
#329|Redirect Lightning|R|TLA
#330|Sozin's Comet|M|TLA
#331|White Lotus Tile|M|TLA
#332|Empty City Ruse|M|TLE
#333|Mystic Remora|M|TLE
#334|Training Grounds|M|TLE
#335|Bloodchief Ascension|M|TLE
#336|Cruel Tutor|M|TLE
#337|Heartbeat of Spring|M|TLE
#338|Rites of Flourishing|M|TLE
#339|Sundial of the Infinite|M|TLE
#340|Dark Depths|M|TLE
#341|Tarnished Citadel|M|TLE
#342|Intruder Alarm|M|TLE
#343|Plains|C|TLA
#344|Island|C|TLA
#345|Swamp|C|TLA
#346|Mountain|C|TLA
#347|Forest|C|TLA

View File

@@ -6,6 +6,8 @@ Type=Expansion
ScryfallCode=TLE
[cards]
[borderless]
1 M Brought Back @Viacom
2 M Drannith Magistrate @Viacom ${"flavorName": "Mayor Tong of Chin Village"}
3 M Empty City Ruse @Viacom
@@ -67,18 +69,24 @@ ScryfallCode=TLE
59 M Tarnished Citadel @Viacom
60 M Treetop Village @Viacom
61 M Valakut, the Molten Pinnacle @Viacom ${"flavorName": "Volcano of Roku's Island"}
[black sun invasion]
62 R Appa, the Vigilant @Fahmi Fauzi
63 R Katara's Reversal @Fahmi Fauzi
64 R Fire Nation Turret @Fahmi Fauzi
65 R Swampbenders @Fahmi Fauzi
66 R Sokka's Charge @Fahmi Fauzi
67 R Earthshape @Fahmi Fauzi
[tea time]
68 R Mai and Zuko @Brian Yuen
69 R Aang and Katara @Brian Yuen
70 R Toph, Greatest Earthbender @Brian Yuen
71 R Sokka and Suki @Brian Yuen
72 R Momo's Heist @Brian Yuen
73 R Uncle's Musings @Brian Yuen
[extended art]
74 M Aang, Airbending Master @Tomoyo Asatani
75 U Air Nomad Student @Tky
76 U The Duke, Rebel Sentry @Logan Feliciano
@@ -151,6 +159,8 @@ ScryfallCode=TLE
143 R Tale of Katara and Toph @Ichiko Milk Tei
144 R Tectonic Split @Mengxuan Li
145 M Toph, Earthbending Master @Phima
[jumpstart]
146 U Aang, A Lot to Learn @Tomoyo Asatani
147 U Hook Swords @Eliz Roxs
148 U Katara, Seeking Revenge @Yoshioka
@@ -215,6 +225,8 @@ ScryfallCode=TLE
207 R Tale of Katara and Toph @Ichiko Milk Tei
208 R Tectonic Split @Mengxuan Li
209 M Toph, Earthbending Master @Phima
[tutorial]
210 R Aang, Air Nomad @Jinho Bae
211 C Aang's Defense @Jo Cordisco
212 C Aardvark Sloth @Ionomycin
@@ -310,6 +322,8 @@ ScryfallCode=TLE
302 L Plains @Slawek Fedorczuk
303 L Plains @Slawek Fedorczuk
304 L Plains @Slawek Fedorczuk
[commander bundle]
305 R Enlightened Tutor @Brigitte Roka & Clifton Stommel
306 R Flawless Maneuver @Irina Nordsol
307 R Fierce Guardianship @Ina Wong

View File

@@ -4,6 +4,77 @@ Date=2025-11-21
Name=Avatar: The Last Airbender
Type=Expansion
ScryfallCode=TLA
#https://mtgscribe.com/2025/11/08/avatar-play-booster-fact-sheet/
BoosterSlots=Common,Common-Borderless,Uncommon,RareMythic,Land,Wildcard,WildcardFoil
Booster=6 Common, 1 Common-Borderless, 3 Uncommon, 1 RareMythic, 1 Wildcard, 1 WildcardFoil+, 1 Land
Prerelease=6 Boosters, 1 RareMythic+
BoosterBox=30
[Common]
Base=Common:fromSheet("TLA cards")
[Common-Borderless]
Base=Common:fromSheet("TLA cards")
Replace=.0384F fromSheet("TLE borderless")
[Uncommon]
Base=Uncommon:fromSheet("TLA cards")
Replace=0.036F Uncommon:fromSheet("TLA scene cards")
[RareMythic]
Base=Rare:fromSheet("TLA cards")
Replace=.126F Mythic:fromSheet("TLA cards")
Replace=.016F Rare:fromSheet("TLA scene cards")
Replace=.004F Mythic:fromSheet("TLA scene cards")
Replace=.006F Rare:fromSheet("TLA field notes")
Replace=.004F Mythic:fromSheet("TLA field notes")
Replace=.001F Rare:fromSheet("TLA battle pose")
Replace=.0005F Mythic:fromSheet("TLA battle pose")
Replace=.001F Rare:fromSheet("TLA elemental frame")
Replace=.0005F Mythic:fromSheet("TLA elemental frame")
Replace=.0005F Mythic:fromSheet("TLA borderless saga")
[Wildcard]
Base=Uncommon:fromSheet("TLA cards")
Replace=0.042F Common:fromSheet("TLA cards")
Replace=0.167F Rare:fromSheet("TLA cards")
Replace=0.0026F Mythic:fromSheet("TLA cards")
Replace=0.008F Uncommon:fromSheet("TLA scene cards")
Replace=.006F Rare:fromSheet("TLA scene cards")
Replace=.004F Mythic:fromSheet("TLA scene cards")
Replace=.006F Rare:fromSheet("TLA field notes")
Replace=.004F Mythic:fromSheet("TLA field notes")
Replace=.001F Rare:fromSheet("TLA battle pose")
Replace=.0005F Mythic:fromSheet("TLA battle pose")
Replace=.001F Rare:fromSheet("TLA elemental frame")
Replace=.0005F Mythic:fromSheet("TLA elemental frame")
Replace=.0005F Mythic:fromSheet("TLA borderless dfc saga")
[WildcardFoil]
Base=Common:fromSheet("TLA cards")
Replace=0.367F Uncommon:fromSheet("TLA cards")
Replace=0.067F Rare:fromSheet("TLA cards")
Replace=0.012F Mythic:fromSheet("TLA cards")
Replace=0.008F Uncommon:fromSheet("TLA scene cards")
Replace=.006F Rare:fromSheet("TLA scene cards")
Replace=.004F Mythic:fromSheet("TLA scene cards")
Replace=.006F Rare:fromSheet("TLA field notes")
Replace=.004F Mythic:fromSheet("TLA field notes")
Replace=.001F Rare:fromSheet("TLA battle pose")
Replace=.0005F Mythic:fromSheet("TLA battle pose")
Replace=.001F Rare:fromSheet("TLA elemental frame")
Replace=.0005F Mythic:fromSheet("TLA elemental frame")
Replace=.0005F Mythic:fromSheet("TLA borderless dfc saga")
[Land]
Base=fromSheet("TLA allied lands")
Replace=0.20F BasicLand:fromSheet("TLA default basic")
Replace=0.10F BasicLand:fromSheet("TLA Avatar journey basic")
Replace=0.10F BasicLand:fromSheet("TLA Appa basic")
Replace=0.10F fromSheet("TLA allied lands")+
Replace=0.05F BasicLand:fromSheet("TLA default basic")+
Replace=0.025F BasicLand:fromSheet("TLA Avatar journey basic")+
Replace=0.025F BasicLand:fromSheet("TLA Appa basic")+
[cards]
1 C Aang's Journey @Kotakan
@@ -292,6 +363,8 @@ ScryfallCode=TLA
284 L Swamp @Matteo Bassini
285 L Mountain @Salvatorre Zee Yazzie
286 L Forest @Maojin Lee
[full art]
287 L Plains @Salvatorre Zee Yazzie
288 L Island @Grady Frederick
289 L Swamp @John Di Giovanni
@@ -302,6 +375,8 @@ ScryfallCode=TLA
294 L Swamp @Robin Olausson
295 L Mountain @Maojin Lee
296 L Forest @Slawek Fedorczuk
[scene cards]
297 M Fated Firepower @Claudiu-Antoniu Magherusan
298 R Aang, Swift Savior @Claudiu-Antoniu Magherusan
299 U Fire Nation Attacks @Claudiu-Antoniu Magherusan
@@ -321,6 +396,8 @@ ScryfallCode=TLA
313 R Fire Lord Azula @Dominik Mayer
314 R The Last Agni Kai @Dominik Mayer
315 R Fire Lord Zuko @Dominik Mayer
[borderless]
316 M Appa, Steadfast Guardian @Ilse Gort
317 R Momo, Friendly Flier @Filip Burburan
318 R Tiger-Seal @Andrea Piparo
@@ -401,6 +478,92 @@ ScryfallCode=TLA
393 R Firebending Student @Airi Yoshihisa
394 R Momo, Friendly Flier @Ryota Murayama
[field notes]
1 Appa, Steadfast Guardian|TLA|[316]
1 Momo, Friendly Flier|TLA|[317]
1 Tiger-Seal|TLA|[318]
1 The Unagi of Kyoshi Island|TLA|[319]
1 Wan Shi Tong, Librarian|TLA|[320]
1 The Fire Nation Drill|TLA|[321]
1 Koh, the Face Stealer|TLA|[322]
1 Phoenix Fleet Airship|TLA|[323]
1 Raven Eagle|TLA|[324]
1 Ran and Shaw|TLA|[325]
1 Badgermole Cub|TLA|[326]
1 Diligent Zookeeper|TLA|[327]
1 The Lion-Turtle|TLA|[328]
1 The Walls of Ba Sing Se|TLA|[329]
1 White Lotus Tile|TLA|[330]
[battle pose]
1 Aang, Swift Savior|TLA|[359]
1 Fire Lord Zuko|TLA|[360]
1 Katara, the Fearless|TLA|[361]
1 Toph, the First Metalbender|TLA|[362]
1 United Front|TLA|[331]
1 Sozin's Comet|TLA|[332]
1 Avatar Destiny|TLA|[333]
1 Fire Lord Azula|TLA|[334]
1 Ozai, the Phoenix King|TLA|[335]
[elemental frame]
1 Aang's Iceberg|TLA|[336]
1 Fated Firepower|TLA|[337]
1 Yue, the Moon Spirit|TLA|[338]
1 Foggy Swamp Visions|TLA|[339]
1 Obsessive Pursuit|TLA|[340]
1 Firebending Student|TLA|[342]
1 Redirect Lightning|TLA|[343]
1 The Earth King|TLA|[344]
1 Great Divide Guide|TLA|[345]
1 Aang, at the Crossroads|TLA|[346]
1 Bumi, Unleashed|TLA|[348]
1 Iroh, Grand Lotus|TLA|[349]
1 Katara, the Fearless|TLA|[350]
1 Katara, Water Tribe's Hope|TLA|[351]
1 Sokka, Tenacious Tactician|TLA|[352]
1 Toph, the First Metalbender|TLA|[353]
[borderless dfc saga]
1 The Legend of Yangchen|TLA|[354]
1 The Legend of Kuruk|TLA|[355]
1 The Rise of Sozin|TLA|[356]
1 The Legend of Roku|TLA|[357]
1 The Legend of Kyoshi|TLA|[358]
[allied lands]
1 Airship Engine Room|TLA|[265]
1 Boiling Rock Prison|TLA|[267]
1 Foggy Bottom Swamp|TLA|[269]
1 Kyoshi Village|TLA|[271]
1 Meditation Pools|TLA|[272]
1 Misty Palms Oasis|TLA|[273]
1 North Pole Gates|TLA|[274]
1 Omashu City|TLA|[275]
1 Serpent's Pass|TLA|[279]
1 Sun-Blessed Peak|TLA|[280]
[default basic]
1 Plains|TLA|[282]
1 Island|TLA|[283]
1 Swamp|TLA|[284]
1 Mountain|TLA|[285]
1 Forest|TLA|[286]
[Appa basic]
1 Plains|TLA|[287]
1 Island|TLA|[288]
1 Swamp|TLA|[289]
1 Mountain|TLA|[290]
1 Forest|TLA|[291]
[Avatar journey basic]
1 Plains|TLA|[292]
1 Island|TLA|[293]
1 Swamp|TLA|[294]
1 Mountain|TLA|[295]
1 Forest|TLA|[296]
[tokens]
3 c_1_1_spirit_spiritshadow @Valera Lutfullina
4 w_1_1_ally @Rose Benjamin

View File

@@ -103,7 +103,7 @@ public final class InputSelectCardsForConvokeOrImprovise extends InputSelectMany
}
if (colors.isMulticolor()) {
//prompt user if more than one option for which color to pay towards convoke
chosenColor = player.getController().chooseColorAllowColorless("Convoke " + card.toString() + " for which color?", card, colors).getColorMask();
chosenColor = player.getController().chooseColorAllowColorless("Convoke " + card.toString() + " for which color?", card, colors);
} else {
// Since the convoke mana logic can use colored mana as generic if needed,
// there is no need to prompt the user when convoking with a mono-color creature.

View File

@@ -10,6 +10,7 @@ import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostShard;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckRecognizer;
import forge.deck.DeckSection;
import forge.game.*;
import forge.game.ability.AbilityKey;
@@ -1835,51 +1836,53 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override
public List<String> chooseColors(final String message, final SpellAbility sa, final int min, final int max,
List<String> options) {
List<MagicColor.Color> enumOptions = options.stream().map(s -> MagicColor.Color.fromByte(MagicColor.fromName(s))).collect(Collectors.toList());
List<MagicColor.Color> enumChoices = getGui().getChoices(message, min, max, enumOptions);
return enumChoices.stream().map(MagicColor.Color::getName).collect(Collectors.toList());
options = options.stream().map(DeckRecognizer::getLocalisedMagicColorName).collect(Collectors.toList());
List<String> choices = getGui().getChoices(message, min, max, options);
return choices.stream().map(DeckRecognizer::getColorNameByLocalisedName).collect(Collectors.toList());
}
@Override
public MagicColor.Color chooseColor(final String message, final SpellAbility sa, final ColorSet colors) {
public byte chooseColor(final String message, final SpellAbility sa, final ColorSet colors) {
final int cntColors = colors.countColors();
switch (cntColors) {
case 0:
return null;
return 0;
case 1:
return MagicColor.Color.fromByte(colors.getColor());
return colors.getColor();
default:
return chooseColorCommon(message, sa == null ? null : sa.getHostCard(), colors, false);
}
}
@Override
public MagicColor.Color chooseColorAllowColorless(final String message, final Card c, final ColorSet colors) {
public byte chooseColorAllowColorless(final String message, final Card c, final ColorSet colors) {
final int cntColors = 1 + colors.countColors();
switch (cntColors) {
case 1:
return MagicColor.Color.COLORLESS;
return 0;
default:
return chooseColorCommon(message, c, colors, true);
}
}
private MagicColor.Color chooseColorCommon(final String message, final Card c, final ColorSet colors,
private byte chooseColorCommon(final String message, final Card c, final ColorSet colors,
final boolean withColorless) {
List<MagicColor.Color> options = Lists.newArrayList(colors.toEnumSet());
if (withColorless && colors.countColors() > 0) {
options.add(MagicColor.Color.COLORLESS);
final ImmutableList.Builder<String> colorNamesBuilder = ImmutableList.builder();
if (withColorless) {
colorNamesBuilder.add(MagicColor.toLongString(MagicColor.COLORLESS));
}
if (options.size() > 2) {
return getGui().one(message, options);
for (final MagicColor.Color color : colors) {
colorNamesBuilder.add(color.getName());
}
final ImmutableList<String> colorNames = colorNamesBuilder.build();
if (colorNames.size() > 2) {
return MagicColor.fromName(getGui().one(message, colorNames));
}
boolean confirmed = false;
confirmed = InputConfirm.confirm(this, CardView.get(c), message, true,
options.stream().map(MagicColor.Color::toString).collect(Collectors.toList()));
confirmed = InputConfirm.confirm(this, CardView.get(c), message, true, colorNames);
final int idxChosen = confirmed ? 0 : 1;
return options.get(idxChosen);
return MagicColor.fromName(colorNames.get(idxChosen));
}
@Override

View File

@@ -2,8 +2,26 @@ import argparse
import json
import requests
def manualRankings(edition='TLA'):
with open(edition + '.json', 'r') as f:
cardlist = json.load(f)
# remove duplicates
unique_cards = dict()
for card in cardlist:
if card['name'] not in unique_cards:
unique_cards[card['name']] = card
def draftsimRankings(edition='SPM', extra=None):
cardlist = list(unique_cards.values())
cardlist.sort(key=lambda k:k['myrating'], reverse=True)
with open("../res/draft/rankings/" + edition.lower() + '.rnk', 'w') as out:
out.write('//Rank|Name|Rarity|Set\n')
for counter, card in enumerate(cardlist):
l = [str(counter+1), card['name'].replace('_', ' '), card['rarity'], edition]
out.write('#')
out.write('|'.join(l))
out.write('\n')
def draftsimRankings(edition='TLA', extra=None):
edition = edition.upper()
url1 = 'https://draftsim.com/generated/%s/' % (edition)
url2 = '%s' % edition
@@ -76,11 +94,14 @@ def idToNameLoops(name, code=None):
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Edition File Generator')
parser = argparse.ArgumentParser(description='Edition File Generator')
parser.add_argument('-c', action='store', dest='setcode', help='Required setcode', required=True)
parser.add_argument('-x', action='store', dest='altpage', help='Additional rankings page', required=False)
result = parser.parse_args()
draftsimRankings(result.setcode, result.altpage)
parser.add_argument('-c', action='store', dest='setcode', help='Required setcode', required=True)
parser.add_argument('-x', action='store', dest='altpage', help='Additional rankings page', required=False)
parser.add_argument('-m', action='store_true', dest='manual', help='Additional rankings page', required=False)
result = parser.parse_args()
manual = result.manual is not None
if manual:
manualRankings(result.setcode)
else:
draftsimRankings(result.setcode, result.altpage)