mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-12 08:48:39 +00:00
Compare commits
32 Commits
paperCardI
...
forge-2.0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08719b1596 | ||
|
|
840f3ea96c | ||
|
|
51929434be | ||
|
|
3ec480afa4 | ||
|
|
3d19e9e444 | ||
|
|
6d987791f7 | ||
|
|
7b7da00c22 | ||
|
|
34791bd892 | ||
|
|
e6bcd1be72 | ||
|
|
4cac354983 | ||
|
|
042f7f77a9 | ||
|
|
5fbb1dd0cd | ||
|
|
bb14dfc00e | ||
|
|
f83cc4ccfa | ||
|
|
d0d6835a5d | ||
|
|
104bc8fc55 | ||
|
|
057dd867a8 | ||
|
|
9eed8f5095 | ||
|
|
1f62be9773 | ||
|
|
7a46f92059 | ||
|
|
cfa79b9676 | ||
|
|
c0a63fa15b | ||
|
|
c61537ae16 | ||
|
|
3871095b92 | ||
|
|
dee846da49 | ||
|
|
2477553d13 | ||
|
|
c9df7d7f8e | ||
|
|
53cb093f9e | ||
|
|
28e86970dc | ||
|
|
f847fc1669 | ||
|
|
f3df55177a | ||
|
|
be6f345127 |
40
.github/workflows/maven-publish.yml
vendored
40
.github/workflows/maven-publish.yml
vendored
@@ -81,7 +81,7 @@ jobs:
|
|||||||
export _JAVA_OPTIONS="-Xmx2g"
|
export _JAVA_OPTIONS="-Xmx2g"
|
||||||
d=$(date +%m.%d)
|
d=$(date +%m.%d)
|
||||||
# build only desktop and only try to move desktop files
|
# build only desktop and only try to move desktop files
|
||||||
mvn -U -B clean -P windows-linux install -e -T 1C release:clean release:prepare release:perform -DskipTests
|
mvn -U -B clean -P windows-linux install -DskipTests -Dskip.flatten=true -e -T 1C release:clean release:prepare release:perform
|
||||||
mkdir izpack
|
mkdir izpack
|
||||||
# move bz2 and jar from work dir to izpack dir
|
# move bz2 and jar from work dir to izpack dir
|
||||||
mv /home/runner/work/forge/forge/forge-installer/*/*.{bz2,jar} izpack/
|
mv /home/runner/work/forge/forge/forge-installer/*/*.{bz2,jar} izpack/
|
||||||
@@ -128,6 +128,44 @@ jobs:
|
|||||||
removeArtifacts: true
|
removeArtifacts: true
|
||||||
makeLatest: true
|
makeLatest: true
|
||||||
|
|
||||||
|
- name: 🔧 Install XML tools
|
||||||
|
run: sudo apt-get install -y libxml2-utils
|
||||||
|
|
||||||
|
- name: 🔼 Bump versionCode in root POM
|
||||||
|
id: bump_version
|
||||||
|
run: |
|
||||||
|
cd /home/runner/work/forge/forge/
|
||||||
|
|
||||||
|
current_version=$(xmllint --xpath "//*[local-name()='versionCode']/text()" pom.xml)
|
||||||
|
echo "Current versionCode: $current_version"
|
||||||
|
|
||||||
|
IFS='.' read -r major minor patch <<< "${current_version}"
|
||||||
|
new_patch=$(printf "%02d" $((10#$patch + 1)))
|
||||||
|
new_version="${major}.${minor}.${new_patch}"
|
||||||
|
|
||||||
|
sed -i -E "s|<versionCode>.*</versionCode>|<versionCode>${new_version}</versionCode>|" pom.xml
|
||||||
|
|
||||||
|
echo "version_code=${new_version}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: ♻️ Restore {revision} in child POMs
|
||||||
|
run: |
|
||||||
|
find . -name pom.xml ! -path "./pom.xml" | while read -r pom; do
|
||||||
|
sed -i -E 's|<version>2\.0+\.[0-9]+(-SNAPSHOT)?</version>|<version>${revision}</version>|' "$pom"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: 💾 Commit restored {revision}
|
||||||
|
run: |
|
||||||
|
# Add only pom.xml files
|
||||||
|
find . -name pom.xml -exec git add {} \;
|
||||||
|
|
||||||
|
# Commit if there are changes
|
||||||
|
if git diff --cached --quiet; then
|
||||||
|
echo "No pom.xml changes to commit."
|
||||||
|
else
|
||||||
|
git commit -m "Restore POM files for preparation of next release" || echo "No changes to commit"
|
||||||
|
git push
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Send failure notification to Discord
|
- name: Send failure notification to Discord
|
||||||
if: failure() # This step runs only if the job fails
|
if: failure() # This step runs only if the job fails
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>${revision}</version>
|
<version>2.0.04</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>${revision}</version>
|
<version>2.0.04</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-ai</artifactId>
|
<artifactId>forge-ai</artifactId>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>${revision}</version>
|
<version>2.0.04</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-core</artifactId>
|
<artifactId>forge-core</artifactId>
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ public final class ImageKeys {
|
|||||||
public static final String RADIATION_IMAGE = "radiation";
|
public static final String RADIATION_IMAGE = "radiation";
|
||||||
|
|
||||||
public static final String BACKFACE_POSTFIX = "$alt";
|
public static final String BACKFACE_POSTFIX = "$alt";
|
||||||
|
public static final String SPECFACE_W = "$wspec";
|
||||||
|
public static final String SPECFACE_U = "$uspec";
|
||||||
|
public static final String SPECFACE_B = "$bspec";
|
||||||
|
public static final String SPECFACE_R = "$rspec";
|
||||||
|
public static final String SPECFACE_G = "$gspec";
|
||||||
|
|
||||||
private static String CACHE_CARD_PICS_DIR, CACHE_TOKEN_PICS_DIR, CACHE_ICON_PICS_DIR, CACHE_BOOSTER_PICS_DIR,
|
private static String CACHE_CARD_PICS_DIR, CACHE_TOKEN_PICS_DIR, CACHE_ICON_PICS_DIR, CACHE_BOOSTER_PICS_DIR,
|
||||||
CACHE_FATPACK_PICS_DIR, CACHE_BOOSTERBOX_PICS_DIR, CACHE_PRECON_PICS_DIR, CACHE_TOURNAMENTPACK_PICS_DIR;
|
CACHE_FATPACK_PICS_DIR, CACHE_BOOSTERBOX_PICS_DIR, CACHE_PRECON_PICS_DIR, CACHE_TOURNAMENTPACK_PICS_DIR;
|
||||||
@@ -92,28 +97,13 @@ public final class ImageKeys {
|
|||||||
return cachedCards.get(key);
|
return cachedCards.get(key);
|
||||||
}
|
}
|
||||||
public static File getImageFile(String key) {
|
public static File getImageFile(String key) {
|
||||||
return getImageFile(key, false);
|
|
||||||
}
|
|
||||||
public static File getImageFile(String key, boolean artCrop) {
|
|
||||||
if (StringUtils.isEmpty(key))
|
if (StringUtils.isEmpty(key))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
final String dir;
|
final String dir;
|
||||||
final String filename;
|
final String filename;
|
||||||
String[] tempdata = null;
|
String[] tempdata = null;
|
||||||
if (key.startsWith(ImageKeys.CARD_PREFIX)) {
|
if (key.startsWith(ImageKeys.TOKEN_PREFIX)) {
|
||||||
tempdata = key.substring(ImageKeys.CARD_PREFIX.length()).split("\\|");
|
|
||||||
String tokenname = tempdata[0];
|
|
||||||
if (tempdata.length > 1) {
|
|
||||||
tokenname += "_" + tempdata[1];
|
|
||||||
}
|
|
||||||
if (tempdata.length > 2) {
|
|
||||||
tokenname += "_" + tempdata[2];
|
|
||||||
}
|
|
||||||
filename = tokenname ;
|
|
||||||
|
|
||||||
dir = CACHE_CARD_PICS_DIR;
|
|
||||||
} else if (key.startsWith(ImageKeys.TOKEN_PREFIX)) {
|
|
||||||
tempdata = key.substring(ImageKeys.TOKEN_PREFIX.length()).split("\\|");
|
tempdata = key.substring(ImageKeys.TOKEN_PREFIX.length()).split("\\|");
|
||||||
String tokenname = tempdata[0];
|
String tokenname = tempdata[0];
|
||||||
if (tempdata.length > 1) {
|
if (tempdata.length > 1) {
|
||||||
@@ -164,31 +154,7 @@ public final class ImageKeys {
|
|||||||
cachedCards.put(filename, file);
|
cachedCards.put(filename, file);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
if (tempdata != null && dir.equals(CACHE_CARD_PICS_DIR)) {
|
if (dir.equals(CACHE_TOKEN_PICS_DIR)) {
|
||||||
String setlessFilename = tempdata[0] + (artCrop ? ".artcrop" : ".fullborder");
|
|
||||||
String setCode = tempdata.length > 1 ? tempdata[1] : "";
|
|
||||||
String collectorNumber = tempdata.length > 2 ? tempdata[2] : "";
|
|
||||||
if (!setCode.isEmpty()) {
|
|
||||||
if (!collectorNumber.isEmpty()) {
|
|
||||||
file = findFile(dir, setCode + "/" + collectorNumber + "_" + setlessFilename);
|
|
||||||
if (file != null) {
|
|
||||||
cachedCards.put(filename, file);
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file = findFile(dir, setCode + "/" + setlessFilename);
|
|
||||||
if (file != null) {
|
|
||||||
cachedCards.put(filename, file);
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file = findFile(dir, setlessFilename);
|
|
||||||
if (file != null) {
|
|
||||||
cachedCards.put(filename, file);
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tempdata != null && dir.equals(CACHE_TOKEN_PICS_DIR)) {
|
|
||||||
String setlessFilename = tempdata[0];
|
String setlessFilename = tempdata[0];
|
||||||
String setCode = tempdata.length > 1 ? tempdata[1] : "";
|
String setCode = tempdata.length > 1 ? tempdata[1] : "";
|
||||||
String collectorNumber = tempdata.length > 2 ? tempdata[2] : "";
|
String collectorNumber = tempdata.length > 2 ? tempdata[2] : "";
|
||||||
|
|||||||
@@ -433,17 +433,6 @@ public final class CardEdition implements Comparable<CardEdition> {
|
|||||||
|
|
||||||
public Multimap<String, EditionEntry> getTokens() { return tokenMap; }
|
public Multimap<String, EditionEntry> getTokens() { return tokenMap; }
|
||||||
|
|
||||||
public EditionEntry getTokenFromCollectorNumber(String collectorNumber) {
|
|
||||||
if(collectorNumber == null || collectorNumber.isEmpty())
|
|
||||||
return null;
|
|
||||||
for(EditionEntry c : this.tokenMap.values()) {
|
|
||||||
//Could build a map for this one too if it's used for more than one-offs.
|
|
||||||
if (c.collectorNumber.equalsIgnoreCase(collectorNumber))
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTokenSet(String token) {
|
public String getTokenSet(String token) {
|
||||||
if (tokenMap.containsKey(token)) {
|
if (tokenMap.containsKey(token)) {
|
||||||
return this.getCode();
|
return this.getCode();
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ package forge.card;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
import forge.StaticData;
|
|
||||||
import forge.card.mana.IParserManaCost;
|
import forge.card.mana.IParserManaCost;
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.card.mana.ManaCostShard;
|
import forge.card.mana.ManaCostShard;
|
||||||
@@ -151,10 +149,6 @@ public final class CardRules implements ICardCharacteristics {
|
|||||||
return splitType;
|
return splitType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasBackSide() {
|
|
||||||
return CardSplitType.DUAL_FACED_CARDS.contains(splitType) || splitType == CardSplitType.Flip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ICardFace getMainPart() {
|
public ICardFace getMainPart() {
|
||||||
return mainPart;
|
return mainPart;
|
||||||
}
|
}
|
||||||
@@ -171,32 +165,20 @@ public final class CardRules implements ICardCharacteristics {
|
|||||||
return Iterables.concat(Arrays.asList(mainPart, otherPart), specializedParts.values());
|
return Iterables.concat(Arrays.asList(mainPart, otherPart), specializedParts.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getImageName(CardStateName state) {
|
public ICardFace getWSpecialize() {
|
||||||
if (splitType == CardSplitType.Split) {
|
return specializedParts.get(CardStateName.SpecializeW);
|
||||||
return mainPart.getName() + otherPart.getName();
|
}
|
||||||
} else if (state.equals(splitType.getChangedStateName())) {
|
public ICardFace getUSpecialize() {
|
||||||
if (otherPart != null) {
|
return specializedParts.get(CardStateName.SpecializeU);
|
||||||
return otherPart.getName();
|
}
|
||||||
} else if (this.hasBackSide()) {
|
public ICardFace getBSpecialize() {
|
||||||
if (!getMeldWith().isEmpty()) {
|
return specializedParts.get(CardStateName.SpecializeB);
|
||||||
final CardDb db = StaticData.instance().getCommonCards();
|
}
|
||||||
return db.getRules(getMeldWith()).getOtherPart().getName();
|
public ICardFace getRSpecialize() {
|
||||||
}
|
return specializedParts.get(CardStateName.SpecializeR);
|
||||||
return null;
|
}
|
||||||
}
|
public ICardFace getGSpecialize() {
|
||||||
}
|
return specializedParts.get(CardStateName.SpecializeG);
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case SpecializeW:
|
|
||||||
case SpecializeU:
|
|
||||||
case SpecializeB:
|
|
||||||
case SpecializeR:
|
|
||||||
case SpecializeG:
|
|
||||||
ICardFace face = specializedParts.get(state);
|
|
||||||
return face != null ? face.getName() : null;
|
|
||||||
default:
|
|
||||||
return getName();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import forge.util.CardTranslation;
|
|||||||
import forge.util.ImageUtil;
|
import forge.util.ImageUtil;
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -346,13 +347,34 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
if (pc == null) {
|
if (pc == null) {
|
||||||
pc = StaticData.instance().getVariantCards().getCard(name, edition, artIndex);
|
pc = StaticData.instance().getVariantCards().getCard(name, edition, artIndex);
|
||||||
if (pc == null) {
|
if (pc == null) {
|
||||||
throw new IOException(TextUtil.concatWithSpace("Card", name, "not found"));
|
System.out.println("PaperCard: " + name + " not found with set and index " + edition + ", " + artIndex);
|
||||||
|
pc = readObjectAlternate(name, edition);
|
||||||
|
if (pc == null) {
|
||||||
|
throw new IOException(TextUtil.concatWithSpace("Card", name, "not found with set and index", edition, Integer.toString(artIndex)));
|
||||||
|
}
|
||||||
|
System.out.println("Alternate object found: " + pc.getName() + ", " + pc.getEdition() + ", " + pc.getArtIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rules = pc.getRules();
|
rules = pc.getRules();
|
||||||
rarity = pc.getRarity();
|
rarity = pc.getRarity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IPaperCard readObjectAlternate(String name, String edition) throws ClassNotFoundException, IOException {
|
||||||
|
IPaperCard pc = StaticData.instance().getCommonCards().getCard(name, edition);
|
||||||
|
if (pc == null) {
|
||||||
|
pc = StaticData.instance().getVariantCards().getCard(name, edition);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc == null) {
|
||||||
|
pc = StaticData.instance().getCommonCards().getCard(name);
|
||||||
|
if (pc == null) {
|
||||||
|
pc = StaticData.instance().getVariantCards().getCard(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private Object readResolve() throws ObjectStreamException {
|
private Object readResolve() throws ObjectStreamException {
|
||||||
//If we deserialize an old PaperCard with no flags, reinitialize as a fresh copy to set default flags.
|
//If we deserialize an old PaperCard with no flags, reinitialize as a fresh copy to set default flags.
|
||||||
@@ -363,14 +385,20 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getImageKey(boolean altState) {
|
public String getImageKey(boolean altState) {
|
||||||
return altState ? this.getCardAltImageKey() : this.getCardImageKey();
|
String normalizedName = StringUtils.stripAccents(name);
|
||||||
|
String imageKey = ImageKeys.CARD_PREFIX + normalizedName + CardDb.NameSetSeparator
|
||||||
|
+ edition + CardDb.NameSetSeparator + artIndex;
|
||||||
|
if (altState) {
|
||||||
|
imageKey += ImageKeys.BACKFACE_POSTFIX;
|
||||||
|
}
|
||||||
|
return imageKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String cardImageKey = null;
|
private String cardImageKey = null;
|
||||||
@Override
|
@Override
|
||||||
public String getCardImageKey() {
|
public String getCardImageKey() {
|
||||||
if (this.cardImageKey == null)
|
if (this.cardImageKey == null)
|
||||||
this.cardImageKey = ImageUtil.getImageKey(this, CardStateName.Original);
|
this.cardImageKey = ImageUtil.getImageKey(this, "", true);
|
||||||
return cardImageKey;
|
return cardImageKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,9 +407,9 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
public String getCardAltImageKey() {
|
public String getCardAltImageKey() {
|
||||||
if (this.cardAltImageKey == null){
|
if (this.cardAltImageKey == null){
|
||||||
if (this.hasBackFace())
|
if (this.hasBackFace())
|
||||||
this.cardAltImageKey = ImageUtil.getImageKey(this, this.getRules().getSplitType().getChangedStateName());
|
this.cardAltImageKey = ImageUtil.getImageKey(this, "back", true);
|
||||||
else // altImageKey will be the same as cardImageKey
|
else // altImageKey will be the same as cardImageKey
|
||||||
this.cardAltImageKey = getCardImageKey();
|
this.cardAltImageKey = ImageUtil.getImageKey(this, "", true);
|
||||||
}
|
}
|
||||||
return cardAltImageKey;
|
return cardAltImageKey;
|
||||||
}
|
}
|
||||||
@@ -391,9 +419,9 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
public String getCardWSpecImageKey() {
|
public String getCardWSpecImageKey() {
|
||||||
if (this.cardWSpecImageKey == null) {
|
if (this.cardWSpecImageKey == null) {
|
||||||
if (this.rules.getSplitType() == CardSplitType.Specialize)
|
if (this.rules.getSplitType() == CardSplitType.Specialize)
|
||||||
this.cardWSpecImageKey = ImageUtil.getImageKey(this, CardStateName.SpecializeW);
|
this.cardWSpecImageKey = ImageUtil.getImageKey(this, "white", true);
|
||||||
else // just use cardImageKey
|
else // just use cardImageKey
|
||||||
this.cardWSpecImageKey = getCardImageKey();
|
this.cardWSpecImageKey = ImageUtil.getImageKey(this, "", true);
|
||||||
}
|
}
|
||||||
return cardWSpecImageKey;
|
return cardWSpecImageKey;
|
||||||
}
|
}
|
||||||
@@ -403,9 +431,9 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
public String getCardUSpecImageKey() {
|
public String getCardUSpecImageKey() {
|
||||||
if (this.cardUSpecImageKey == null) {
|
if (this.cardUSpecImageKey == null) {
|
||||||
if (this.rules.getSplitType() == CardSplitType.Specialize)
|
if (this.rules.getSplitType() == CardSplitType.Specialize)
|
||||||
this.cardUSpecImageKey = ImageUtil.getImageKey(this, CardStateName.SpecializeU);
|
this.cardUSpecImageKey = ImageUtil.getImageKey(this, "blue", true);
|
||||||
else // just use cardImageKey
|
else // just use cardImageKey
|
||||||
this.cardUSpecImageKey = getCardImageKey();
|
this.cardUSpecImageKey = ImageUtil.getImageKey(this, "", true);
|
||||||
}
|
}
|
||||||
return cardUSpecImageKey;
|
return cardUSpecImageKey;
|
||||||
}
|
}
|
||||||
@@ -415,9 +443,9 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
public String getCardBSpecImageKey() {
|
public String getCardBSpecImageKey() {
|
||||||
if (this.cardBSpecImageKey == null) {
|
if (this.cardBSpecImageKey == null) {
|
||||||
if (this.rules.getSplitType() == CardSplitType.Specialize)
|
if (this.rules.getSplitType() == CardSplitType.Specialize)
|
||||||
this.cardBSpecImageKey = ImageUtil.getImageKey(this, CardStateName.SpecializeB);
|
this.cardBSpecImageKey = ImageUtil.getImageKey(this, "black", true);
|
||||||
else // just use cardImageKey
|
else // just use cardImageKey
|
||||||
this.cardBSpecImageKey = getCardImageKey();
|
this.cardBSpecImageKey = ImageUtil.getImageKey(this, "", true);
|
||||||
}
|
}
|
||||||
return cardBSpecImageKey;
|
return cardBSpecImageKey;
|
||||||
}
|
}
|
||||||
@@ -427,9 +455,9 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
public String getCardRSpecImageKey() {
|
public String getCardRSpecImageKey() {
|
||||||
if (this.cardRSpecImageKey == null) {
|
if (this.cardRSpecImageKey == null) {
|
||||||
if (this.rules.getSplitType() == CardSplitType.Specialize)
|
if (this.rules.getSplitType() == CardSplitType.Specialize)
|
||||||
this.cardRSpecImageKey = ImageUtil.getImageKey(this, CardStateName.SpecializeR);
|
this.cardRSpecImageKey = ImageUtil.getImageKey(this, "red", true);
|
||||||
else // just use cardImageKey
|
else // just use cardImageKey
|
||||||
this.cardRSpecImageKey = getCardImageKey();
|
this.cardRSpecImageKey = ImageUtil.getImageKey(this, "", true);
|
||||||
}
|
}
|
||||||
return cardRSpecImageKey;
|
return cardRSpecImageKey;
|
||||||
}
|
}
|
||||||
@@ -439,16 +467,18 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
public String getCardGSpecImageKey() {
|
public String getCardGSpecImageKey() {
|
||||||
if (this.cardGSpecImageKey == null) {
|
if (this.cardGSpecImageKey == null) {
|
||||||
if (this.rules.getSplitType() == CardSplitType.Specialize)
|
if (this.rules.getSplitType() == CardSplitType.Specialize)
|
||||||
this.cardGSpecImageKey = ImageUtil.getImageKey(this, CardStateName.SpecializeG);
|
this.cardGSpecImageKey = ImageUtil.getImageKey(this, "green", true);
|
||||||
else // just use cardImageKey
|
else // just use cardImageKey
|
||||||
this.cardGSpecImageKey = getCardImageKey();
|
this.cardGSpecImageKey = ImageUtil.getImageKey(this, "", true);
|
||||||
}
|
}
|
||||||
return cardGSpecImageKey;
|
return cardGSpecImageKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasBackFace(){
|
public boolean hasBackFace(){
|
||||||
return this.rules.hasBackSide();
|
CardSplitType cst = this.rules.getSplitType();
|
||||||
|
return cst == CardSplitType.Transform || cst == CardSplitType.Flip || cst == CardSplitType.Meld
|
||||||
|
|| cst == CardSplitType.Modal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import forge.StaticData;
|
|||||||
import forge.card.CardDb;
|
import forge.card.CardDb;
|
||||||
import forge.card.CardRules;
|
import forge.card.CardRules;
|
||||||
import forge.card.CardSplitType;
|
import forge.card.CardSplitType;
|
||||||
import forge.card.CardStateName;
|
|
||||||
import forge.item.IPaperCard;
|
import forge.item.IPaperCard;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -25,17 +24,20 @@ public class ImageUtil {
|
|||||||
key = imageKey.substring(ImageKeys.CARD_PREFIX.length());
|
key = imageKey.substring(ImageKeys.CARD_PREFIX.length());
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (key.endsWith(ImageKeys.BACKFACE_POSTFIX)) {
|
|
||||||
key = key.substring(0, key.length() - ImageKeys.BACKFACE_POSTFIX.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key.isEmpty())
|
if (key.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
String[] tempdata = key.split("\\|");
|
CardDb db = StaticData.instance().getCommonCards();
|
||||||
PaperCard cp = StaticData.instance().fetchCard(tempdata[0], tempdata[1], tempdata[2]);
|
PaperCard cp = null;
|
||||||
|
//db shouldn't be null
|
||||||
|
if (db != null) {
|
||||||
|
cp = db.getCard(key);
|
||||||
|
if (cp == null) {
|
||||||
|
db = StaticData.instance().getVariantCards();
|
||||||
|
if (db != null)
|
||||||
|
cp = db.getCard(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (cp == null)
|
if (cp == null)
|
||||||
System.err.println("Can't find PaperCard from key: " + key);
|
System.err.println("Can't find PaperCard from key: " + key);
|
||||||
// return cp regardless if it's null
|
// return cp regardless if it's null
|
||||||
@@ -52,21 +54,6 @@ public class ImageUtil {
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getImageRelativePath(String name, String set, String collectorNumber, boolean artChop) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
sb.append(set).append("/");
|
|
||||||
if (!collectorNumber.isEmpty() && !collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)) {
|
|
||||||
sb.append(collectorNumber).append("_");
|
|
||||||
}
|
|
||||||
sb.append(StringUtils.stripAccents(name));
|
|
||||||
|
|
||||||
sb.append(artChop ? ".artcrop" : ".fullborder");
|
|
||||||
sb.append(".jpg");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static String getImageRelativePath(PaperCard cp, String face, boolean includeSet, boolean isDownloadUrl) {
|
public static String getImageRelativePath(PaperCard cp, String face, boolean includeSet, boolean isDownloadUrl) {
|
||||||
final String nameToUse = cp == null ? null : getNameToUse(cp, face);
|
final String nameToUse = cp == null ? null : getNameToUse(cp, face);
|
||||||
if (nameToUse == null) {
|
if (nameToUse == null) {
|
||||||
@@ -136,15 +123,25 @@ public class ImageUtil {
|
|||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
} else if (face.equals("white")) {
|
} else if (face.equals("white")) {
|
||||||
return card.getImageName(CardStateName.SpecializeW);
|
if (card.getWSpecialize() != null) {
|
||||||
|
return card.getWSpecialize().getName();
|
||||||
|
}
|
||||||
} else if (face.equals("blue")) {
|
} else if (face.equals("blue")) {
|
||||||
return card.getImageName(CardStateName.SpecializeU);
|
if (card.getUSpecialize() != null) {
|
||||||
|
return card.getUSpecialize().getName();
|
||||||
|
}
|
||||||
} else if (face.equals("black")) {
|
} else if (face.equals("black")) {
|
||||||
return card.getImageName(CardStateName.SpecializeB);
|
if (card.getBSpecialize() != null) {
|
||||||
|
return card.getBSpecialize().getName();
|
||||||
|
}
|
||||||
} else if (face.equals("red")) {
|
} else if (face.equals("red")) {
|
||||||
return card.getImageName(CardStateName.SpecializeR);
|
if (card.getRSpecialize() != null) {
|
||||||
|
return card.getRSpecialize().getName();
|
||||||
|
}
|
||||||
} else if (face.equals("green")) {
|
} else if (face.equals("green")) {
|
||||||
return card.getImageName(CardStateName.SpecializeG);
|
if (card.getGSpecialize() != null) {
|
||||||
|
return card.getGSpecialize().getName();
|
||||||
|
}
|
||||||
} else if (CardSplitType.Split == cp.getRules().getSplitType()) {
|
} else if (CardSplitType.Split == cp.getRules().getSplitType()) {
|
||||||
return card.getMainPart().getName() + card.getOtherPart().getName();
|
return card.getMainPart().getName() + card.getOtherPart().getName();
|
||||||
} else if (!IPaperCard.NO_FUNCTIONAL_VARIANT.equals(cp.getFunctionalVariant())) {
|
} else if (!IPaperCard.NO_FUNCTIONAL_VARIANT.equals(cp.getFunctionalVariant())) {
|
||||||
@@ -153,86 +150,50 @@ public class ImageUtil {
|
|||||||
return cp.getName();
|
return cp.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getNameToUse(PaperCard cp, CardStateName face) {
|
|
||||||
if (!IPaperCard.NO_FUNCTIONAL_VARIANT.equals(cp.getFunctionalVariant())) {
|
|
||||||
return cp.getFunctionalVariant();
|
|
||||||
}
|
|
||||||
final CardRules card = cp.getRules();
|
|
||||||
return card.getImageName(face);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getImageKey(PaperCard cp, String face, boolean includeSet) {
|
public static String getImageKey(PaperCard cp, String face, boolean includeSet) {
|
||||||
return getImageRelativePath(cp, face, includeSet, false);
|
return getImageRelativePath(cp, face, includeSet, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getImageKey(PaperCard cp, CardStateName face) {
|
|
||||||
String name = getNameToUse(cp, face);
|
|
||||||
String number = cp.getCollectorNumber();
|
|
||||||
String suffix = "";
|
|
||||||
switch (face) {
|
|
||||||
case SpecializeB:
|
|
||||||
number += "b";
|
|
||||||
break;
|
|
||||||
case SpecializeG:
|
|
||||||
number += "g";
|
|
||||||
break;
|
|
||||||
case SpecializeR:
|
|
||||||
number += "r";
|
|
||||||
break;
|
|
||||||
case SpecializeU:
|
|
||||||
number += "u";
|
|
||||||
break;
|
|
||||||
case SpecializeW:
|
|
||||||
number += "w";
|
|
||||||
break;
|
|
||||||
case Meld:
|
|
||||||
case Modal:
|
|
||||||
case Secondary:
|
|
||||||
case Transformed:
|
|
||||||
suffix = ImageKeys.BACKFACE_POSTFIX;
|
|
||||||
break;
|
|
||||||
case Flipped:
|
|
||||||
break; // add info to rotate the image?
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
return ImageKeys.CARD_PREFIX + name + CardDb.NameSetSeparator + cp.getEdition()
|
|
||||||
+ CardDb.NameSetSeparator + number + CardDb.NameSetSeparator + cp.getArtIndex() + suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getDownloadUrl(PaperCard cp, String face) {
|
public static String getDownloadUrl(PaperCard cp, String face) {
|
||||||
return getImageRelativePath(cp, face, true, true);
|
return getImageRelativePath(cp, face, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getScryfallDownloadUrl(String collectorNumber, String setCode, String langCode, String faceParam, boolean useArtCrop){
|
public static String getScryfallDownloadUrl(PaperCard cp, String face, String setCode, String langCode, boolean useArtCrop){
|
||||||
return getScryfallDownloadUrl(collectorNumber, setCode, langCode, faceParam, useArtCrop, false);
|
return getScryfallDownloadUrl(cp, face, setCode, langCode, useArtCrop, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getScryfallDownloadUrl(String collectorNumber, String setCode, String langCode, String faceParam, boolean useArtCrop, boolean hyphenateAlchemy){
|
public static String getScryfallDownloadUrl(PaperCard cp, String face, String setCode, String langCode, boolean useArtCrop, boolean hyphenateAlchemy){
|
||||||
|
String editionCode;
|
||||||
|
if ((setCode != null) && (setCode.length() > 0))
|
||||||
|
editionCode = setCode;
|
||||||
|
else
|
||||||
|
editionCode = cp.getEdition().toLowerCase();
|
||||||
|
String cardCollectorNumber = cp.getCollectorNumber();
|
||||||
// Hack to account for variations in Arabian Nights
|
// Hack to account for variations in Arabian Nights
|
||||||
collectorNumber = collectorNumber.replace("+", "†");
|
cardCollectorNumber = cardCollectorNumber.replace("+", "†");
|
||||||
// override old planechase sets from their modified id since scryfall move the planechase cards outside their original setcode
|
// override old planechase sets from their modified id since scryfall move the planechase cards outside their original setcode
|
||||||
if (collectorNumber.startsWith("OHOP")) {
|
if (cardCollectorNumber.startsWith("OHOP")) {
|
||||||
setCode = "ohop";
|
editionCode = "ohop";
|
||||||
collectorNumber = collectorNumber.substring("OHOP".length());
|
cardCollectorNumber = cardCollectorNumber.substring("OHOP".length());
|
||||||
} else if (collectorNumber.startsWith("OPCA")) {
|
} else if (cardCollectorNumber.startsWith("OPCA")) {
|
||||||
setCode = "opca";
|
editionCode = "opca";
|
||||||
collectorNumber = collectorNumber.substring("OPCA".length());
|
cardCollectorNumber = cardCollectorNumber.substring("OPCA".length());
|
||||||
} else if (collectorNumber.startsWith("OPC2")) {
|
} else if (cardCollectorNumber.startsWith("OPC2")) {
|
||||||
setCode = "opc2";
|
editionCode = "opc2";
|
||||||
collectorNumber = collectorNumber.substring("OPC2".length());
|
cardCollectorNumber = cardCollectorNumber.substring("OPC2".length());
|
||||||
} else if (hyphenateAlchemy) {
|
} else if (hyphenateAlchemy) {
|
||||||
if (!collectorNumber.startsWith("A")) {
|
if (!cardCollectorNumber.startsWith("A")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
collectorNumber = collectorNumber.replace("A", "A-");
|
cardCollectorNumber = cardCollectorNumber.replace("A", "A-");
|
||||||
}
|
}
|
||||||
String versionParam = useArtCrop ? "art_crop" : "normal";
|
String versionParam = useArtCrop ? "art_crop" : "normal";
|
||||||
if (!faceParam.isEmpty()) {
|
String faceParam = "";
|
||||||
faceParam = (faceParam.equals("back") ? "&face=back" : "&face=front");
|
if (cp.getRules().getOtherPart() != null) {
|
||||||
|
faceParam = (face.equals("back") ? "&face=back" : "&face=front");
|
||||||
}
|
}
|
||||||
return String.format("%s/%s/%s?format=image&version=%s%s", setCode, collectorNumber,
|
return String.format("%s/%s/%s?format=image&version=%s%s", editionCode, cardCollectorNumber,
|
||||||
langCode, versionParam, faceParam);
|
langCode, versionParam, faceParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>${revision}</version>
|
<version>2.0.04</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-game</artifactId>
|
<artifactId>forge-game</artifactId>
|
||||||
|
|||||||
@@ -548,20 +548,20 @@ public class GameAction {
|
|||||||
|
|
||||||
copied.updateStateForView();
|
copied.updateStateForView();
|
||||||
|
|
||||||
|
// we don't want always trigger before counters are placed
|
||||||
|
game.getTriggerHandler().suppressMode(TriggerType.Always);
|
||||||
|
// Need to apply any static effects to produce correct triggers
|
||||||
|
checkStaticAbilities();
|
||||||
|
|
||||||
// needed for counters + ascend
|
// needed for counters + ascend
|
||||||
if (!suppress && toBattlefield) {
|
if (!suppress && toBattlefield) {
|
||||||
game.getTriggerHandler().registerActiveTrigger(copied, false);
|
game.getTriggerHandler().registerActiveTrigger(copied, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!table.isEmpty()) {
|
// do ETB counters after zone add
|
||||||
// we don't want always trigger before counters are placed
|
table.replaceCounterEffect(game, null, true, true, params);
|
||||||
game.getTriggerHandler().suppressMode(TriggerType.Always);
|
|
||||||
// Need to apply any static effects to produce correct triggers
|
game.getTriggerHandler().clearSuppression(TriggerType.Always);
|
||||||
checkStaticAbilities();
|
|
||||||
// do ETB counters after zone add
|
|
||||||
table.replaceCounterEffect(game, null, true, true, params);
|
|
||||||
game.getTriggerHandler().clearSuppression(TriggerType.Always);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update static abilities after etb counters have been placed
|
// update static abilities after etb counters have been placed
|
||||||
checkStaticAbilities();
|
checkStaticAbilities();
|
||||||
@@ -2794,6 +2794,7 @@ public class GameAction {
|
|||||||
if (aura == null) {
|
if (aura == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
aura.setActivatingPlayer(source.getController());
|
||||||
|
|
||||||
Set<ZoneType> zones = EnumSet.noneOf(ZoneType.class);
|
Set<ZoneType> zones = EnumSet.noneOf(ZoneType.class);
|
||||||
boolean canTargetPlayer = false;
|
boolean canTargetPlayer = false;
|
||||||
|
|||||||
@@ -6515,6 +6515,29 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|
|||||||
if(uiCard != null)
|
if(uiCard != null)
|
||||||
uiCard.currentState.setImageKey(iFN);
|
uiCard.currentState.setImageKey(iFN);
|
||||||
}
|
}
|
||||||
|
public final void setImageKey(final IPaperCard ipc, final CardStateName stateName) {
|
||||||
|
if (ipc == null)
|
||||||
|
return;
|
||||||
|
switch (stateName) {
|
||||||
|
case SpecializeB:
|
||||||
|
setImageKey(ipc.getCardBSpecImageKey());
|
||||||
|
break;
|
||||||
|
case SpecializeR:
|
||||||
|
setImageKey(ipc.getCardRSpecImageKey());
|
||||||
|
break;
|
||||||
|
case SpecializeG:
|
||||||
|
setImageKey(ipc.getCardGSpecImageKey());
|
||||||
|
break;
|
||||||
|
case SpecializeU:
|
||||||
|
setImageKey(ipc.getCardUSpecImageKey());
|
||||||
|
break;
|
||||||
|
case SpecializeW:
|
||||||
|
setImageKey(ipc.getCardWSpecImageKey());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getImageKey(CardStateName state) {
|
public String getImageKey(CardStateName state) {
|
||||||
if (!getRenderForUI()) {
|
if (!getRenderForUI()) {
|
||||||
@@ -6814,6 +6837,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|
|||||||
}
|
}
|
||||||
public final void setSpecialized(final boolean bool) {
|
public final void setSpecialized(final boolean bool) {
|
||||||
specialized = bool;
|
specialized = bool;
|
||||||
|
setImageKey(getPaperCard(), getCurrentStateName());
|
||||||
}
|
}
|
||||||
public final boolean canSpecialize() {
|
public final boolean canSpecialize() {
|
||||||
return getRules() != null && getRules().getSplitType() == CardSplitType.Specialize;
|
return getRules() != null && getRules().getSplitType() == CardSplitType.Specialize;
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ public class CardFactory {
|
|||||||
c.setRarity(cp.getRarity());
|
c.setRarity(cp.getRarity());
|
||||||
|
|
||||||
// Would like to move this away from in-game entities
|
// Would like to move this away from in-game entities
|
||||||
String originalPicture = cp.getCardImageKey();
|
String originalPicture = cp.getImageKey(false);
|
||||||
c.setImageKey(originalPicture);
|
c.setImageKey(originalPicture);
|
||||||
|
|
||||||
if(cp.isToken())
|
if(cp.isToken())
|
||||||
@@ -198,11 +198,11 @@ public class CardFactory {
|
|||||||
if (c.hasAlternateState()) {
|
if (c.hasAlternateState()) {
|
||||||
if (c.isFlipCard()) {
|
if (c.isFlipCard()) {
|
||||||
c.setState(CardStateName.Flipped, false);
|
c.setState(CardStateName.Flipped, false);
|
||||||
c.setImageKey(cp.getCardAltImageKey());
|
c.setImageKey(cp.getImageKey(true));
|
||||||
}
|
}
|
||||||
else if (c.isDoubleFaced() && cardRules != null) {
|
else if (c.isDoubleFaced() && cardRules != null) {
|
||||||
c.setState(cardRules.getSplitType().getChangedStateName(), false);
|
c.setState(cardRules.getSplitType().getChangedStateName(), false);
|
||||||
c.setImageKey(cp.getCardAltImageKey());
|
c.setImageKey(cp.getImageKey(true));
|
||||||
}
|
}
|
||||||
else if (c.isSplitCard()) {
|
else if (c.isSplitCard()) {
|
||||||
c.setState(CardStateName.LeftSplit, false);
|
c.setState(CardStateName.LeftSplit, false);
|
||||||
@@ -216,23 +216,23 @@ public class CardFactory {
|
|||||||
c.setImageKey(originalPicture);
|
c.setImageKey(originalPicture);
|
||||||
} else if (c.canSpecialize()) {
|
} else if (c.canSpecialize()) {
|
||||||
c.setState(CardStateName.SpecializeW, false);
|
c.setState(CardStateName.SpecializeW, false);
|
||||||
c.setImageKey(cp.getCardWSpecImageKey());
|
c.setImageKey(cp.getImageKey(false) + ImageKeys.SPECFACE_W);
|
||||||
c.setSetCode(cp.getEdition());
|
c.setSetCode(cp.getEdition());
|
||||||
c.setRarity(cp.getRarity());
|
c.setRarity(cp.getRarity());
|
||||||
c.setState(CardStateName.SpecializeU, false);
|
c.setState(CardStateName.SpecializeU, false);
|
||||||
c.setImageKey(cp.getCardUSpecImageKey());
|
c.setImageKey(cp.getImageKey(false) + ImageKeys.SPECFACE_U);
|
||||||
c.setSetCode(cp.getEdition());
|
c.setSetCode(cp.getEdition());
|
||||||
c.setRarity(cp.getRarity());
|
c.setRarity(cp.getRarity());
|
||||||
c.setState(CardStateName.SpecializeB, false);
|
c.setState(CardStateName.SpecializeB, false);
|
||||||
c.setImageKey(cp.getCardBSpecImageKey());
|
c.setImageKey(cp.getImageKey(false) + ImageKeys.SPECFACE_B);
|
||||||
c.setSetCode(cp.getEdition());
|
c.setSetCode(cp.getEdition());
|
||||||
c.setRarity(cp.getRarity());
|
c.setRarity(cp.getRarity());
|
||||||
c.setState(CardStateName.SpecializeR, false);
|
c.setState(CardStateName.SpecializeR, false);
|
||||||
c.setImageKey(cp.getCardRSpecImageKey());
|
c.setImageKey(cp.getImageKey(false) + ImageKeys.SPECFACE_R);
|
||||||
c.setSetCode(cp.getEdition());
|
c.setSetCode(cp.getEdition());
|
||||||
c.setRarity(cp.getRarity());
|
c.setRarity(cp.getRarity());
|
||||||
c.setState(CardStateName.SpecializeG, false);
|
c.setState(CardStateName.SpecializeG, false);
|
||||||
c.setImageKey(cp.getCardGSpecImageKey());
|
c.setImageKey(cp.getImageKey(false) + ImageKeys.SPECFACE_G);
|
||||||
c.setSetCode(cp.getEdition());
|
c.setSetCode(cp.getEdition());
|
||||||
c.setRarity(cp.getRarity());
|
c.setRarity(cp.getRarity());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import java.util.Collection;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class CardState extends GameObject implements IHasSVars, ITranslatable {
|
public class CardState extends GameObject implements IHasSVars, ITranslatable {
|
||||||
private String name = "";
|
private String name = "";
|
||||||
@@ -366,14 +367,16 @@ public class CardState extends GameObject implements IHasSVars, ITranslatable {
|
|||||||
public final FCollectionView<SpellAbility> getManaAbilities() {
|
public final FCollectionView<SpellAbility> getManaAbilities() {
|
||||||
FCollection<SpellAbility> newCol = new FCollection<>();
|
FCollection<SpellAbility> newCol = new FCollection<>();
|
||||||
updateSpellAbilities(newCol, true);
|
updateSpellAbilities(newCol, true);
|
||||||
newCol.addAll(abilities.stream().filter(SpellAbility::isManaAbility).toList());
|
// stream().toList() causes crash on Android, use Collectors.toList()
|
||||||
|
newCol.addAll(abilities.stream().filter(SpellAbility::isManaAbility).collect(Collectors.toList()));
|
||||||
card.updateSpellAbilities(newCol, this, true);
|
card.updateSpellAbilities(newCol, this, true);
|
||||||
return newCol;
|
return newCol;
|
||||||
}
|
}
|
||||||
public final FCollectionView<SpellAbility> getNonManaAbilities() {
|
public final FCollectionView<SpellAbility> getNonManaAbilities() {
|
||||||
FCollection<SpellAbility> newCol = new FCollection<>();
|
FCollection<SpellAbility> newCol = new FCollection<>();
|
||||||
updateSpellAbilities(newCol, false);
|
updateSpellAbilities(newCol, false);
|
||||||
newCol.addAll(abilities.stream().filter(Predicate.not(SpellAbility::isManaAbility)).toList());
|
// stream().toList() causes crash on Android, use Collectors.toList()
|
||||||
|
newCol.addAll(abilities.stream().filter(Predicate.not(SpellAbility::isManaAbility)).collect(Collectors.toList()));
|
||||||
card.updateSpellAbilities(newCol, this, false);
|
card.updateSpellAbilities(newCol, this, false);
|
||||||
return newCol;
|
return newCol;
|
||||||
}
|
}
|
||||||
@@ -385,7 +388,10 @@ public class CardState extends GameObject implements IHasSVars, ITranslatable {
|
|||||||
CardState leftState = getCard().getState(CardStateName.LeftSplit);
|
CardState leftState = getCard().getState(CardStateName.LeftSplit);
|
||||||
Collection<SpellAbility> leftAbilities = leftState.abilities;
|
Collection<SpellAbility> leftAbilities = leftState.abilities;
|
||||||
if (null != mana) {
|
if (null != mana) {
|
||||||
leftAbilities = leftAbilities.stream().filter(mana ? SpellAbility::isManaAbility : Predicate.not(SpellAbility::isManaAbility)).toList();
|
leftAbilities = leftAbilities.stream()
|
||||||
|
.filter(mana ? SpellAbility::isManaAbility : Predicate.not(SpellAbility::isManaAbility))
|
||||||
|
// stream().toList() causes crash on Android, use Collectors.toList()
|
||||||
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
newCol.addAll(leftAbilities);
|
newCol.addAll(leftAbilities);
|
||||||
leftState.updateSpellAbilities(newCol, mana);
|
leftState.updateSpellAbilities(newCol, mana);
|
||||||
@@ -394,7 +400,10 @@ public class CardState extends GameObject implements IHasSVars, ITranslatable {
|
|||||||
CardState rightState = getCard().getState(CardStateName.RightSplit);
|
CardState rightState = getCard().getState(CardStateName.RightSplit);
|
||||||
Collection<SpellAbility> rightAbilities = rightState.abilities;
|
Collection<SpellAbility> rightAbilities = rightState.abilities;
|
||||||
if (null != mana) {
|
if (null != mana) {
|
||||||
rightAbilities = rightAbilities.stream().filter(mana ? SpellAbility::isManaAbility : Predicate.not(SpellAbility::isManaAbility)).toList();
|
rightAbilities = rightAbilities.stream()
|
||||||
|
.filter(mana ? SpellAbility::isManaAbility : Predicate.not(SpellAbility::isManaAbility))
|
||||||
|
// stream().toList() causes crash on Android, use Collectors.toList()
|
||||||
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
newCol.addAll(rightAbilities);
|
newCol.addAll(rightAbilities);
|
||||||
rightState.updateSpellAbilities(newCol, mana);
|
rightState.updateSpellAbilities(newCol, mana);
|
||||||
@@ -428,8 +437,7 @@ public class CardState extends GameObject implements IHasSVars, ITranslatable {
|
|||||||
CardTypeView type = getTypeWithChanges();
|
CardTypeView type = getTypeWithChanges();
|
||||||
if (type.isLand()) {
|
if (type.isLand()) {
|
||||||
if (landAbility == null) {
|
if (landAbility == null) {
|
||||||
landAbility = new LandAbility(card);
|
landAbility = new LandAbility(card, this);
|
||||||
landAbility.setCardState(this);
|
|
||||||
}
|
}
|
||||||
newCol.add(landAbility);
|
newCol.add(landAbility);
|
||||||
} else if (type.isAura()) {
|
} else if (type.isAura()) {
|
||||||
|
|||||||
@@ -1335,29 +1335,9 @@ public class CardView extends GameEntityView {
|
|||||||
}
|
}
|
||||||
void updateImageKey(Card c) {
|
void updateImageKey(Card c) {
|
||||||
set(TrackableProperty.ImageKey, c.getImageKey());
|
set(TrackableProperty.ImageKey, c.getImageKey());
|
||||||
// currently only works for Cards
|
|
||||||
if (!c.getGamePieceType().equals(GamePieceType.CARD)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
IPaperCard pc = c.getPaperCard();
|
|
||||||
if (pc != null) {
|
|
||||||
set(TrackableProperty.Artist, pc.getArtist());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void updateImageKey(CardState c) {
|
void updateImageKey(CardState c) {
|
||||||
set(TrackableProperty.ImageKey, c.getImageKey());
|
set(TrackableProperty.ImageKey, c.getImageKey());
|
||||||
// currently only works for Cards
|
|
||||||
if (!c.getCard().getGamePieceType().equals(GamePieceType.CARD)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
IPaperCard pc = c.getCard().getPaperCard();
|
|
||||||
if (pc != null) { // currently Artist is per Card
|
|
||||||
set(TrackableProperty.Artist, pc.getArtist());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getArtist() {
|
|
||||||
return get(TrackableProperty.Artist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardTypeView getType() {
|
public CardTypeView getType() {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.esotericsoftware.minlog.Log;
|
|||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardState;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +38,9 @@ public abstract class Ability extends SpellAbility {
|
|||||||
protected Ability(final Card sourceCard, final ManaCost manaCost) {
|
protected Ability(final Card sourceCard, final ManaCost manaCost) {
|
||||||
this(sourceCard, new Cost(manaCost, true), null);
|
this(sourceCard, new Cost(manaCost, true), null);
|
||||||
}
|
}
|
||||||
|
protected Ability(final Card sourceCard, final ManaCost manaCost, final CardState state) {
|
||||||
|
super(sourceCard, new Cost(manaCost, true), null, state);
|
||||||
|
}
|
||||||
protected Ability(final Card sourceCard, final ManaCost manaCost, SpellAbilityView view0) {
|
protected Ability(final Card sourceCard, final ManaCost manaCost, SpellAbilityView view0) {
|
||||||
this(sourceCard, new Cost(manaCost, true), view0);
|
this(sourceCard, new Cost(manaCost, true), view0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package forge.game.spellability;
|
|||||||
|
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardState;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,6 +44,9 @@ public abstract class AbilityStatic extends Ability implements Cloneable {
|
|||||||
public AbilityStatic(final Card sourceCard, final ManaCost manaCost) {
|
public AbilityStatic(final Card sourceCard, final ManaCost manaCost) {
|
||||||
super(sourceCard, manaCost);
|
super(sourceCard, manaCost);
|
||||||
}
|
}
|
||||||
|
public AbilityStatic(final Card sourceCard, final ManaCost manaCost, final CardState state) {
|
||||||
|
super(sourceCard, manaCost, state);
|
||||||
|
}
|
||||||
|
|
||||||
public AbilityStatic(final Card sourceCard, final Cost abCost, final TargetRestrictions tgt) {
|
public AbilityStatic(final Card sourceCard, final Cost abCost, final TargetRestrictions tgt) {
|
||||||
super(sourceCard, abCost);
|
super(sourceCard, abCost);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import forge.card.CardStateName;
|
|||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCopyService;
|
import forge.game.card.CardCopyService;
|
||||||
|
import forge.game.card.CardState;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -31,8 +32,8 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
|
|
||||||
public class LandAbility extends AbilityStatic {
|
public class LandAbility extends AbilityStatic {
|
||||||
|
|
||||||
public LandAbility(Card sourceCard) {
|
public LandAbility(Card sourceCard, CardState state) {
|
||||||
super(sourceCard, ManaCost.NO_COST);
|
super(sourceCard, ManaCost.NO_COST, state);
|
||||||
|
|
||||||
getRestrictions().setZone(ZoneType.Hand);
|
getRestrictions().setZone(ZoneType.Hand);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,12 +195,18 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected SpellAbility(final Card iSourceCard, final Cost toPay) {
|
protected SpellAbility(final Card iSourceCard, final Cost toPay) {
|
||||||
this(iSourceCard, toPay, null);
|
this(iSourceCard, toPay, null, null);
|
||||||
}
|
}
|
||||||
protected SpellAbility(final Card iSourceCard, final Cost toPay, SpellAbilityView view0) {
|
protected SpellAbility(final Card iSourceCard, final Cost toPay, SpellAbilityView view0) {
|
||||||
|
this(iSourceCard, toPay, view0, null);
|
||||||
|
}
|
||||||
|
protected SpellAbility(final Card iSourceCard, final Cost toPay, SpellAbilityView view0, CardState cs) {
|
||||||
id = nextId();
|
id = nextId();
|
||||||
hostCard = iSourceCard;
|
hostCard = iSourceCard;
|
||||||
payCosts = toPay;
|
payCosts = toPay;
|
||||||
|
if (cs != null) {
|
||||||
|
cardState = cs;
|
||||||
|
}
|
||||||
if (view0 == null) {
|
if (view0 == null) {
|
||||||
view0 = new SpellAbilityView(this);
|
view0 = new SpellAbilityView(this);
|
||||||
}
|
}
|
||||||
@@ -1222,12 +1228,14 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
try {
|
try {
|
||||||
clone = (SpellAbility) clone();
|
clone = (SpellAbility) clone();
|
||||||
clone.id = lki ? id : nextId();
|
clone.id = lki ? id : nextId();
|
||||||
clone.view = new SpellAbilityView(clone, lki || host.getGame() == null ? null : host.getGame().getTracker());
|
|
||||||
|
|
||||||
// don't use setHostCard to not trigger the not copied parts yet
|
// don't use setHostCard to not trigger the not copied parts yet
|
||||||
|
|
||||||
copyHelper(clone, host, lki || keepTextChanges);
|
copyHelper(clone, host, lki || keepTextChanges);
|
||||||
|
|
||||||
|
// need CardState before View
|
||||||
|
clone.view = new SpellAbilityView(clone, lki || host.getGame() == null ? null : host.getGame().getTracker());
|
||||||
|
|
||||||
// always set this to false, it is only set in CopyEffect
|
// always set this to false, it is only set in CopyEffect
|
||||||
clone.mayChooseNewTargets = false;
|
clone.mayChooseNewTargets = false;
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,6 @@ public enum TrackableProperty {
|
|||||||
|
|
||||||
//Card State
|
//Card State
|
||||||
Name(TrackableTypes.StringType),
|
Name(TrackableTypes.StringType),
|
||||||
Artist(TrackableTypes.StringType),
|
|
||||||
Colors(TrackableTypes.ColorSetType),
|
Colors(TrackableTypes.ColorSetType),
|
||||||
OriginalColors(TrackableTypes.ColorSetType),
|
OriginalColors(TrackableTypes.ColorSetType),
|
||||||
LeftSplitColors(TrackableTypes.ColorSetType),
|
LeftSplitColors(TrackableTypes.ColorSetType),
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>${revision}</version>
|
<version>2.0.04</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui-android</artifactId>
|
<artifactId>forge-gui-android</artifactId>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>${revision}</version>
|
<version>2.0.04</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui-desktop</artifactId>
|
<artifactId>forge-gui-desktop</artifactId>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
|
|||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.mortennobel.imagescaling.ResampleOp;
|
import com.mortennobel.imagescaling.ResampleOp;
|
||||||
|
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardSplitType;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardView;
|
import forge.game.card.CardView;
|
||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
@@ -56,8 +56,8 @@ import forge.model.FModel;
|
|||||||
import forge.toolbox.FSkin;
|
import forge.toolbox.FSkin;
|
||||||
import forge.toolbox.FSkin.SkinIcon;
|
import forge.toolbox.FSkin.SkinIcon;
|
||||||
import forge.toolbox.imaging.FCardImageRenderer;
|
import forge.toolbox.imaging.FCardImageRenderer;
|
||||||
import forge.util.Aggregates;
|
|
||||||
import forge.util.ImageUtil;
|
import forge.util.ImageUtil;
|
||||||
|
import forge.util.TextUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class stores ALL card images in a cache with soft values. this means
|
* This class stores ALL card images in a cache with soft values. this means
|
||||||
@@ -171,41 +171,65 @@ public class ImageCache {
|
|||||||
|
|
||||||
IPaperCard ipc = null;
|
IPaperCard ipc = null;
|
||||||
boolean altState = imageKey.endsWith(ImageKeys.BACKFACE_POSTFIX);
|
boolean altState = imageKey.endsWith(ImageKeys.BACKFACE_POSTFIX);
|
||||||
boolean useArtCrop = "Crop".equals(FModel.getPreferences().getPref(ForgePreferences.FPref.UI_CARD_ART_FORMAT));
|
String specColor = "";
|
||||||
String fileName = imageKey;
|
if (imageKey.endsWith(ImageKeys.SPECFACE_W)) {
|
||||||
|
specColor = "white";
|
||||||
|
} else if (imageKey.endsWith(ImageKeys.SPECFACE_U)) {
|
||||||
|
specColor = "blue";
|
||||||
|
} else if (imageKey.endsWith(ImageKeys.SPECFACE_B)) {
|
||||||
|
specColor = "black";
|
||||||
|
} else if (imageKey.endsWith(ImageKeys.SPECFACE_R)) {
|
||||||
|
specColor = "red";
|
||||||
|
} else if (imageKey.endsWith(ImageKeys.SPECFACE_G)) {
|
||||||
|
specColor = "green";
|
||||||
|
}
|
||||||
if (altState)
|
if (altState)
|
||||||
imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.BACKFACE_POSTFIX.length());
|
imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.BACKFACE_POSTFIX.length());
|
||||||
|
if (!specColor.isEmpty())
|
||||||
|
imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.SPECFACE_W.length());
|
||||||
if (imageKey.startsWith(ImageKeys.CARD_PREFIX)) {
|
if (imageKey.startsWith(ImageKeys.CARD_PREFIX)) {
|
||||||
String[] tempdata = imageKey.substring(2).split("\\|"); //We want to check the edition first.
|
ipc = ImageUtil.getPaperCardFromImageKey(imageKey);
|
||||||
|
if (ipc != null) {
|
||||||
String name = tempdata[0];
|
if (altState) {
|
||||||
String setCode = tempdata.length > 1 ? tempdata[1] : CardEdition.UNKNOWN_CODE;
|
imageKey = ipc.getCardAltImageKey();
|
||||||
String collectorNumber = tempdata.length > 3 ? tempdata[2] : IPaperCard.NO_COLLECTOR_NUMBER;
|
} else if (!specColor.isEmpty()) {
|
||||||
|
switch (specColor) {
|
||||||
CardEdition edition = StaticData.instance().getEditions().get(setCode);
|
case "white":
|
||||||
|
imageKey = ipc.getCardWSpecImageKey();
|
||||||
if (useArtCrop) {
|
break;
|
||||||
CardEdition.EditionEntry ee;
|
case "blue":
|
||||||
if (!collectorNumber.isEmpty() && !collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)) {
|
imageKey = ipc.getCardUSpecImageKey();
|
||||||
ee = edition.getCardFromCollectorNumber(collectorNumber);
|
break;
|
||||||
if (ee != null) { // TODO handle Specialize Collector number
|
case "black":
|
||||||
ee = edition.getCardFromCollectorNumber(collectorNumber.substring(0, collectorNumber.length() - 1));
|
imageKey = ipc.getCardBSpecImageKey();
|
||||||
|
break;
|
||||||
|
case "red":
|
||||||
|
imageKey = ipc.getCardRSpecImageKey();
|
||||||
|
break;
|
||||||
|
case "green":
|
||||||
|
imageKey = ipc.getCardGSpecImageKey();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ee = Aggregates.random(edition.getCardInSet(name));
|
imageKey = ipc.getCardImageKey();
|
||||||
}
|
|
||||||
|
|
||||||
// Skip fetching if artist info is not available for art crop
|
|
||||||
if (ee != null && ee.artistName().isEmpty()) {
|
|
||||||
useArtCrop = false;
|
|
||||||
}
|
}
|
||||||
|
if (StringUtils.isBlank(imageKey))
|
||||||
|
return Pair.of(_defaultImage, true);
|
||||||
}
|
}
|
||||||
ipc = StaticData.instance().fetchCard(name, setCode, collectorNumber);
|
}
|
||||||
|
|
||||||
fileName = ImageUtil.getImageRelativePath(name, setCode, collectorNumber, useArtCrop);
|
|
||||||
} // TODO add artCrop for Token
|
|
||||||
|
|
||||||
|
// 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;
|
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 = ipc.getCardImageKey();
|
||||||
|
}
|
||||||
|
imageKey = TextUtil.fastReplace(imageKey, ".full", ".artcrop");
|
||||||
|
}
|
||||||
|
|
||||||
// Load from file and add to cache if not found in cache initially.
|
// Load from file and add to cache if not found in cache initially.
|
||||||
BufferedImage original = getImage(imageKey);
|
BufferedImage original = getImage(imageKey);
|
||||||
@@ -215,11 +239,16 @@ public class ImageCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if art crop is exist, check also if the full card image is also cached.
|
// 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 noBorder = !useArtCrop && !isPreferenceEnabled(ForgePreferences.FPref.UI_RENDER_BLACK_BORDERS);
|
||||||
boolean fetcherEnabled = isPreferenceEnabled(ForgePreferences.FPref.UI_ENABLE_ONLINE_IMAGE_FETCHER);
|
boolean fetcherEnabled = isPreferenceEnabled(ForgePreferences.FPref.UI_ENABLE_ONLINE_IMAGE_FETCHER);
|
||||||
boolean isPlaceholder = (original == null) && fetcherEnabled;
|
boolean isPlaceholder = (original == null) && fetcherEnabled;
|
||||||
String setCode = fileName.split("/")[0].trim().toUpperCase();
|
String setCode = imageKey.split("/")[0].trim().toUpperCase();
|
||||||
|
|
||||||
// If the user has indicated that they prefer Forge NOT render a black border, round the image corners
|
// 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.
|
// to account for JPEG images that don't have a transparency.
|
||||||
@@ -272,7 +301,7 @@ public class ImageCache {
|
|||||||
CardView card = ipc != null ? Card.getCardForUi(ipc).getView() : cardView;
|
CardView card = ipc != null ? Card.getCardForUi(ipc).getView() : cardView;
|
||||||
String legalString = null;
|
String legalString = null;
|
||||||
original = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
original = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||||
if (art != null && ipc != null) {
|
if (art != null) {
|
||||||
Calendar cal = Calendar.getInstance();
|
Calendar cal = Calendar.getInstance();
|
||||||
cal.setTime(StaticData.instance().getCardEdition(ipc.getEdition()).getDate());
|
cal.setTime(StaticData.instance().getCardEdition(ipc.getEdition()).getDate());
|
||||||
int year = cal.get(Calendar.YEAR);
|
int year = cal.get(Calendar.YEAR);
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ final class ImageLoader extends CacheLoader<String, BufferedImage> {
|
|||||||
if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_CARD_IMAGES))
|
if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_CARD_IMAGES))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
boolean useArtCrop = "Crop".equals(FModel.getPreferences().getPref(ForgePreferences.FPref.UI_CARD_ART_FORMAT));
|
File file = ImageKeys.getImageFile(key);
|
||||||
File file = ImageKeys.getImageFile(key, useArtCrop);
|
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -77,11 +77,41 @@ public final class FImageUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean altState = key.endsWith(ImageKeys.BACKFACE_POSTFIX);
|
boolean altState = key.endsWith(ImageKeys.BACKFACE_POSTFIX);
|
||||||
|
String specColor = "";
|
||||||
|
if (key.endsWith(ImageKeys.SPECFACE_W)) {
|
||||||
|
specColor = "white";
|
||||||
|
} else if (key.endsWith(ImageKeys.SPECFACE_U)) {
|
||||||
|
specColor = "blue";
|
||||||
|
} else if (key.endsWith(ImageKeys.SPECFACE_B)) {
|
||||||
|
specColor = "black";
|
||||||
|
} else if (key.endsWith(ImageKeys.SPECFACE_R)) {
|
||||||
|
specColor = "red";
|
||||||
|
} else if (key.endsWith(ImageKeys.SPECFACE_G)) {
|
||||||
|
specColor = "green";
|
||||||
|
}
|
||||||
String imageKey = key;
|
String imageKey = key;
|
||||||
if (prefix.equals(ImageKeys.CARD_PREFIX)) {
|
if (prefix.equals(ImageKeys.CARD_PREFIX)) {
|
||||||
PaperCard card = ImageUtil.getPaperCardFromImageKey(key);
|
PaperCard card = ImageUtil.getPaperCardFromImageKey(key);
|
||||||
if (altState) {
|
if (altState) {
|
||||||
imageKey = card.getCardAltImageKey();
|
imageKey = card.getCardAltImageKey();
|
||||||
|
} else if (!specColor.isEmpty()) {
|
||||||
|
switch (specColor) {
|
||||||
|
case "white":
|
||||||
|
imageKey = card.getCardWSpecImageKey();
|
||||||
|
break;
|
||||||
|
case "blue":
|
||||||
|
imageKey = card.getCardUSpecImageKey();
|
||||||
|
break;
|
||||||
|
case "black":
|
||||||
|
imageKey = card.getCardBSpecImageKey();
|
||||||
|
break;
|
||||||
|
case "red":
|
||||||
|
imageKey = card.getCardRSpecImageKey();
|
||||||
|
break;
|
||||||
|
case "green":
|
||||||
|
imageKey = card.getCardGSpecImageKey();
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
imageKey = card.getCardImageKey();
|
imageKey = card.getCardImageKey();
|
||||||
}
|
}
|
||||||
@@ -89,6 +119,9 @@ public final class FImageUtil {
|
|||||||
if(altState) {
|
if(altState) {
|
||||||
imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.BACKFACE_POSTFIX.length());
|
imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.BACKFACE_POSTFIX.length());
|
||||||
imageKey += "full.jpg";
|
imageKey += "full.jpg";
|
||||||
|
} else if (!specColor.isEmpty()) {
|
||||||
|
imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.SPECFACE_W.length());
|
||||||
|
imageKey += "full.jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = ImageKeys.getImageFile(imageKey);
|
File file = ImageKeys.getImageFile(imageKey);
|
||||||
|
|||||||
@@ -34,14 +34,10 @@ public class SwingImageFetcher extends ImageFetcher {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String newdespath = destPath;
|
String newdespath = urlToDownload.contains(".fullborder.jpg") || urlToDownload.startsWith(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD) ?
|
||||||
if (!destPath.contains(".artcrop")) {
|
TextUtil.fastReplace(destPath, ".full.jpg", ".fullborder.jpg") : destPath;
|
||||||
newdespath = urlToDownload.contains(".fullborder.jpg") || urlToDownload.startsWith(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD) ?
|
if (!newdespath.contains(".full") && urlToDownload.startsWith(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD) && !destPath.startsWith(ForgeConstants.CACHE_TOKEN_PICS_DIR))
|
||||||
TextUtil.fastReplace(destPath, ".full.jpg", ".fullborder.jpg") : destPath;
|
newdespath = newdespath.replace(".jpg", ".fullborder.jpg"); //fix planes/phenomenon for round border options
|
||||||
if (!newdespath.contains(".full") && urlToDownload.startsWith(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD) && !destPath.startsWith(ForgeConstants.CACHE_TOKEN_PICS_DIR))
|
|
||||||
newdespath = newdespath.replace(".jpg", ".fullborder.jpg"); //fix planes/phenomenon for round border options
|
|
||||||
}
|
|
||||||
|
|
||||||
URL url = new URL(urlToDownload);
|
URL url = new URL(urlToDownload);
|
||||||
System.out.println("Attempting to fetch: " + url);
|
System.out.println("Attempting to fetch: " + url);
|
||||||
BufferedImage image = ImageIO.read(url);
|
BufferedImage image = ImageIO.read(url);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>${revision}</version>
|
<version>2.0.04</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui-ios</artifactId>
|
<artifactId>forge-gui-ios</artifactId>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>${revision}</version>
|
<version>2.0.04</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui-mobile-dev</artifactId>
|
<artifactId>forge-gui-mobile-dev</artifactId>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>${revision}</version>
|
<version>2.0.04</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui-mobile</artifactId>
|
<artifactId>forge-gui-mobile</artifactId>
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ import java.util.*;
|
|||||||
* Class that represents the player (not the player sprite)
|
* Class that represents the player (not the player sprite)
|
||||||
*/
|
*/
|
||||||
public class AdventurePlayer implements Serializable, SaveFileContent {
|
public class AdventurePlayer implements Serializable, SaveFileContent {
|
||||||
public static final int NUMBER_OF_DECKS = 10;
|
public static final int MIN_DECK_COUNT = 10;
|
||||||
|
// this is a purely arbitrary limit, could be higher or lower; just meant as some sort of reasonable limit for the user
|
||||||
|
public static final int MAX_DECK_COUNT = 20;
|
||||||
// Player profile data.
|
// Player profile data.
|
||||||
private String name;
|
private String name;
|
||||||
private int heroRace;
|
private int heroRace;
|
||||||
@@ -45,7 +47,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
|
|
||||||
// Deck data
|
// Deck data
|
||||||
private Deck deck;
|
private Deck deck;
|
||||||
private final Deck[] decks = new Deck[NUMBER_OF_DECKS];
|
private final ArrayList<Deck> decks = new ArrayList<Deck>(MIN_DECK_COUNT);
|
||||||
private int selectedDeckIndex = 0;
|
private int selectedDeckIndex = 0;
|
||||||
private final DifficultyData difficultyData = new DifficultyData();
|
private final DifficultyData difficultyData = new DifficultyData();
|
||||||
|
|
||||||
@@ -91,9 +93,13 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
return statistic;
|
return statistic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getDeckCount() { return decks.size(); }
|
||||||
|
|
||||||
private void clearDecks() {
|
private void clearDecks() {
|
||||||
for (int i = 0; i < NUMBER_OF_DECKS; i++) decks[i] = new Deck(Forge.getLocalizer().getMessage("lblEmptyDeck"));
|
decks.clear();
|
||||||
deck = decks[0];
|
for (int i = 0; i < MIN_DECK_COUNT; i++)
|
||||||
|
decks.add(new Deck(Forge.getLocalizer().getMessage("lblEmptyDeck")));
|
||||||
|
deck = decks.get(0);
|
||||||
selectedDeckIndex = 0;
|
selectedDeckIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +146,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
announceCustom = usingCustomDeck = isUsingCustomDeck;
|
announceCustom = usingCustomDeck = isUsingCustomDeck;
|
||||||
|
|
||||||
deck = startingDeck;
|
deck = startingDeck;
|
||||||
decks[0] = deck;
|
decks.set(0, deck);
|
||||||
|
|
||||||
cards.addAllFlat(deck.getAllCardsInASinglePool().toFlatList());
|
cards.addAllFlat(deck.getAllCardsInASinglePool().toFlatList());
|
||||||
|
|
||||||
@@ -173,9 +179,9 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedDeckSlot(int slot) {
|
public void setSelectedDeckSlot(int slot) {
|
||||||
if (slot >= 0 && slot < NUMBER_OF_DECKS) {
|
if (slot >= 0 && slot < getDeckCount()) {
|
||||||
selectedDeckIndex = slot;
|
selectedDeckIndex = slot;
|
||||||
deck = decks[selectedDeckIndex];
|
deck = decks.get(selectedDeckIndex);
|
||||||
setColorIdentity(DeckProxy.getColorIdentity(deck));
|
setColorIdentity(DeckProxy.getColorIdentity(deck));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,7 +220,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Deck getDeck(int index) {
|
public Deck getDeck(int index) {
|
||||||
return decks[index];
|
return decks.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardPool getCards() {
|
public CardPool getCards() {
|
||||||
@@ -448,17 +454,44 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < NUMBER_OF_DECKS; i++) {
|
// load decks
|
||||||
if (!data.containsKey("deck_name_" + i)) {
|
// check if this save has dynamic deck count, use set-count load if not
|
||||||
if (i == 0) decks[i] = deck;
|
boolean hasDynamicDeckCount = data.containsKey("deckCount");
|
||||||
else decks[i] = new Deck(Forge.getLocalizer().getMessage("lblEmptyDeck"));
|
if (hasDynamicDeckCount) {
|
||||||
continue;
|
int dynamicDeckCount = data.readInt("deckCount");
|
||||||
|
// in case the save had previously saved more decks than the current version allows (in case of the max being lowered)
|
||||||
|
dynamicDeckCount = Math.min(MAX_DECK_COUNT, dynamicDeckCount);
|
||||||
|
for (int i = 0; i < dynamicDeckCount; i++){
|
||||||
|
// the first x elements are pre-created
|
||||||
|
if (i < MIN_DECK_COUNT) {
|
||||||
|
decks.set(i, new Deck(data.readString("deck_name_" + i)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
decks.add(new Deck(data.readString("deck_name_" + i)));
|
||||||
|
}
|
||||||
|
decks.get(i).getMain().addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("deck_" + i))));
|
||||||
|
if (data.containsKey("sideBoardCards_" + i))
|
||||||
|
decks.get(i).getOrCreate(DeckSection.Sideboard).addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("sideBoardCards_" + i))));
|
||||||
|
}
|
||||||
|
// in case we allow removing decks from the deck selection GUI, populate up to the minimum
|
||||||
|
for (int i = dynamicDeckCount++; i < MIN_DECK_COUNT; i++) {
|
||||||
|
decks.set(i, new Deck(Forge.getLocalizer().getMessage("lblEmptyDeck")));
|
||||||
|
}
|
||||||
|
// legacy load
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < MIN_DECK_COUNT; i++) {
|
||||||
|
if (!data.containsKey("deck_name_" + i)) {
|
||||||
|
if (i == 0) decks.set(i, deck);
|
||||||
|
else decks.set(i, new Deck(Forge.getLocalizer().getMessage("lblEmptyDeck")));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
decks.set(i, new Deck(data.readString("deck_name_" + i)));
|
||||||
|
decks.get(i).getMain().addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("deck_" + i))));
|
||||||
|
if (data.containsKey("sideBoardCards_" + i))
|
||||||
|
decks.get(i).getOrCreate(DeckSection.Sideboard).addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("sideBoardCards_" + i))));
|
||||||
}
|
}
|
||||||
decks[i] = new Deck(data.readString("deck_name_" + i));
|
|
||||||
decks[i].getMain().addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("deck_" + i))));
|
|
||||||
if (data.containsKey("sideBoardCards_" + i))
|
|
||||||
decks[i].getOrCreate(DeckSection.Sideboard).addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("sideBoardCards_" + i))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedDeckSlot(data.readInt("selectedDeckIndex"));
|
setSelectedDeckSlot(data.readInt("selectedDeckIndex"));
|
||||||
cards.addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("cards"))));
|
cards.addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("cards"))));
|
||||||
|
|
||||||
@@ -602,11 +635,14 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
data.storeObject("deckCards", deck.getMain().toCardList("\n").split("\n"));
|
data.storeObject("deckCards", deck.getMain().toCardList("\n").split("\n"));
|
||||||
if (deck.get(DeckSection.Sideboard) != null)
|
if (deck.get(DeckSection.Sideboard) != null)
|
||||||
data.storeObject("sideBoardCards", deck.get(DeckSection.Sideboard).toCardList("\n").split("\n"));
|
data.storeObject("sideBoardCards", deck.get(DeckSection.Sideboard).toCardList("\n").split("\n"));
|
||||||
for (int i = 0; i < NUMBER_OF_DECKS; i++) {
|
|
||||||
data.store("deck_name_" + i, decks[i].getName());
|
// save decks dynamically
|
||||||
data.storeObject("deck_" + i, decks[i].getMain().toCardList("\n").split("\n"));
|
data.store("deckCount", getDeckCount());
|
||||||
if (decks[i].get(DeckSection.Sideboard) != null)
|
for (int i = 0; i < getDeckCount(); i++) {
|
||||||
data.storeObject("sideBoardCards_" + i, decks[i].get(DeckSection.Sideboard).toCardList("\n").split("\n"));
|
data.store("deck_name_" + i, decks.get(i).getName());
|
||||||
|
data.storeObject("deck_" + i, decks.get(i).getMain().toCardList("\n").split("\n"));
|
||||||
|
if (decks.get(i).get(DeckSection.Sideboard) != null)
|
||||||
|
data.storeObject("sideBoardCards_" + i, decks.get(i).get(DeckSection.Sideboard).toCardList("\n").split("\n"));
|
||||||
}
|
}
|
||||||
data.store("selectedDeckIndex", selectedDeckIndex);
|
data.store("selectedDeckIndex", selectedDeckIndex);
|
||||||
data.storeObject("cards", cards.toCardList("\n").split("\n"));
|
data.storeObject("cards", cards.toCardList("\n").split("\n"));
|
||||||
@@ -933,7 +969,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
|
|
||||||
public void renameDeck(String text) {
|
public void renameDeck(String text) {
|
||||||
deck = (Deck) deck.copyTo(text);
|
deck = (Deck) deck.copyTo(text);
|
||||||
decks[selectedDeckIndex] = deck;
|
decks.set(selectedDeckIndex, deck);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int cardSellPrice(PaperCard card) {
|
public int cardSellPrice(PaperCard card) {
|
||||||
@@ -1182,10 +1218,23 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a deck by replacing the current selected deck with a new deck
|
* Clears a deck by replacing the current selected deck with a new deck
|
||||||
*/
|
*/
|
||||||
public void deleteDeck() {
|
public void clearDeck() {
|
||||||
deck = decks[selectedDeckIndex] = new Deck(Forge.getLocalizer().getMessage("lblEmptyDeck"));
|
deck = decks.set(selectedDeckIndex, new Deck(Forge.getLocalizer().getMessage("lblEmptyDeck")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually removes the deck from the list of decks.
|
||||||
|
*/
|
||||||
|
public void deleteDeck(){
|
||||||
|
int oldIndex = selectedDeckIndex;
|
||||||
|
this.setSelectedDeckSlot(0);
|
||||||
|
decks.remove(oldIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDeck(){
|
||||||
|
decks.add(new Deck(Forge.getLocalizer().getMessage("lblEmptyDeck")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1194,9 +1243,9 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
* @return int - index of new copy slot, or -1 if no slot was available
|
* @return int - index of new copy slot, or -1 if no slot was available
|
||||||
*/
|
*/
|
||||||
public int copyDeck() {
|
public int copyDeck() {
|
||||||
for (int i = 0; i < decks.length; i++) {
|
for (int i = 0; i < MAX_DECK_COUNT; i++) {
|
||||||
if (isEmptyDeck(i)) {
|
if (isEmptyDeck(i)) {
|
||||||
decks[i] = (Deck) deck.copyTo(deck.getName() + " (" + Forge.getLocalizer().getMessage("lblCopy") + ")");
|
decks.set(i, (Deck) deck.copyTo(deck.getName() + " (" + Forge.getLocalizer().getMessage("lblCopy") + ")"));
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1205,7 +1254,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmptyDeck(int deckIndex) {
|
public boolean isEmptyDeck(int deckIndex) {
|
||||||
return decks[deckIndex].isEmpty() && decks[deckIndex].getName().equals(Forge.getLocalizer().getMessage("lblEmptyDeck"));
|
return decks.get(deckIndex).isEmpty() && decks.get(deckIndex).getName().equals(Forge.getLocalizer().getMessage("lblEmptyDeck"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeEvent(AdventureEventData completedEvent) {
|
public void removeEvent(AdventureEventData completedEvent) {
|
||||||
@@ -1227,8 +1276,8 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
|
|
||||||
// 2. Count max cards across all decks in excess of unsellable
|
// 2. Count max cards across all decks in excess of unsellable
|
||||||
Map<PaperCard, Integer> maxCardCounts = new HashMap<>();
|
Map<PaperCard, Integer> maxCardCounts = new HashMap<>();
|
||||||
for (int i = 0; i < NUMBER_OF_DECKS; i++) {
|
for (int i = 0; i < getDeckCount(); i++) {
|
||||||
for (final Map.Entry<PaperCard, Integer> cp : decks[i].getAllCardsInASinglePool()) {
|
for (final Map.Entry<PaperCard, Integer> cp : decks.get(i).getAllCardsInASinglePool()) {
|
||||||
int count = cp.getValue();
|
int count = cp.getValue();
|
||||||
if (count > maxCardCounts.getOrDefault(cp.getKey(), 0)) {
|
if (count > maxCardCounts.getOrDefault(cp.getKey(), 0)) {
|
||||||
maxCardCounts.put(cp.getKey(), cp.getValue());
|
maxCardCounts.put(cp.getKey(), cp.getValue());
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ public class AdventureDeckEditor extends TabPageScreen<AdventureDeckEditor> {
|
|||||||
@Override
|
@Override
|
||||||
public void onActivate() {
|
public void onActivate() {
|
||||||
decksUsingMyCards = new ItemPool<>(InventoryItem.class);
|
decksUsingMyCards = new ItemPool<>(InventoryItem.class);
|
||||||
for (int i = 0; i < AdventurePlayer.NUMBER_OF_DECKS; i++) {
|
for (int i = 0; i < AdventurePlayer.current().getDeckCount(); i++) {
|
||||||
final Deck deck = AdventurePlayer.current().getDeck(i);
|
final Deck deck = AdventurePlayer.current().getDeck(i);
|
||||||
CardPool main = deck.getMain();
|
CardPool main = deck.getMain();
|
||||||
for (final Map.Entry<PaperCard, Integer> e : main) {
|
for (final Map.Entry<PaperCard, Integer> e : main) {
|
||||||
@@ -649,6 +649,7 @@ public class AdventureDeckEditor extends TabPageScreen<AdventureDeckEditor> {
|
|||||||
Map<String, CardEdition> editionsByName = new HashMap<>();
|
Map<String, CardEdition> editionsByName = new HashMap<>();
|
||||||
for (CardEdition e : FModel.getMagicDb().getEditions()) {
|
for (CardEdition e : FModel.getMagicDb().getEditions()) {
|
||||||
editionsByName.put(e.getName().toLowerCase(), e);
|
editionsByName.put(e.getName().toLowerCase(), e);
|
||||||
|
editionsByName.put(e.getName().replace(":", "").toLowerCase(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String sketchbookPrefix = "landscape sketchbook - ";
|
String sketchbookPrefix = "landscape sketchbook - ";
|
||||||
|
|||||||
@@ -16,11 +16,12 @@ import forge.adventure.util.Current;
|
|||||||
|
|
||||||
public class DeckSelectScene extends UIScene {
|
public class DeckSelectScene extends UIScene {
|
||||||
private final IntMap<TextraButton> buttons = new IntMap<>();
|
private final IntMap<TextraButton> buttons = new IntMap<>();
|
||||||
|
private final IntMap<Label> labels = new IntMap<>();
|
||||||
Color defColor;
|
Color defColor;
|
||||||
TextField textInput;
|
TextField textInput;
|
||||||
Table layout;
|
Table layout;
|
||||||
TextraLabel header;
|
TextraLabel header;
|
||||||
TextraButton back, edit, rename;
|
TextraButton back, edit, rename, add;
|
||||||
int currentSlot = 0;
|
int currentSlot = 0;
|
||||||
ScrollPane scrollPane;
|
ScrollPane scrollPane;
|
||||||
Dialog renameDialog;
|
Dialog renameDialog;
|
||||||
@@ -45,13 +46,13 @@ public class DeckSelectScene extends UIScene {
|
|||||||
root.add(header).colspan(2);
|
root.add(header).colspan(2);
|
||||||
root.row();
|
root.row();
|
||||||
root.add(scrollPane).expand().width(window.getWidth() - 20);
|
root.add(scrollPane).expand().width(window.getWidth() - 20);
|
||||||
for (int i = 0; i < AdventurePlayer.NUMBER_OF_DECKS; i++)
|
this.layoutDeckButtons();
|
||||||
addDeckSlot(Forge.getLocalizer().getMessage("lblDeck") + ": " + (i + 1), i);
|
|
||||||
|
|
||||||
textInput = Controls.newTextField("");
|
textInput = Controls.newTextField("");
|
||||||
back = ui.findActor("return");
|
back = ui.findActor("return");
|
||||||
edit = ui.findActor("edit");
|
edit = ui.findActor("edit");
|
||||||
rename = ui.findActor("rename");
|
rename = ui.findActor("rename");
|
||||||
|
add = ui.findActor("add");
|
||||||
ui.onButtonPress("return", DeckSelectScene.this::back);
|
ui.onButtonPress("return", DeckSelectScene.this::back);
|
||||||
ui.onButtonPress("edit", DeckSelectScene.this::edit);
|
ui.onButtonPress("edit", DeckSelectScene.this::edit);
|
||||||
ui.onButtonPress("rename", () -> {
|
ui.onButtonPress("rename", () -> {
|
||||||
@@ -59,11 +60,44 @@ public class DeckSelectScene extends UIScene {
|
|||||||
showRenameDialog();
|
showRenameDialog();
|
||||||
});
|
});
|
||||||
ui.onButtonPress("copy", DeckSelectScene.this::copy);
|
ui.onButtonPress("copy", DeckSelectScene.this::copy);
|
||||||
ui.onButtonPress("delete", DeckSelectScene.this::maybeDelete);
|
ui.onButtonPress("delete", DeckSelectScene.this::promptDelete);
|
||||||
|
ui.onButtonPress("add", DeckSelectScene.this::addDeck);
|
||||||
defColor = ui.findActor("return").getColor();
|
defColor = ui.findActor("return").getColor();
|
||||||
window.add(root);
|
window.add(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void refreshDeckButtons(){
|
||||||
|
clearDeckButtons();
|
||||||
|
layoutDeckButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearDeckButtons(){
|
||||||
|
int count = AdventurePlayer.current().getDeckCount();
|
||||||
|
for (int i = count; i >= 0; i--){
|
||||||
|
clearDeckButton(i);
|
||||||
|
}
|
||||||
|
layout.clearChildren();
|
||||||
|
buttons.clear();
|
||||||
|
labels.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void layoutDeckButtons() {
|
||||||
|
for (int i = 0; i < AdventurePlayer.current().getDeckCount(); i++)
|
||||||
|
addDeckButton(Forge.getLocalizer().getMessage("lblDeck") + ": " + (i + 1), i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDeck(){
|
||||||
|
if (Current.player().getDeckCount() >= AdventurePlayer.MAX_DECK_COUNT){
|
||||||
|
showDialog(createGenericDialog(Forge.getLocalizer().getMessage("lblAddDeck"), Forge.getLocalizer().getMessage("lblMaxDeckCountReached"),
|
||||||
|
Forge.getLocalizer().getMessage("lblOK"), null, this::removeDialog, null));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Current.player().addDeck();
|
||||||
|
refreshDeckButtons();
|
||||||
|
select(Current.player().getSelectedDeckIndex());
|
||||||
|
}
|
||||||
|
|
||||||
private void copy() {
|
private void copy() {
|
||||||
if (Current.player().isEmptyDeck(currentSlot)) return;
|
if (Current.player().isEmptyDeck(currentSlot)) return;
|
||||||
int index = Current.player().copyDeck();
|
int index = Current.player().copyDeck();
|
||||||
@@ -79,17 +113,32 @@ public class DeckSelectScene extends UIScene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void maybeDelete() {
|
private void promptDelete() {
|
||||||
if (Current.player().isEmptyDeck(currentSlot)) return;
|
|
||||||
Dialog deleteDialog = createGenericDialog(Forge.getLocalizer().getMessage("lblDelete"), Forge.getLocalizer().getMessage("lblAreYouSureProceedDelete"),
|
Dialog deleteDialog = createGenericDialog(Forge.getLocalizer().getMessage("lblDelete"), Forge.getLocalizer().getMessage("lblAreYouSureProceedDelete"),
|
||||||
Forge.getLocalizer().getMessage("lblOK"),
|
Forge.getLocalizer().getMessage("lblOK"),
|
||||||
Forge.getLocalizer().getMessage("lblAbort"), this::delete, this::removeDialog);
|
Forge.getLocalizer().getMessage("lblAbort"), this::clearOrDelete, this::removeDialog);
|
||||||
|
|
||||||
showDialog(deleteDialog);
|
showDialog(deleteDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void delete() {
|
/**
|
||||||
Current.player().deleteDeck();
|
* Clears or deletes the currently selected deck.
|
||||||
|
*/
|
||||||
|
private void clearOrDelete(){
|
||||||
|
if (currentSlot >= AdventurePlayer.MIN_DECK_COUNT){
|
||||||
|
Current.player().deleteDeck();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Current.player().clearDeck();
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshDeckButtons();
|
||||||
|
select(0);
|
||||||
|
removeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clear() {
|
||||||
|
Current.player().clearDeck();
|
||||||
updateDeckButton(currentSlot);
|
updateDeckButton(currentSlot);
|
||||||
removeDialog();
|
removeDialog();
|
||||||
}
|
}
|
||||||
@@ -117,7 +166,18 @@ public class DeckSelectScene extends UIScene {
|
|||||||
showDialog(renameDialog);
|
showDialog(renameDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TextraButton addDeckSlot(String name, int i) {
|
/**
|
||||||
|
* Not sure if this is strictly necessary in Java but wouldn't want to leak before clearing the layout table.
|
||||||
|
*/
|
||||||
|
private void clearDeckButton(int i){
|
||||||
|
if (buttons.containsKey(i)) {
|
||||||
|
TextraButton button = buttons.remove(i);
|
||||||
|
button.clearListeners();
|
||||||
|
button.clearActions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextraButton addDeckButton(String name, int i) {
|
||||||
TextraButton button = Controls.newTextButton("-");
|
TextraButton button = Controls.newTextButton("-");
|
||||||
button.addListener(new ClickListener() {
|
button.addListener(new ClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -131,9 +191,12 @@ public class DeckSelectScene extends UIScene {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
button.setText(Current.player().getDeck(i).getName());
|
||||||
|
Label label = Controls.newLabel(name);
|
||||||
layout.add(Controls.newLabel(name)).pad(2);
|
layout.add(Controls.newLabel(name)).pad(2);
|
||||||
layout.add(button).fill(true, false).expand(true, false).align(Align.left).expandX().pad(2);
|
layout.add(button).fill(true, false).expand(true, false).align(Align.left).expandX().pad(2);
|
||||||
buttons.put(i, button);
|
buttons.put(i, button);
|
||||||
|
labels.put(i, label);
|
||||||
addToSelectable(new Selectable(button));
|
addToSelectable(new Selectable(button));
|
||||||
layout.row();
|
layout.row();
|
||||||
return button;
|
return button;
|
||||||
@@ -158,13 +221,7 @@ public class DeckSelectScene extends UIScene {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enter() {
|
public void enter() {
|
||||||
for (int i = 0; i < AdventurePlayer.NUMBER_OF_DECKS; i++) {
|
refreshDeckButtons();
|
||||||
if (buttons.containsKey(i)) {
|
|
||||||
buttons.get(i).setText(Current.player().getDeck(i).getName());
|
|
||||||
buttons.get(i).getTextraLabel().layout();
|
|
||||||
buttons.get(i).layout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GameHUD.getInstance().switchAudio();
|
GameHUD.getInstance().switchAudio();
|
||||||
select(Current.player().getSelectedDeckIndex());
|
select(Current.player().getSelectedDeckIndex());
|
||||||
performTouch(scrollPane); //can use mouse wheel if available to scroll after selection
|
performTouch(scrollPane); //can use mouse wheel if available to scroll after selection
|
||||||
@@ -175,9 +232,7 @@ public class DeckSelectScene extends UIScene {
|
|||||||
private void rename() {
|
private void rename() {
|
||||||
String text = textInput.getText();
|
String text = textInput.getText();
|
||||||
Current.player().renameDeck(text);
|
Current.player().renameDeck(text);
|
||||||
buttons.get(currentSlot).setText(Current.player().getDeck(currentSlot).getName());
|
updateDeckButton(currentSlot);
|
||||||
buttons.get(currentSlot).getTextraLabel().layout();
|
|
||||||
buttons.get(currentSlot).layout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void edit() {
|
private void edit() {
|
||||||
|
|||||||
@@ -511,13 +511,11 @@ public class EventScene extends MenuScene implements IAfterMatch {
|
|||||||
|
|
||||||
if (match.p1 instanceof AdventureEventData.AdventureEventHuman) {
|
if (match.p1 instanceof AdventureEventData.AdventureEventHuman) {
|
||||||
humanMatch = match;
|
humanMatch = match;
|
||||||
continue;
|
|
||||||
} else if (match.p2 instanceof AdventureEventData.AdventureEventHuman) {
|
} else if (match.p2 instanceof AdventureEventData.AdventureEventHuman) {
|
||||||
AdventureEventData.AdventureEventParticipant placeholder = match.p1;
|
AdventureEventData.AdventureEventParticipant placeholder = match.p1;
|
||||||
match.p1 = match.p2;
|
match.p1 = match.p2;
|
||||||
match.p2 = placeholder;
|
match.p2 = placeholder;
|
||||||
humanMatch = match;
|
humanMatch = match;
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
//Todo: Actually run match simulation here
|
//Todo: Actually run match simulation here
|
||||||
if (MyRandom.percentTrue(50)) {
|
if (MyRandom.percentTrue(50)) {
|
||||||
@@ -530,7 +528,6 @@ public class EventScene extends MenuScene implements IAfterMatch {
|
|||||||
match.winner = match.p2;
|
match.winner = match.p2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (humanMatch != null && humanMatch.round != currentEvent.currentRound)
|
if (humanMatch != null && humanMatch.round != currentEvent.currentRound)
|
||||||
@@ -539,14 +536,16 @@ public class EventScene extends MenuScene implements IAfterMatch {
|
|||||||
DuelScene duelScene = DuelScene.instance();
|
DuelScene duelScene = DuelScene.instance();
|
||||||
EnemySprite enemy = humanMatch.p2.getSprite();
|
EnemySprite enemy = humanMatch.p2.getSprite();
|
||||||
currentEvent.nextOpponent = humanMatch.p2;
|
currentEvent.nextOpponent = humanMatch.p2;
|
||||||
|
advance.setDisabled(true);
|
||||||
FThreads.invokeInEdtNowOrLater(() -> Forge.setTransitionScreen(new TransitionScreen(() -> {
|
FThreads.invokeInEdtNowOrLater(() -> Forge.setTransitionScreen(new TransitionScreen(() -> {
|
||||||
duelScene.initDuels(WorldStage.getInstance().getPlayerSprite(), enemy, false, currentEvent);
|
duelScene.initDuels(WorldStage.getInstance().getPlayerSprite(), enemy, false, currentEvent);
|
||||||
|
advance.setDisabled(false);
|
||||||
Forge.switchScene(duelScene);
|
Forge.switchScene(duelScene);
|
||||||
}, Forge.takeScreenshot(), true, false, false, false, "", Current.player().avatar(), enemy.getAtlasPath(), Current.player().getName(), enemy.getName(), humanMatch.p1.getRecord(), humanMatch.p2.getRecord())));
|
}, Forge.takeScreenshot(), true, false, false, false, "", Current.player().avatar(), enemy.getAtlasPath(), Current.player().getName(), enemy.getName(), humanMatch.p1.getRecord(), humanMatch.p2.getRecord())));
|
||||||
} else {
|
} else {
|
||||||
finishRound();
|
finishRound();
|
||||||
|
advance.setDisabled(false);
|
||||||
}
|
}
|
||||||
advance.setDisabled(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AdventureEventData.AdventureEventMatch humanMatch = null;
|
AdventureEventData.AdventureEventMatch humanMatch = null;
|
||||||
|
|||||||
@@ -249,6 +249,27 @@ public class Controls {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public SelectBox<Integer> newComboBox(Integer[] text, int item, Function<Object, Void> func) {
|
||||||
|
SelectBox<Integer> ret = newComboBox();
|
||||||
|
ret.getStyle().listStyle.selection.setTopHeight(4);
|
||||||
|
ret.setItems(text);
|
||||||
|
ret.addListener(new ChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void changed(ChangeEvent event, Actor actor) {
|
||||||
|
try {
|
||||||
|
func.apply(((SelectBox) actor).getSelected());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
func.apply(item);
|
||||||
|
ret.getList().setAlignment(Align.center);
|
||||||
|
ret.setSelected(item);
|
||||||
|
ret.setAlignment(Align.right);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static public TextField newTextField(String text) {
|
static public TextField newTextField(String text) {
|
||||||
return new TextField(text, getSkin());
|
return new TextField(text, getSkin());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
|
|||||||
|
|
||||||
if(reward.type.equals(Reward.Type.Card)) {
|
if(reward.type.equals(Reward.Type.Card)) {
|
||||||
imageKey = reward.getCard().getImageKey(false);
|
imageKey = reward.getCard().getImageKey(false);
|
||||||
|
PaperCard card = ImageUtil.getPaperCardFromImageKey(imageKey);
|
||||||
|
imageKey = card.getCardImageKey();
|
||||||
|
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -246,7 +248,8 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
|
|||||||
hasbackface = reward.getCard().hasBackFace();
|
hasbackface = reward.getCard().hasBackFace();
|
||||||
if (ImageCache.getInstance().imageKeyFileExists(reward.getCard().getImageKey(false)) && !Forge.enableUIMask.equals("Art")) {
|
if (ImageCache.getInstance().imageKeyFileExists(reward.getCard().getImageKey(false)) && !Forge.enableUIMask.equals("Art")) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
File frontFace = ImageKeys.getImageFile(reward.getCard().getImageKey(false));
|
PaperCard card = ImageUtil.getPaperCardFromImageKey(reward.getCard().getImageKey(false));
|
||||||
|
File frontFace = ImageKeys.getImageFile(card.getCardImageKey());
|
||||||
if (frontFace != null) {
|
if (frontFace != null) {
|
||||||
try {
|
try {
|
||||||
Texture front = Forge.getAssets().manager().get(frontFace.getPath(), Texture.class, false);
|
Texture front = Forge.getAssets().manager().get(frontFace.getPath(), Texture.class, false);
|
||||||
@@ -272,7 +275,8 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
|
|||||||
//preload card back for performance
|
//preload card back for performance
|
||||||
if (hasbackface) {
|
if (hasbackface) {
|
||||||
if (ImageCache.getInstance().imageKeyFileExists(reward.getCard().getImageKey(true))) {
|
if (ImageCache.getInstance().imageKeyFileExists(reward.getCard().getImageKey(true))) {
|
||||||
File backFace = ImageKeys.getImageFile(reward.getCard().getImageKey(true));
|
PaperCard cardBack = ImageUtil.getPaperCardFromImageKey(reward.getCard().getImageKey(true));
|
||||||
|
File backFace = ImageKeys.getImageFile(cardBack.getCardAltImageKey());
|
||||||
if (backFace != null) {
|
if (backFace != null) {
|
||||||
try {
|
try {
|
||||||
Texture back = Forge.getAssets().manager().get(backFace.getPath(), Texture.class, false);
|
Texture back = Forge.getAssets().manager().get(backFace.getPath(), Texture.class, false);
|
||||||
@@ -396,7 +400,8 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
|
|||||||
if (imageKey != "") {
|
if (imageKey != "") {
|
||||||
isBooster = true;
|
isBooster = true;
|
||||||
File file = new File(IMAGE_LIST_QUEST_BOOSTERS_FILE);
|
File file = new File(IMAGE_LIST_QUEST_BOOSTERS_FILE);
|
||||||
try (Scanner scanner = new Scanner(file)) {
|
try {
|
||||||
|
Scanner scanner = new Scanner(file);
|
||||||
String boosterPath = "";
|
String boosterPath = "";
|
||||||
while(scanner.hasNextLine())
|
while(scanner.hasNextLine())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -247,6 +247,9 @@ public class ImageCache {
|
|||||||
imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.BACKFACE_POSTFIX.length());
|
imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.BACKFACE_POSTFIX.length());
|
||||||
}
|
}
|
||||||
if (imageKey.startsWith(ImageKeys.CARD_PREFIX)) {
|
if (imageKey.startsWith(ImageKeys.CARD_PREFIX)) {
|
||||||
|
PaperCard card = ImageUtil.getPaperCardFromImageKey(imageKey);
|
||||||
|
if (card != null)
|
||||||
|
imageKey = altState ? card.getCardAltImageKey() : card.getCardImageKey();
|
||||||
if (StringUtils.isBlank(imageKey)) {
|
if (StringUtils.isBlank(imageKey)) {
|
||||||
if (useDefaultIfNotFound)
|
if (useDefaultIfNotFound)
|
||||||
return getDefaultImage();
|
return getDefaultImage();
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import java.util.List;
|
|||||||
|
|
||||||
import forge.ImageKeys;
|
import forge.ImageKeys;
|
||||||
import forge.assets.*;
|
import forge.assets.*;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.util.ImageUtil;
|
||||||
import forge.util.TextBounds;
|
import forge.util.TextBounds;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
@@ -156,7 +156,13 @@ public class CardImageRenderer {
|
|||||||
}
|
}
|
||||||
//space for artist
|
//space for artist
|
||||||
textBoxHeight -= 2 * PT_FONT.getCapHeight();
|
textBoxHeight -= 2 * PT_FONT.getCapHeight();
|
||||||
String artist = ObjectUtils.firstNonNull(state.getArtist(), "WOTC");
|
PaperCard paperCard = null;
|
||||||
|
try {
|
||||||
|
paperCard = ImageUtil.getPaperCardFromImageKey(state.getImageKey());
|
||||||
|
} catch (Exception e) {}
|
||||||
|
String artist = "WOTC";
|
||||||
|
if (paperCard != null && !paperCard.getArtist().isEmpty())
|
||||||
|
artist = paperCard.getArtist();
|
||||||
float minTextBoxHeight = 2 * headerHeight;
|
float minTextBoxHeight = 2 * headerHeight;
|
||||||
if (textBoxHeight < minTextBoxHeight) {
|
if (textBoxHeight < minTextBoxHeight) {
|
||||||
artHeight -= (minTextBoxHeight - textBoxHeight); //subtract from art height if text box not big enough otherwise
|
artHeight -= (minTextBoxHeight - textBoxHeight); //subtract from art height if text box not big enough otherwise
|
||||||
|
|||||||
@@ -103,22 +103,27 @@ public class CardZoom extends FOverlay {
|
|||||||
if (pc != null) {
|
if (pc != null) {
|
||||||
Card cardW = Card.fromPaperCard(pc, null);
|
Card cardW = Card.fromPaperCard(pc, null);
|
||||||
cardW.setState(CardStateName.SpecializeW, true);
|
cardW.setState(CardStateName.SpecializeW, true);
|
||||||
|
cardW.setImageKey(pc, CardStateName.SpecializeW);
|
||||||
list.add(cardW.getView());
|
list.add(cardW.getView());
|
||||||
|
|
||||||
Card cardU = Card.fromPaperCard(pc, null);
|
Card cardU = Card.fromPaperCard(pc, null);
|
||||||
cardU.setState(CardStateName.SpecializeU, true);;
|
cardU.setState(CardStateName.SpecializeU, true);
|
||||||
|
cardU.setImageKey(pc, CardStateName.SpecializeU);
|
||||||
list.add(cardU.getView());
|
list.add(cardU.getView());
|
||||||
|
|
||||||
Card cardB = Card.fromPaperCard(pc, null);
|
Card cardB = Card.fromPaperCard(pc, null);
|
||||||
cardB.setState(CardStateName.SpecializeB, true);
|
cardB.setState(CardStateName.SpecializeB, true);
|
||||||
|
cardB.setImageKey(pc, CardStateName.SpecializeB);
|
||||||
list.add(cardB.getView());
|
list.add(cardB.getView());
|
||||||
|
|
||||||
Card cardR = Card.fromPaperCard(pc, null);
|
Card cardR = Card.fromPaperCard(pc, null);
|
||||||
cardR.setState(CardStateName.SpecializeR, true);
|
cardR.setState(CardStateName.SpecializeR, true);
|
||||||
|
cardR.setImageKey(pc, CardStateName.SpecializeR);
|
||||||
list.add(cardR.getView());
|
list.add(cardR.getView());
|
||||||
|
|
||||||
Card cardG = Card.fromPaperCard(pc, null);
|
Card cardG = Card.fromPaperCard(pc, null);
|
||||||
cardG.setState(CardStateName.SpecializeG, true);
|
cardG.setState(CardStateName.SpecializeG, true);
|
||||||
|
cardG.setImageKey(pc, CardStateName.SpecializeG);
|
||||||
list.add(cardG.getView());
|
list.add(cardG.getView());
|
||||||
}
|
}
|
||||||
if (!list.isEmpty())
|
if (!list.isEmpty())
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>${revision}</version>
|
<version>2.0.04</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui</artifactId>
|
<artifactId>forge-gui</artifactId>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
<object id="53" template="../../obj/treasure.tx" x="194" y="125"/>
|
<object id="53" template="../../obj/treasure.tx" x="194" y="125"/>
|
||||||
<object id="54" template="../../obj/enemy.tx" x="201.253" y="161.473">
|
<object id="54" template="../../obj/enemy.tx" x="201.253" y="161.473">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="effect" value="{ "startBattleWithCard": [ "Dreadhorde Invasion" }"/>
|
<property name="effect" value="{ "startBattleWithCard": ["Dreadhorde Invasion"]}"/>
|
||||||
<property name="enemy" value="Big Zombie"/>
|
<property name="enemy" value="Big Zombie"/>
|
||||||
<property name="speedModifier" type="float" value="3"/>
|
<property name="speedModifier" type="float" value="3"/>
|
||||||
<property name="threatRange" type="int" value="60"/>
|
<property name="threatRange" type="int" value="60"/>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Deathknightidle.png
|
deathknightidle.png
|
||||||
size: 80,16
|
size: 80,16
|
||||||
format: RGBA8888
|
format: RGBA8888
|
||||||
filter: Nearest,Nearest
|
filter: Nearest,Nearest
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
"width": 100,
|
"width": 100,
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"x": 365,
|
"x": 365,
|
||||||
"y": 60
|
"y": 50
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "TextButton",
|
"type": "TextButton",
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
"width": 100,
|
"width": 100,
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"x": 365,
|
"x": 365,
|
||||||
"y": 110
|
"y": 90
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "TextButton",
|
"type": "TextButton",
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
"width": 100,
|
"width": 100,
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"x": 365,
|
"x": 365,
|
||||||
"y": 160
|
"y": 130
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "TextButton",
|
"type": "TextButton",
|
||||||
@@ -62,6 +62,15 @@
|
|||||||
"width": 100,
|
"width": 100,
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"x": 365,
|
"x": 365,
|
||||||
|
"y": 170
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "add",
|
||||||
|
"text": "tr(lblAddDeck)",
|
||||||
|
"width": 100,
|
||||||
|
"height": 30,
|
||||||
|
"x": 365,
|
||||||
"y": 210
|
"y": 210
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -15,33 +15,42 @@
|
|||||||
"x": 4,
|
"x": 4,
|
||||||
"y": 4,
|
"y": 4,
|
||||||
"width": 262,
|
"width": 262,
|
||||||
"height": 414
|
"height": 384
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "add",
|
||||||
|
"text": "tr(lblAddDeck)",
|
||||||
|
"width": 130,
|
||||||
|
"height": 30,
|
||||||
|
"x": 4,
|
||||||
|
"y": 388
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "TextButton",
|
"type": "TextButton",
|
||||||
"name": "delete",
|
"name": "delete",
|
||||||
"text": "tr(lblDelete)",
|
"text": "tr(lblDelete)",
|
||||||
"width": 86,
|
"width": 130,
|
||||||
|
"height": 30,
|
||||||
|
"x": 136,
|
||||||
|
"y": 388
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "copy",
|
||||||
|
"text": "tr(lblCopy)",
|
||||||
|
"width": 130,
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"x": 4,
|
"x": 4,
|
||||||
"y": 418
|
"y": 418
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "TextButton",
|
|
||||||
"name": "copy",
|
|
||||||
"text": "tr(lblCopy)",
|
|
||||||
"width": 86,
|
|
||||||
"height": 30,
|
|
||||||
"x": 92,
|
|
||||||
"y": 418
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "TextButton",
|
"type": "TextButton",
|
||||||
"name": "rename",
|
"name": "rename",
|
||||||
"text": "tr(lblRename)",
|
"text": "tr(lblRename)",
|
||||||
"width": 86,
|
"width": 130,
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"x": 180,
|
"x": 136,
|
||||||
"y": 418
|
"y": 418
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -141,3 +141,4 @@ Pioneer Masters, 3/6/PIO, PIO
|
|||||||
Innistrad Remastered, 3/6/INR, INR
|
Innistrad Remastered, 3/6/INR, INR
|
||||||
Aetherdrift, 3/6/DFT, DFT
|
Aetherdrift, 3/6/DFT, DFT
|
||||||
Tarkir Dragonstorm, 3/6/TDM, TDM
|
Tarkir Dragonstorm, 3/6/TDM, TDM
|
||||||
|
Final Fantasy, 3/6/FIN, FIN
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ A:SP$ Charm | Choices$ DBTokens,DBTap | CharmNum$ 1
|
|||||||
SVar:DBTokens:DB$ Token | TokenScript$ c_1_1_hero | TokenOwner$ You | TokenAmount$ 3 | SpellDescription$ Take the Elevator — Create three 1/1 colorless Hero creature tokens.
|
SVar:DBTokens:DB$ Token | TokenScript$ c_1_1_hero | TokenOwner$ You | TokenAmount$ 3 | SpellDescription$ Take the Elevator — Create three 1/1 colorless Hero creature tokens.
|
||||||
SVar:DBTap:DB$ Tap | ValidTgts$ Creature | TargetMin$ 0 | TargetMax$ 3 | TgtPrompt$ Select up to three target creatures | SubAbility$ DBPutCounter | SpellDescription$ Take 59 Flights of Stairs — Tap up to three target creatures. Put a stun counter on one of them.
|
SVar:DBTap:DB$ Tap | ValidTgts$ Creature | TargetMin$ 0 | TargetMax$ 3 | TgtPrompt$ Select up to three target creatures | SubAbility$ DBPutCounter | SpellDescription$ Take 59 Flights of Stairs — Tap up to three target creatures. Put a stun counter on one of them.
|
||||||
SVar:DBPutCounter:DB$ PutCounter | Choices$ Creature.targetedBy | CounterType$ Stun | CounterNum$ 1
|
SVar:DBPutCounter:DB$ PutCounter | Choices$ Creature.targetedBy | CounterType$ Stun | CounterNum$ 1
|
||||||
Oracle:Choose one—\n• Take the Elevator — Create three 1/1 colorless Hero creature tokens.\n• Take 59 Flights of Stairs — Tap up to three target creatures. Put a stun counter on one of them. (If a permanent with a stun counter would become untapped, remove one from it instead.)
|
Oracle:Choose one —\n• Take the Elevator — Create three 1/1 colorless Hero creature tokens.\n• Take 59 Flights of Stairs — Tap up to three target creatures. Put a stun counter on one of them. (If a permanent with a stun counter would become untapped, remove one from it instead.)
|
||||||
@@ -3,7 +3,7 @@ ManaCost:1 B
|
|||||||
Types:Enchantment Aura
|
Types:Enchantment Aura
|
||||||
K:Enchant:Creature.inZoneGraveyard:creature card in a graveyard
|
K:Enchant:Creature.inZoneGraveyard:creature card in a graveyard
|
||||||
SVar:AttachAILogic:Reanimate
|
SVar:AttachAILogic:Reanimate
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReanimate | TriggerDescription$ When CARDNAME enters, if it's on the battlefield, it loses "enchant creature card in a graveyard" and gains "enchant creature put onto the battlefield with CARDNAME." Return enchanted creature card to the battlefield under your control and attach CARDNAME to it. When CARDNAME leaves the battlefield, that creature's controller sacrifices it.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | IsPresent$ Card.StrictlySelf | Execute$ TrigReanimate | TriggerDescription$ When CARDNAME enters, if it's on the battlefield, it loses "enchant creature card in a graveyard" and gains "enchant creature put onto the battlefield with CARDNAME." Return enchanted creature card to the battlefield under your control and attach CARDNAME to it. When CARDNAME leaves the battlefield, that creature's controller sacrifices it.
|
||||||
SVar:TrigReanimate:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ Enchanted | RememberChanged$ True | GainControl$ True | SubAbility$ DBAnimate
|
SVar:TrigReanimate:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ Enchanted | RememberChanged$ True | GainControl$ True | SubAbility$ DBAnimate
|
||||||
SVar:DBAnimate:DB$ Animate | Defined$ Self | Keywords$ Enchant:Creature.IsRemembered:creature put onto the battlefield with CARDNAME | RemoveKeywords$ Enchant:Creature.inZoneGraveyard:creature card in a graveyard | Duration$ Permanent | SubAbility$ DBAttach
|
SVar:DBAnimate:DB$ Animate | Defined$ Self | Keywords$ Enchant:Creature.IsRemembered:creature put onto the battlefield with CARDNAME | RemoveKeywords$ Enchant:Creature.inZoneGraveyard:creature card in a graveyard | Duration$ Permanent | SubAbility$ DBAttach
|
||||||
SVar:DBAttach:DB$ Attach | Defined$ Remembered | SubAbility$ DBDelay
|
SVar:DBAttach:DB$ Attach | Defined$ Remembered | SubAbility$ DBDelay
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ SVar:DBUntap:DB$ Untap
|
|||||||
A:AB$ PumpAll | Cost$ R | ValidCards$ Creature.YouCtrl | KW$ Haste | Exhaust$ True | SpellDescription$ Creatures you control gain haste until end of turn.
|
A:AB$ PumpAll | Cost$ R | ValidCards$ Creature.YouCtrl | KW$ Haste | Exhaust$ True | SpellDescription$ Creatures you control gain haste until end of turn.
|
||||||
DeckHas:Ability$Graveyard
|
DeckHas:Ability$Graveyard
|
||||||
DeckHints:Name$Audacious Knuckleblade
|
DeckHints:Name$Audacious Knuckleblade
|
||||||
Oracle:Exhaust — {2}{G}: Seek a card named Audacious Knuckleblade and put it onto the battlefield tapped.\nExhaust — {1}{U}: Surveil 2, then untap this creature./nExhaust — {R}: Creatures you control gain haste until end of turn.
|
Oracle:Exhaust — {2}{G}: Seek a card named Audacious Knuckleblade and put it onto the battlefield tapped.\nExhaust — {1}{U}: Surveil 2, then untap this creature.\nExhaust — {R}: Creatures you control gain haste until end of turn.
|
||||||
@@ -9,4 +9,4 @@ SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ Count$DifferentCounterKinds_Ca
|
|||||||
SVar:DBEffect:DB$ Effect | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | StaticAbilities$ Unblockable
|
SVar:DBEffect:DB$ Effect | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | StaticAbilities$ Unblockable
|
||||||
SVar:Unblockable:Mode$ CantBlockBy | ValidAttacker$ Card.IsRemembered | Description$ This creature can't be blocked this turn.
|
SVar:Unblockable:Mode$ CantBlockBy | ValidAttacker$ Card.IsRemembered | Description$ This creature can't be blocked this turn.
|
||||||
SVar:X:Count$xPaid
|
SVar:X:Count$xPaid
|
||||||
Oracle:When this artifact enters, support X. (Put a +1/+1 counter on each of up to X target creatures.)\nGo for the Goal! — {3},{T}: Until end of turn, target creature gains "Whenever this creature deals combat damage to a player, draw a card for each kind of counter on it" and it can't be blocked this turn.
|
Oracle:When this artifact enters, support X. (Put a +1/+1 counter on each of up to X target creatures.)\nGo for the Goal! — {3}, {T}: Until end of turn, target creature gains "Whenever this creature deals combat damage to a player, draw a card for each kind of counter on it" and it can't be blocked this turn.
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user