mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-13 01:08:06 +00:00
Compare commits
4 Commits
betterImag
...
Hanmac-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a21656521f | ||
|
|
bdec4095c0 | ||
|
|
8475456c0b | ||
|
|
651caccd71 |
@@ -39,9 +39,6 @@ public final class ImageKeys {
|
||||
public static final String SPECFACE_R = "$rspec";
|
||||
public static final String SPECFACE_G = "$gspec";
|
||||
|
||||
private static final String URL_SCRYFALL = "https://api.scryfall.com";
|
||||
public static final String URL_PIC_SCRYFALL_DOWNLOAD = URL_SCRYFALL + "/cards/";
|
||||
|
||||
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;
|
||||
public static String ADVENTURE_CARD_PICS_DIR;
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package forge.item;
|
||||
|
||||
public enum ArtStyle {
|
||||
Normal("fullborder", "normal"),
|
||||
Crop("artcrop", "art_crop");
|
||||
|
||||
public final String filename;
|
||||
public final String scryfall;
|
||||
ArtStyle(String filename, String scryfall) {
|
||||
this.filename = filename;
|
||||
this.scryfall = scryfall;
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
package forge.item;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ImageKeys;
|
||||
import forge.StaticData;
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.CardStateName;
|
||||
|
||||
public record ImageKey(String setCode, String name, String collectorNumber, String artistName, CardStateName state, ImageType type, boolean custom) implements Serializable
|
||||
{
|
||||
|
||||
public List<String> getFilename(ArtStyle art) {
|
||||
List<String> result = Lists.newArrayList();
|
||||
String cn = collectorNumber;
|
||||
if (type == ImageType.Token) {
|
||||
if (ImageKeys.HIDDEN_CARD.equals(name)) {
|
||||
// hidden only exist as png
|
||||
result.add("hidden.png");
|
||||
return result;
|
||||
}
|
||||
// TODO Token doesn't use fullborder or artcrop ArtStyle yet
|
||||
if (!StringUtils.isEmpty(setCode) && !setCode.equals(CardEdition.UNKNOWN_CODE)) {
|
||||
if (!StringUtils.isEmpty(cn) && !cn.equals(IPaperCard.NO_COLLECTOR_NUMBER)) {
|
||||
result.add(setCode + "/" + cn + "_" + name);
|
||||
}
|
||||
result.add(setCode + "/" + name);
|
||||
}
|
||||
result.add(name);
|
||||
} else if (type == ImageType.Card) {
|
||||
if (!StringUtils.isEmpty(setCode) && !setCode.equals(CardEdition.UNKNOWN_CODE)) {
|
||||
if (!StringUtils.isEmpty(cn) && !cn.equals(IPaperCard.NO_COLLECTOR_NUMBER)) {
|
||||
result.add(setCode + "/" + cn + "_" + name + "." + art.filename);
|
||||
}
|
||||
result.add(setCode + "/" + name + "." + art.filename);
|
||||
}
|
||||
result.add(name + "." + art.filename);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Pair<String, String> getDownloadUrl(ArtStyle art) {
|
||||
if (custom) {
|
||||
return null;
|
||||
}
|
||||
if (type == ImageType.Token && ImageKeys.HIDDEN_CARD.equals(name)) {
|
||||
return Pair.of("hidden.png", "https://cards.scryfall.io/back.png");
|
||||
}
|
||||
if (StringUtils.isEmpty(collectorNumber) || collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)) {
|
||||
return null;
|
||||
}
|
||||
// Scryfall only for Cards or Tokens
|
||||
if (type != ImageType.Card && type != ImageType.Token) {
|
||||
return null;
|
||||
}
|
||||
if (StringUtils.isEmpty(setCode) || setCode.equals(CardEdition.UNKNOWN_CODE)) {
|
||||
return null;
|
||||
}
|
||||
CardEdition edition = StaticData.instance().getCardEdition(setCode);
|
||||
if (edition == null || edition.getType() == CardEdition.Type.CUSTOM_SET) return null;
|
||||
// differ token code
|
||||
String setCode = type == ImageType.Card ? edition.getScryfallCode() : edition.getTokensCode();
|
||||
String langCode = edition.getCardsLangCode();
|
||||
String faceParam = "";
|
||||
switch(state) {
|
||||
case Modal:
|
||||
case Secondary:
|
||||
case Transformed:
|
||||
faceParam = "&face=back";
|
||||
break;
|
||||
default:
|
||||
faceParam = "&face=front";
|
||||
break;
|
||||
}
|
||||
|
||||
String ext = art.scryfall == "png" ? ".png" : ".jpg";
|
||||
String filepath = setCode + "/" + collectorNumber + "_" + name + ext;
|
||||
// TODO make scryfall art_crop of split cards separate
|
||||
String collectorNumberEncoded;
|
||||
try {
|
||||
// encode with Charset isn't supported on Android
|
||||
collectorNumberEncoded = URLEncoder.encode(collectorNumber, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
collectorNumberEncoded = collectorNumber;
|
||||
}
|
||||
|
||||
String url = ImageKeys.URL_PIC_SCRYFALL_DOWNLOAD + String.format(
|
||||
"%s/%s/%s?format=image&version=%s%s", setCode, collectorNumberEncoded, langCode, art.scryfall, faceParam
|
||||
);
|
||||
return Pair.of(filepath, url);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package forge.item;
|
||||
|
||||
public enum ImageType {
|
||||
Card,
|
||||
Token,
|
||||
Booster,
|
||||
FatPack,
|
||||
BoosterBox,
|
||||
Precon,
|
||||
TournamentPack,
|
||||
;
|
||||
}
|
||||
@@ -523,29 +523,6 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
||||
return StaticData.instance().isRebalanced(name);
|
||||
}
|
||||
|
||||
public String getCollectorNumberSuffix(CardStateName state) {
|
||||
if (this.collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)) {
|
||||
return "";
|
||||
}
|
||||
if (getRules().getSplitType() == CardSplitType.Meld) {
|
||||
return state == CardStateName.Meld ? "b" : "a";
|
||||
}
|
||||
switch(state) {
|
||||
case SpecializeB:
|
||||
return "b";
|
||||
case SpecializeG:
|
||||
return "g";
|
||||
case SpecializeR:
|
||||
return "r";
|
||||
case SpecializeU:
|
||||
return "u";
|
||||
case SpecializeW:
|
||||
return "w";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains properties of a card which distinguish it from an otherwise identical copy of the card with the same
|
||||
* name, edition, and collector number. Examples include permanent markings on the card, and flags for Adventure
|
||||
|
||||
@@ -4234,12 +4234,12 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|
||||
return ImmutableList.of();
|
||||
}
|
||||
Iterable<CardChangedType> byText = changedTypeByText == null ? ImmutableList.of() : ImmutableList.of(this.changedTypeByText);
|
||||
return ImmutableList.copyOf(Iterables.concat(
|
||||
changedCardTypesByText.values(), // Layer 3
|
||||
byText, // Layer 3 by Word Changes,
|
||||
changedCardTypesCharacterDefining.values(), // Layer 4
|
||||
changedCardTypes.values() // Layer 6
|
||||
));
|
||||
return ImmutableList.<CardChangedType>builder()
|
||||
.addAll(changedCardTypesByText.values()) // Layer 3
|
||||
.addAll(byText) // Layer 3 by Word Changes,
|
||||
.addAll(changedCardTypesCharacterDefining.values()) // Layer 4
|
||||
.addAll(changedCardTypes.values()) // Layer 6
|
||||
.build();
|
||||
}
|
||||
|
||||
public boolean clearChangedCardTypes() {
|
||||
|
||||
@@ -904,10 +904,8 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
runParams.put(AbilityKey.CounterAmount, oldValue + i + 1);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.CounterAdded, AbilityKey.newMap(runParams), false);
|
||||
}
|
||||
if (addAmount > 0) {
|
||||
runParams.put(AbilityKey.CounterAmount, addAmount);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.CounterAddedOnce, AbilityKey.newMap(runParams), false);
|
||||
}
|
||||
runParams.put(AbilityKey.CounterAmount, addAmount);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.CounterAddedOnce, AbilityKey.newMap(runParams), false);
|
||||
if (table != null) {
|
||||
table.put(source, this, counterType, addAmount);
|
||||
}
|
||||
@@ -3605,7 +3603,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
}
|
||||
|
||||
String trigStr = "Mode$ Phase | Phase$ Main1 | ValidPlayer$ You | TriggerZones$ Command | TriggerDescription$ " +
|
||||
"At the beginning of your precombat main phase, if you have any rad counters, mill that many cards. For each nonland card milled this way, you lose 1 life and a rad counter.";
|
||||
"At the beginning of your precombat main phase, if you have any rad counters, mill that many cards. For each nonland card milled this way, you lose 1 life and a rad counter.";
|
||||
|
||||
Trigger tr = TriggerHandler.parseTrigger(trigStr, radiationEffect, true);
|
||||
SpellAbility sa = AbilityFactory.getAbility("DB$ InternalRadiation", radiationEffect);
|
||||
|
||||
@@ -2,6 +2,6 @@ Name:Channeled Force
|
||||
ManaCost:2 U R
|
||||
Types:Instant
|
||||
A:SP$ Draw | Cost$ 2 U R Discard<X/Card/card> | CostDesc$ As an additional cost to cast this spell, discard X cards. | NumCards$ X | ValidTgts$ Player | TgtPrompt$ Choose a player | SubAbility$ DBDamage | SpellDescription$ Target player draws X cards. CARDNAME deals X damage to up to one target creature or planeswalker.
|
||||
SVar:DBDamage:DB$ DealDamage | ValidTgts$ Creature,Planeswalker | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select target creature or planeswalker. | NumDmg$ X
|
||||
SVar:DBDamage:DB$ DealDamage | ValidTgts$ Creature,Planeswalker | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select target creature or planeswalker | NumDmg$ X
|
||||
SVar:X:Count$xPaid
|
||||
Oracle:As an additional cost to cast this spell, discard X cards.\nTarget player draws X cards. Channeled Force deals X damage to up to one target creature or planeswalker.
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Enchantment Aura
|
||||
K:Enchant:Planeswalker
|
||||
SVar:AttachAILogic:Pump
|
||||
S:Mode$ Continuous | Affected$ Planeswalker.EnchantedBy | AddAbility$ TeferiUlt | Description$ Enchanted planeswalker has "[-12]: You get an emblem with 'You may activate loyalty abilities of planeswalkers you control on any player's turn any time you could cast an instant.'"
|
||||
SVar:TeferiUlt:AB$ Effect | Cost$ SubCounter<12/LOYALTY> | Planeswalker$ True | Name$ Emblem — Teferi, Temporal Archmage | StaticAbilities$ InstantPlaneswalkers | Stackable$ False | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "You may activate loyalty abilities of planeswalkers you control on any player's turn any time you could cast an instant."
|
||||
SVar:TeferiUlt:AB$ Effect | Cost$ SubCounter<12/LOYALTY> | Planeswalker$ True | Name$ Emblem — Teferi, Temporal Archmage | Image$ emblem_teferis_talent | StaticAbilities$ InstantPlaneswalkers | Stackable$ False | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "You may activate loyalty abilities of planeswalkers you control on any player's turn any time you could cast an instant."
|
||||
SVar:InstantPlaneswalkers:Mode$ CastWithFlash | ValidCard$ Planeswalker.YouCtrl | ValidSA$ Activated.Loyalty | Caster$ You | Description$ You may activate loyalty abilities of planeswalkers you control on any player's turn any time you could cast an instant.
|
||||
T:Mode$ Drawn | ValidCard$ Card.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever you draw a card, put a loyalty counter on enchanted planeswalker.
|
||||
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Enchanted | CounterType$ LOYALTY | CounterNum$ 1
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
Name:Dawnsire, Sunstar Dreadnought
|
||||
ManaCost:5
|
||||
Types:Legendary Artifact Spacecraft
|
||||
PT:20/20
|
||||
K:Station:20
|
||||
S:Mode$ Continuous | Affected$ Card.Self+counters_GE10_CHARGE | AddTrigger$ AttackTrig | Description$ STATION 10+ Whenever you attack, NICKNAME deals 100 damage to up to one target creature or planeswalker.
|
||||
S:Mode$ Continuous | Affected$ Card.Self+counters_GE20_CHARGE | AddType$ Creature | AddKeyword$ Flying | Description$ STATION 20+ Flying
|
||||
SVar:AttackTrig:Mode$ AttackersDeclared | AttackingPlayer$ You | Execute$ TrigDamage | TriggerZones$ Battlefield | TriggerDescription$ Whenever you attack, NICKNAME deals 100 damage to up to one target creature or planeswalker.
|
||||
SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Creature,Planeswalker | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select target creature or planeswalker | NumDmg$ 100
|
||||
Oracle:Station (Tap another creature you control: Put charge counters equal to its power on this Spacecraft. Station only as a sorcery. It's an artifact creature at 20+.)\nSTATION 10+\nWhenever you attack, Dawnsire deals 100 damage to up to one target creature or planeswalker.\nSTATION 20+\nFlying
|
||||
@@ -447,4 +447,5 @@ ScryfallCode=C21
|
||||
29 c_1_1_a_thopter_flying @Svetlin Velinov
|
||||
|
||||
[other]
|
||||
eternalize_champion_of_wits
|
||||
6 eternalize_champion_of_wits @Eliteven Amundsen
|
||||
30 copy @David Palumbo
|
||||
@@ -352,4 +352,5 @@ ScryfallCode=AFC
|
||||
12 c_1_1_a_thopter_flying @Richard Wright
|
||||
|
||||
[other]
|
||||
eternalize_champion_of_wits
|
||||
4 eternalize_champion_of_wits @Even Amundsen
|
||||
13 monarch @Volkan Baǵa
|
||||
@@ -1095,3 +1095,6 @@ ScryfallCode=PIP
|
||||
18 c_a_treasure_sac @Rafater
|
||||
19 c_a_treasure_sac @Rafater
|
||||
20 wasteland_survival_guide @Sergio Cosmai
|
||||
|
||||
[other]
|
||||
22 radiation @Skinnyelbows
|
||||
@@ -500,3 +500,9 @@ ScryfallCode=MOC
|
||||
40 c_x_x_a_phyrexian_horror @Scott Chou
|
||||
41 replicated_ring @Olena Richards
|
||||
42 c_1_1_a_servo @Victor Adame Minguez
|
||||
|
||||
[other]
|
||||
43 emblem_elspeth_suns_champion @Tyler Jacobson
|
||||
44 emblem_teferis_talent @Dominik Mayer
|
||||
45 blessing @Yeong-Hao Han
|
||||
46 monarch @Volkan Baǵa
|
||||
@@ -580,3 +580,6 @@ ScryfallCode=LTC
|
||||
12 g_1_1_insect_flying_deathtouch @Oleg Bulakh
|
||||
13 g_x_x_treefolk @Audrey Benjaminsen
|
||||
14 br_6_6_dragon_flying_menace_steal @Crystal Sully
|
||||
|
||||
[other]
|
||||
15 monarch @Audrey Benjaminsen
|
||||
@@ -393,3 +393,8 @@ ScryfallCode=LCC
|
||||
13 g_3_3_frog_lizard @Jack Wang
|
||||
14 wb_1_1_vampire_lifelink @Zoltan Boros
|
||||
15 c_a_blood_draw @Miranda Meeks
|
||||
|
||||
[other]
|
||||
16 emblem_sorin_lord_of_innistrad @Michael Komarck
|
||||
17 blessing @Alfven Ato
|
||||
18 monarch @Volkan Baǵa
|
||||
@@ -106,7 +106,7 @@ public class MainWorldDuelReader extends StorageReaderFolder<QuestEventDuel> {
|
||||
qc.setDifficulty(QuestEventDifficulty.fromString(sectionMeta.get("Difficulty")));
|
||||
qc.setDescription(sectionMeta.get("Description", "").replace("\\n", "\n"));
|
||||
qc.setCardReward(sectionMeta.get("Card Reward"));
|
||||
qc.setIconImageKey(ImageKeys.ICON_PREFIX + sectionMeta.get("Icon", WILD_DEFAULT_ICON_NAME));
|
||||
qc.setIconImageKey(ImageKeys.ICON_PREFIX + sectionMeta.get("Icon"));
|
||||
if (sectionMeta.contains("Profile")) {
|
||||
qc.setProfile(sectionMeta.get("Profile"));
|
||||
}
|
||||
@@ -114,7 +114,7 @@ public class MainWorldDuelReader extends StorageReaderFolder<QuestEventDuel> {
|
||||
qc.setDifficulty(QuestEventDifficulty.WILD);
|
||||
qc.setTitle(sectionMeta.get("Title") != null ? sectionMeta.get("Title") : qc.getName());
|
||||
qc.setDescription(sectionMeta.get("Description") != null ? sectionMeta.get("Description") : "Wild opponent");
|
||||
qc.setIconImageKey(ImageKeys.ICON_PREFIX + sectionMeta.get("Icon", WILD_DEFAULT_ICON_NAME));
|
||||
qc.setIconImageKey(ImageKeys.ICON_PREFIX + (sectionMeta.get("Icon") != null ? sectionMeta.get("Icon") : WILD_DEFAULT_ICON_NAME));
|
||||
}
|
||||
|
||||
// Deck
|
||||
|
||||
@@ -192,7 +192,6 @@ public abstract class ImageFetcher {
|
||||
updateLink = true;
|
||||
} catch (Exception e) {
|
||||
filename = paperCard.getCardAltImageKey();
|
||||
updateLink = false;
|
||||
}
|
||||
}
|
||||
destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR, filename + ".jpg");
|
||||
@@ -271,7 +270,6 @@ public abstract class ImageFetcher {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Load the paper token from filename + edition
|
||||
CardEdition edition = StaticData.instance().getEditions().get(setCode);
|
||||
if (edition == null || edition.getType() == CardEdition.Type.CUSTOM_SET) return; //Custom set token, skip fetching.
|
||||
|
||||
Reference in New Issue
Block a user