mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 10:18:01 +00:00
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:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) : "");
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,18 +497,25 @@ public class CardRenderer {
|
||||
//render card name and mana cost on first line
|
||||
float manaCostWidth = 0;
|
||||
ManaCost mainManaCost = cardCurrentState.getManaCost();
|
||||
if (card.isSplitCard()) {
|
||||
//handle rendering both parts of split card
|
||||
mainManaCost = card.getLeftSplitState().getManaCost();
|
||||
ManaCost otherManaCost = card.getAlternateState().getManaCost();
|
||||
manaCostWidth = CardFaceSymbols.getWidth(otherManaCost, MANA_SYMBOL_SIZE) + MANA_COST_PADDING;
|
||||
CardFaceSymbols.drawManaCost(g, otherManaCost, x + w - manaCostWidth + MANA_COST_PADDING, y, MANA_SYMBOL_SIZE);
|
||||
//draw "//" between two parts of mana cost
|
||||
manaCostWidth += font.getBounds("//").width + MANA_COST_PADDING;
|
||||
g.drawText("//", font, foreColor, x + w - manaCostWidth + MANA_COST_PADDING, y, w, MANA_SYMBOL_SIZE, false, Align.left, true);
|
||||
if (!mainManaCost.isNoCost() || (card.isSplitCard() && !card.getLeftSplitState().getManaCost().isNoCost())) {
|
||||
if (card.isSplitCard()) {
|
||||
//handle rendering both parts of split card
|
||||
mainManaCost = card.getLeftSplitState().getManaCost();
|
||||
ManaCost otherManaCost = card.getAlternateState().getManaCost();
|
||||
manaCostWidth = CardFaceSymbols.getWidth(otherManaCost, MANA_SYMBOL_SIZE) + MANA_COST_PADDING;
|
||||
CardFaceSymbols.drawManaCost(g, otherManaCost, x + w - manaCostWidth + MANA_COST_PADDING, y, MANA_SYMBOL_SIZE);
|
||||
//draw "//" between two parts of mana cost
|
||||
manaCostWidth += font.getBounds("//").width + MANA_COST_PADDING;
|
||||
g.drawText("//", font, foreColor, x + w - manaCostWidth + MANA_COST_PADDING, y, w, MANA_SYMBOL_SIZE, false, Align.left, true);
|
||||
}
|
||||
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);
|
||||
}
|
||||
manaCostWidth += CardFaceSymbols.getWidth(mainManaCost, MANA_SYMBOL_SIZE);
|
||||
CardFaceSymbols.drawManaCost(g, mainManaCost, x + w - manaCostWidth, y, MANA_SYMBOL_SIZE);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
BIN
forge-gui/res/skins/default/sprite_attraction_lights.png
Normal file
BIN
forge-gui/res/skins/default/sprite_attraction_lights.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 128 KiB |
@@ -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 + "]";
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -113,30 +113,32 @@ public final class ForgeConstants {
|
||||
public static final String COMMON_FONTS_DIR = RES_DIR + "fonts" + PATH_SEPARATOR;
|
||||
public static final String DEFAULT_SKINS_DIR = BASE_SKINS_DIR + "default" + PATH_SEPARATOR;
|
||||
//don't associate these skin files with a directory since skin directory will be determined later
|
||||
public static final String SPRITE_ICONS_FILE = "sprite_icons.png";
|
||||
public static final String SPRITE_FOILS_FILE = "sprite_foils.png";
|
||||
public static final String SPRITE_OLD_FOILS_FILE = "sprite_old_foils.png";
|
||||
public static final String SPRITE_TROPHIES_FILE = "sprite_trophies.png";
|
||||
public static final String SPRITE_ABILITY_FILE = "sprite_ability.png";
|
||||
public static final String SPRITE_BORDER_FILE = "sprite_border.png";
|
||||
public static final String SPRITE_ADV_BUTTONS_FILE = "sprite_adv_buttons.png";
|
||||
public static final String SPRITE_BUTTONS_FILE = "sprite_buttons.png";
|
||||
public static final String SPRITE_DECKBOX_FILE = "sprite_deckbox.png";
|
||||
public static final String SPRITE_START_FILE = "sprite_start.png";
|
||||
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_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";
|
||||
public static final String SPRITE_SLEEVES_FILE = "sprite_sleeves.png";
|
||||
public static final String SPRITE_SLEEVES2_FILE = "sprite_sleeves2.png";
|
||||
public static final String SPRITE_FAVICONS_FILE = "sprite_favicons.png";
|
||||
public static final String SPRITE_PLANAR_CONQUEST_FILE = "sprite_planar_conquest.png";
|
||||
public static final String SPRITE_ADVENTURE_FILE = "sprite_adventure.png";
|
||||
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 SPRITE_ICONS_FILE = "sprite_icons.png";
|
||||
public static final String SPRITE_FOILS_FILE = "sprite_foils.png";
|
||||
public static final String SPRITE_OLD_FOILS_FILE = "sprite_old_foils.png";
|
||||
public static final String SPRITE_TROPHIES_FILE = "sprite_trophies.png";
|
||||
public static final String SPRITE_ABILITY_FILE = "sprite_ability.png";
|
||||
public static final String SPRITE_BORDER_FILE = "sprite_border.png";
|
||||
public static final String SPRITE_ADV_BUTTONS_FILE = "sprite_adv_buttons.png";
|
||||
public static final String SPRITE_BUTTONS_FILE = "sprite_buttons.png";
|
||||
public static final String SPRITE_DECKBOX_FILE = "sprite_deckbox.png";
|
||||
public static final String SPRITE_START_FILE = "sprite_start.png";
|
||||
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";
|
||||
public static final String SPRITE_SLEEVES_FILE = "sprite_sleeves.png";
|
||||
public static final String SPRITE_SLEEVES2_FILE = "sprite_sleeves2.png";
|
||||
public static final String SPRITE_FAVICONS_FILE = "sprite_favicons.png";
|
||||
public static final String SPRITE_PLANAR_CONQUEST_FILE = "sprite_planar_conquest.png";
|
||||
public static final String SPRITE_ADVENTURE_FILE = "sprite_adventure.png";
|
||||
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";
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user