Added attraction light icons (#5663)

Refactored functional variants to be merged in the card face rather than the card factory
Some variant characteristics now show in deck builder columns
Fixed loading progress amount
"[card] has neither ManaCost nor Color" warning now actually displays when these are missing.

Co-authored-by: Jetz <Jetz722@gmail.com>
Co-authored-by: tool4ever <therealtoolkit@hotmail.com>
This commit is contained in:
Jetz72
2024-07-30 01:28:45 -04:00
committed by GitHub
parent 20ed52af4b
commit ec9f6e2d2b
20 changed files with 316 additions and 137 deletions

View File

@@ -28,11 +28,12 @@ final class CardFace implements ICardFace, Cloneable {
private final static List<String> emptyList = Collections.unmodifiableList(new ArrayList<>());
private final static Map<String, String> emptyMap = Collections.unmodifiableMap(new TreeMap<>());
private final static Set<Integer> emptySet = Collections.unmodifiableSet(new HashSet<>());
private String name;
private String altName = null;
private CardType type = null;
private ManaCost manaCost = ManaCost.NO_COST;
private ManaCost manaCost = null;
private ColorSet color = null;
private String oracleText = null;
@@ -147,7 +148,7 @@ final class CardFace implements ICardFace, Cloneable {
//Functional variant methods. Used for Attractions and some Un-cards,
//when cards with the same name can have different logic.
public boolean hasFunctionalVariants() {
@Override public boolean hasFunctionalVariants() {
return this.functionalVariants != null;
}
@Override public ICardFace getFunctionalVariant(String variant) {
@@ -169,6 +170,7 @@ final class CardFace implements ICardFace, Cloneable {
void assignMissingFields() { // Most scripts do not specify color explicitly
if ( null == oracleText ) { System.err.println(name + " has no Oracle text."); oracleText = ""; }
if ( manaCost == null && color == null ) System.err.println(name + " has neither ManaCost nor Color");
if ( manaCost == null ) manaCost = ManaCost.NO_COST;
if ( color == null ) color = ColorSet.fromManaCost(manaCost);
if ( keywords == null ) keywords = emptyList;
@@ -178,7 +180,54 @@ final class CardFace implements ICardFace, Cloneable {
if ( replacements == null ) replacements = emptyList;
if ( variables == null ) variables = emptyMap;
if ( null == nonAbilityText ) nonAbilityText = "";
//Not assigning attractionLightVariants here. Too rarely used. Will test for it downstream.
if ( attractionLights == null) attractionLights = emptySet;
if(this.functionalVariants != null) {
//Copy fields to undefined ones in functional variants
for (CardFace variant : this.functionalVariants.values()) {
if(variant.oracleText == null) variant.oracleText = this.oracleText;
if(variant.manaCost == null) variant.manaCost = this.manaCost;
if(variant.color == null) variant.color = ColorSet.fromManaCost(variant.manaCost);
if(variant.type == null) variant.type = this.type;
if(variant.power == null) {
variant.power = this.power;
variant.iPower = this.iPower;
}
if(variant.toughness == null) {
variant.toughness = this.toughness;
variant.iToughness = this.iToughness;
}
if("".equals(variant.initialLoyalty)) variant.initialLoyalty = this.initialLoyalty;
if("".equals(variant.defense)) variant.defense = this.defense;
//variant.assignMissingFields();
if(variant.keywords == null) variant.keywords = this.keywords;
else variant.keywords.addAll(0, this.keywords);
if(variant.abilities == null) variant.abilities = this.abilities;
else variant.abilities.addAll(0, this.abilities);
if(variant.staticAbilities == null) variant.staticAbilities = this.staticAbilities;
else variant.staticAbilities.addAll(0, this.staticAbilities);
if(variant.triggers == null) variant.triggers = this.triggers;
else variant.triggers.addAll(0, this.triggers);
if(variant.replacements == null) variant.replacements = this.replacements;
else variant.replacements.addAll(0, this.replacements);
if(variant.variables == null) variant.variables = this.variables;
else variant.variables.putAll(this.variables);
if(variant.nonAbilityText == null) variant.nonAbilityText = this.nonAbilityText;
if(variant.draftActions == null) variant.draftActions = this.draftActions;
if(variant.attractionLights == null) variant.attractionLights = this.attractionLights;
if(variant.altName == null) variant.altName = this.altName;
}
}
}

View File

@@ -5,6 +5,7 @@ import com.google.common.collect.Lists;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.card.CardType.CoreType;
import forge.card.ICardFace;
import forge.card.MagicColor;
import forge.util.PredicateCard;
import forge.util.PredicateString;
@@ -253,6 +254,8 @@ public interface IPaperCard extends InventoryItem, Serializable {
String getArtist();
String getItemType();
boolean hasBackFace();
ICardFace getMainFace();
ICardFace getOtherFace();
String getCardImageKey();
String getCardAltImageKey();
String getCardWSpecImageKey();

View File

@@ -178,7 +178,7 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
public PaperCard(final CardRules rules0, final String edition0, final CardRarity rarity0) {
this(rules0, edition0, rarity0, IPaperCard.DEFAULT_ART_INDEX, false,
IPaperCard.NO_COLLECTOR_NUMBER, IPaperCard.NO_ARTIST_NAME, "");
IPaperCard.NO_COLLECTOR_NUMBER, IPaperCard.NO_ARTIST_NAME, IPaperCard.NO_FUNCTIONAL_VARIANT);
}
public PaperCard(final CardRules rules0, final String edition0, final CardRarity rarity0,
@@ -417,6 +417,29 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|| cst == CardSplitType.Modal;
}
@Override
public ICardFace getMainFace() {
ICardFace face = this.rules.getMainPart();
return this.getVariantForFace(face);
}
@Override
public ICardFace getOtherFace() {
ICardFace face = this.rules.getOtherPart();
return this.getVariantForFace(face);
}
private ICardFace getVariantForFace(ICardFace face) {
if(!face.hasFunctionalVariants() || this.functionalVariant.equals(NO_FUNCTIONAL_VARIANT))
return face;
ICardFace variant = face.getFunctionalVariant(this.functionalVariant);
if(variant == null) {
System.err.printf("Tried to apply unknown or unsupported variant - Card: \"%s\"; Variant: %s\n", face.getName(), this.functionalVariant);
return face;
}
return variant;
}
// Return true if card is one of the five basic lands that can be added for free
public boolean isVeryBasicLand() {
return (this.getName().equals("Swamp"))

View File

@@ -3,14 +3,10 @@ package forge.item;
import java.util.ArrayList;
import java.util.Locale;
import forge.card.*;
import org.apache.commons.lang3.StringUtils;
import forge.ImageKeys;
import forge.card.CardEdition;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.card.CardSplitType;
import forge.card.ColorSet;
import forge.util.MyRandom;
public class PaperToken implements InventoryItemFromSet, IPaperCard {
@@ -204,6 +200,16 @@ public class PaperToken implements InventoryItemFromSet, IPaperCard {
return cst == CardSplitType.Transform;
}
@Override
public ICardFace getMainFace() {
return this.getRules().getMainPart();
}
@Override
public ICardFace getOtherFace() {
return this.getRules().getOtherPart();
}
@Override
public boolean isToken() {
return true;

View File

@@ -357,6 +357,18 @@ public class CardFactory {
}
private static void readCardFace(Card c, ICardFace face) {
//If it's a functional variant card, switch to that first.
if(face.hasFunctionalVariants()) {
String variantName = c.getPaperCard().getFunctionalVariant();
if (!IPaperCard.NO_FUNCTIONAL_VARIANT.equals(variantName)) {
ICardFace variant = face.getFunctionalVariant(variantName);
if (variant != null)
face = variant;
else
System.err.printf("Tried to apply unknown or unsupported variant - Card: \"%s\"; Variant: %s\n", face.getName(), variantName);
}
}
// Build English oracle and translated oracle mapping
if (c.getId() >= 0) {
CardTranslation.buildOracleMapping(face.getName(), face.getOracleText());
@@ -417,73 +429,6 @@ public class CardFactory {
}
CardFactoryUtil.addAbilityFactoryAbilities(c, face.getAbilities());
if (face.hasFunctionalVariants()) {
applyFunctionalVariant(c, face);
}
}
private static void applyFunctionalVariant(Card c, ICardFace originalFace) {
String variantName = c.getPaperCard().getFunctionalVariant();
if (IPaperCard.NO_FUNCTIONAL_VARIANT.equals(variantName))
return;
ICardFace variant = originalFace.getFunctionalVariant(variantName);
if (variant == null) {
System.out.printf("Tried to apply unknown or unsupported variant - Card: \"%s\"; Variant: %s\n", originalFace.getName(), variantName);
return;
}
if (variant.getVariables() != null)
for (Entry<String, String> v : variant.getVariables())
c.setSVar(v.getKey(), v.getValue());
if (variant.getReplacements() != null)
for (String r : variant.getReplacements())
c.addReplacementEffect(ReplacementHandler.parseReplacement(r, c, true, c.getCurrentState()));
if (variant.getStaticAbilities() != null)
for (String s : variant.getStaticAbilities())
c.addStaticAbility(s);
if (variant.getTriggers() != null)
for (String t : variant.getTriggers())
c.addTrigger(TriggerHandler.parseTrigger(t, c, true, c.getCurrentState()));
if (variant.getKeywords() != null)
c.addIntrinsicKeywords(variant.getKeywords(), false);
if (variant.getManaCost() != ManaCost.NO_COST)
c.setManaCost(variant.getManaCost());
if (variant.getNonAbilityText() != null)
c.setText(variant.getNonAbilityText());
if (!"".equals(variant.getInitialLoyalty()))
c.getCurrentState().setBaseLoyalty(variant.getInitialLoyalty());
if (!"".equals(variant.getDefense()))
c.getCurrentState().setBaseDefense(variant.getDefense());
if (variant.getOracleText() != null)
c.getCurrentState().setOracleText(variant.getOracleText());
if (variant.getType() != null) {
for(String type : variant.getType())
c.addType(type);
}
if (variant.getColor() != null)
c.setColor(variant.getColor().getColor());
if (variant.getIntPower() != Integer.MAX_VALUE) {
c.setBasePower(variant.getIntPower());
c.setBasePowerString(variant.getPower());
}
if (variant.getIntToughness() != Integer.MAX_VALUE) {
c.setBaseToughness(variant.getIntToughness());
c.setBaseToughnessString(variant.getToughness());
}
if (variant.getAttractionLights() != null)
c.setAttractionLights(variant.getAttractionLights());
if (variant.getAbilities() != null)
CardFactoryUtil.addAbilityFactoryAbilities(c, variant.getAbilities());
}
public static void copySpellAbility(SpellAbility from, SpellAbility to, final Card host, final Player p, final boolean lki, final boolean keepTextChanges) {

View File

@@ -251,7 +251,7 @@ public class CardDetailPanel extends SkinnedPanel {
updateBorder(state, mayView);
}
powerToughnessLabel.setText(CardDetailUtil.formatPrimaryCharacteristic(state, mayView));
powerToughnessLabel.setText(FSkin.encodeSymbols(CardDetailUtil.formatPrimaryCharacteristic(state, mayView), false));
idLabel.setText(mayView ? CardDetailUtil.formatCardId(state) : "");

View File

@@ -0,0 +1,69 @@
package forge.itemmanager.views;
import forge.toolbox.CardFaceSymbols;
import org.apache.commons.lang3.StringUtils;
import javax.swing.*;
import java.awt.*;
import java.util.Set;
public class AttractionLightRenderer extends ItemCellRenderer {
private static final int elementWidth = 13;
private static final int elementGap = 2;
private static final int padding = 2;
//Can't check for type params via instanceof, but it doesn't really matter since all we're using is .contains()
private Set<?> lights;
/*
* (non-Javadoc)
*
* @see
* javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent
* (javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
*/
@Override
public final Component getTableCellRendererComponent(final JTable table, final Object value,
final boolean isSelected, final boolean hasFocus, final int row, final int column) {
if (value instanceof Set) {
this.lights = (Set<?>) value;
this.setToolTipText(StringUtils.join(this.lights, ", "));
}
else {
this.lights = null;
this.setToolTipText(null);
}
return super.getTableCellRendererComponent(table, "", isSelected, hasFocus, row, column);
}
/*
* (non-Javadoc)
*
* @see javax.swing.JComponent#paint(java.awt.Graphics)
*/
@Override
public final void paint(final Graphics g) {
super.paint(g);
if(this.lights == null)
return;
final int cellWidth = this.getWidth();
int x = padding;
int y = padding + 1;
final int cntGlyphs = 6;
final int offsetIfNoSpace = (cellWidth - padding - elementWidth) / (cntGlyphs - 1);
final int dx = Math.min(elementWidth + elementGap, offsetIfNoSpace);
CardFaceSymbols.drawManaSymbol(lights.contains(1) ? "AL1ON" : "AL1OFF", g, x, y);
CardFaceSymbols.drawManaSymbol(lights.contains(2) ? "AL2ON" : "AL2OFF", g, x + (dx), y);
CardFaceSymbols.drawManaSymbol(lights.contains(3) ? "AL3ON" : "AL3OFF", g, x + (dx * 2), y);
CardFaceSymbols.drawManaSymbol(lights.contains(4) ? "AL4ON" : "AL4OFF", g, x + (dx * 3), y);
CardFaceSymbols.drawManaSymbol(lights.contains(5) ? "AL5ON" : "AL5OFF", g, x + (dx * 4), y);
CardFaceSymbols.drawManaSymbol(lights.contains(6) ? "AL6ON" : "AL6OFF", g, x + (dx * 5), y);
}
}

View File

@@ -50,6 +50,8 @@ public class ItemCellRenderer extends DefaultTableCellRenderer {
return new SetCodeRenderer();
case COST:
return new ManaCostRenderer();
case ATTRACTION_LIGHTS:
return new AttractionLightRenderer();
case DECK_COLOR:
return new ColorSetRenderer();
case FAVORITE:

View File

@@ -1120,7 +1120,7 @@ public class FSkin {
private static String preferredName;
private static BufferedImage bimDefaultSprite, bimFavIcon, bimPreferredSprite, bimFoils, bimQuestDraftDeck, bimOldFoils,
bimDefaultAvatars, bimPreferredAvatars, bimTrophies, bimAbilities, bimManaIcons, bimPhyrexian, bimColorlessHybrid, bimDefaultSleeve,
bimDefaultSleeve2, bimDefaultDeckbox, bimPrefferedSetLogo, bimDefaultWatermark, bimDefaultDraftRank;
bimDefaultSleeve2, bimDefaultDeckbox, bimPrefferedSetLogo, bimDefaultWatermark, bimDefaultDraftRank, bimAttractionLights;
private static int x0, y0, w0, h0, newW, newH, preferredW, preferredH;
private static int defaultFontSize = 12;
private static boolean loaded = false;
@@ -1239,7 +1239,7 @@ public class FSkin {
}
final Localizer localizer = Localizer.getInstance();
FView.SINGLETON_INSTANCE.setSplashProgessBarMessage(localizer.getMessage("splash.loading.processingimagesprites") + ": ", 12);
FView.SINGLETON_INSTANCE.setSplashProgessBarMessage(localizer.getMessage("splash.loading.processingimagesprites") + ": ", 20);
// Grab and test various sprite files.
final String defaultDir = ForgeConstants.DEFAULT_SKINS_DIR;
@@ -1263,6 +1263,7 @@ public class FSkin {
final File f18 = new File(defaultDir + ForgeConstants.SPRITE_PHYREXIAN_FILE);
final File f19 = new File(defaultDir + ForgeConstants.SPRITE_COLORLESS_HYBRID_FILE);
final File f20 = new File(defaultDir + ForgeConstants.SPRITE_DRAFTRANKS_FILE);
final File f21 = new File(defaultDir + ForgeConstants.SPRITE_ATTRACTION_LIGHTS_FILE);
try {
int p = 0;
@@ -1276,6 +1277,8 @@ public class FSkin {
FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
bimColorlessHybrid = ImageIO.read(f19);
FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
bimAttractionLights = ImageIO.read(f21);
FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
bimPreferredSprite = ImageIO.read(f2);
FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
bimFoils = ImageIO.read(f3);
@@ -1363,6 +1366,9 @@ public class FSkin {
case COLORLESS_HYBRID:
setImage(prop, bimColorlessHybrid);
break;
case ATTRACTION_LIGHTS:
setImage(prop, bimAttractionLights);
break;
case DECKBOX:
setImage(prop, bimDefaultDeckbox);
break;
@@ -1407,6 +1413,7 @@ public class FSkin {
bimPhyrexian.flush();
bimColorlessHybrid.flush();
bimManaIcons.flush();
bimAttractionLights.flush();
if (bimPreferredAvatars != null) { bimPreferredAvatars.flush(); }
@@ -1428,6 +1435,7 @@ public class FSkin {
bimPhyrexian = null;
bimColorlessHybrid = null;
bimManaIcons = null;
bimAttractionLights = null;
//establish encoding symbols
final File dir = new File(ForgeConstants.CACHE_SYMBOLS_DIR);

View File

@@ -18,6 +18,7 @@
package forge.card;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import forge.Forge;
@@ -194,6 +195,16 @@ public class CardFaceSymbols {
}
}
public static void drawAttractionLights(Graphics g, Set<Integer> lights, float x, float y, final float imageSize, boolean vertical) {
for(int i = 1; i <= 6; i++) {
drawSymbol("AL" + i + (lights.contains(i) ? "ON" : "OFF"), g, x, y, imageSize, imageSize);
if (!vertical)
x += imageSize;
else
y += imageSize;
}
}
public static void drawOther(final Graphics g, String s, float x, final float y, final float w, final float h, boolean rotate) {
if (s.length() == 0) {
return;

View File

@@ -11,6 +11,7 @@ import forge.ImageKeys;
import forge.assets.*;
import forge.item.PaperCard;
import forge.util.ImageUtil;
import forge.util.TextBounds;
import org.apache.commons.lang3.StringUtils;
import com.badlogic.gdx.graphics.Color;
@@ -1173,14 +1174,15 @@ public class CardImageRenderer {
return;
}
TextBounds bounds = cardTextRenderer.getBounds(ptText, PT_FONT);
float padding = PT_FONT.getCapHeight() / 2;
float boxWidth = Math.min(PT_FONT.getBounds(ptText).width + 2 * padding,
float boxWidth = Math.min(bounds.width + 2 * padding,
w - idWidth - padding); //prevent box overlapping ID
x += w - boxWidth;
w = boxWidth;
fillColorBackground(g, colors, x, y, w, h);
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
g.drawText(ptText, PT_FONT, Color.BLACK, x, y, w, h, false, Align.center, true);
cardTextRenderer.drawText(g, ptText, PT_FONT, Color.BLACK, x, y, w, h, y, h, false, Align.center, true);
}
}

View File

@@ -497,6 +497,7 @@ public class CardRenderer {
//render card name and mana cost on first line
float manaCostWidth = 0;
ManaCost mainManaCost = cardCurrentState.getManaCost();
if (!mainManaCost.isNoCost() || (card.isSplitCard() && !card.getLeftSplitState().getManaCost().isNoCost())) {
if (card.isSplitCard()) {
//handle rendering both parts of split card
mainManaCost = card.getLeftSplitState().getManaCost();
@@ -509,6 +510,12 @@ public class CardRenderer {
}
manaCostWidth += CardFaceSymbols.getWidth(mainManaCost, MANA_SYMBOL_SIZE);
CardFaceSymbols.drawManaCost(g, mainManaCost, x + w - manaCostWidth, y, MANA_SYMBOL_SIZE);
}
else if(cardCurrentState.isAttraction()) {
//For attractions, draw their lights instead of a mana cost.
float lightWidth = (6 * MANA_SYMBOL_SIZE) + MANA_COST_PADDING;
CardFaceSymbols.drawAttractionLights(g, cardCurrentState.getAttractionLights(), x + w - lightWidth, y, MANA_SYMBOL_SIZE, false);
}
x += cardArtWidth;
String name = CardTranslation.getTranslatedName(card.getCurrentState().getName());
@@ -544,9 +551,6 @@ public class CardRenderer {
type += String.format(" [%s / %s]", power, toughness);
} else if (cardCurrentState.isBattle()) {
type += " (" + cardCurrentState.getDefense() + ")";
} else if (cardCurrentState.isAttraction()) {
//TODO: Probably shouldn't be non-localized text here? Not sure what to do if someone makes an attraction with no lights...
type += " (" + (cardCurrentState.getAttractionLights().isEmpty() ? "No Lights" : StringUtils.join(cardCurrentState.getAttractionLights(), ", ")) + ")";
}
g.drawText(type, typeFont, foreColor, x, y, availableTypeWidth, lineHeight, false, Align.left, true);
}

View File

@@ -1,4 +1,5 @@
Name:Backup Plan
ManaCost:no cost
Types:Conspiracy
Text:Draw an additional hand of seven cards as the game begins. Before taking mulligans, shuffle all but one of your hands into your library.
Oracle:(Start the game with this conspiracy face up in the command zone.)\nDraw an additional hand of seven cards as the game begins. Before taking mulligans, shuffle all but one of your hands into your library.

View File

@@ -1,4 +1,5 @@
Name:Paliano, the High City
ManaCost:no cost
Types:Legendary Land
Draft:Reveal CARDNAME as you draft it.
Draft:As you draft CARDNAME, the player to your right chooses a color, you choose another color, then the player to your left chooses a third color.

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

View File

@@ -217,19 +217,22 @@ public class CardDetailUtil {
}
if (card.isAttraction()) {
ptText.append(Localizer.getInstance().getMessage("lblLights")).append(": (");
Set<Integer> lights = card.getAttractionLights();
//TODO: It'd be really nice if the actual lights were drawn as symbols here. Need to look into that...
if (lights == null || lights.isEmpty())
ptText.append(Localizer.getInstance().getMessage("lblNone"));
else
ptText.append(StringUtils.join(lights, ", "));
ptText.append(")");
ptText.append(Localizer.getInstance().getMessage("lblLights")).append(": ");
ptText.append(formatAttractionLights(card.getAttractionLights()));
}
return ptText.toString();
}
public static String formatAttractionLights(Set<Integer> lights) {
return (lights.contains(1) ? "{AL1ON} " : "{AL1OFF} ") +
(lights.contains(2) ? "{AL2ON} " : "{AL2OFF} ") +
(lights.contains(3) ? "{AL3ON} " : "{AL3OFF} ") +
(lights.contains(4) ? "{AL4ON} " : "{AL4OFF} ") +
(lights.contains(5) ? "{AL5ON} " : "{AL5OFF} ") +
(lights.contains(6) ? "{AL6ON}" : "{AL6OFF}");
}
public static String formatCardId(final CardStateView card) {
final String id = card.getDisplayId();
return id.isEmpty() ? id : "[" + id + "]";

View File

@@ -198,6 +198,10 @@ public enum ColumnDef {
return toCMC(from.getKey());
}
}),
ATTRACTION_LIGHTS("lblLights", "lblLights", 94, true, SortState.NONE,
from -> toAttractionLightSort(from.getKey()),
from -> toAttractionLights(from.getKey())
),
/**
* The rarity column.
*/
@@ -615,10 +619,11 @@ public enum ColumnDef {
private static Integer toPower(final InventoryItem i) {
int result = Integer.MAX_VALUE;
if (i instanceof PaperCard) {
result = ((IPaperCard) i).getRules().getIntPower();
ICardFace face = ((IPaperCard) i).getMainFace();
result = face.getIntPower();
if (result == Integer.MAX_VALUE) {
if (((IPaperCard) i).getRules().getType().isPlaneswalker()) {
String loy = ((IPaperCard) i).getRules().getInitialLoyalty();
if (face.getType().isPlaneswalker()) {
String loy = face.getInitialLoyalty();
result = StringUtils.isNumeric(loy) ? Integer.parseInt(loy) : 0;
}
}
@@ -627,7 +632,7 @@ public enum ColumnDef {
}
private static Integer toToughness(final InventoryItem i) {
return i instanceof PaperCard ? ((IPaperCard) i).getRules().getIntToughness() : Integer.MAX_VALUE;
return i instanceof PaperCard ? ((IPaperCard) i).getMainFace().getIntToughness() : Integer.MAX_VALUE;
}
private static Integer toCMC(final InventoryItem i) {
@@ -703,7 +708,7 @@ public enum ColumnDef {
* @return Part of a sortable numeric string.
*/
private static String toArtifactsWithColorlessCostsLast(final InventoryItem i) {
forge.card.mana.ManaCost manaCost = ((IPaperCard) i).getRules().getManaCost();
ManaCost manaCost = ((IPaperCard) i).getRules().getManaCost();
return !(((IPaperCard) i).getRules().getType().isArtifact() && (toColor(i).isColorless() ||
//If it isn't colorless, see if it can be paid with only white, only blue, only black.
@@ -766,7 +771,7 @@ public enum ColumnDef {
* @return Part of a sortable numeric string.
*/
private static String toGoldFirst(final InventoryItem i) {
forge.card.mana.ManaCost manaCost = ((IPaperCard) i).getRules().getManaCost();
ManaCost manaCost = ((IPaperCard) i).getRules().getManaCost();
return !(manaCost.canBePaidWithAvailable(MagicColor.WHITE) | manaCost.canBePaidWithAvailable(MagicColor.BLUE) |
manaCost.canBePaidWithAvailable(MagicColor.BLACK) | manaCost.canBePaidWithAvailable(MagicColor.RED) |
@@ -784,9 +789,8 @@ public enum ColumnDef {
//Split card sorting is probably as complex as sorting gets.
//This method serves as an entry point only, separating the two card parts for convenience.
private static String toSplitCardSort(final InventoryItem i) {
CardRules rules = ((IPaperCard) i).getRules();
forge.card.ICardFace mainPart = rules.getMainPart();
forge.card.ICardFace otherPart = rules.getOtherPart();
ICardFace mainPart = ((IPaperCard) i).getMainFace();
ICardFace otherPart = ((IPaperCard) i).getOtherFace();
return toSplitSort(mainPart, otherPart);
}
@@ -924,4 +928,20 @@ public enum ColumnDef {
)
);
}
private static Set<Integer> toAttractionLights(final InventoryItem i) {
return i instanceof PaperCard ? ((PaperCard) i).getMainFace().getAttractionLights() : null;
}
private static String toAttractionLightSort(final InventoryItem i) {
if(!(i instanceof PaperCard))
return "";
Set<Integer> lights = ((PaperCard) i).getRules().getAttractionLights();
return (lights.contains(1) ? "0" : "1") +
(lights.contains(2) ? "0" : "1") +
(lights.contains(3) ? "0" : "1") +
(lights.contains(4) ? "0" : "1") +
(lights.contains(5) ? "0" : "1") +
(lights.contains(6) ? "0" : "1");
}
}

View File

@@ -148,6 +148,7 @@ public final class SColumnUtil {
List<ColumnDef> colDefs = new ArrayList<>();
colDefs.add(ColumnDef.FAVORITE);
colDefs.add(ColumnDef.NAME);
colDefs.add(ColumnDef.ATTRACTION_LIGHTS);
colDefs.add(ColumnDef.RARITY);
colDefs.add(ColumnDef.SET);
colDefs.add(ColumnDef.COLLECTOR_ORDER);

View File

@@ -126,6 +126,7 @@ public final class ForgeConstants {
public static final String SPRITE_MANAICONS_FILE = "sprite_manaicons.png";
public static final String SPRITE_PHYREXIAN_FILE = "sprite_phyrexian.png";
public static final String SPRITE_COLORLESS_HYBRID_FILE = "sprite_hybrid_colorless.png";
public static final String SPRITE_ATTRACTION_LIGHTS_FILE = "sprite_attraction_lights.png";
public static final String SPRITE_CURSOR_FILE = "sprite_cursor.png";
public static final String SPRITE_AVATARS_FILE = "sprite_avatars.png";
public static final String SPRITE_CRACKS_FILE = "sprite_cracks.png";
@@ -137,6 +138,7 @@ public final class ForgeConstants {
public static final String SPRITE_SETLOGO_FILE = "sprite_setlogo.png";
public static final String SPRITE_WATERMARK_FILE = "sprite_watermark.png";
public static final String SPRITE_DRAFTRANKS_FILE = "sprite_draftranks.png";
public static final String FONT_FILE = "font1.ttf";
public static final String SPLASH_BG_FILE = "bg_splash.png";
public static final String MATCH_BG_FILE = "bg_match.jpg";

View File

@@ -177,6 +177,20 @@ public enum FSkinProp {
IMG_CMC_MID_HIGH (new int[] {2, 166, 160, 160}, PropType.MANAICONS),
IMG_CMC_HIGH (new int[] {2, 248, 160, 160}, PropType.MANAICONS),
//attraction lights
IMG_ATTR_1_ON (new int[] {0, 0, 200, 200}, PropType.ATTRACTION_LIGHTS),
IMG_ATTR_2_ON (new int[] {210, 0, 200, 200}, PropType.ATTRACTION_LIGHTS),
IMG_ATTR_3_ON (new int[] {420, 0, 200, 200}, PropType.ATTRACTION_LIGHTS),
IMG_ATTR_4_ON (new int[] {630, 0, 200, 200}, PropType.ATTRACTION_LIGHTS),
IMG_ATTR_5_ON (new int[] {840, 0, 200, 200}, PropType.ATTRACTION_LIGHTS),
IMG_ATTR_6_ON (new int[] {1050, 0, 200, 200}, PropType.ATTRACTION_LIGHTS),
IMG_ATTR_1_OFF (new int[] {0, 210, 200, 200}, PropType.ATTRACTION_LIGHTS),
IMG_ATTR_2_OFF (new int[] {210, 210, 200, 200}, PropType.ATTRACTION_LIGHTS),
IMG_ATTR_3_OFF (new int[] {420, 210, 200, 200}, PropType.ATTRACTION_LIGHTS),
IMG_ATTR_4_OFF (new int[] {630, 210, 200, 200}, PropType.ATTRACTION_LIGHTS),
IMG_ATTR_5_OFF (new int[] {840, 210, 200, 200}, PropType.ATTRACTION_LIGHTS),
IMG_ATTR_6_OFF (new int[] {1050, 210, 200, 200}, PropType.ATTRACTION_LIGHTS),
//PAWPRINT
IMG_PAWPRINT (new int[] {2, 902, 80, 80}, PropType.MANAICONS),
@@ -660,6 +674,20 @@ public enum FSkinProp {
MANA_IMG.put("Q", FSkinProp.IMG_UNTAP);
MANA_IMG.put("T", FSkinProp.IMG_TAP);
MANA_IMG.put("P", FSkinProp.IMG_PAWPRINT);
//Attraction lights. Not really mana icons but they're loaded into the card symbols in all the same places.
MANA_IMG.put("AL1ON", FSkinProp.IMG_ATTR_1_ON);
MANA_IMG.put("AL2ON", FSkinProp.IMG_ATTR_2_ON);
MANA_IMG.put("AL3ON", FSkinProp.IMG_ATTR_3_ON);
MANA_IMG.put("AL4ON", FSkinProp.IMG_ATTR_4_ON);
MANA_IMG.put("AL5ON", FSkinProp.IMG_ATTR_5_ON);
MANA_IMG.put("AL6ON", FSkinProp.IMG_ATTR_6_ON);
MANA_IMG.put("AL1OFF", FSkinProp.IMG_ATTR_1_OFF);
MANA_IMG.put("AL2OFF", FSkinProp.IMG_ATTR_2_OFF);
MANA_IMG.put("AL3OFF", FSkinProp.IMG_ATTR_3_OFF);
MANA_IMG.put("AL4OFF", FSkinProp.IMG_ATTR_4_OFF);
MANA_IMG.put("AL5OFF", FSkinProp.IMG_ATTR_5_OFF);
MANA_IMG.put("AL6OFF", FSkinProp.IMG_ATTR_6_OFF);
}
public enum PropType {
@@ -678,6 +706,7 @@ public enum FSkinProp {
MANAICONS(ForgeConstants.SPRITE_MANAICONS_FILE),
PHYREXIAN(ForgeConstants.SPRITE_PHYREXIAN_FILE),
COLORLESS_HYBRID(ForgeConstants.SPRITE_COLORLESS_HYBRID_FILE),
ATTRACTION_LIGHTS(ForgeConstants.SPRITE_ATTRACTION_LIGHTS_FILE),
PLANAR_CONQUEST(ForgeConstants.SPRITE_PLANAR_CONQUEST_FILE),
ADVENTURE(ForgeConstants.SPRITE_ADVENTURE_FILE),
DECKBOX(ForgeConstants.SPRITE_DECKBOX_FILE),