Merge branch 'master' of git.cardforge.org:core-developers/forge into agetian-master

This commit is contained in:
Michael Kamensky
2021-08-18 07:29:58 +03:00
18 changed files with 150 additions and 29 deletions

View File

@@ -239,7 +239,10 @@ public class ComputerUtilCost {
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostSacrifice) {
CardCollection list = new CardCollection();
final CardCollection exclude = new CardCollection(AiCardMemory.getMemorySet(ai, MemorySet.PAYS_SAC_COST));
final CardCollection exclude = new CardCollection();
if (AiCardMemory.getMemorySet(ai, MemorySet.PAYS_SAC_COST) != null) {
exclude.addAll(AiCardMemory.getMemorySet(ai, MemorySet.PAYS_SAC_COST));
}
if (part.payCostFromSource()) {
list.add(source);
} else if (part.getType().equals("OriginalHost")) {
@@ -448,7 +451,10 @@ public class ComputerUtilCost {
if (c == null) {
c = AbilityUtils.calculateAmount(source, part.getAmount(), sa);
}
CardCollection exclude = new CardCollection(AiCardMemory.getMemorySet(ai, MemorySet.PAYS_TAP_COST));
CardCollection exclude = new CardCollection();
if (AiCardMemory.getMemorySet(ai, MemorySet.PAYS_TAP_COST) != null) {
exclude.addAll(AiCardMemory.getMemorySet(ai, MemorySet.PAYS_TAP_COST));
}
// trying to produce mana that includes tapping source that will already be tapped
if (exclude.contains(source) && cost.hasTapCost()) {
return false;

View File

@@ -146,6 +146,14 @@ public class AnimateAi extends SpellAbilityAi {
if (!ComputerUtilCost.checkTapTypeCost(aiPlayer, sa.getPayCosts(), source, sa)) {
return false; // prevent crewing with equal or better creatures
}
if (sa.costHasManaX() && sa.getSVar("X").equals("Count$xPaid")) {
// Set PayX here to maximum value.
final int xPay = ComputerUtilCost.getMaxXValue(sa, aiPlayer);
sa.setXManaCostPaid(xPay);
}
if (!sa.usesTargeting()) {
final List<Card> defined = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
boolean bFlag = false;

View File

@@ -129,6 +129,23 @@ public final class ImageKeys {
// if there's a 1st art variant try with it for .full images
file = findFile(dir, filename.replaceAll("[0-9]*.full", "1.full"));
if (file != null) { return file; }
//setlookup
if (!StaticData.instance().getSetLookup().isEmpty()) {
for (String setKey : StaticData.instance().getSetLookup().keySet()) {
for (String setLookup : StaticData.instance().getSetLookup().get(setKey)) {
//.fullborder lookup
file = findFile(dir, TextUtil.fastReplace(fullborderFile, setKey, getSetFolder(setLookup)));
if (file != null) { return file; }
file = findFile(dir, TextUtil.fastReplace(fullborderFile, setKey, getSetFolder(setLookup)).replaceAll("[0-9]*.fullborder", "1.fullborder"));
if (file != null) { return file; }
//.full lookup
file = findFile(dir, TextUtil.fastReplace(filename, setKey, getSetFolder(setLookup)));
if (file != null) { return file; }
file = findFile(dir, TextUtil.fastReplace(filename, setKey, getSetFolder(setLookup)).replaceAll("[0-9]*.full", "1.full"));
if (file != null) { return file; }
}
}
}
}
//if an image, like phenomenon or planes is missing .full in their filenames but you have an existing images that have .full/.fullborder
if (!filename.contains(".full")) {
@@ -137,12 +154,6 @@ public final class ImageKeys {
file = findFile(dir, TextUtil.addSuffix(filename,".fullborder"));
if (file != null) { return file; }
}
// some S00 cards are really part of 6ED
String s2kAlias = getSetFolder("S00");
if (filename.startsWith(s2kAlias)) {
file = findFile(dir, TextUtil.fastReplace(filename, s2kAlias, getSetFolder("6ED")));
if (file != null) { return file; }
}
if (dir.equals(CACHE_TOKEN_PICS_DIR)) {
int index = filename.lastIndexOf('_');

View File

@@ -10,6 +10,7 @@ import forge.item.FatPack;
import forge.item.PaperCard;
import forge.item.SealedProduct;
import forge.token.TokenDb;
import forge.util.FileUtil;
import forge.util.TextUtil;
import forge.util.storage.IStorage;
import forge.util.storage.StorageBase;
@@ -57,18 +58,19 @@ public class StaticData {
private IStorage<FatPack.Template> fatPacks;
private IStorage<BoosterBox.Template> boosterBoxes;
private IStorage<PrintSheet> printSheets;
private final Map<String, List<String>> setLookup = new HashMap<>();
private static StaticData lastInstance = null;
public StaticData(CardStorageReader cardReader, CardStorageReader customCardReader, String editionFolder, String customEditionsFolder, String blockDataFolder, String cardArtPreference, boolean enableUnknownCards, boolean loadNonLegalCards) {
this(cardReader, null, customCardReader, editionFolder, customEditionsFolder, blockDataFolder, cardArtPreference, enableUnknownCards, loadNonLegalCards, false, false);
this(cardReader, null, customCardReader, editionFolder, customEditionsFolder, blockDataFolder, "", cardArtPreference, enableUnknownCards, loadNonLegalCards, false, false);
}
public StaticData(CardStorageReader cardReader, CardStorageReader tokenReader, CardStorageReader customCardReader, String editionFolder, String customEditionsFolder, String blockDataFolder, String cardArtPreference, boolean enableUnknownCards, boolean loadNonLegalCards, boolean allowCustomCardsInDecksConformance){
this(cardReader, tokenReader, customCardReader, editionFolder, customEditionsFolder, blockDataFolder, cardArtPreference, enableUnknownCards, loadNonLegalCards, allowCustomCardsInDecksConformance, false);
public StaticData(CardStorageReader cardReader, CardStorageReader tokenReader, CardStorageReader customCardReader, String editionFolder, String customEditionsFolder, String blockDataFolder, String setLookupFolder, String cardArtPreference, boolean enableUnknownCards, boolean loadNonLegalCards, boolean allowCustomCardsInDecksConformance){
this(cardReader, tokenReader, customCardReader, editionFolder, customEditionsFolder, blockDataFolder, setLookupFolder, cardArtPreference, enableUnknownCards, loadNonLegalCards, allowCustomCardsInDecksConformance, false);
}
public StaticData(CardStorageReader cardReader, CardStorageReader tokenReader, CardStorageReader customCardReader, String editionFolder, String customEditionsFolder, String blockDataFolder, String cardArtPreference, boolean enableUnknownCards, boolean loadNonLegalCards, boolean allowCustomCardsInDecksConformance, boolean enableSmartCardArtSelection) {
public StaticData(CardStorageReader cardReader, CardStorageReader tokenReader, CardStorageReader customCardReader, String editionFolder, String customEditionsFolder, String blockDataFolder, String setLookupFolder, String cardArtPreference, boolean enableUnknownCards, boolean loadNonLegalCards, boolean allowCustomCardsInDecksConformance, boolean enableSmartCardArtSelection) {
this.cardReader = cardReader;
this.tokenReader = tokenReader;
this.editions = new CardEdition.Collection(new CardEdition.Reader(new File(editionFolder)));
@@ -143,12 +145,24 @@ public class StaticData {
} else {
allTokens = null;
}
//initialize setLookup
if (FileUtil.isDirectoryWithFiles(setLookupFolder)){
for (File f : Objects.requireNonNull(new File(setLookupFolder).listFiles())){
if (f.isFile()) {
setLookup.put(f.getName().replace(".txt",""), FileUtil.readFile(f));
}
}
}
}
public static StaticData instance() {
return lastInstance;
}
public Map<String, List<String>> getSetLookup() {
return setLookup;
}
public final CardEdition.Collection getEditions() {
return this.editions;
}

View File

@@ -3,6 +3,6 @@ ManaCost:3 U U R R
Types:Instant
A:SP$ DealDamage | Cost$ 3 U U R R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 5 | SubAbility$ DBDig | SpellDescription$ CARDNAME deals 5 damage to any target. Look at the top five cards of your library. Put one of them into your hand and the rest on the bottom of your library in a random order.
SVar:DBDig:DB$Dig | DigNum$ 5 | RestRandomOrder$ True
A:AB$ Token | Cost$ UR UR Discard<1/CARDNAME> | ActivationZone$ Hand | TokenScript$ c_a_treasure_sac | SpellDescription$ Create a Treasure token.
A:AB$ Token | Cost$ UR UR Discard<1/CARDNAME> | ActivationZone$ Hand | TokenScript$ c_a_treasure_sac | AILogic$ AlwaysOnDiscard | SpellDescription$ Create a Treasure token.
DeckHas:Ability$Token
Oracle:Creative Outburst deals 5 damage to any target. Look at the top five cards of your library. Put one of them into your hand and the rest on the bottom of your library in a random order.\n{U/R}{U/R}, Discard Creative Outburst: Create a Treasure token.

View File

@@ -2,6 +2,6 @@ Name:Elemental Masterpiece
ManaCost:5 U R
Types:Sorcery
A:SP$ Token | Cost$ 5 U R | TokenAmount$ 2 | TokenScript$ ur_4_4_elemental | TokenOwner$ You | SpellDescription$ Create two 4/4 blue and red Elemental creature tokens.
A:AB$ Token | Cost$ UR UR Discard<1/CARDNAME> | ActivationZone$ Hand | TokenScript$ c_a_treasure_sac | SpellDescription$ Create a Treasure token.
A:AB$ Token | Cost$ UR UR Discard<1/CARDNAME> | ActivationZone$ Hand | TokenScript$ c_a_treasure_sac | AILogic$ AlwaysOnDiscard | SpellDescription$ Create a Treasure token.
DeckHas:Ability$Token
Oracle:Create two 4/4 blue and red Elemental creature tokens.\n{U/R}{U/R}, Discard Elemental Masterpiece: Create a Treasure token. (It's an artifact with "{T}, Sacrifice this artifact: Add one mana of any color.")

View File

@@ -2,7 +2,7 @@ Name:Tempt with Discovery
ManaCost:3 G
Types:Sorcery
A:SP$ ChangeZone | Cost$ 3 G | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.YouCtrl | ChangeNum$ 1 | Hidden$ True | NoShuffle$ True | SubAbility$ DBRepeat | StackDescription$ SpellDescription | SpellDescription$ Tempting offer — Search your library for a land card and put it onto the battlefield. Each opponent may search their library for a land card and put it onto the battlefield. For each opponent who searches a library this way, search your library for a land card and put it onto the battlefield. Then each player who searched a library this way shuffles.
SVar:DBRepeat:DB$ RepeatEach | RepeatSubAbility$ DBChangeZone | RepeatPlayers$ Player.Opponent | SubAbility$ DBSearchAgain | RepeatOptionalForEachPlayer$ True | RepeatOptionalMessage$ Do you want to search their library for a land card and put it onto the battlefield?
SVar:DBRepeat:DB$ RepeatEach | RepeatSubAbility$ DBChangeZone | RepeatPlayers$ Player.Opponent | SubAbility$ DBSearchAgain | RepeatOptionalForEachPlayer$ True | RepeatOptionalMessage$ Do you want to search your library for a land card and put it onto the battlefield?
SVar:DBChangeZone:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.RememberedPlayerCtrl | DefinedPlayer$ Player.IsRemembered | Chooser$ Player.IsRemembered | ChangeNum$ 1 | Hidden$ True | SubAbility$ DBCount
SVar:DBCount:DB$ StoreSVar | SVar$ X | Type$ CountSVar | Expression$ X/Plus.1
SVar:DBSearchAgain:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.YouCtrl | ChangeNum$ X | Hidden$ True | Shuffle$ True | StackDescription$ None | SubAbility$ DBReset

View File

@@ -8,7 +8,8 @@ Type=Expansion
BoosterCovers=3
Booster=10 Common:fromSheet("IKO cards"):!fromSheet("IKO Lands"), 3 Uncommon:fromSheet("IKO cards"), 1 RareMythic:fromSheet("IKO cards"), 1 fromSheet("IKO Lands")
Prerelease=6 Boosters, 1 RareMythic+
FatPackExtraSlots=20 BasicLands, 20 BasicLands+, 1 Colossification+|IKO|3
FatPackExtraSlots=20 BasicLands, 20 BasicLands+
#, 1 Colossification+|IKO|3
ScryfallCode=IKO
[cards]

View File

@@ -6,7 +6,8 @@ Type=Core
BoosterCovers=3
Booster=10 Common:fromSheet("M21 cards"):!fromSheet("M21 Lands"), 3 Uncommon:fromSheet("M21 cards"), 1 RareMythic:fromSheet("M21 cards"), 1 fromSheet("M21 Lands")
Prerelease=6 Boosters, 1 RareMythic+
FatPackExtraSlots=20 BasicLands, 20 BasicLands+, 1 Pack Leader+|M21|3
FatPackExtraSlots=20 BasicLands, 20 BasicLands+
#, 1 Pack Leader+|M21|3
ChaosDraftThemes=CORE_SET
ScryfallCode=M21

View File

@@ -7,7 +7,8 @@ Type=Expansion
BoosterCovers=3
Booster=10 Common:fromSheet("THB Commons"), 3 Uncommon:fromSheet("THB Uncommons"), 1 RareMythic:fromSheet("THB RareMythics"), 1 BasicLand
Prerelease=6 Boosters, 1 RareMythic+
FatPackExtraSlots=20 BasicLands, 20 BasicLands+, 1 Arasta of the Endless Web+|THB|3
FatPackExtraSlots=20 BasicLands, 20 BasicLands+
#, 1 Arasta of the Endless Web+|THB|3
ChaosDraftThemes=GRAVEYARD_MATTERS
ScryfallCode=THB

View File

@@ -9,7 +9,8 @@ BoosterCovers=3
Booster=10 Common:fromSheet("ELD cards"), 3 Uncommon:fromSheet("ELD cards"), 1 RareMythic:fromSheet("ELD cards"), 1 BasicLand
Prerelease=6 Boosters, 1 RareMythic+
FatPack=10
FatPackExtraSlots=20 BasicLands, 20 BasicLands+, 1 Piper of the Swarm+|ELD|3
FatPackExtraSlots=20 BasicLands, 20 BasicLands+
#, 1 Piper of the Swarm+|ELD|3
ScryfallCode=ELD
[cards]

View File

@@ -10,7 +10,8 @@ Booster=10 Common:!dfc:fromSheet("ZNR cards"), 3 Uncommon:!dfc:fromSheet("ZNR ca
BoosterReplaceSlotFromPrintSheet=ZNR ModalDoubleFaceCards
Prerelease=6 Boosters, 1 RareMythic+
#BoosterBox=36 Boosters, 1 fromSheet('ZNR buy a box')+
FatPackExtraSlots=20 BasicLands, 20 BasicLands+, 1 Charix; the Raging Isle+|ZNR|3
FatPackExtraSlots=20 BasicLands, 20 BasicLands+
#, 1 Charix; the Raging Isle+|ZNR|3
ScryfallCode=ZNR
[cards]

View File

@@ -121,15 +121,15 @@ lblAltLifeDisplay=Alternatives Spieler-Layout (Landscape-Modus)
nlAltLifeDisplay=Alternative Anzeige von Lebens-, Gift-, Energie- und Erfahrungspunkten.
lblAltZoneTabs=Alternatives Spielerbereich-Layout (Landscape-Modus)
nlAltZoneTabs=Alternative Anzeige von Kartenhand, Friedhof, Bibliothek und Exilzone.
lblPreferredArt=Kartenkunst-Präferenz
lblPreferredArt=Kartenbild-Präferenz
nlPreferredArt=Gibt an, welche Grafik für Karten ausgewählt werden soll, wenn keine Edition angegeben ist.
lblPrefArtExpansionOnly=Kartenkunst aus Kern-, Erweiterungs- und Nachdrucksets bevorzugen
nlPrefArtExpansionOnly=Bevorzugen Sie, wann immer möglich, Kartenkunst aus Basis-, Erweiterungs- und Reprint-Sets (z. B. keine Promo, keine Online-Editionen).
lblSmartCardArtOpt=Aktivieren Sie die intelligente Auswahl für Kartengrafiken in Decks
nlSmartCardArtOpt=Wenn diese Option aktiviert ist, wird Kartenkunst in Decks automatisch optimiert, um mit Kartenrahmen, Editionen und mehreren Kunstillustrationen zusammenzupassen.
nlSmartCardArtOptNote=HINWEIS: Diese Option wirkt sich nur auf Karten aus, die keine angegebene Edition haben. Andere Karten bleiben unverändert. (Warnung: Experimentell)
latestArtOpt=Neueste Kunst
originalArtOpt=Originalkunst
lblPrefArtExpansionOnly=Kartenbilder aus Haupt-, Erweiterungs- und Reprint-Sets bevorzugen
nlPrefArtExpansionOnly=Bevorzugt, wann immer möglich, Kartenbilder aus Haupt-, Erweiterungs- und Reprint-Sets (z. B. keine Promo, keine Online-Editionen).
lblSmartCardArtOpt=Aktiviert die intelligente Auswahl für Kartenbilder in Decks
nlSmartCardArtOpt=Wenn diese Option aktiviert ist, werden Kartenbilder in Decks automatisch optimiert, um mit Kartenrahmen, Editionen und mehrfachen Bildvarianten zusammenzupassen.
nlSmartCardArtOptNote=HINWEIS: Diese Option wirkt sich nur auf Karten aus, die keine angegebene Edition haben. Andere Karten bleiben unverändert. Warnung: Experimentell!!!
latestArtOpt=Neueste Version
originalArtOpt=Originalbild
Troubleshooting=Fehlerbehebung
GeneralConfiguration=Allgemeine Einstellungen
lblPlayerName=Spielername

View File

@@ -0,0 +1,74 @@
AFR
MH2
STX
TSR
KHM
CMR
KLR
ZNC
ZNR
AKR
ANB
2XM
JMP
M21
IKO
C20
THB
SLD
GN2
ELD
C19
M20
MH1
WAR
GK2
RNA
UMA
GK1
GRN
C18
M19
BBD
CM2
DOM
A25
RIX
IMA
DDT
XLN
HOU
AKH
MM3
AER
PCA
DDR
CN2
SOI
W16
DDQ
OGW
BFZ
ORI
MM2
DTK
FRF
KTK
EMN
M15
VMA
THS
M14
DGM
GTC
ISD
MBS
ALA
MOR
LRW
10E
LGN
ONS
PCY
P02
WTH

View File

@@ -0,0 +1 @@
6ED

View File

@@ -0,0 +1 @@
6ED

View File

@@ -32,6 +32,7 @@ public final class ForgeConstants {
public static final String RES_DIR = ASSETS_DIR + "res" + PATH_SEPARATOR;
public static final String LISTS_DIR = RES_DIR + "lists" + PATH_SEPARATOR;
public static final String SETLOOKUP_DIR = RES_DIR + "setlookup" + PATH_SEPARATOR;
public static final String KEYWORD_LIST_FILE = LISTS_DIR + "NonStackingKWList.txt";
public static final String TYPE_LIST_FILE = LISTS_DIR + "TypeLists.txt";
public static final String PLANESWALKER_ACHIEVEMENT_LIST_FILE = LISTS_DIR + "planeswalker-achievements.txt";

View File

@@ -179,7 +179,7 @@ public final class FModel {
customReader = null;
}
magicDb = new StaticData(reader, tokenReader, customReader, ForgeConstants.EDITIONS_DIR,
ForgeConstants.USER_CUSTOM_EDITIONS_DIR, ForgeConstants.BLOCK_DATA_DIR,
ForgeConstants.USER_CUSTOM_EDITIONS_DIR, ForgeConstants.BLOCK_DATA_DIR, ForgeConstants.SETLOOKUP_DIR,
FModel.getPreferences().getPref(FPref.UI_PREFERRED_ART),
FModel.getPreferences().getPrefBoolean(FPref.UI_LOAD_UNKNOWN_CARDS),
FModel.getPreferences().getPrefBoolean(FPref.UI_LOAD_NONLEGAL_CARDS),