Merge remote-tracking branch 'upstream/master' into collector-number-in-card-list-and-card-db-refactoring

This commit is contained in:
leriomaggio
2021-08-04 08:51:56 +01:00
610 changed files with 49923 additions and 49745 deletions

View File

@@ -389,7 +389,7 @@ public class AiController {
final List<SpellAbility> spellAbility = Lists.newArrayList();
for (final Card c : l) {
for (final SpellAbility sa : c.getNonManaAbilities()) {
// Check if this AF is a Counterpsell
// Check if this AF is a Counterspell
if (sa.getApi() == ApiType.Counter) {
spellAbility.add(sa);
}

View File

@@ -1307,7 +1307,7 @@ public class ComputerUtil {
}
if (abCost.hasTapCost() && source.hasSVar("AITapDown")) {
return true;
} else if (sa.hasParam("Planeswalker") && ai.getGame().getPhaseHandler().is(PhaseType.MAIN2)) {
} else if (sa.isPwAbility() && ai.getGame().getPhaseHandler().is(PhaseType.MAIN2)) {
for (final CostPart part : abCost.getCostParts()) {
if (part instanceof CostPutCounter) {
return true;
@@ -2859,7 +2859,6 @@ public class ComputerUtil {
public static boolean lifegainNegative(final Player player, final Card source) {
return lifegainNegative(player, source, 1);
}
public static boolean lifegainNegative(final Player player, final Card source, final int n) {
if (!player.canGainLife()) {
return false;

View File

@@ -1236,7 +1236,7 @@ public abstract class GameState {
// (will be overridden later, so the actual value shouldn't matter)
//FIXME it shouldn't be able to attach itself
c.setEntityAttachedTo(c);
c.setEntityAttachedTo(CardFactory.copyCard(c, true));
}
if (cardsWithoutETBTrigs.contains(c)) {

View File

@@ -98,4 +98,3 @@ public class AmassAi extends SpellAbilityAi {
return ComputerUtilCard.getBestAI(better);
}
}

View File

@@ -252,7 +252,7 @@ public class AnimateAi extends SpellAbilityAi {
private boolean animateTgtAI(final SpellAbility sa) {
final Player ai = sa.getActivatingPlayer();
final PhaseHandler ph = ai.getGame().getPhaseHandler();
final boolean alwaysActivatePWAbility = sa.hasParam("Planeswalker")
final boolean alwaysActivatePWAbility = sa.isPwAbility()
&& sa.getPayCosts().hasSpecificCostType(CostPutCounter.class)
&& sa.getTargetRestrictions() != null
&& sa.getTargetRestrictions().getMinTargets(sa.getHostCard(), sa) == 0;

View File

@@ -50,7 +50,6 @@ public final class BondAi extends SpellAbilityAi {
return true;
} // end bondCanPlayAI()
@Override
protected Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> options, boolean isOptional, Player targetedPlayer, Map<String, Object> params) {
return ComputerUtilCard.getBestCreatureAI(options);

View File

@@ -36,7 +36,6 @@ public class CanPlayAsDrawbackAi extends SpellAbilityAi {
return false;
}
@Override
public SpellAbility chooseSingleSpellAbility(Player player, SpellAbility sa, List<SpellAbility> spells,
Map<String, Object> params) {

View File

@@ -1130,7 +1130,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
}
}
boolean doWithoutTarget = sa.hasParam("Planeswalker") && sa.usesTargeting()
boolean doWithoutTarget = sa.isPwAbility() && sa.usesTargeting()
&& sa.getMinTargets() == 0
&& sa.getPayCosts().hasSpecificCostType(CostPutCounter.class);

View File

@@ -30,8 +30,7 @@ public class CharmAi extends SpellAbilityAi {
final int min;
if (sa.isEntwine()) {
num = min = choices.size();
}
else {
} else {
num = AbilityUtils.calculateAmount(source, sa.getParamOrDefault("CharmNum", "1"), sa);
min = sa.hasParam("MinCharmNum") ? AbilityUtils.calculateAmount(source, sa.getParamOrDefault("MinCharmNum", "1"), sa) : num;
}

View File

@@ -33,7 +33,6 @@ public class ClashAi extends SpellAbilityAi {
return legalAction;
}
/*
* (non-Javadoc)
*

View File

@@ -64,7 +64,6 @@ public class CounterAi extends SpellAbilityAi {
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
final SpellAbility topSA = ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa);
if (!CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa) || topSA.getActivatingPlayer() == ai
|| ai.getAllies().contains(topSA.getActivatingPlayer())) {
@@ -317,7 +316,7 @@ public class CounterAi extends SpellAbilityAi {
Iterator<SpellAbilityStackInstance> it = game.getStack().iterator();
SpellAbilityStackInstance si = null;
while(it.hasNext()) {
while (it.hasNext()) {
si = it.next();
tgtSA = si.getSpellAbility(true);
if (!sa.canTargetSpellAbility(tgtSA)) {

View File

@@ -501,7 +501,7 @@ public class CountersPutAi extends SpellAbilityAi {
// Activate +Loyalty planeswalker abilities even if they have no target (e.g. Vivien of the Arkbow),
// but try to do it in Main 2 then so that the AI has a chance to play creatures first.
if (list.isEmpty()
&& sa.hasParam("Planeswalker")
&& sa.isPwAbility()
&& sa.getPayCosts().hasOnlySpecificCostType(CostPutCounter.class)
&& sa.isTargetNumberValid()
&& sa.getTargets().size() == 0

View File

@@ -57,7 +57,6 @@ public final class EncodeAi extends SpellAbilityAi {
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
return true;

View File

@@ -69,4 +69,3 @@ public class ExploreAi extends SpellAbilityAi {
}
}

View File

@@ -14,7 +14,6 @@ public class FlipACoinAi extends SpellAbilityAi {
*/
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
if (sa.hasParam("AILogic")) {
String ailogic = sa.getParam("AILogic");
if (ailogic.equals("Never")) {

View File

@@ -24,4 +24,3 @@ public class InvestigateAi extends SpellAbilityAi {
return true;
}
}

View File

@@ -74,7 +74,6 @@ public class LifeExchangeAi extends SpellAbilityAi {
@Override
protected boolean doTriggerAINoCost(final Player ai, final SpellAbility sa,
final boolean mandatory) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
Player opp = AiAttackController.choosePreferredDefenderPlayer(ai);
if (tgt != null) {

View File

@@ -53,7 +53,7 @@ public class MillAi extends SpellAbilityAi {
} else if ("ExileAndPlayOrDealDamage".equals(sa.getParam("AILogic"))) {
return (ph.is(PhaseType.MAIN1) || ph.is(PhaseType.MAIN2)) && ph.isPlayerTurn(ai); // Chandra, Torch of Defiance and similar
}
if (!sa.hasParam("Planeswalker")) { // Planeswalker abilities are only activated at sorcery speed
if (!sa.isPwAbility()) { // Planeswalker abilities are only activated at sorcery speed
if ("You".equals(sa.getParam("Defined")) && !(!SpellAbilityAi.isSorcerySpeed(sa) && ph.is(PhaseType.END_OF_TURN)
&& ph.getNextTurn().equals(ai))) {
return false; // only self-mill at opponent EOT

View File

@@ -24,7 +24,6 @@ public class ScryAi extends SpellAbilityAi {
*/
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
if (sa.usesTargeting()) { // It doesn't appear that Scry ever targets
// ability is targeted
sa.resetTargets();
@@ -69,7 +68,7 @@ public class ScryAi extends SpellAbilityAi {
// in the playerturn Scry should only be done in Main1 or in upkeep if able
if (ph.isPlayerTurn(ai)) {
if (SpellAbilityAi.isSorcerySpeed(sa)) {
return ph.is(PhaseType.MAIN1) || sa.hasParam("Planeswalker");
return ph.is(PhaseType.MAIN1) || sa.isPwAbility();
} else {
return ph.is(PhaseType.UPKEEP);
}

View File

@@ -199,7 +199,6 @@ public class SetStateAi extends SpellAbilityAi {
return false;
}
// check which state would be better for attacking
if (ph.isPlayerTurn(ai) && ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
boolean transformAttack = false;

View File

@@ -66,7 +66,6 @@ public class StoreSVarAi extends SpellAbilityAi {
return false;
}
return true;
}

View File

@@ -24,7 +24,6 @@ public class SurveilAi extends SpellAbilityAi {
*/
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
if (sa.usesTargeting()) { // TODO: It doesn't appear that Surveil ever targets, is this necessary?
sa.resetTargets();
sa.getTargets().add(ai);
@@ -60,7 +59,7 @@ public class SurveilAi extends SpellAbilityAi {
// in the player's turn Surveil should only be done in Main1 or in Upkeep if able
if (ph.isPlayerTurn(ai)) {
if (SpellAbilityAi.isSorcerySpeed(sa)) {
return ph.is(PhaseType.MAIN1) || sa.hasParam("Planeswalker");
return ph.is(PhaseType.MAIN1) || sa.isPwAbility();
} else {
return ph.is(PhaseType.UPKEEP);
}

View File

@@ -47,8 +47,7 @@ public class TwoPilesAi extends SpellAbilityAi {
CardCollectionView pool;
if (sa.hasParam("DefinedCards")) {
pool = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("DefinedCards"), sa);
}
else {
} else {
pool = p.getCardsIn(zone);
}
pool = CardLists.getValidCards(pool, valid, card.getController(), card, sa);

View File

@@ -224,7 +224,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
}
artIds.put(key, artIdx);
addCard(new PaperCard(cr, e.getCode(), cis.rarity, artIdx, cis.collectorNumber));
addCard(new PaperCard(cr, e.getCode(), cis.rarity, artIdx, false, cis.collectorNumber, cis.artistName));
}
public void loadCard(String cardName, CardRules cr) {
@@ -236,6 +236,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
for (CardInSet cis : cardsInSet)
addSetCard(e, cis, cr);
}
reIndex();
}
@@ -289,10 +290,10 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
for (CardRules cr : rulesByName.values()) {
if (!contains(cr.getName())) {
if (upcomingSet != null) {
addCard(new PaperCard(cr, upcomingSet.getCode(), CardRarity.Unknown));
addCard(new PaperCard(cr, upcomingSet.getCode(), CardRarity.Unknown, IPaperCard.DEFAULT_ART_INDEX));
} else if (enableUnknownCards && !this.filtered.contains(cr.getName())) {
System.err.println("The card " + cr.getName() + " was not assigned to any set. Adding it to UNKNOWN set... to fix see res/editions/ folder. ");
addCard(new PaperCard(cr, CardEdition.UNKNOWN.getCode(), CardRarity.Special));
addCard(new PaperCard(cr, CardEdition.UNKNOWN.getCode(), CardRarity.Special, IPaperCard.DEFAULT_ART_INDEX));
}
}
}
@@ -958,7 +959,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
System.err.println("We're sorry, but this card is not supported yet.");
}
return new PaperCard(CardRules.getUnsupportedCardNamed(request.cardName), cardEdition.getCode(), cardRarity);
return new PaperCard(CardRules.getUnsupportedCardNamed(request.cardName), cardEdition.getCode(), cardRarity, IPaperCard.DEFAULT_ART_INDEX);
}
@@ -1016,7 +1017,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
}
}
if (paperCards.isEmpty()) {
paperCards.add(new PaperCard(rules, CardEdition.UNKNOWN.getCode(), CardRarity.Special));
paperCards.add(new PaperCard(rules, CardEdition.UNKNOWN.getCode(), CardRarity.Special, IPaperCard.DEFAULT_ART_INDEX));
}
// 2. add them to db
for (PaperCard paperCard : paperCards) {

View File

@@ -163,11 +163,13 @@ public final class CardEdition implements Comparable<CardEdition> {
public final CardRarity rarity;
public final String collectorNumber;
public final String name;
public final String artistName;
public CardInSet(final String name, final String collectorNumber, final CardRarity rarity) {
public CardInSet(final String name, final String collectorNumber, final CardRarity rarity, final String artistName) {
this.name = name;
this.collectorNumber = collectorNumber;
this.rarity = rarity;
this.artistName = artistName;
}
public String toString() {
@@ -181,6 +183,10 @@ public final class CardEdition implements Comparable<CardEdition> {
sb.append(' ');
}
sb.append(name);
if (artistName != null) {
sb.append(" @");
sb.append(artistName);
}
return sb.toString();
}
@@ -535,7 +541,7 @@ public final class CardEdition implements Comparable<CardEdition> {
* name - grouping #5
*/
// "(^(.?[0-9A-Z]+.?))?(([SCURML]) )?(.*)$"
"(^(.?[0-9A-Z]+\\S?[A-Z]*)\\s)?(([SCURML])\\s)?(.*)$"
"(^(.?[0-9A-Z]+\\S?[A-Z]*)\\s)?(([SCURML])\\s)?([^@]*)( @(.*))?$"
);
ListMultimap<String, CardInSet> cardMap = ArrayListMultimap.create();
@@ -560,7 +566,8 @@ public final class CardEdition implements Comparable<CardEdition> {
String collectorNumber = matcher.group(2);
CardRarity r = CardRarity.smartValueOf(matcher.group(4));
String cardName = matcher.group(5);
CardInSet cis = new CardInSet(cardName, collectorNumber, r);
String artistName = matcher.group(7);
CardInSet cis = new CardInSet(cardName, collectorNumber, r, artistName);
cardMap.put(sectionName, cis);
}

View File

@@ -234,6 +234,7 @@ public interface IPaperCard extends InventoryItem, Serializable {
boolean isToken();
CardRules getRules();
CardRarity getRarity();
String getArtist();
String getItemType();

View File

@@ -17,7 +17,12 @@
*/
package forge.item;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import com.google.common.base.Function;
import forge.ImageKeys;
import forge.StaticData;
import forge.card.CardDb;
@@ -28,10 +33,6 @@ import forge.util.CardTranslation;
import forge.util.Localizer;
import forge.util.TextUtil;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
/**
* A lightweight version of a card that matches real-world cards, to use outside of games (eg. inventory, decks, trade).
* <br><br>
@@ -53,9 +54,10 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
(see getCollectorNumber())
*/
private String collectorNumber = null;
private final String artist;
private final int artIndex;
private final boolean foil;
private Boolean hasImage = null;
private Boolean hasImage;
// Calculated fields are below:
private transient CardRarity rarity; // rarity is given in ctor when set is assigned
@@ -114,6 +116,11 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
return rarity;
}
@Override
public String getArtist() {
return artist;
}
/* FIXME: At the moment, every card can get Foiled, with no restriction on the
corresponding Edition - so we could Foil even Alpha cards.
*/
@@ -123,7 +130,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
if (this.foiledVersion == null) {
this.foiledVersion = new PaperCard(this.rules, this.edition, this.rarity,
this.artIndex, true, String.valueOf(collectorNumber));
this.artIndex, true, String.valueOf(collectorNumber), this.artist);
}
return this.foiledVersion;
}
@@ -162,16 +169,12 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
}
};
public PaperCard(final CardRules rules0, final String edition0, final CardRarity rarity0) {
this(rules0, edition0, rarity0, IPaperCard.DEFAULT_ART_INDEX, false);
}
public PaperCard(final CardRules rules0, final String edition0, final CardRarity rarity0, final int artIndex0) {
this(rules0, edition0, rarity0, artIndex0, false);
this(rules0, edition0, rarity0, artIndex0, false, "");
}
public PaperCard(final CardRules rules0, final String edition0, final CardRarity rarity0, final int artIndex0,
final boolean foil0) {
final boolean foil0, final String artist0) {
if (rules0 == null || edition0 == null || rarity0 == null) {
throw new IllegalArgumentException("Cannot create card without rules, edition or rarity");
}
@@ -181,16 +184,12 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
artIndex = artIndex0 >= IPaperCard.DEFAULT_ART_INDEX ? artIndex0 : IPaperCard.DEFAULT_ART_INDEX;
foil = foil0;
rarity = rarity0;
}
public PaperCard(final CardRules rules0, final String edition0, final CardRarity rarity0, final int artIndex0,
final String collectorNumber0) {
this(rules0, edition0, rarity0, artIndex0, false, collectorNumber0);
artist = (artist0 != null ? artist0 : "");
}
public PaperCard(final CardRules rules0, final String edition0, final CardRarity rarity0,
final int artIndex0, final boolean foil0, final String collectorNumber0) {
this(rules0, edition0, rarity0, artIndex0, foil0);
final int artIndex0, final boolean foil0, final String collectorNumber0, final String artist) {
this(rules0, edition0, rarity0, artIndex0, foil0, artist);
if ((collectorNumber0 == null) || (collectorNumber0.length() == 0))
collectorNumber = IPaperCard.NO_COLLECTOR_NUMBER;
else

View File

@@ -143,6 +143,7 @@ public class PaperToken implements InventoryItemFromSet, IPaperCard {
@Override public CardRules getRules() { return card; }
@Override public CardRarity getRarity() { return CardRarity.None; }
@Override public String getArtist() { /*TODO*/ return ""; }
// Unfortunately this is a property of token, cannot move it outside of class
public String getImageFilename() { return getImageFilename(1); }

View File

@@ -6,7 +6,6 @@ import forge.card.CardDb;
import forge.card.CardRules;
import forge.card.CardSplitType;
import forge.item.PaperCard;
import forge.item.PaperToken;
public class ImageUtil {
public static float getNearestHQSize(float baseSize, float actualSize) {
@@ -30,28 +29,6 @@ public class ImageUtil {
return cp;
}
public static PaperToken getPaperTokenFromImageKey(String key) {
if ( key == null ) {
return null;
}
key = key.substring(2);
int index = key.lastIndexOf('_');
if (index != -1) {
String script = key.substring(0, index);
String edition = key.substring(index + 1);
if (script.startsWith("emblem"))
return null;
if (null == StaticData.instance().getCardEdition(edition)) {
script = key;
edition = "???";
}
script = script.replaceAll("[0-9]*$", "");
return StaticData.instance().getAllTokens().getToken(script, edition);
}
return null;
}
public static String getImageRelativePath(PaperCard cp, boolean backFace, boolean includeSet, boolean isDownloadUrl) {
final String nameToUse = cp == null ? null : getNameToUse(cp, backFace);
if (nameToUse == null) {
@@ -78,7 +55,7 @@ public class ImageUtil {
int artIdx = cp.getArtIndex() - 1;
if (hasManyPictures) {
if ( cntPictures <= artIdx ) // prevent overflow
if (cntPictures <= artIdx) // prevent overflow
artIdx = cntPictures == 0 ? 0 : artIdx % cntPictures;
s.append(artIdx + 1);
}
@@ -113,8 +90,8 @@ public class ImageUtil {
public static String getNameToUse(PaperCard cp, boolean backFace) {
final CardRules card = cp.getRules();
if (backFace ) {
if ( hasBackFacePicture(cp) )
if (backFace) {
if (hasBackFacePicture(cp))
if (card.getOtherPart() != null) {
return card.getOtherPart().getName();
} else if (!card.getMeldWith().isEmpty()) {
@@ -140,7 +117,7 @@ public class ImageUtil {
return getImageRelativePath(cp, backFace, true, true);
}
public static String getScryfallDownloadUrl(PaperCard cp, boolean backFace, String setCode, String langCode){
public static String getScryfallDownloadUrl(PaperCard cp, boolean backFace, String setCode, String langCode, boolean useArtCrop){
String editionCode;
if ((setCode != null) && (setCode.length() > 0))
editionCode = setCode;
@@ -149,12 +126,13 @@ public class ImageUtil {
String cardCollectorNumber = cp.getCollectorNumber();
// Hack to account for variations in Arabian Nights
cardCollectorNumber = cardCollectorNumber.replace("+", "");
String versionParam = useArtCrop ? "art_crop" : "normal";
String faceParam = "";
if (cp.getRules().getOtherPart() != null) {
faceParam = (backFace ? "&face=back" : "&face=front");
}
return String.format("%s/%s/%s?format=image&version=normal%s", editionCode, cardCollectorNumber,
langCode, faceParam);
return String.format("%s/%s/%s?format=image&version=%s%s", editionCode, cardCollectorNumber,
langCode, versionParam, faceParam);
}
public static String toMWSFilename(String in) {

View File

@@ -1024,7 +1024,6 @@ public class Game {
}
public void clearCaches() {
lastStateBattlefield.clear();
lastStateGraveyard.clear();
//playerCache.clear();

View File

@@ -56,10 +56,10 @@ public class ChangeTargetsEffect extends SpellAbilityEffect {
if (sa.hasParam("ChangeSingleTarget")) {
// 1. choose a target of target spell
List<Pair<SpellAbilityStackInstance, GameObject>> allTargets = new ArrayList<>();
while(changingTgtSI != null) {
while (changingTgtSI != null) {
SpellAbility changedSa = changingTgtSI.getSpellAbility(true);
if (changedSa.usesTargeting()) {
for(GameObject it : changedSa.getTargets())
for (GameObject it : changedSa.getTargets())
allTargets.add(ImmutablePair.of(changingTgtSI, it));
}
changingTgtSI = changingTgtSI.getSubInstance();
@@ -76,12 +76,14 @@ public class ChangeTargetsEffect extends SpellAbilityEffect {
GameObject oldTarget = chosenTarget.getValue();
TargetChoices oldTargetBlock = replaceIn.getTargetChoices();
TargetChoices newTargetBlock = oldTargetBlock.clone();
// gets the divied value from old target
// gets the divided value from old target
Integer div = oldTargetBlock.getDividedValue(oldTarget);
// 3. test if updated choices would be correct.
GameObject newTarget = Iterables.getFirst(getDefinedCardsOrTargeted(sa, "DefinedMagnet"), null);
if (replaceIn.getSpellAbility(true).canTarget(newTarget)) {
// CR 115.3. The same target cant be chosen multiple times for
// any one instance of the word “target” on a spell or ability.
if (!oldTargetBlock.contains(newTarget) && replaceIn.getSpellAbility(true).canTarget(newTarget)) {
newTargetBlock.remove(oldTarget);
newTargetBlock.add(newTarget);
if (div != null) {
@@ -89,9 +91,8 @@ public class ChangeTargetsEffect extends SpellAbilityEffect {
}
replaceIn.updateTarget(newTargetBlock, sa.getHostCard());
}
}
else {
while(changingTgtSI != null) {
} else {
while (changingTgtSI != null) {
SpellAbility changingTgtSA = changingTgtSI.getSpellAbility(true);
if (changingTgtSA.usesTargeting()) {
// random target and DefinedMagnet works on single targets
@@ -126,8 +127,7 @@ public class ChangeTargetsEffect extends SpellAbilityEffect {
changingTgtSA.addDividedAllocation(newTarget, div);
}
}
}
else {
} else {
// Update targets, with a potential new target
Predicate<GameObject> filter = sa.hasParam("TargetRestriction") ? GameObjectPredicates.restriction(sa.getParam("TargetRestriction").split(","), activator, sa.getHostCard(), sa) : null;
// TODO Creature.Other might not work yet as it should

View File

@@ -32,6 +32,12 @@ public class ChooseGenericEffect extends SpellAbilityEffect {
final Card host = sa.getHostCard();
final List<SpellAbility> abilities = Lists.newArrayList(sa.getAdditionalAbilityList("Choices"));
if (sa.hasParam("NumRandomChoices")) {
int n = AbilityUtils.calculateAmount(host, sa.getParam("NumRandomChoices"), sa);
while (abilities.size() > n) {
Aggregates.removeRandom(abilities);
}
}
final SpellAbility fallback = sa.getAdditionalAbility("FallbackAbility");
final int amount = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("ChoiceAmount", "1"), sa);

View File

@@ -124,8 +124,6 @@ public class EffectEffect extends SpellAbilityEffect {
}
String image;
String set = hostCard.getSetCode().toLowerCase();
StringBuilder imageSet = new StringBuilder();
if (sa.hasParam("Image")) {
image = ImageKeys.getTokenKey(sa.getParam("Image"));
} else if (name.startsWith("Emblem")) { // try to get the image from name
@@ -138,8 +136,6 @@ public class EffectEffect extends SpellAbilityEffect {
} else { // use host image
image = hostCard.getImageKey();
}
imageSet.append(image).append("_").append(set);
image = imageSet.toString();
for (Player controller : effectOwner) {
final Card eff = createEffect(sa, controller, name, image);

View File

@@ -36,16 +36,25 @@ public class RevealEffect extends SpellAbilityEffect {
}
final CardCollection revealed = new CardCollection();
if (sa.hasParam("Random")) {
CardCollection valid = new CardCollection(cardsInHand);
if (sa.hasParam("RevealValid")) {
valid = CardLists.getValidCards(valid, sa.getParam("RevealValid"), p, host, sa);
}
if (valid.isEmpty())
continue;
if (sa.hasParam("NumCards")) {
final int revealnum = Math.min(cardsInHand.size(), cnt);
final CardCollection hand = new CardCollection(cardsInHand);
for (int i = 0; i < revealnum; i++) {
final Card random = Aggregates.random(hand);
final Card random = Aggregates.random(valid);
revealed.add(random);
hand.remove(random);
valid.remove(random);
}
} else {
revealed.add(Aggregates.random(cardsInHand));
revealed.add(Aggregates.random(valid));
}
} else if (sa.hasParam("RevealDefined")) {

View File

@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import forge.game.event.GameEventRollDie;
import org.apache.commons.lang3.StringUtils;
import forge.game.ability.AbilityKey;
@@ -75,6 +76,8 @@ public class RollDiceEffect extends SpellAbilityEffect {
for (int i = 0; i < amount; i++) {
int roll = MyRandom.getRandom().nextInt(sides) + 1;
// Play the die roll sound
player.getGame().fireEvent(new GameEventRollDie());
rolls.add(roll);
total += roll;
}

View File

@@ -3,6 +3,7 @@ package forge.game.ability.effects;
import forge.game.Game;
import forge.game.PlanarDice;
import forge.game.ability.SpellAbilityEffect;
import forge.game.event.GameEventRollDie;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.util.Localizer;
@@ -26,6 +27,8 @@ public class RollPlanarDiceEffect extends SpellAbilityEffect {
game.getPhaseHandler().incPlanarDiceRolledthisTurn();
}
PlanarDice result = PlanarDice.roll(activator, null);
// Play the die roll sound
activator.getGame().fireEvent(new GameEventRollDie());
String message = Localizer.getInstance().getMessage("lblPlayerRolledResult", activator.getName(), result.toString());
game.getAction().notifyOfValue(sa, activator, message, null);

View File

@@ -27,6 +27,16 @@ import forge.card.CardDb.CardArtPreference;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostParser;
import forge.game.*;
import forge.game.CardTraitBase;
import forge.game.Direction;
import forge.game.EvenOdd;
import forge.game.Game;
import forge.game.GameActionUtil;
import forge.game.GameEntity;
import forge.game.GameEntityCounterTable;
import forge.game.GameStage;
import forge.game.GlobalRuleChange;
import forge.game.IHasSVars;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
@@ -2271,7 +2281,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
if (!stAb.isSecondary() && !stAb.isClassAbility()) {
final String stAbD = stAb.toString();
if (!stAbD.equals("")) {
boolean disabled = getGame() != null && !stAb.checkConditions();
boolean disabled = getGame() != null && getController() != null && game.getAge() != GameStage.Play && !stAb.checkConditions();
if (disabled) sb.append(grayTag);
sb.append(stAbD);
if (disabled) sb.append(endTag);

View File

@@ -0,0 +1,9 @@
package forge.game.event;
public class GameEventRollDie extends GameEvent {
@Override
public <T> T visit(IGameEventVisitor<T> visitor) {
return visitor.visit(this);
}
}

View File

@@ -38,6 +38,7 @@ public interface IGameEventVisitor<T> {
T visit(GameEventPlayerPoisoned event);
T visit(GameEventPlayerPriority event);
T visit(GameEventPlayerStatsChanged event);
T visit(GameEventRollDie event);
T visit(GameEventTokenStateUpdate event);
T visit(GameEventScry event);
T visit(GameEventShuffle event);
@@ -88,6 +89,7 @@ public interface IGameEventVisitor<T> {
public T visit(GameEventPlayerPoisoned event) { return null; }
public T visit(GameEventPlayerPriority event) { return null; }
public T visit(GameEventPlayerStatsChanged event) { return null; }
public T visit(GameEventRollDie event) { return null; }
public T visit(GameEventTokenStateUpdate event) { return null; }
public T visit(GameEventScry event) { return null; }
public T visit(GameEventShuffle event) { return null; }

View File

@@ -413,7 +413,8 @@ public final class StaticAbilityContinuous {
});
}
if (layer == StaticAbilityLayer.TYPE && params.containsKey("RemoveType")) {
if (layer == StaticAbilityLayer.TYPE) {
if (params.containsKey("RemoveType")) {
removeTypes = Lists.newArrayList(Arrays.asList(params.get("RemoveType").split(" & ")));
Iterables.removeIf(removeTypes, new Predicate<String>() {
@@ -426,20 +427,15 @@ public final class StaticAbilityContinuous {
}
});
}
if (layer == StaticAbilityLayer.TYPE) {
if (params.containsKey("RemoveSuperTypes")) {
removeSuperTypes = true;
}
if (params.containsKey("RemoveCardTypes")) {
removeCardTypes = true;
}
if (params.containsKey("RemoveSubTypes")) {
removeSubTypes = true;
}
if (params.containsKey("RemoveLandTypes")) {
removeLandTypes = true;
}

View File

@@ -24,6 +24,7 @@ import java.awt.RenderingHints;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
@@ -32,12 +33,14 @@ import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
import com.google.common.cache.LoadingCache;
import com.mortennobel.imagescaling.ResampleOp;
import forge.card.CardSplitType;
import forge.game.card.Card;
import forge.game.card.CardView;
import forge.game.player.PlayerView;
@@ -54,6 +57,7 @@ import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinIcon;
import forge.toolbox.imaging.FCardImageRenderer;
import forge.util.ImageUtil;
import forge.util.TextUtil;
/**
* This class stores ALL card images in a cache with soft values. this means
@@ -150,8 +154,13 @@ public class ImageCache {
*
*/
public static BufferedImage getOriginalImage(String imageKey, boolean useDefaultIfNotFound, CardView cardView) {
return getOriginalImageInternal(imageKey, useDefaultIfNotFound, cardView).getLeft();
}
// return the pair of image and a flag to indicate if it is a placeholder image.
private static Pair<BufferedImage, Boolean> getOriginalImageInternal(String imageKey, boolean useDefaultIfNotFound, CardView cardView) {
if (null == imageKey) {
return null;
return Pair.of(null, false);
}
IPaperCard ipc = null;
@@ -163,20 +172,44 @@ public class ImageCache {
ipc = pc;
imageKey = ImageUtil.getImageKey(pc, altState, true);
if (StringUtils.isBlank(imageKey)) {
return _defaultImage;
return Pair.of(_defaultImage, true);
}
} else if (imageKey.startsWith(ImageKeys.TOKEN_PREFIX) && cardView != null && cardView.isToken()) {
ipc = ImageUtil.getPaperTokenFromImageKey(imageKey);
}
// Replace .full to .artcrop if art crop is preferred
// Only allow use art if the artist info is available
boolean useArtCrop = "Crop".equals(FModel.getPreferences().getPref(ForgePreferences.FPref.UI_CARD_ART_FORMAT))
&& ipc != null && !ipc.getArtist().isEmpty();
String originalKey = imageKey;
if (useArtCrop) {
if (ipc != null && ipc.getRules().getSplitType() == CardSplitType.Flip) {
// Art crop will always use front face as image key for flip cards
imageKey = ImageUtil.getImageKey((PaperCard) ipc, false, true);
}
imageKey = TextUtil.fastReplace(imageKey, ".full", ".artcrop");
}
// Load from file and add to cache if not found in cache initially.
BufferedImage original = getImage(imageKey);
if (original == null && !useDefaultIfNotFound) {
return Pair.of(null, false);
}
// if art crop is exist, check also if the full card image is also cached.
if (useArtCrop && original != null) {
BufferedImage cached = _CACHE.getIfPresent(originalKey);
if (cached != null)
return Pair.of(cached, false);
}
boolean noBorder = !useArtCrop && !isPreferenceEnabled(ForgePreferences.FPref.UI_RENDER_BLACK_BORDERS);
boolean fetcherEnabled = isPreferenceEnabled(ForgePreferences.FPref.UI_ENABLE_ONLINE_IMAGE_FETCHER);
boolean isPlaceholder = (original == null) && fetcherEnabled;
// If the user has indicated that they prefer Forge NOT render a black border, round the image corners
// to account for JPEG images that don't have a transparency.
boolean noBorder = !isPreferenceEnabled(ForgePreferences.FPref.UI_RENDER_BLACK_BORDERS);
if (original != null && noBorder) {
// use a quadratic equation to calculate the needed radius from an image dimension
int radius;
float width = original.getWidth();
@@ -209,19 +242,28 @@ public class ImageCache {
// No image file exists for the given key so optionally associate with
// a default "not available" image, however do not add it to the cache,
// as otherwise it's problematic to update if the real image gets fetched.
if (original == null && useDefaultIfNotFound) {
if (original == null || useArtCrop) {
if (ipc != null || cardView != null) {
int width = 488, height = 680;
BufferedImage art = original;
CardView card = ipc != null ? Card.getCardForUi(ipc).getView() : cardView;
original = new BufferedImage(480, 680, BufferedImage.TYPE_INT_ARGB);
FCardImageRenderer.drawCardImage(original.createGraphics(), card, altState, 480, 680);
if (!isPreferenceEnabled(ForgePreferences.FPref.UI_ENABLE_ONLINE_IMAGE_FETCHER))
_CACHE.put(imageKey, original);
String legalString = null;
original = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
if (art != null) {
Calendar cal = Calendar.getInstance();
cal.setTime(StaticData.instance().getCardEdition(ipc.getEdition()).getDate());
int year = cal.get(Calendar.YEAR);
legalString = "Illus. " + ipc.getArtist() + " ©" + year + " WOTC";
}
FCardImageRenderer.drawCardImage(original.createGraphics(), card, altState, width, height, art, legalString);
if (art != null || !fetcherEnabled)
_CACHE.put(originalKey, original);
} else {
original = _defaultImage;
}
}
return original;
return Pair.of(original, isPlaceholder);
}
// cardView is for Emblem, since there is no paper card for them
@@ -238,7 +280,9 @@ public class ImageCache {
return cached;
}
BufferedImage original = getOriginalImage(key, useDefaultImage, cardView);
Pair<BufferedImage, Boolean> orgImgs = getOriginalImageInternal(key, useDefaultImage, cardView);
BufferedImage original = orgImgs.getLeft();
boolean isPlaceholder = orgImgs.getRight();
if (original == null) { return null; }
if (original == _defaultImage) {
@@ -274,7 +318,9 @@ public class ImageCache {
result = resampler.filter(original, null);
}
if (!isPlaceholder) {
_CACHE.put(resizedKey, result);
}
return result;
}
/**

View File

@@ -541,7 +541,8 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
existingCard.getEdition(),
existingCard.getRarity(),
existingCard.getArtIndex(),
true);
true,
existingCard.getArtist());
// remove *quantity* instances of existing card
CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(false, quantity);
// add *quantity* into the deck and set them as selected

View File

@@ -256,6 +256,7 @@ public enum CSubmenuPreferences implements ICDoc {
initializeGameLogVerbosityComboBox();
initializeCloseActionComboBox();
initializeDefaultFontSizeComboBox();
initializeCardArtFormatComboBox();
initializeCardArtPreference();
initializeAutoUpdaterComboBox();
initializeMulliganRuleComboBox();
@@ -447,6 +448,15 @@ public enum CSubmenuPreferences implements ICDoc {
panel.setComboBox(comboBox, selectedItem);
}
private void initializeCardArtFormatComboBox() {
final String [] choices = {"Full", "Crop"};
final FPref userSetting = FPref.UI_CARD_ART_FORMAT;
final FComboBoxPanel<String> panel = this.view.getCbpCardArtFormatComboBoxPanel();
final FComboBox<String> comboBox = createComboBox(choices, userSetting);
final String selectedItem = this.prefs.getPref(userSetting);
panel.setComboBox(comboBox, selectedItem);
}
private void initializeAiProfilesComboBox() {
final FPref userSetting = FPref.UI_CURRENT_AI_PROFILE;
final FComboBoxPanel<String> panel = this.view.getAiProfilesComboBoxPanel();

View File

@@ -124,6 +124,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
private final FComboBoxPanel<GameLogEntryType> cbpGameLogEntryType = new FComboBoxPanel<>(localizer.getMessage("cbpGameLogEntryType")+":");
private final FComboBoxPanel<CloseAction> cbpCloseAction = new FComboBoxPanel<>(localizer.getMessage("cbpCloseAction")+":");
private final FComboBoxPanel<String> cbpDefaultFontSize = new FComboBoxPanel<>(localizer.getMessage("cbpDefaultFontSize")+":");
private final FComboBoxPanel<String> cbpCardArtFormat = new FComboBoxPanel<>(localizer.getMessage("cbpCardArtFormat")+":");
private final FComboBoxPanel<String> cbpCardArtPreference = new FComboBoxPanel<>(localizer.getMessage("lblPreferredArt")+":");
private final FComboBoxPanel<String> cbpMulliganRule = new FComboBoxPanel<>(localizer.getMessage("cbpMulliganRule")+":");
private final FComboBoxPanel<String> cbpAiProfiles = new FComboBoxPanel<>(localizer.getMessage("cbpAiProfiles")+":");
@@ -331,6 +332,9 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
pnlPrefs.add(cbpDefaultFontSize, comboBoxConstraints);
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlDefaultFontSize")), descriptionConstraints);
pnlPrefs.add(cbpCardArtFormat, comboBoxConstraints);
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlCardArtFormat")), descriptionConstraints);
pnlPrefs.add(cbImageFetcher, titleConstraints);
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlImageFetcher")), descriptionConstraints);
@@ -764,6 +768,10 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
return cbpDefaultFontSize;
}
public FComboBoxPanel<String> getCbpCardArtFormatComboBoxPanel() {
return cbpCardArtFormat;
}
public FComboBoxPanel<String> getCbpDefaultLanguageComboBoxPanel() {
return cbpDefaultLanguage;
}

View File

@@ -10,6 +10,7 @@ import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.HashMap;
@@ -37,16 +38,17 @@ import forge.util.CardTranslation;
public class FCardImageRenderer {
private static boolean isInitialed = false;
private static final float BASE_IMAGE_WIDTH = 480;
private static final float BASE_IMAGE_WIDTH = 488;
private static final float BASE_IMAGE_HEIGHT = 680;
private static final float BLACK_BORDER_THICKNESS_RATIO = 0.021f;
private static final float NAME_BOX_TINT = 0.2f;
private static final float TEXT_BOX_TINT = 0.1f;
private static final float PT_BOX_TINT = 0.2f;
private static float CARD_ART_RATIO;
private static int PT_BOX_WIDTH, HEADER_PADDING, TYPE_PADDING, BLACK_BORDER_THICKNESS, BORDER_THICKNESS;
private static Font NAME_FONT, TYPE_FONT, TEXT_FONT, REMINDER_FONT, PT_FONT;
private static int NAME_SIZE, TYPE_SIZE, TEXT_SIZE, REMINDER_SIZE, PT_SIZE;
private static int PT_BOX_WIDTH, HEADER_PADDING, TYPE_PADDING, BLACK_BORDER_THICKNESS, BOX_LINE_THICKNESS;
private static int ART_INSET, OUTER_BORDER_THICKNESS;
private static Font NAME_FONT, TYPE_FONT, TEXT_FONT, REMINDER_FONT, PT_FONT, ARTIST_FONT;
private static int NAME_SIZE, TYPE_SIZE, TEXT_SIZE, REMINDER_SIZE, PT_SIZE, ARTIST_SIZE;
private static Map<Font, Font[]> cachedFonts;
private static Color TEXT_COLOR;
private static BreakIterator boundary;
@@ -54,7 +56,6 @@ public class FCardImageRenderer {
private static Pattern reminderPattern;
private static Pattern reminderHidePattern;
private static Pattern symbolPattern;
private static Map<Font, Font[]> shrinkFonts;
private static void initialize() {
Locale locale = new Locale(FModel.getPreferences().getPref(FPref.UI_LANGUAGE));
@@ -79,12 +80,14 @@ public class FCardImageRenderer {
}
}
PT_FONT = NAME_FONT;
ARTIST_FONT = new Font(Font.SERIF, Font.BOLD, 20);
shrinkFonts = new HashMap<>();
shrinkFonts.put(NAME_FONT, new Font[NAME_FONT.getSize()]);
shrinkFonts.put(TYPE_FONT, new Font[TYPE_FONT.getSize()]);
shrinkFonts.put(TEXT_FONT, new Font[TEXT_FONT.getSize()]);
shrinkFonts.put(REMINDER_FONT, new Font[REMINDER_FONT.getSize()]);
cachedFonts = new HashMap<>();
cachedFonts.put(NAME_FONT, new Font[NAME_FONT.getSize() * 2]);
cachedFonts.put(TYPE_FONT, new Font[TYPE_FONT.getSize() * 2]);
cachedFonts.put(TEXT_FONT, new Font[TEXT_FONT.getSize() * 2]);
cachedFonts.put(REMINDER_FONT, new Font[REMINDER_FONT.getSize() * 2]);
cachedFonts.put(ARTIST_FONT, new Font[ARTIST_FONT.getSize() * 2]);
isInitialed = true;
}
@@ -107,11 +110,11 @@ public class FCardImageRenderer {
private static Color fromDetailColor(DetailColors detailColor) {
return new Color(detailColor.r, detailColor.g, detailColor.b);
}
private static Color C_COMMON = fromDetailColor(DetailColors.COMMON);
private static Color C_UNCOMMON = fromDetailColor(DetailColors.UNCOMMON);
private static Color C_RARE = fromDetailColor(DetailColors.RARE);
private static Color C_MYTHIC = fromDetailColor(DetailColors.MYTHIC);
private static Color C_SPECIAL = fromDetailColor(DetailColors.SPECIAL);
private static final Color C_COMMON = fromDetailColor(DetailColors.COMMON);
private static final Color C_UNCOMMON = fromDetailColor(DetailColors.UNCOMMON);
private static final Color C_RARE = fromDetailColor(DetailColors.RARE);
private static final Color C_MYTHIC = fromDetailColor(DetailColors.MYTHIC);
private static final Color C_SPECIAL = fromDetailColor(DetailColors.SPECIAL);
private static Color getRarityColor(CardRarity rarity) {
if (rarity == null)// NPE from Rarity weird...
return Color.MAGENTA;
@@ -129,122 +132,172 @@ public class FCardImageRenderer {
}
}
private static Font getShrinkFont(Font orgFont, int newSize) {
private static Font getFontBySize(Font orgFont, int newSize) {
if (newSize == orgFont.getSize())
return orgFont;
Font font = shrinkFonts.get(orgFont)[newSize];
Font font = cachedFonts.get(orgFont)[newSize];
if (font == null) {
font = orgFont.deriveFont((float)newSize);
shrinkFonts.get(orgFont)[newSize] = font;
cachedFonts.get(orgFont)[newSize] = font;
}
return font;
}
public static void drawCardImage(Graphics2D g, CardView card, boolean altState, int width, int height) {
if (!isInitialed)
initialize();
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
float ratio = Math.min((float)width / BASE_IMAGE_WIDTH, (float)height / BASE_IMAGE_HEIGHT);
TEXT_COLOR = Color.BLACK;
if (card.isSplitCard()) {
boolean needTranslation = !"en-US".equals(FModel.getPreferences().getPref(FPref.UI_LANGUAGE));
final CardStateView leftState = card.getLeftSplitState();
final String leftText = needTranslation ? CardTranslation.getTranslatedOracle(leftState.getName()) : leftState.getOracleText();
final CardStateView rightState = card.getRightSplitState();
String rightText = needTranslation ? CardTranslation.getTranslatedOracle(rightState.getName()) : rightState.getOracleText();
boolean isAftermath = (rightState.getKeywordKey().contains("Aftermath"));
if (isAftermath) {
int halfHeight = Math.round(380 * ratio);
int halfWidth = Math.round((halfHeight - 10) * ratio);
CARD_ART_RATIO = 2.68f;
updateAreaSizes(ratio, ratio);
drawCardStateImage(g, leftState, leftText, width, halfHeight);
CARD_ART_RATIO = 1.66f;
g.translate((double) width, (double)halfWidth);
g.rotate(Math.PI / 2.);
drawCardStateImage(g, rightState, rightText, height - halfWidth, width);
} else {
CARD_ART_RATIO = 1.36f;
updateAreaSizes(ratio, (float)height / 2f / (float)width);
AffineTransform tf = g.getTransform();
g.translate(0., (double)height);
g.rotate(-Math.PI / 2.);
drawCardStateImage(g, leftState, leftText, height / 2, width);
g.setTransform(tf);
g.translate(0., (double)height / 2);
g.rotate(-Math.PI / 2.);
drawCardStateImage(g, rightState, rightText, height / 2, width);
}
} else if (card.isFlipCard()) {
boolean needTranslation = !card.isToken() || !(card.getCloneOrigin() == null);
final CardStateView state = card.getState(altState);
final String text = card.getText(state, needTranslation ? CardTranslation.getTranslationTexts(state.getName(), "") : null);
final CardStateView flipState = card.getState(!altState);
final String flipText = card.getText(flipState, needTranslation ? CardTranslation.getTranslationTexts(flipState.getName(), "") : null);
CARD_ART_RATIO = 1.72f;
updateAreaSizes(ratio, ratio);
drawFlipCardImage(g, state, text, flipState, flipText, width, height, altState);
} else if (card.isAdventureCard()) {
boolean needTranslation = !card.isToken() || !(card.getCloneOrigin() == null);
final CardStateView state = card.getState(false);
final String text = card.getText(state, needTranslation ? CardTranslation.getTranslationTexts(state.getName(), "") : null);
final CardStateView advState = card.getState(true);
final String advText = card.getText(advState, needTranslation ? CardTranslation.getTranslationTexts(advState.getName(), "") : null);
CARD_ART_RATIO = 1.32f;
updateAreaSizes(ratio, ratio);
drawAdvCardImage(g, state, text, advState, advText, width, height);
} else {
boolean needTranslation = !card.isToken() || !(card.getCloneOrigin() == null);
final CardStateView state = card.getState(altState);
final String text = card.getText(state, needTranslation ? CardTranslation.getTranslationTexts(state.getName(), "") : null);
CARD_ART_RATIO = 1.32f;
updateAreaSizes(ratio, ratio);
drawCardStateImage(g, state, text, width, height);
}
}
private static void updateAreaSizes(float mainRatio, float subRatio) {
NAME_SIZE = Math.round(NAME_FONT.getSize() * mainRatio);
TYPE_SIZE = Math.round(TYPE_FONT.getSize() * subRatio);
TEXT_SIZE = Math.round(TEXT_FONT.getSize() * mainRatio);
REMINDER_SIZE = Math.round(REMINDER_FONT.getSize() * mainRatio);
PT_SIZE = Math.round(PT_FONT.getSize() * mainRatio);
ARTIST_SIZE = Math.round(ARTIST_FONT.getSize() * mainRatio);
PT_BOX_WIDTH = Math.round(75 * mainRatio);
HEADER_PADDING = Math.round(7 * mainRatio);
TYPE_PADDING = Math.round(7 * subRatio) + (mainRatio == subRatio ? (NAME_SIZE - TYPE_SIZE) / 2 : 0);
BORDER_THICKNESS = Math.max(Math.round(2 * mainRatio), 1);
BOX_LINE_THICKNESS = Math.max(Math.round(2 * mainRatio), 1);
BLACK_BORDER_THICKNESS = Math.round(10 * mainRatio);
ART_INSET = Math.round(BLACK_BORDER_THICKNESS * 0.6f);
OUTER_BORDER_THICKNESS = Math.round(1.2f * BLACK_BORDER_THICKNESS) - ART_INSET;
}
private static void drawCardStateImage(Graphics2D g, CardStateView state, String text, int w, int h) {
int x = 0, y = 0;
public static void drawCardImage(Graphics2D g, CardView card, boolean altState, int width, int height, BufferedImage art, String legalString) {
if (!isInitialed) {
initialize();
}
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
float ratio = Math.min((float)width / BASE_IMAGE_WIDTH, (float)height / BASE_IMAGE_HEIGHT);
BLACK_BORDER_THICKNESS = Math.round(10 * ratio);
g.setColor(Color.BLACK);
g.fillRect(x, y, w, h);
x += BLACK_BORDER_THICKNESS;
y += BLACK_BORDER_THICKNESS;
w -= 2 * BLACK_BORDER_THICKNESS;
h -= 2 * BLACK_BORDER_THICKNESS;
g.fillRect(0, 0, width, height);
if (legalString != null) {
TEXT_COLOR = Color.LIGHT_GRAY;
int x = BLACK_BORDER_THICKNESS * 3;
int y = height - BLACK_BORDER_THICKNESS * 3;
int w = width;
boolean hasPTBox = false;
if (!card.isSplitCard() && !card.isFlipCard()) {
final CardStateView state = card.getState(card.isAdventureCard() ? false : altState);
if ((state.isCreature() && !state.getKeywordKey().contains("Level up"))
|| state.isPlaneswalker() || state.getType().hasSubtype("Vehicle"))
hasPTBox = true;
}
if (hasPTBox) {
w -= PT_BOX_WIDTH + BLACK_BORDER_THICKNESS * 5;
} else {
w -= BLACK_BORDER_THICKNESS * 6;
}
int h = BLACK_BORDER_THICKNESS * 3;
drawVerticallyCenteredString(g, legalString, new Rectangle(x, y, w, h), ARTIST_FONT, ARTIST_SIZE);
}
width -= 2 * BLACK_BORDER_THICKNESS;
height -= 2 * BLACK_BORDER_THICKNESS;
g.translate(BLACK_BORDER_THICKNESS, BLACK_BORDER_THICKNESS);
TEXT_COLOR = Color.BLACK;
if (card.isSplitCard()) {
boolean needTranslation = !"en-US".equals(FModel.getPreferences().getPref(FPref.UI_LANGUAGE));
final CardStateView leftState = card.getLeftSplitState();
final String leftText = needTranslation ? CardTranslation.getTranslatedOracle(leftState.getName()) : leftState.getOracleText();
final CardStateView rightState = card.getRightSplitState();
String rightText = needTranslation ? CardTranslation.getTranslatedOracle(rightState.getName()) : rightState.getOracleText();
boolean isAftermath = (rightState.getKeywordKey().contains("Aftermath"));
BufferedImage leftArt = null;
BufferedImage rightArt = null;
if (isAftermath) {
if (art != null) {
int leftWidth = Math.round(art.getWidth() * 0.61328125f);
leftArt = art.getSubimage(0, 0, leftWidth, art.getHeight());
rightArt = art.getSubimage(leftWidth, 0, art.getWidth() - leftWidth, art.getHeight());
}
int halfHeight = Math.round(370 * ratio);
int halfWidth = Math.round(360 * ratio);
CARD_ART_RATIO = 2.719f;
updateAreaSizes(ratio, ratio);
drawCardStateImage(g, leftState, leftText, width, halfHeight, leftArt);
CARD_ART_RATIO = 1.714f;
int widthAdjust = OUTER_BORDER_THICKNESS;
int heightAdjust = OUTER_BORDER_THICKNESS + PT_SIZE / 2;
g.translate((double) width - widthAdjust, (double)halfWidth);
g.rotate(Math.PI / 2.);
drawCardStateImage(g, rightState, rightText, height - halfWidth - heightAdjust, width, rightArt);
} else {
if (art != null) {
leftArt = art.getSubimage(0, 0, art.getWidth() / 2, art.getHeight());
rightArt = art.getSubimage(art.getWidth() / 2, 0, art.getWidth() / 2, art.getHeight());
}
CARD_ART_RATIO = 1.443f;
updateAreaSizes(ratio, ((float)height / 2f / (float)width) * ratio);
int widthAdjust = OUTER_BORDER_THICKNESS + PT_SIZE / 2;
int heightAdjust = height - widthAdjust - BLACK_BORDER_THICKNESS;
AffineTransform tf = g.getTransform();
g.translate(0., (double)(height - widthAdjust));
g.rotate(-Math.PI / 2.);
drawCardStateImage(g, leftState, leftText, heightAdjust / 2, width + widthAdjust, leftArt);
g.setTransform(tf);
g.translate(0., (double)(heightAdjust / 2));
g.rotate(-Math.PI / 2.);
drawCardStateImage(g, rightState, rightText, heightAdjust / 2, width + widthAdjust, rightArt);
}
} else if (card.isFlipCard()) {
boolean needTranslation = !card.isToken() || !(card.getCloneOrigin() == null);
final CardStateView state = card.getState(false);
final String text = card.getText(state, needTranslation ? CardTranslation.getTranslationTexts(state.getName(), "") : null);
final CardStateView flipState = card.getState(true);
final String flipText = card.getText(flipState, needTranslation ? CardTranslation.getTranslationTexts(flipState.getName(), "") : null);
CARD_ART_RATIO = 1.728f;
updateAreaSizes(ratio, ratio);
int heightAdjust = OUTER_BORDER_THICKNESS + PT_SIZE / 2;
if (altState) {
g.translate(width, height);
g.rotate(Math.PI);
}
drawFlipCardImage(g, state, text, flipState, flipText, width, height - heightAdjust, art);
} else if (card.isAdventureCard()) {
boolean needTranslation = !card.isToken() || !(card.getCloneOrigin() == null);
final CardStateView state = card.getState(false);
final String text = card.getText(state, needTranslation ? CardTranslation.getTranslationTexts(state.getName(), "") : null);
final CardStateView advState = card.getState(true);
final String advText = card.getText(advState, needTranslation ? CardTranslation.getTranslationTexts(advState.getName(), "") : null);
CARD_ART_RATIO = 1.37f;
updateAreaSizes(ratio, ratio);
drawAdvCardImage(g, state, text, advState, advText, width, height, art);
} else {
boolean needTranslation = !card.isToken() || !(card.getCloneOrigin() == null);
final CardStateView state = card.getState(altState);
final String text = card.getText(state, needTranslation ? CardTranslation.getTranslationTexts(state.getName(), "") : null);
CARD_ART_RATIO = 1.37f;
if (art != null && Math.abs((float)art.getWidth() / (float)art.getHeight() - CARD_ART_RATIO) > 0.1f) {
CARD_ART_RATIO = (float)art.getWidth() / (float)art.getHeight();
}
updateAreaSizes(ratio, ratio);
drawCardStateImage(g, state, text, width, height, art);
}
g.dispose();
}
private static void drawCardStateImage(Graphics2D g, CardStateView state, String text, int w, int h, BufferedImage art) {
int x = 0, y = 0;
//determine colors for borders
final List<DetailColors> borderColors = CardDetailUtil.getBorderColors(state, true);
Color[] colors = fillColorBackground(g, borderColors, x, y, w, h);
Color[] colors = fillColorBackground(g, borderColors, x, y, w, h, BLACK_BORDER_THICKNESS);
int artInset = Math.round(BLACK_BORDER_THICKNESS * 0.8f);
int outerBorderThickness = 2 * BLACK_BORDER_THICKNESS - artInset;
x += outerBorderThickness;
y += outerBorderThickness;
w -= 2 * outerBorderThickness;
x += OUTER_BORDER_THICKNESS;
y += OUTER_BORDER_THICKNESS;
w -= 2 * OUTER_BORDER_THICKNESS;
int headerHeight = NAME_SIZE + 2 * HEADER_PADDING;
int typeBoxHeight = TYPE_SIZE + 2 * TYPE_PADDING;
int ptBoxHeight = 0;
if (state.isCreature() || state.isPlaneswalker() || state.getType().hasSubtype("Vehicle")) {
//if P/T box needed, make room for it
ptBoxHeight = NAME_SIZE + HEADER_PADDING;
ptBoxHeight = headerHeight;
}
int artWidth = w - 2 * artInset;
int artWidth = w - 2 * ART_INSET;
int artHeight = Math.round(artWidth / CARD_ART_RATIO);
int textBoxHeight = h - headerHeight - artHeight - typeBoxHeight - outerBorderThickness - artInset - PT_FONT.getSize() / 2;
int textBoxHeight = h - headerHeight - artHeight - typeBoxHeight - OUTER_BORDER_THICKNESS - ART_INSET - PT_SIZE / 2;
int artY = y + headerHeight;
int typeY = artY + artHeight;
@@ -257,7 +310,7 @@ public class FCardImageRenderer {
boolean isDungeon = state.getType().isDungeon();
if (isSaga || isClass || isDungeon) {
// Move type line to the bottom
typeY = ptY - typeBoxHeight;
typeY = ptY - Math.round(typeBoxHeight * 1.2f);
if (!isDungeon)
artWidth = artWidth / 2;
artHeight = typeY - artY;
@@ -268,8 +321,8 @@ public class FCardImageRenderer {
//draw art box with Forge icon
if (!isDungeon) {
Color[] artBoxColors = tintColors(Color.DARK_GRAY, colors, NAME_BOX_TINT);
int artX = x + artInset + (isSaga ? artWidth : 0);
drawArt(g, artBoxColors, artX, artY, artWidth, artHeight);
int artX = x + ART_INSET + (isSaga ? artWidth : 0);
drawArt(g, artBoxColors, artX, artY, artWidth, artHeight, art);
}
//handle leveler cards
@@ -320,7 +373,7 @@ public class FCardImageRenderer {
}
}
int textX = x + artInset;
int textX = x + ART_INSET;
//draw text box
Color[] textBox1Colors = tintColors(Color.WHITE, colors, TEXT_BOX_TINT);
@@ -364,7 +417,7 @@ public class FCardImageRenderer {
} else {
//draw text box
Color[] textBoxColors = tintColors(Color.WHITE, colors, TEXT_BOX_TINT);
int textX = x + artInset + (isClass ? artWidth : 0);
int textX = x + ART_INSET + (isClass ? artWidth : 0);
drawTextBox(g, state, text, textBoxColors, textX, textY, artWidth, textBoxHeight, ptBoxHeight > 0 ? 1 : 0);
//draw P/T box
@@ -377,63 +430,53 @@ public class FCardImageRenderer {
//draw header containing name and mana cost
Color[] headerColors = tintColors(Color.WHITE, colors, NAME_BOX_TINT);
drawHeader(g, state, headerColors, x, y, w, headerHeight, true);
drawHeader(g, state, headerColors, x, y, w, headerHeight, true, true);
//draw type line
drawTypeLine(g, state, headerColors, x, typeY, w, typeBoxHeight, 0, true);
drawTypeLine(g, state, headerColors, x, typeY, w, typeBoxHeight, 0, true, true);
}
private static void drawFlipCardImage(Graphics2D g, CardStateView state, String text, CardStateView flipState, String flipText, int w, int h, boolean isFlipped) {
private static void drawFlipCardImage(Graphics2D g, CardStateView state, String text, CardStateView flipState, String flipText, int w, int h, BufferedImage art) {
int width = w, height = h;
int x = 0, y = 0;
g.setColor(Color.BLACK);
g.fillRect(x, y, w, h);
x += BLACK_BORDER_THICKNESS;
y += BLACK_BORDER_THICKNESS;
w -= 2 * BLACK_BORDER_THICKNESS;
h -= 2 * BLACK_BORDER_THICKNESS;
//determine colors for borders
final List<DetailColors> borderColors = CardDetailUtil.getBorderColors(state, true);
Color[] colors = fillColorBackground(g, borderColors, x, y, w, h);
Color[] colors = fillColorBackground(g, borderColors, x, y, w, h, 0);
int artInset = Math.round(BLACK_BORDER_THICKNESS * 0.8f);
int outerBorderThickness = 2 * BLACK_BORDER_THICKNESS - artInset;
x += outerBorderThickness;
y += outerBorderThickness;
w -= 2 * outerBorderThickness;
h -= 2 * outerBorderThickness;
x += OUTER_BORDER_THICKNESS;
y += OUTER_BORDER_THICKNESS;
w -= 2 * OUTER_BORDER_THICKNESS;
h -= 2 * OUTER_BORDER_THICKNESS;
int headerHeight = NAME_SIZE + 2 * HEADER_PADDING;
int typeBoxHeight = TYPE_SIZE + 2 * TYPE_PADDING;
int artWidth = w - 2 * artInset;
int artWidth = w - 2 * ART_INSET;
int artHeight = Math.round(artWidth / CARD_ART_RATIO);
int textBoxHeight = (h - (headerHeight + typeBoxHeight) * 2 - artHeight) / 2;
int ptBoxHeight = NAME_SIZE + HEADER_PADDING;
int ptBoxHeight = headerHeight;
int textY = y + headerHeight;
int typeY = textY + textBoxHeight;
int artY = typeY + typeBoxHeight;
int ptY = typeY - 4;
int ptY = typeY + 1;
//draw art box with Forge icon
if (!isFlipped) {
Color[] artBoxColors = tintColors(Color.DARK_GRAY, colors, NAME_BOX_TINT);
int artX = x + artInset;
drawArt(g, artBoxColors, artX, artY, artWidth, artHeight);
}
int artX = x + ART_INSET;
drawArt(g, artBoxColors, artX, artY, artWidth, artHeight, art);
//draw text box
Color[] textBoxColors = tintColors(Color.WHITE, colors, TEXT_BOX_TINT);
int textX = x + artInset;
int textX = x + ART_INSET;
drawTextBox(g, state, text, textBoxColors, textX, textY, artWidth, textBoxHeight, 0);
//draw header containing name and mana cost
Color[] headerColors = tintColors(Color.WHITE, colors, NAME_BOX_TINT);
drawHeader(g, state, headerColors, x, y, w, headerHeight, !isFlipped);
drawHeader(g, state, headerColors, x, y, w, headerHeight, true, true);
//draw type line
drawTypeLine(g, state, headerColors, x, typeY, w, typeBoxHeight, state.isCreature() ? PT_BOX_WIDTH : 0, !isFlipped);
drawTypeLine(g, state, headerColors, x, typeY, w, typeBoxHeight, state.isCreature() ? PT_BOX_WIDTH : 0, true, true);
//draw P/T box
if (state.isCreature()) {
@@ -445,21 +488,14 @@ public class FCardImageRenderer {
g.translate(width, height);
g.rotate(Math.PI);
//draw art box with Forge icon
if (isFlipped) {
Color[] artBoxColors = tintColors(Color.DARK_GRAY, colors, NAME_BOX_TINT);
int artX = x + artInset;
drawArt(g, artBoxColors, artX, artY, artWidth, artHeight);
}
//draw text box
drawTextBox(g, flipState, flipText, textBoxColors, textX, textY, artWidth, textBoxHeight, 0);
//draw header containing name and mana cost
drawHeader(g, flipState, headerColors, x, y, w, headerHeight, isFlipped);
drawHeader(g, flipState, headerColors, x, y, w, headerHeight, false, true);
//draw type line
drawTypeLine(g, flipState, headerColors, x, typeY, w, typeBoxHeight, flipState.isCreature() ? PT_BOX_WIDTH : 0, isFlipped);
drawTypeLine(g, flipState, headerColors, x, typeY, w, typeBoxHeight, flipState.isCreature() ? PT_BOX_WIDTH : 0, false, true);
//draw P/T box
if (flipState.isCreature()) {
@@ -468,32 +504,24 @@ public class FCardImageRenderer {
}
}
private static void drawAdvCardImage(Graphics2D g, CardStateView state, String text, CardStateView advState, String advText, int w, int h) {
private static void drawAdvCardImage(Graphics2D g, CardStateView state, String text, CardStateView advState, String advText, int w, int h, BufferedImage art) {
int x = 0, y = 0;
g.setColor(Color.BLACK);
g.fillRect(x, y, w, h);
x += BLACK_BORDER_THICKNESS;
y += BLACK_BORDER_THICKNESS;
w -= 2 * BLACK_BORDER_THICKNESS;
h -= 2 * BLACK_BORDER_THICKNESS;
//determine colors for borders
final List<DetailColors> borderColors = CardDetailUtil.getBorderColors(state, true);
Color[] colors = fillColorBackground(g, borderColors, x, y, w, h);
Color[] colors = fillColorBackground(g, borderColors, x, y, w, h, BLACK_BORDER_THICKNESS);
int artInset = Math.round(BLACK_BORDER_THICKNESS * 0.8f);
int outerBorderThickness = 2 * BLACK_BORDER_THICKNESS - artInset;
x += outerBorderThickness;
y += outerBorderThickness;
w -= 2 * outerBorderThickness;
x += OUTER_BORDER_THICKNESS;
y += OUTER_BORDER_THICKNESS;
w -= 2 * OUTER_BORDER_THICKNESS;
int headerHeight = NAME_SIZE + 2 * HEADER_PADDING;
int typeBoxHeight = TYPE_SIZE + 2 * TYPE_PADDING;
int ptBoxHeight = NAME_SIZE + HEADER_PADDING;
int ptBoxHeight = headerHeight;
int artWidth = w - 2 * artInset;
int artWidth = w - 2 * ART_INSET;
int artHeight = Math.round(artWidth / CARD_ART_RATIO);
int textBoxWidth = artWidth / 2;
int textBoxHeight = h - headerHeight - artHeight - typeBoxHeight - outerBorderThickness - artInset - PT_FONT.getSize() / 2;
int textBoxHeight = h - headerHeight - artHeight - typeBoxHeight - OUTER_BORDER_THICKNESS - ART_INSET - PT_SIZE / 2;
int artY = y + headerHeight;
int typeY = artY + artHeight;
@@ -502,20 +530,20 @@ public class FCardImageRenderer {
//draw art box with Forge icon
Color[] artBoxColors = tintColors(Color.DARK_GRAY, colors, NAME_BOX_TINT);
int artX = x + artInset;
drawArt(g, artBoxColors, artX, artY, artWidth, artHeight);
int artX = x + ART_INSET;
drawArt(g, artBoxColors, artX, artY, artWidth, artHeight, art);
//draw text box
Color[] textBoxColors = tintColors(Color.WHITE, colors, TEXT_BOX_TINT);
int textX = x + artInset + textBoxWidth;
int textX = x + ART_INSET + textBoxWidth;
drawTextBox(g, state, text, textBoxColors, textX, textY, textBoxWidth, textBoxHeight, 1);
//draw header containing name and mana cost
Color[] headerColors = tintColors(Color.WHITE, colors, NAME_BOX_TINT);
drawHeader(g, state, headerColors, x, y, w, headerHeight, true);
drawHeader(g, state, headerColors, x, y, w, headerHeight, true, true);
//draw type line
drawTypeLine(g, state, headerColors, x, typeY, w, typeBoxHeight, 0, true);
drawTypeLine(g, state, headerColors, x, typeY, w, typeBoxHeight, 0, true, true);
//draw P/T box
Color[] ptColors = tintColors(Color.WHITE, colors, PT_BOX_TINT);
@@ -525,32 +553,31 @@ public class FCardImageRenderer {
int advTypeHeight = advHeaderHeight - 1;
NAME_SIZE = TYPE_SIZE - 2;
TYPE_SIZE = NAME_SIZE - 1;
textX = x + artInset;
textX = x + ART_INSET;
//draw header containing name and mana cost
Color[] advheaderColors = tintColors(Color.GRAY, colors, 0.6f);
TEXT_COLOR = Color.WHITE;
drawHeader(g, advState, advheaderColors, textX, textY, textBoxWidth, advHeaderHeight, true);
drawHeader(g, advState, advheaderColors, textX, textY, textBoxWidth, advHeaderHeight, true, false);
//draw type line
Color[] advTypeColors = tintColors(Color.DARK_GRAY, colors, 0.6f);
textY += advHeaderHeight;
drawTypeLine(g, advState, advTypeColors, textX, textY, textBoxWidth, advTypeHeight, 0, false);
drawTypeLine(g, advState, advTypeColors, textX, textY + advHeaderHeight, textBoxWidth, advTypeHeight, 0, false, false);
//draw text box
TEXT_COLOR = Color.BLACK;
textY += advTypeHeight;
textBoxHeight -= advHeaderHeight + advTypeHeight;
drawTextBox(g, advState, advText, textBoxColors, textX, textY, textBoxWidth, textBoxHeight, 0);
int yAdjust = advHeaderHeight + advTypeHeight;
drawTextBox(g, advState, advText, textBoxColors, textX, textY, textBoxWidth, textBoxHeight, (yAdjust << 16));
}
private static Color[] fillColorBackground(Graphics2D g, List<DetailColors> backColors, int x, int y, int w, int h) {
private static Color[] fillColorBackground(Graphics2D g, List<DetailColors> backColors, int x, int y, int w, int h, int borderThickness) {
Color[] colors = new Color[backColors.size()];
for (int i = 0; i < colors.length; i++) {
DetailColors dc = backColors.get(i);
colors[i] = new Color(dc.r, dc.g, dc.b);
}
fillColorBackground(g, colors, x, y, w, h);
fillRoundColorBackground(g, colors, x, y, w, h - 2 * borderThickness, borderThickness * 12, borderThickness * 10);
fillColorBackground(g, colors, x, y, w, 10 * borderThickness);
return colors;
}
private static void fillColorBackground(Graphics2D g, Color[] colors, float x, float y, float w, float h) {
@@ -577,15 +604,39 @@ public class FCardImageRenderer {
}
g.setPaint(oldPaint);
}
private static void fillRoundColorBackground(Graphics2D g, Color[] colors, float x, float y, float w, float h, float arcWidth, float arcHeight) {
Paint oldPaint = g.getPaint();
switch (colors.length) {
case 1:
g.setColor(colors[0]);
g.fillRoundRect(Math.round(x), Math.round(y), Math.round(w), Math.round(h), Math.round(arcWidth), Math.round(arcHeight));
break;
case 2:
GradientPaint gradient = new GradientPaint(x, y, colors[0], x + w, y, colors[1]);
g.setPaint(gradient);
g.fillRoundRect(Math.round(x), Math.round(y), Math.round(w), Math.round(h), Math.round(arcWidth), Math.round(arcHeight));
break;
case 3:
float halfWidth = w / 2;
GradientPaint gradient1 = new GradientPaint(x, y, colors[0], x + halfWidth, y, colors[1]);
g.setPaint(gradient1);
g.fillRoundRect(Math.round(x), Math.round(y), Math.round(halfWidth + arcWidth), Math.round(h), Math.round(arcWidth), Math.round(arcHeight));
GradientPaint gradient2 = new GradientPaint(x + halfWidth, y, colors[1], x + w, y, colors[2]);
g.setPaint(gradient2);
g.fillRoundRect(Math.round(x + halfWidth - arcWidth), Math.round(y), Math.round(halfWidth + arcWidth), Math.round(h), Math.round(arcWidth), Math.round(arcHeight));
break;
}
g.setPaint(oldPaint);
}
private static void drawVerticallyCenteredString(Graphics2D g, String text, Rectangle area, Font originalFont, int size) {
Font font = getShrinkFont(originalFont, size);
Font font = getFontBySize(originalFont, size);
FontMetrics fontMetrics = g.getFontMetrics(font);
// Shrink font if the text is too long
while (fontMetrics.stringWidth(text) > area.width) {
--size;
font = getShrinkFont(originalFont, size);
font = getFontBySize(originalFont, size);
fontMetrics = g.getFontMetrics(font);
}
@@ -597,19 +648,20 @@ public class FCardImageRenderer {
g.drawString(text, x, y);
}
private static void drawHeader(Graphics2D g, CardStateView state, Color[] colors, int x, int y, int w, int h, boolean drawMana) {
fillColorBackground(g, colors, x, y, w, h);
g.setStroke(new BasicStroke(BORDER_THICKNESS));
private static void drawHeader(Graphics2D g, CardStateView state, Color[] colors, int x, int y, int w, int h, boolean drawMana, boolean drawRoundRect) {
int padding = h / 3;
fillRoundColorBackground(g, colors, x, y, w, h, drawRoundRect ? padding : 0, drawRoundRect ? h : 0);
if (drawRoundRect) {
g.setStroke(new BasicStroke(BOX_LINE_THICKNESS));
g.setColor(Color.BLACK);
g.drawRect(x, y, w, h);
int padding = h / 4;
g.drawRoundRect(x, y, w, h, padding, h);
}
//draw mana cost for card
if (drawMana) {
ManaCost manaCost = state.getManaCost();
int manaCostWidth = manaCost.getGlyphCount() * NAME_SIZE + HEADER_PADDING;
CardFaceSymbols.draw(g, manaCost, x + w - manaCostWidth, y + (h - NAME_SIZE) / 2 + 1, NAME_SIZE);
CardFaceSymbols.draw(g, manaCost, x + w - manaCostWidth, y + (h - NAME_SIZE) / 2 + 1, NAME_SIZE - 1);
w -= padding + manaCostWidth;
}
@@ -621,31 +673,47 @@ public class FCardImageRenderer {
}
private static void drawArt(Graphics2D g, Color[] colors, int x, int y, int w, int h) {
private static void drawArt(Graphics2D g, Color[] colors, int x, int y, int w, int h, BufferedImage art) {
if (art != null) {
int artWidth = art.getWidth();
int artHeight = art.getHeight();
if ((float)artWidth / (float)artHeight >= (float)w / (float)h) {
int newW = Math.round(artHeight * ((float)w / (float)h));
int newX = (artWidth - newW) / 2;
g.drawImage(art, x, y, x + w, y + h, newX, 0, newX + newW, art.getHeight(), null);
} else {
int newH = Math.round(artWidth * ((float)h / (float)w));
int newY = (artHeight - newH) / 2;
g.drawImage(art, x, y, x + w, y + h, 0, newY, art.getWidth(), newY + newH, null);
}
} else {
fillColorBackground(g, colors, x, y, w, h);
SkinIcon art = FSkin.getIcon(FSkinProp.ICO_LOGO);
float artWidth = (float)art.getSizeForPaint(g).getWidth();
float artHeight = (float)art.getSizeForPaint(g).getHeight();
SkinIcon icon = FSkin.getIcon(FSkinProp.ICO_LOGO);
float artWidth = (float)icon.getSizeForPaint(g).getWidth();
float artHeight = (float)icon.getSizeForPaint(g).getHeight();
if (artWidth / artHeight >= (float)w / (float)h) {
int newH = Math.round(w * (artHeight / artWidth));
FSkin.drawImage(g, art, x, y + (h - newH) / 2, w, newH);
FSkin.drawImage(g, icon, x, y + (h - newH) / 2, w, newH);
} else {
int newW = Math.round(h * (artWidth / artHeight));
FSkin.drawImage(g, art, x + (w - newW) / 2, y, newW, h);
FSkin.drawImage(g, icon, x + (w - newW) / 2, y, newW, h);
}
g.setStroke(new BasicStroke(BORDER_THICKNESS));
}
g.setStroke(new BasicStroke(BOX_LINE_THICKNESS));
g.setColor(Color.BLACK);
g.drawRect(x, y, w, h);
}
private static void drawTypeLine(Graphics2D g, CardStateView state, Color[] colors, int x, int y, int w, int h, int adjust, boolean drawRarity) {
fillColorBackground(g, colors, x, y, w, h);
g.setStroke(new BasicStroke(BORDER_THICKNESS));
private static void drawTypeLine(Graphics2D g, CardStateView state, Color[] colors, int x, int y, int w, int h, int adjust, boolean drawRarity, boolean drawRoundRect) {
int padding = h / 3;
fillRoundColorBackground(g, colors, x, y, w, h, drawRoundRect ? padding : 0, drawRoundRect ? h : 0);
if (drawRoundRect) {
g.setStroke(new BasicStroke(BOX_LINE_THICKNESS));
g.setColor(Color.BLACK);
g.drawRect(x, y, w, h);
g.drawRoundRect(x, y, w, h, padding, h);
}
w -= adjust;
int padding = h / 4;
//draw square icon for rarity
if (drawRarity) {
@@ -653,7 +721,7 @@ public class FCardImageRenderer {
int iconPadding = (h - iconSize) / 2;
w -= iconSize + iconPadding * 2;
g.setColor(getRarityColor(state.getRarity()));
g.fillRect(x + w + iconPadding, y + (h - iconSize) / 2, iconSize, iconSize);
g.fillRect(x + w + iconPadding, y + (h - iconSize + 1) / 2, iconSize, iconSize);
}
//draw type
@@ -664,12 +732,13 @@ public class FCardImageRenderer {
}
/**
* @param flagPTBox [0] bit: has PT box, [1] bit: leveler PT box, [2] bit: leveler Level box
* @param textBoxFlags [0] bit: has PT box, [1] bit: leveler PT box, [2] bit: leveler Level box, [16~31] bit: y adjust
*/
private static void drawTextBox(Graphics2D g, CardStateView state, String text, Color[] colors,
int x, int y, int w, int h, int flagPTBox) {
fillColorBackground(g, colors, x, y, w, h);
g.setStroke(new BasicStroke(BORDER_THICKNESS));
int x, int y, int w, int h, int textBoxFlags) {
int yAdjust = (textBoxFlags >> 16);
fillColorBackground(g, colors, x, y + yAdjust, w, h - yAdjust);
g.setStroke(new BasicStroke(BOX_LINE_THICKNESS));
g.setColor(Color.BLACK);
g.drawRect(x, y, w, h);
@@ -705,9 +774,9 @@ public class FCardImageRenderer {
int padding = TEXT_SIZE / 4;
x += padding;
w -= 2 * padding;
if ((flagPTBox & 2) == 2)
if ((textBoxFlags & 2) == 2)
w -= PT_BOX_WIDTH;
drawTextBoxText(g, text, x, y, w, h, flagPTBox);
drawTextBoxText(g, text, x, y + yAdjust, w, h - yAdjust, textBoxFlags);
}
}
@@ -726,18 +795,22 @@ public class FCardImageRenderer {
}
}
else if (state.isPlaneswalker()) {
Color [] pwColor = { Color.BLACK };
colors = pwColor;
TEXT_COLOR = Color.WHITE;
pieces.add(String.valueOf(state.getLoyalty()));
}
else if (state.getType().hasSubtype("Vehicle")) {
pieces.add("[");
Color [] vhColor = { new Color(128, 96, 64) };
colors = vhColor;
TEXT_COLOR = Color.WHITE;
pieces.add(String.valueOf(state.getPower()));
pieces.add("/");
pieces.add(String.valueOf(state.getToughness()));
pieces.add("]");
}
else { return; }
Font font = getShrinkFont(PT_FONT, PT_SIZE);
Font font = getFontBySize(PT_FONT, PT_SIZE);
FontMetrics metrics = g.getFontMetrics(font);
int padding = PT_SIZE / 4;
int totalPieceWidth = -padding;
@@ -747,24 +820,21 @@ public class FCardImageRenderer {
pieceWidths[i] = pieceWidth;
totalPieceWidth += pieceWidth;
}
int boxHeight = metrics.getMaxAscent() + padding;
x += w - PT_BOX_WIDTH;
w = PT_BOX_WIDTH;
int boxWidth = Math.max(PT_BOX_WIDTH, totalPieceWidth + 2 * padding);
x += w - boxWidth;
y += h - boxHeight;
w = boxWidth;
h = boxHeight;
int arcWidth = h / 3;
fillRoundColorBackground(g, colors, x, y, w, h, arcWidth, h);
g.setStroke(new BasicStroke(BOX_LINE_THICKNESS));
g.setColor(state.isPlaneswalker() ? Color.WHITE : Color.BLACK);
g.drawRoundRect(x, y, w, h, arcWidth, h);
fillColorBackground(g, colors, x, y, w, h);
g.setStroke(new BasicStroke(BORDER_THICKNESS));
g.setColor(Color.BLACK);
g.drawRect(x, y, w, h);
x += (boxWidth - totalPieceWidth) / 2;
x += (PT_BOX_WIDTH - totalPieceWidth) / 2;
for (int i = 0; i < pieces.size(); i++) {
drawVerticallyCenteredString(g, pieces.get(i), new Rectangle(x, y - 2, w, h), PT_FONT, PT_SIZE);
x += pieceWidths[i];
}
TEXT_COLOR = Color.BLACK;
}
private static abstract class Piece {
@@ -986,8 +1056,8 @@ public class FCardImageRenderer {
}
// Find font size that fit in the text box area
Font txFont = getShrinkFont(TEXT_FONT, TEXT_SIZE);
Font rmFont = getShrinkFont(REMINDER_FONT, REMINDER_SIZE);
Font txFont = getFontBySize(TEXT_FONT, TEXT_SIZE);
Font rmFont = getFontBySize(REMINDER_FONT, REMINDER_SIZE);
FontMetrics txMetrics = g.getFontMetrics(txFont);
FontMetrics rmMetrics = g.getFontMetrics(rmFont);
int txFontSize = txFont.getSize(), rmFontSize = rmFont.getSize();
@@ -1017,10 +1087,10 @@ public class FCardImageRenderer {
break;
//Shrink font and do again
--txFontSize;
txFont = getShrinkFont(TEXT_FONT, txFontSize);
txFont = getFontBySize(TEXT_FONT, txFontSize);
txMetrics = g.getFontMetrics(txFont);
--rmFontSize;
rmFont = getShrinkFont(REMINDER_FONT, rmFontSize);
rmFont = getFontBySize(REMINDER_FONT, rmFontSize);
rmMetrics = g.getFontMetrics(rmFont);
} while (txFontSize >= 8 && rmFontSize >= 8);
@@ -1037,7 +1107,7 @@ public class FCardImageRenderer {
y += pg.drawPieces(g, x + xoffset, y, w, lineSpacing + lineHeight, txFont, txMetrics, rmFont, rmMetrics);
y += paraSpacing - lineSpacing;
if (isLevelBox) {
txFont = getShrinkFont(TEXT_FONT, txFontSize + 10);
txFont = getFontBySize(TEXT_FONT, txFontSize + 10);
txMetrics = g.getFontMetrics(txFont);
y -= paraSpacing;
}

View File

@@ -3,8 +3,7 @@ ManaCost:2 W W
Types:Creature Bird
PT:3/3
K:Flying
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigEnergy | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, you get {E} (an energy counter).
T:Mode$ ChangesZone | ValidCard$ Creature.Other+YouCtrl | Origin$ Any | Destination$ Battlefield | Execute$ TrigEnergy | TriggerZones$ Battlefield | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, you get {E} (an energy counter).
T:Mode$ ChangesZone | ValidCard$ Card.Self,Creature.YouCtrl | Origin$ Any | Destination$ Battlefield | Execute$ TrigEnergy | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, you get {E} (an energy counter).
SVar:TrigEnergy:DB$ PutCounter | Defined$ You | CounterType$ ENERGY | CounterNum$ 1
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it and tap up to one target creature defending player controls.
SVar:TrigPutCounter:AB$ PutCounter | Cost$ PayEnergy<2> | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBTap

View File

@@ -2,8 +2,7 @@ Name:Agent of Erebos
ManaCost:3 B
Types:Enchantment Creature Zombie
PT:2/2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, exile all cards from target player's graveyard.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigExile | Secondary$ True | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, exile all cards from target player's graveyard.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.YouCtrl | Execute$ TrigExile | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, exile all cards from target player's graveyard.
SVar:TrigExile:DB$ ChangeZoneAll | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Player | TgtPrompt$ Select target player | ChangeType$ Card
AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/agent_of_erebos.jpg

View File

@@ -3,8 +3,7 @@ ManaCost:2 B
Types:Creature Orc Shaman
PT:2/2
K:Dash:3 B
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, that creature gets +2/+2.
T:Mode$ ChangesZone | ValidCard$ Creature.Other+YouCtrl | Origin$ Any | Destination$ Battlefield | Execute$ TrigPump | TriggerZones$ Battlefield | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, that creature gets +2/+2.
T:Mode$ ChangesZone | ValidCard$ Card.Self,Creature.YouCtrl | Origin$ Any | Destination$ Battlefield | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, that creature gets +2/+2.
SVar:TrigPump:DB$ Pump | Defined$ TriggeredCard | NumAtt$ +2 | NumDef$ +2
SVar:BuffedBy:Creature
SVar:Picture:http://www.wizards.com/global/images/magic/general/ambuscade_shaman.jpg

View File

@@ -3,8 +3,7 @@ ManaCost:3 W W
Types:Creature Archon
PT:3/4
K:Flying
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigGainLife | TriggerDescription$ Whenever CARDNAME or another creature with flying enters the battlefield under your control, you may gain life equal to that creature's power.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Other+YouCtrl+withFlying | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigGainLife | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature with flying enters the battlefield under your control, you may gain life equal to that creature's power.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Creature.Other+YouCtrl+withFlying | OptionalDecider$ You | Execute$ TrigGainLife | TriggerDescription$ Whenever CARDNAME or another creature with flying enters the battlefield under your control, you may gain life equal to that creature's power.
SVar:TrigGainLife:DB$GainLife | Defined$ You | LifeAmount$ X
SVar:X:TriggeredCard$CardPower
SVar:Picture:http://www.wizards.com/global/images/magic/general/archon_of_redemption.jpg

View File

@@ -2,8 +2,7 @@ Name:Ayara, First of Locthwain
ManaCost:B B B
Types:Legendary Creature Elf Noble
PT:2/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDrain | TriggerDescription$ Whenever CARDNAME or another black creature enters the battlefield under your control, each opponent loses 1 life and you gain 1 life.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Black+Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDrain | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another black creature enters the battlefield under your control, each opponent loses 1 life and you gain 1 life.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Creature.Black+Other+YouCtrl | Execute$ TrigDrain | TriggerDescription$ Whenever CARDNAME or another black creature enters the battlefield under your control, each opponent loses 1 life and you gain 1 life.
SVar:TrigDrain:DB$ LoseLife | Defined$ Player.Opponent | LifeAmount$ 1 | SubAbility$ DBGainLife
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1
A:AB$ Draw | Cost$ T Sac<1/Creature.Other+Black/another black creature> | NumCards$ 1 | SpellDescription$ Draw a card.

View File

@@ -2,8 +2,7 @@ Name:Bala Ged Thief
ManaCost:3 B
Types:Creature Human Rogue Ally
PT:2/2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ DBDiscard | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, target player reveals a number of cards from their hand equal to the number of Allies you control. You choose one of them. That player discards that card.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ DBDiscard | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, target player reveals a number of cards from their hand equal to the number of Allies you control. You choose one of them. That player discards that card.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | Execute$ DBDiscard | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, target player reveals a number of cards from their hand equal to the number of Allies you control. You choose one of them. That player discards that card.
SVar:DBDiscard:DB$ Discard | ValidTgts$ Player | NumCards$ 1 | RevealNumber$ X | Mode$ RevealYouChoose | DiscardValid$ Card
SVar:X:Count$TypeYouCtrl.Ally
SVar:BuffedBy:Ally

View File

@@ -2,8 +2,7 @@ Name:Blood Artist
ManaCost:1 B
Types:Creature Vampire
PT:0/1
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.Other | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ Whenever CARDNAME or another creature dies, target player loses 1 life and you gain 1 life.
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | TriggerController$ TriggeredCardController | Execute$ TrigLoseLife | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature dies, target player loses 1 life and you gain 1 life.
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self,Creature.Other | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ Whenever CARDNAME or another creature dies, target player loses 1 life and you gain 1 life.
SVar:TrigLoseLife:DB$ LoseLife | ValidTgts$ Player | TgtPrompt$ Choose a player to lose life | LifeAmount$ 1 | SubAbility$ DBGainLife
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1
SVar:Picture:http://www.wizards.com/global/images/magic/general/blood_artist.jpg

View File

@@ -3,8 +3,7 @@ ManaCost:1 B
Types:Creature Human Warrior Ally
PT:1/1
K:CARDNAME can't block.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
SVar:BuffedBy:Ally
SVar:Picture:http://www.wizards.com/global/images/magic/general/bojuka_brigand.jpg

View File

@@ -2,5 +2,5 @@ Name:Bond of Flourishing
ManaCost:1 G
Types:Sorcery
A:SP$ Dig | Cost$ 1 G | DigNum$ 3 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Permanent | DestinationZone$ Hand | DestinationZone2$ Library | LibraryPosition$ -1 | RestRandomOrder$ True | SubAbility$ GainLife | SpellDescription$ Look at the top three cards of your library. You may reveal a permanent card from among them and put it into your hand. Put the rest on the bottom of your library in any order. You gain 3 life.
SVar:GainLife:DB$GainLife | LifeAmount$ 3
SVar:GainLife:DB$ GainLife | LifeAmount$ 3
Oracle:Look at the top three cards of your library. You may reveal a permanent card from among them and put it into your hand. Put the rest on the bottom of your library in any order. You gain 3 life.

View File

@@ -2,5 +2,5 @@ Name:Bond of Passion
ManaCost:4 R R
Types:Sorcery
A:SP$ GainControl | Cost$ 4 R R | ValidTgts$ Creature | TgtPrompt$ Select target creature. | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SubAbility$ DBDamage | SpellDescription$ Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. CARDNAME deals 2 damage to any target.
SVar:DBDamage:DB$DealDamage | ValidTgts$ Creature,Player,Planeswalker | NumDmg$ 2 | TargetUnique$ True | TgtPrompt$ Select any target.
SVar:DBDamage:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | NumDmg$ 2 | TargetUnique$ True | TgtPrompt$ Select any target.
Oracle:Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. Bond of Passion deals 2 damage to any other target.

View File

@@ -2,8 +2,7 @@ Name:Coercive Recruiter
ManaCost:4 R
Types:Creature Orc Pirate
PT:4/3
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigGainControl | TriggerDescription$ Whenever CARDNAME or another Pirate enters the battlefield under your control, gain control of target creature until end of turn. Untap that creature. Until end of turn, it gains haste and becomes a Pirate in addition to its other types.
T:Mode$ ChangesZone | ValidCard$ Pirate.Other+YouCtrl | Origin$ Any | Destination$ Battlefield | Execute$ TrigGainControl | Secondary$ True | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME or another Pirate enters the battlefield under your control, gain control of target creature until end of turn. Untap that creature. Until end of turn, it gains haste and becomes a Pirate in addition to its other types.
T:Mode$ ChangesZone | ValidCard$ Card.Self,Pirate.Other+YouCtrl | Origin$ Any | Destination$ Battlefield | Execute$ TrigGainControl | TriggerDescription$ Whenever CARDNAME or another Pirate enters the battlefield under your control, gain control of target creature until end of turn. Untap that creature. Until end of turn, it gains haste and becomes a Pirate in addition to its other types.
SVar:TrigGainControl:DB$ GainControl | ValidTgts$ Creature | TgtPrompt$ Select target creature | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SubAbility$ DBAnimate
SVar:DBAnimate:DB$ Animate | Defined$ Targeted | Types$ Pirate | UntilEndOfTurn$ True
DeckNeeds:Type$Pirate

View File

@@ -1,8 +1,7 @@
Name:Daxos's Torment
ManaCost:3 B
Types:Enchantment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigAnimate | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, CARDNAME becomes a 5/5 Demon creature with flying and haste in addition to its other types until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Secondary$ True | Execute$ TrigAnimate | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, CARDNAME becomes a 5/5 Demon creature with flying and haste in addition to its other types until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigAnimate | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, CARDNAME becomes a 5/5 Demon creature with flying and haste in addition to its other types until end of turn.
SVar:TrigAnimate:DB$ Animate | Defined$ Self | Power$ 5 | Toughness$ 5 | Types$ Creature,Demon | Keywords$ Flying & Haste
SVar:PlayMain1:ALWAYS
SVar:BuffedBy:Enchantment

View File

@@ -2,8 +2,7 @@ Name:Doomwake Giant
ManaCost:4 B
Types:Enchantment Creature Giant
PT:4/6
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigMassacre | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, creatures your opponents control get -1/-1 until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigMassacre | Secondary$ True | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, creatures your opponents control get -1/-1 until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigMassacre | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, creatures your opponents control get -1/-1 until end of turn.
SVar:TrigMassacre:DB$ PumpAll | NumAtt$ -1 | NumDef$ -1 | ValidCards$ Creature.OppCtrl | IsCurse$ True
SVar:PlayMain1:TRUE
SVar:BuffedBy:Enchantment

View File

@@ -2,8 +2,7 @@ Name:Dreadbringer Lampads
ManaCost:4 B
Types:Enchantment Creature Nymph
PT:4/2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature gains intimidate until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPump | Secondary$ True | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature gains intimidate until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature gains intimidate until end of turn.
SVar:TrigPump:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ Intimidate
SVar:BuffedBy:Enchantment
SVar:PlayMain1:TRUE

View File

@@ -2,8 +2,7 @@ Name:Eidolon of Blossoms
ManaCost:2 G G
Types:Enchantment Creature Spirit
PT:2/2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, draw a card.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Secondary$ True | Execute$ TrigDraw | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, draw a card.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigDraw | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, draw a card.
SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1
SVar:BuffedBy:Enchantment
SVar:Picture:http://www.wizards.com/global/images/magic/general/eidolon_of_blossoms.jpg

View File

@@ -3,8 +3,7 @@ ManaCost:no cost
Types:Land
K:CARDNAME enters the battlefield tapped.
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | CheckSVar$ X | SVarCompare$ GE7 | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME or another land enters the battlefield under your control, if you control seven or more lands with different names, create a 2/2 black Zombie creature token.
T:Mode$ ChangesZone | TriggerZones$ Battlefield | CheckSVar$ X | SVarCompare$ GE7 | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.Other+YouCtrl | Execute$ TrigToken | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another land enters the battlefield under your control, if you control seven or more lands with different names, create a 2/2 black Zombie creature token.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Land.Other+YouCtrl | CheckSVar$ X | SVarCompare$ GE7 | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME or another land enters the battlefield under your control, if you control seven or more lands with different names, create a 2/2 black Zombie creature token.
SVar:TrigToken:DB$ Token | TokenScript$ b_2_2_zombie | TokenOwner$ You | TokenAmount$ 1 | LegacyImage$ b 2 2 zombie m20
SVar:X:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield
DeckHas:Ability$Token

View File

@@ -2,8 +2,7 @@ Name:Forgeborn Oreads
ManaCost:2 R R
Types:Enchantment Creature Nymph
PT:4/2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDamage | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, CARDNAME deals 1 damage to any target.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDamage | Secondary$ True | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, CARDNAME deals 1 damage to any target.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigDamage | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, CARDNAME deals 1 damage to any target.
SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1
SVar:PlayMain1:TRUE
SVar:BuffedBy:Enchantment

View File

@@ -3,8 +3,7 @@ ManaCost:1 W B
Types:Legendary Creature Human Soldier
PT:3/3
S:Mode$ Continuous | Affected$ Human.Other+YouCtrl | AddPower$ 1 | AddToughness$ 1 | Description$ Other Humans you control get +1/+1.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ Whenever CARDNAME or another Human enters the battlefield under your control, exile target card from an opponent's graveyard.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Other+Human+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigExile | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Human enters the battlefield under your control, exile target card from an opponent's graveyard.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Creature.Other+Human+YouCtrl | Execute$ TrigExile | TriggerDescription$ Whenever CARDNAME or another Human enters the battlefield under your control, exile target card from an opponent's graveyard.
SVar:TrigExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | TgtPrompt$ Choose target card in an opponent's graveyard | ValidTgts$ Card.OppOwn
A:AB$ Destroy | Cost$ 2 Sac<2/Human> | ValidTgts$ Creature.powerGE4 | TgtPrompt$ Select target creature with power 4 or greater | SpellDescription$ Destroy target creature with power 4 or greater.
DeckHints:Type$Human

View File

@@ -2,8 +2,7 @@ Name:Goblin Assassin
ManaCost:3 R R
Types:Creature Goblin Assassin
PT:2/2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ RepeatFlips | TriggerDescription$ Whenever CARDNAME or another Goblin enters the battlefield, each player flips a coin. Each player whose coin comes up tails sacrifices a creature.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Goblin.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ RepeatFlips | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Goblin enters the battlefield, each player flips a coin. Each player whose coin comes up tails sacrifices a creature.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Goblin.Other+YouCtrl | Execute$ RepeatFlips | TriggerDescription$ Whenever CARDNAME or another Goblin enters the battlefield, each player flips a coin. Each player whose coin comes up tails sacrifices a creature.
SVar:RepeatFlips:DB$ RepeatEach | RepeatPlayers$ Player | RepeatSubAbility$ AssassinsFlip | SubAbility$ Assassination
SVar:AssassinsFlip:DB$ FlipACoin | Flipper$ Remembered | NoCall$ True | RememberResult$ True
SVar:Assassination:DB$ Sacrifice | Defined$ FlippedTails | SacValid$ Creature | Amount$ 1 | SubAbility$ ResetFlips

View File

@@ -2,8 +2,7 @@ Name:Goldenhide Ox
ManaCost:5 G
Types:Enchantment Creature Ox
PT:5/4
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature must be blocked this turn if able.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPump | Secondary$ True | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature must be blocked this turn if able.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature must be blocked this turn if able.
SVar:TrigPump:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ HIDDEN CARDNAME must be blocked if able. | AILogic$ Pump
SVar:PlayMain1:TRUE
SVar:BuffedBy:Enchantment

View File

@@ -3,8 +3,7 @@ ManaCost:3 G
Types:Creature Human Warrior Ally
PT:2/2
K:Trample
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
SVar:BuffedBy:Ally
SVar:Picture:http://www.wizards.com/global/images/magic/general/graypelt_hunter.jpg

View File

@@ -2,8 +2,7 @@ Name:Grim Guardian
ManaCost:2 B
Types:Enchantment Creature Zombie
PT:1/4
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDrain | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, each opponent loses 1 life.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDrain | Secondary$ True | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, each opponent loses 1 life.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigDrain | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, each opponent loses 1 life.
SVar:TrigDrain:DB$ LoseLife | Defined$ Player.Opponent | LifeAmount$ 1
SVar:Picture:http://www.wizards.com/global/images/magic/general/grim_guardian.jpg
Oracle:Constellation — Whenever Grim Guardian or another enchantment enters the battlefield under your control, each opponent loses 1 life.

View File

@@ -2,8 +2,7 @@ Name:Grovetender Druids
ManaCost:2 G W
Types:Creature Elf Druid Ally
PT:3/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, you may pay {1}. If you do, create a 1/1 green Plant creature token.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigToken | Secondary$ True | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, you may pay {1}. If you do, create a 1/1 green Plant creature token.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | Execute$ TrigToken | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, you may pay {1}. If you do, create a 1/1 green Plant creature token.
SVar:TrigToken:AB$ Token | Cost$ 1 | TokenAmount$ 1 | TokenScript$ g_1_1_plant | LegacyImage$ g 1 1 plant bfz | TokenOwner$ You
DeckHints:Type$Ally
SVar:Picture:http://www.wizards.com/global/images/magic/general/grovetender_druids.jpg

View File

@@ -2,8 +2,7 @@ Name:Gruul Ragebeast
ManaCost:5 R G
Types:Creature Beast
PT:6/6
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigFight | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, that creature fights target creature an opponent controls.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigFight | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, that creature fights target creature an opponent controls.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Creature.Other+YouCtrl | Execute$ TrigFight | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, that creature fights target creature an opponent controls.
SVar:TrigFight:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls.
SVar:Picture:http://www.wizards.com/global/images/magic/general/gruul_ragebeast.jpg
Oracle:Whenever Gruul Ragebeast or another creature enters the battlefield under your control, that creature fights target creature an opponent controls.

View File

@@ -2,8 +2,7 @@ Name:Hada Freeblade
ManaCost:W
Types:Creature Human Soldier Ally
PT:0/1
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
SVar:BuffedBy:Ally
SVar:Picture:http://www.wizards.com/global/images/magic/general/hada_freeblade.jpg

View File

@@ -2,8 +2,7 @@ Name:Halimar Excavator
ManaCost:1 U
Types:Creature Human Wizard Ally
PT:1/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigMill | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, target player mills X cards, where X is the number of Allies you control.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigMill | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, target player mills X cards, where X is the number of Allies you control.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | Execute$ TrigMill | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, target player mills X cards, where X is the number of Allies you control.
SVar:TrigMill:DB$ Mill | ValidTgts$ Player | NumCards$ X | TgtPrompt$ Select a target player. | SpellDescription$ Target player mills X cards, where X is the number of Allies you control.
SVar:X:Count$Valid Ally.YouCtrl
SVar:BuffedBy:Ally

View File

@@ -1,8 +1,7 @@
Name:Hammer of Nazahn
ManaCost:4
Types:Legendary Artifact Equipment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigAttach | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME or another Equipment enters the battlefield under your control, you may attach that Equipment to target creature you control.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Equipment+Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigAttach | OptionalDecider$ You | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Equipment enters the battlefield under your control, that Equipment to target creature you control.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Card.Equipment+Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigAttach | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME or another Equipment enters the battlefield under your control, you may attach that Equipment to target creature you control.
SVar:TrigAttach:DB$ Attach | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Target creature you control | Object$ TriggeredCard
S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 2 | AddKeyword$ Indestructible | Description$ Equipped creature gets +2/+0 and has indestructible.
K:Equip:4

View File

@@ -2,8 +2,7 @@ Name:Harvestguard Alseids
ManaCost:2 W
Types:Enchantment Creature Nymph
PT:2/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, prevent all damage that would be dealt to target creature this turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Secondary$ True | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, prevent all damage that would be dealt to target creature this turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, prevent all damage that would be dealt to target creature this turn.
SVar:TrigPump:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ Prevent all damage that would be dealt to CARDNAME.
SVar:PlayMain1:TRUE
SVar:BuffedBy:Enchantment

View File

@@ -2,8 +2,7 @@ Name:Humbler of Mortals
ManaCost:4 G G
Types:Enchantment Creature Elemental
PT:5/5
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, creatures you control gain trample until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPump | Secondary$ True | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, creatures you control gain trample until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, creatures you control gain trample until end of turn.
SVar:TrigPump:DB$ PumpAll | ValidCards$ Creature.YouCtrl | KW$ Trample | SpellDescription$ Creatures you control gain trample until end of turn.
SVar:PlayMain1:TRUE
SVar:BuffedBy:Enchantment

View File

@@ -2,8 +2,7 @@ Name:Joraga Bard
ManaCost:3 G
Types:Creature Elf Rogue Bard Ally
PT:1/4
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may have Ally creatures you control gain vigilance until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPump | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may have Ally creatures you control gain vigilance until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | OptionalDecider$ You | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may have Ally creatures you control gain vigilance until end of turn.
SVar:TrigPump:DB$ PumpAll | ValidCards$ Ally.YouCtrl | KW$ Vigilance
SVar:PlayMain1:TRUE
SVar:BuffedBy:Ally

View File

@@ -2,8 +2,7 @@ Name:Kalastria Healer
ManaCost:1 B
Types:Creature Vampire Cleric Ally
PT:1/2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDrain | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, each opponent loses 1 life and you gain 1 life.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDrain | Secondary$ True | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, each opponent loses 1 life and you gain 1 life.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | Execute$ TrigDrain | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, each opponent loses 1 life and you gain 1 life.
SVar:TrigDrain:DB$ LoseLife | Defined$ Player.Opponent | LifeAmount$ 1 | SubAbility$ DBGainLife
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1
SVar:PlayMain1:TRUE

View File

@@ -3,8 +3,7 @@ ManaCost:4 U U
Types:Creature Fish
PT:3/3
K:Flying
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigTap | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, tap target creature an opponent controls.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.YouCtrl+Other | TriggerZones$ Battlefield | Execute$ TrigTap | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, tap target creature an opponent controls.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Creature.YouCtrl+Other | Execute$ TrigTap | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, tap target creature an opponent controls.
SVar:TrigTap:DB$ Tap | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Choose target creature an opponent controls.
SVar:BuffedBy:Creature
SVar:PlayMain1:TRUE

View File

@@ -4,8 +4,7 @@ Types:Creature Human Soldier Ally
PT:1/1
K:First Strike
K:Vigilance
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
SVar:BuffedBy:Ally
SVar:Picture:http://www.wizards.com/global/images/magic/general/kazandu_blademaster.jpg

View File

@@ -2,9 +2,8 @@ Name:Kazuul Warlord
ManaCost:4 R
Types:Creature Minotaur Warrior Ally
PT:3/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on each Ally creature you control.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on each Ally creature you control.
SVar:TrigPutCounter:DB$PutCounterAll | ValidCards$ Ally.YouCtrl | CounterType$ P1P1 | CounterNum$ 1
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on each Ally creature you control.
SVar:TrigPutCounter:DB$ PutCounterAll | ValidCards$ Ally.YouCtrl | CounterType$ P1P1 | CounterNum$ 1
SVar:PlayMain1:TRUE
SVar:BuffedBy:Ally
SVar:Picture:http://www.wizards.com/global/images/magic/general/kazuul_warlord.jpg

View File

@@ -2,8 +2,7 @@ Name:Kor Celebrant
ManaCost:2 W
Types:Creature Kor Cleric
PT:1/4
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigGainLife | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, you gain 1 life.
T:Mode$ ChangesZone | ValidCard$ Creature.Other+YouCtrl | Origin$ Any | Destination$ Battlefield | Execute$ TrigGainLife | TriggerZones$ Battlefield | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, you gain 1 life.
T:Mode$ ChangesZone | ValidCard$ Card.Self,Creature.Other+YouCtrl | Origin$ Any | Destination$ Battlefield | Execute$ TrigGainLife | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, you gain 1 life.
SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1
DeckHas:Ability$LifeGain
Oracle:Whenever Kor Celebrant or another creature enters the battlefield under your control, you gain 1 life.

View File

@@ -2,8 +2,7 @@ Name:Kor Entanglers
ManaCost:4 W
Types:Creature Kor Soldier Ally
PT:3/4
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigTap | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, tap target creature an opponent controls.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigTap | Secondary$ True | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, tap target creature an opponent controls.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | Execute$ TrigTap | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, tap target creature an opponent controls.
SVar:TrigTap:DB$ Tap | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Choose target creature an opponent controls.
SVar:PlayMain1:TRUE
SVar:BuffedBy:Ally

View File

@@ -3,8 +3,7 @@ ManaCost:2 W
Types:Creature Kor Soldier Ally
PT:0/3
K:Defender
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtr | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
SVar:BuffedBy:Ally
AI:RemoveDeck:Random

View File

@@ -2,8 +2,7 @@ Name:Mardu Woe-Reaper
ManaCost:W
Types:Creature Human Warrior
PT:2/1
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigExile| TriggerDescription$ Whenever CARDNAME or another Warrior enters the battlefield under your control, you may exile target creature card from a graveyard. If you do, you gain 1 life.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Warrior.Other+YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigExile | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Warrior enters the battlefield under your control, you may exile target creature card from a graveyard. If you do, you gain 1 life.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Warrior.Other+YouCtrl | OptionalDecider$ You | Execute$ TrigExile | TriggerDescription$ Whenever CARDNAME or another Warrior enters the battlefield under your control, you may exile target creature card from a graveyard. If you do, you gain 1 life.
SVar:TrigExile:DB$ ChangeZone | ValidTgts$ Creature | TgtPrompt$ Select target creature card | Origin$ Graveyard | Destination$ Exile | RememberChanged$ True | SubAbility$ DBGainLife
SVar:DBGainLife:DB$ GainLife | LifeAmount$ 1 | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ1 | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True

View File

@@ -1,8 +1,7 @@
Name:Marit Lage's Slumber
ManaCost:1 U
Types:Legendary Snow Enchantment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Permanent.Snow+Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigScry | TriggerDescription$ Whenever CARDNAME or another snow permanent enters the battlefield under your control, scry 1.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Secondary$ True | Execute$ TrigScry | TriggerDescription$ Whenever CARDNAME or another snow permanent enters the battlefield under your control, scry 1.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Permanent.Snow+Other+YouCtrl | Execute$ TrigScry | TriggerDescription$ Whenever CARDNAME or another snow permanent enters the battlefield under your control, scry 1.
SVar:TrigScry:DB$ Scry | ScryNum$ 1 | SpellDescription$ Scry 1.
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | IsPresent$ Permanent.Snow+YouCtrl | PresentCompare$ GE10 | Execute$ TrigSac | TriggerDescription$ At the beginning of your upkeep, if you control ten or more snow permanents, sacrifice CARDNAME. If you do, create Marit Lage, a legendary 20/20 black Avatar creature token with flying and indestructible.
SVar:TrigSac:DB$ Sacrifice | RememberSacrificed$ True | SubAbility$ DBToken

View File

@@ -3,8 +3,7 @@ ManaCost:2 R W
Types:Legendary Creature Kor Ally
PT:3/4
K:Haste
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDig | OptionalDecider$ You | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, you may look at the top four cards of your library. If you do, reveal any number of Ally cards from among them, then put those cards on top of your library in any order and the rest on the bottom in any order.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDig | Secondary$ True | OptionalDecider$ You | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, you may look at the top four cards of your library. If you do, reveal any number of Ally cards from among them, then put those cards on top of your library in any order and the rest on the bottom in any order.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | Execute$ TrigDig | OptionalDecider$ You | TriggerDescription$ Rally — Whenever CARDNAME or another Ally enters the battlefield under your control, you may look at the top four cards of your library. If you do, reveal any number of Ally cards from among them, then put those cards on top of your library in any order and the rest on the bottom in any order.
SVar:TrigDig:DB$ Dig | DigNum$ 4 | AnyNumber$ True | ChangeValid$ Ally | DestinationZone$ Library | LibraryPosition$ 0
DeckHints:Type$Ally
SVar:Picture:http://www.wizards.com/global/images/magic/general/munda_ambush_leader.jpg

View File

@@ -4,8 +4,7 @@ Types:Creature Spirit
PT:2/1
K:Flash
K:Flying
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigTap | TriggerDescription$ Whenever Nebelgast Herald or another Spirit enters the battlefield under your control, tap target creature an opponent controls.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Spirit+YouCtrl+Other | TriggerZones$ Battlefield | Execute$ TrigTap | Secondary$ True | TriggerDescription$ Whenever another white creature enters the battlefield under your control, tap target creature an opponent controls.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Spirit.YouCtrl+Other | Execute$ TrigTap | TriggerDescription$ Whenever CARDNAME or another Spirit enters the battlefield under your control, tap target creature an opponent controls.
SVar:TrigTap:DB$ Tap | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Choose target creature an opponent controls.
SVar:BuffedBy:Spirit
DeckHints:Type$Spirit

View File

@@ -2,8 +2,7 @@ Name:Nimana Sell-Sword
ManaCost:3 B
Types:Creature Human Warrior Ally
PT:2/2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
SVar:BuffedBy:Ally
SVar:Picture:http://www.wizards.com/global/images/magic/general/nimana_sell_sword.jpg

View File

@@ -2,8 +2,7 @@ Name:Noxious Ghoul
ManaCost:3 B B
Types:Creature Zombie
PT:3/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPumpAll | TriggerDescription$ Whenever CARDNAME or another Zombie enters the battlefield, all non-Zombie creatures get -1/-1 until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Zombie.Other | Execute$ TrigPumpAll | TriggerZones$ Battlefield | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Zombie enters the battlefield, all non-Zombie creatures get -1/-1 until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Zombie.Other | Execute$ TrigPumpAll | TriggerDescription$ Whenever CARDNAME or another Zombie enters the battlefield, all non-Zombie creatures get -1/-1 until end of turn.
SVar:TrigPumpAll:DB$ PumpAll | ValidCards$ Creature.nonZombie | NumAtt$ -1 | NumDef$ -1 | IsCurse$ True
SVar:PlayMain1:TRUE
Oracle:Whenever Noxious Ghoul or another Zombie enters the battlefield, all non-Zombie creatures get -1/-1 until end of turn.

View File

@@ -2,8 +2,7 @@ Name:Nylea's Colossus
ManaCost:6 G
Types:Enchantment Creature Giant
PT:6/6
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Constellation Whenever CARDNAME or another enchantment enters the battlefield under your control, double target creature's power and toughness until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Secondary$ True | Execute$ TrigPump | TriggerDescription$ Constellation Whenever CARDNAME or another enchantment enters the battlefield under your control, double target creature's power and toughness until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigPump | TriggerDescription$ Constellation Whenever CARDNAME or another enchantment enters the battlefield under your control, double target creature's power and toughness until end of turn.
SVar:TrigPump:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +X | NumDef$ +Y | RememberTargets$ True | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Remembered$CardPower

View File

@@ -2,8 +2,7 @@ Name:Oakheart Dryads
ManaCost:2 G
Types:Enchantment Creature Nymph Dryad
PT:2/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature gets +1/+1 until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Secondary$ True | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature gets +1/+1 until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature gets +1/+1 until end of turn.
SVar:TrigPump:DB$ Pump | ValidTgts$ Creature | NumAtt$ +1 | NumDef$ +1
SVar:BuffedBy:Enchantment
SVar:PlayMain1:TRUE

View File

@@ -1,8 +1,7 @@
Name:Oath of the Ancient Wood
ManaCost:2 G
Types:Enchantment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another enchantment enters the battlefield under your control, you may put a +1/+1 counter on target creature.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPutCounter | Secondary$ True | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME or another enchantment enters the battlefield under your control, you may put a +1/+1 counter on target creature.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigPutCounter | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME or another enchantment enters the battlefield under your control, you may put a +1/+1 counter on target creature.
SVar:TrigPutCounter:DB$ PutCounter | ValidTgts$ Creature | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ 1
AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/oath_of_the_ancient_wood.jpg

View File

@@ -2,8 +2,7 @@ Name:Oran-Rief Survivalist
ManaCost:1 G
Types:Creature Human Warrior Ally
PT:1/1
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Ally.Other+YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Ally.Other+YouCtrl | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another Ally enters the battlefield under your control, you may put a +1/+1 counter on CARDNAME.
SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
SVar:BuffedBy:Ally
SVar:Picture:http://www.wizards.com/global/images/magic/general/oran_rief_survivalist.jpg

View File

@@ -3,8 +3,7 @@ ManaCost:4 G
Types:Creature Cat Warrior
PT:3/5
K:Reach
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDestroy | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME or another Cat enters the battlefield under your control, you may destroy target artifact or enchantment.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Cat.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDestroy | Secondary$ True | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME or another Cat enters the battlefield under your control, you may destroy target artifact or enchantment.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Cat.Other+YouCtrl | Execute$ TrigDestroy | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME or another Cat enters the battlefield under your control, you may destroy target artifact or enchantment.
SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment
DeckHints:Type$Cat
SVar:Picture:http://www.wizards.com/global/images/magic/general/qasali_slingers.jpg

View File

@@ -2,8 +2,7 @@ Name:Risen Reef
ManaCost:1 G U
Types:Creature Elemental
PT:1/1
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPeek | TriggerDescription$ Whenever CARDNAME or another Elemental enters the battlefield under your control, look at the top card of your library. If it's a land card, you may put it onto the battlefield tapped. If you don't put the card onto the battlefield, put it into your hand.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Elemental.Other+YouCtrl | TriggerZones$ Battlefield | Secondary$ True | Execute$ TrigPeek | TriggerDescription$ Whenever CARDNAME or another Elemental enters the battlefield under your control, look at the top card of your library. If it's a land card, you may put it onto the battlefield tapped. If you don't put the card onto the battlefield, put it into your hand.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Elemental.Other+YouCtrl | Execute$ TrigPeek | TriggerDescription$ Whenever CARDNAME or another Elemental enters the battlefield under your control, look at the top card of your library. If it's a land card, you may put it onto the battlefield tapped. If you don't put the card onto the battlefield, put it into your hand.
SVar:TrigPeek:DB$ PeekAndReveal | PeekAmount$ 1 | NoReveal$ True | RememberPeeked$ True | SubAbility$ DBChangeZone
SVar:DBChangeZone:DB$ ChangeZone | Optional$ True | ForgetChanged$ True | Origin$ Library | Destination$ Battlefield | Defined$ Remembered | ConditionDefined$ Remembered | ConditionPresent$ Land | ConditionCompare$ GE1 | Tapped$ True | SubAbility$ DBHand
SVar:DBHand:DB$ ChangeZone | Origin$ Library | Destination$ Hand | Defined$ Remembered | SubAbility$ DBCleanup

View File

@@ -2,7 +2,6 @@ Name:Sage of the Falls
ManaCost:4 U
Types:Creature Merfolk Wizard
PT:2/5
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigLoot | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME or another non-Human creature enters the battlefield under your control, you may draw a card. If you do, discard a card.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.nonHuman+Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigLoot | OptionalDecider$ You | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another non-Human creature enters the battlefield under your control, you may draw a card. If you do, discard a card.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Creature.nonHuman+Other+YouCtrl | Execute$ TrigLoot | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME or another non-Human creature enters the battlefield under your control, you may draw a card. If you do, discard a card.
SVar:TrigLoot:AB$ Discard | Defined$ You | Mode$ TgtChoose | NumCards$ 1 | Cost$ Draw<1/You>
Oracle:Whenever Sage of the Falls or another non-Human creature enters the battlefield under your control, you may draw a card. If you do, discard a card.

View File

@@ -3,8 +3,7 @@ ManaCost:2 R R R
Types:Creature Dragon
PT:4/4
K:Flying
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDamage | TriggerDescription$ Whenever CARDNAME or another Dragon enters the battlefield under your control, it deals X damage to any target, where X is the number of Dragons you control.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Dragon.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDamage | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another Dragon enters the battlefield under your control, it deals X damage to any target, where X is the number of Dragons you control.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Dragon.Other+YouCtrl | Execute$ TrigDamage | TriggerDescription$ Whenever CARDNAME or another Dragon enters the battlefield under your control, it deals X damage to any target, where X is the number of Dragons you control.
SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | NumDmg$ NumDragons | TgtPrompt$ Select any target | DamageSource$ TriggeredCard
SVar:NumDragons:Count$Valid Dragon.YouCtrl
A:AB$ Pump | Cost$ R | Defined$ Self | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn.

View File

@@ -1,8 +1,7 @@
Name:Serum Tank
ManaCost:3
Types:Artifact
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another artifact enters the battlefield, put a charge counter on CARDNAME.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | TriggerZones$ Battlefield | ValidCard$ Artifact.Other | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another artifact enters the battlefield, put a charge counter on CARDNAME. | Secondary$ True
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Artifact.Other | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another artifact enters the battlefield, put a charge counter on CARDNAME.
A:AB$ Draw | Cost$ 3 T SubCounter<1/CHARGE> | NumCards$ 1 | SpellDescription$ Draw a card.
SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ CHARGE | CounterNum$ 1
AI:RemoveDeck:Random

View File

@@ -2,8 +2,7 @@ Name:Sethron, Hurloon General
ManaCost:3 R R
Types:Legendary Creature Minotaur Warrior
PT:4/4
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | TriggerZones$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME or another nontoken Minotaur enters enters the battlefield under your control, create a 2/3 red Minotaur creature token.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | TriggerZones$ Battlefield | ValidCard$ Minotaur.nonToken+Other+YouCtrl | Execute$ TrigToken | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another nontoken Minotaur enters the battlefield under your control, create a 2/3 red Minotaur creature token.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | TriggerZones$ Battlefield | ValidCard$ Card.Self,Minotaur.nonToken+Other+YouCtrl | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME or another nontoken Minotaur enters enters the battlefield under your control, create a 2/3 red Minotaur creature token.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ r_2_3_minotaur | TokenOwner$ You
A:AB$ PumpAll | Cost$ 2 BR | ValidCards$ Minotaur.YouCtrl | NumAtt$ +1 | KW$ Menace & Haste | SpellDescription$ Minotaurs you control get +1/+0 and gain menace and haste until end of turn.
SVar:PlayMain1:TRUE

View File

@@ -1,8 +1,7 @@
Name:Strength from the Fallen
ManaCost:1 G
Types:Enchantment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature gets +X/+X until end of turn, where X is the number of creature cards in your graveyard.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Secondary$ True | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature gets +X/+X until end of turn, where X is the number of creature cards in your graveyard.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigPump | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target creature gets +X/+X until end of turn, where X is the number of creature cards in your graveyard.
SVar:TrigPump:DB$ Pump | ValidTgts$ Creature | NumAtt$ +X | NumDef$ +X
SVar:X:Count$TypeInYourYard.Creature
SVar:PlayMain1:TRUE

View File

@@ -2,8 +2,7 @@ Name:Thassa's Devourer
ManaCost:4 U
Types:Enchantment Creature Elemental
PT:2/6
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigMill | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target player mills two cards.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Enchantment.Other+YouCtrl | TriggerZones$ Battlefield | Secondary$ True | Execute$ TrigMill | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target player mills two cards.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Enchantment.Other+YouCtrl | Execute$ TrigMill | TriggerDescription$ Constellation — Whenever CARDNAME or another enchantment enters the battlefield under your control, target player mills two cards.
SVar:TrigMill:DB$ Mill | ValidTgts$ Player | TgtPrompt$ Select target player | NumCards$ 2
SVar:BuffedBy:Enchantment
Oracle:Constellation — Whenever Thassa's Devourer or another enchantment enters the battlefield under your control, target player mills two cards.

Some files were not shown because too many files have changed in this diff Show More