mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
Compare commits
104 Commits
untapRewor
...
forge-1.6.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a30d78f54 | ||
|
|
db98ce160b | ||
|
|
ce8b5b53e0 | ||
|
|
0c4055726c | ||
|
|
64ae4bae0c | ||
|
|
044cc793e8 | ||
|
|
e310dc30d7 | ||
|
|
f239755249 | ||
|
|
57686c0554 | ||
|
|
5ecde572c3 | ||
|
|
23e9974950 | ||
|
|
ec98d128f1 | ||
|
|
5c07951604 | ||
|
|
7be34625f6 | ||
|
|
5f6cb893ef | ||
|
|
3b636be2fe | ||
|
|
1af940b034 | ||
|
|
8cb1789e60 | ||
|
|
01782de3a6 | ||
|
|
3a7e35c51d | ||
|
|
bff24a1d3d | ||
|
|
8a075000a2 | ||
|
|
5e0761d085 | ||
|
|
2184ddf1bb | ||
|
|
fd032f6ccd | ||
|
|
164c819523 | ||
|
|
987043ead2 | ||
|
|
4aa9c224d0 | ||
|
|
2ac6fa4542 | ||
|
|
2797f95cd3 | ||
|
|
5eb9be6248 | ||
|
|
23eebf9037 | ||
|
|
b59adab68d | ||
|
|
b2d44105be | ||
|
|
2235546f2a | ||
|
|
59d104f68b | ||
|
|
6abdfd391d | ||
|
|
a6ff0b5b10 | ||
|
|
02969cfe5b | ||
|
|
c6a2c35850 | ||
|
|
4c0a71f37d | ||
|
|
74e3bd1895 | ||
|
|
121c9f5012 | ||
|
|
7b1cd816b7 | ||
|
|
6a76cc8bc6 | ||
|
|
9b9c38126e | ||
|
|
e4ee0c768f | ||
|
|
340de153c8 | ||
|
|
2bf477102d | ||
|
|
42a15b40b3 | ||
|
|
a2589cd433 | ||
|
|
7ec7025ed4 | ||
|
|
5edeb6df94 | ||
|
|
001a1981cf | ||
|
|
446fb59473 | ||
|
|
3b58d6df42 | ||
|
|
a80c683901 | ||
|
|
a5b65eaaed | ||
|
|
31182289b7 | ||
|
|
85eb740264 | ||
|
|
4318e23a40 | ||
|
|
4ca7352d5c | ||
|
|
84905bd726 | ||
|
|
18e16368be | ||
|
|
7ed84c4c3f | ||
|
|
f334211395 | ||
|
|
42f4126aff | ||
|
|
5790e29daa | ||
|
|
88a4a2c6cf | ||
|
|
90b72fc11e | ||
|
|
00391df1f0 | ||
|
|
15de0c0bba | ||
|
|
a2fdce9be9 | ||
|
|
fa6fce9589 | ||
|
|
cc1f03fc94 | ||
|
|
8b25f6f129 | ||
|
|
b37937421c | ||
|
|
4c3e4f2170 | ||
|
|
dc12c50c1a | ||
|
|
2b986f5bac | ||
|
|
2accf7543e | ||
|
|
ba37189410 | ||
|
|
d578eee402 | ||
|
|
5107d89ef5 | ||
|
|
72b8b5c98e | ||
|
|
402885391f | ||
|
|
b4d153ab3b | ||
|
|
1a0cb62ac8 | ||
|
|
c0baf70c59 | ||
|
|
166cf2623c | ||
|
|
8567b69073 | ||
|
|
3a4271e66d | ||
|
|
8b723aebd9 | ||
|
|
eb59d6c86b | ||
|
|
a291b75dd9 | ||
|
|
f1a76e1e76 | ||
|
|
a391f7414f | ||
|
|
299de54ba5 | ||
|
|
37bae14dfd | ||
|
|
d780aa43d4 | ||
|
|
91534776d1 | ||
|
|
31bb611ecf | ||
|
|
53c88f0302 | ||
|
|
ad1cc78578 |
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.30-SNAPSHOT</version>
|
||||
<version>1.6.30</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-ai</artifactId>
|
||||
|
||||
@@ -1281,7 +1281,8 @@ public class AiBlockController {
|
||||
oppCreatureCount = ComputerUtil.countUsefulCreatures(attackersLeft.get(0).getController());
|
||||
}
|
||||
|
||||
if (attacker.getOwner().equals(ai) && "6".equals(attacker.getSVar("SacMe"))) {
|
||||
if (attacker != null && attacker.getOwner() != null)
|
||||
if (attacker.getOwner().equals(ai) && "6".equals(attacker.getSVar("SacMe"))) {
|
||||
// Temporarily controlled object - don't trade with it
|
||||
// TODO: find a more reliable way to figure out that control will be reestablished next turn
|
||||
return false;
|
||||
|
||||
@@ -11,10 +11,7 @@ import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.effects.DetachedCardEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.token.TokenInfo;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
@@ -24,6 +21,7 @@ import forge.game.mana.ManaPool;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilityManaPart;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.trigger.TriggerType;
|
||||
@@ -362,6 +360,12 @@ public abstract class GameState {
|
||||
if (c.isFaceDown()) {
|
||||
newText.append("|FaceDown"); // Exiled face down
|
||||
}
|
||||
if (c.isAdventureCard() && c.getZone().is(ZoneType.Exile)) {
|
||||
// TODO: this will basically default all exiled cards with Adventure to being "On Adventure".
|
||||
// Need to figure out a better way to detect if it's actually on adventure.
|
||||
newText.append("|OnAdventure");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (zoneType == ZoneType.Battlefield || zoneType == ZoneType.Exile) {
|
||||
@@ -1202,6 +1206,16 @@ public abstract class GameState {
|
||||
c.setState(CardStateName.Flipped, true);
|
||||
} else if (info.startsWith("Meld")) {
|
||||
c.setState(CardStateName.Meld, true);
|
||||
} else if (info.startsWith("OnAdventure")) {
|
||||
String abAdventure = "DB$ Effect | RememberObjects$ Self | StaticAbilities$ Play | ExileOnMoved$ Exile | Duration$ Permanent | ConditionDefined$ Self | ConditionPresent$ Card.nonCopiedSpell";
|
||||
AbilitySub saAdventure = (AbilitySub)AbilityFactory.getAbility(abAdventure, c);
|
||||
StringBuilder sbPlay = new StringBuilder();
|
||||
sbPlay.append("Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered+nonAdventure");
|
||||
sbPlay.append(" | AffectedZone$ Exile | Description$ You may cast the card.");
|
||||
saAdventure.setSVar("Play", sbPlay.toString());
|
||||
saAdventure.setActivatingPlayer(c.getOwner());
|
||||
saAdventure.resolve();
|
||||
c.setExiledWith(c); // This seems to be the way it's set up internally. Potentially not needed here?
|
||||
} else if (info.startsWith("IsCommander")) {
|
||||
// TODO: This doesn't seem to properly restore the ability to play the commander. Why?
|
||||
c.setCommander(true);
|
||||
|
||||
@@ -45,6 +45,8 @@ public class FightAi extends SpellAbilityAi {
|
||||
aiCreatures = ComputerUtil.getSafeTargets(ai, sa, aiCreatures);
|
||||
List<Card> humCreatures = ai.getOpponents().getCreaturesInPlay();
|
||||
humCreatures = CardLists.getTargetableCards(humCreatures, sa);
|
||||
if (humCreatures.isEmpty())
|
||||
return false; //prevent IndexOutOfBoundsException on MOJHOSTO variant
|
||||
|
||||
// assumes the triggered card belongs to the ai
|
||||
if (sa.hasParam("Defined")) {
|
||||
|
||||
@@ -63,6 +63,7 @@ public class SacrificeAi extends SpellAbilityAi {
|
||||
final boolean destroy = sa.hasParam("Destroy");
|
||||
|
||||
Player opp = ai.getWeakestOpponent();
|
||||
|
||||
if (tgt != null) {
|
||||
sa.resetTargets();
|
||||
if (!opp.canBeTargetedBy(sa)) {
|
||||
@@ -74,8 +75,16 @@ public class SacrificeAi extends SpellAbilityAi {
|
||||
num = (num == null) ? "1" : num;
|
||||
final int amount = AbilityUtils.calculateAmount(sa.getHostCard(), num, sa);
|
||||
|
||||
List<Card> list =
|
||||
CardLists.getValidCards(opp.getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getHostCard(), sa);
|
||||
List<Card> list = null;
|
||||
try {
|
||||
list = CardLists.getValidCards(opp.getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getHostCard(), sa);
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
} finally {
|
||||
if (list == null)
|
||||
return false;
|
||||
}//prevent NPE on MoJhoSto
|
||||
|
||||
for (Card c : list) {
|
||||
if (c.hasSVar("SacMe") && Integer.parseInt(c.getSVar("SacMe")) > 3) {
|
||||
return false;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.30-SNAPSHOT</version>
|
||||
<version>1.6.30</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-core</artifactId>
|
||||
@@ -21,7 +21,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.7</version>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
public abstract class LobbyPlayer {
|
||||
protected String name;
|
||||
private int avatarIndex = -1;
|
||||
private int sleeveIndex = -1;
|
||||
private String avatarCardImageKey;
|
||||
|
||||
public LobbyPlayer(String name) {
|
||||
@@ -59,9 +60,15 @@ public abstract class LobbyPlayer {
|
||||
public int getAvatarIndex() {
|
||||
return avatarIndex;
|
||||
}
|
||||
public int getSleeveIndex() {
|
||||
return sleeveIndex;
|
||||
}
|
||||
public void setAvatarIndex(int avatarIndex) {
|
||||
this.avatarIndex = avatarIndex;
|
||||
}
|
||||
public void setSleeveIndex(int sleeveIndex) {
|
||||
this.sleeveIndex = sleeveIndex;
|
||||
}
|
||||
|
||||
public String getAvatarCardImageKey() {
|
||||
return avatarCardImageKey;
|
||||
|
||||
@@ -35,6 +35,7 @@ public class StaticData {
|
||||
|
||||
private Predicate<PaperCard> standardPredicate;
|
||||
private Predicate<PaperCard> brawlPredicate;
|
||||
private Predicate<PaperCard> pioneerPredicate;
|
||||
private Predicate<PaperCard> modernPredicate;
|
||||
private Predicate<PaperCard> commanderPredicate;
|
||||
private Predicate<PaperCard> oathbreakerPredicate;
|
||||
@@ -197,13 +198,13 @@ public class StaticData {
|
||||
|
||||
public TokenDb getAllTokens() { return allTokens; }
|
||||
|
||||
public Predicate<PaperCard> getStandardPredicate() {
|
||||
return standardPredicate;
|
||||
}
|
||||
|
||||
|
||||
public void setStandardPredicate(Predicate<PaperCard> standardPredicate) { this.standardPredicate = standardPredicate; }
|
||||
|
||||
public void setModernPredicate(Predicate<PaperCard> modernPredicate) { this.modernPredicate = standardPredicate; }
|
||||
public void setPioneerPredicate(Predicate<PaperCard> pioneerPredicate) { this.pioneerPredicate = pioneerPredicate; }
|
||||
|
||||
public void setModernPredicate(Predicate<PaperCard> modernPredicate) { this.modernPredicate = modernPredicate; }
|
||||
|
||||
public void setCommanderPredicate(Predicate<PaperCard> commanderPredicate) { this.commanderPredicate = commanderPredicate; }
|
||||
|
||||
@@ -211,9 +212,11 @@ public class StaticData {
|
||||
|
||||
public void setBrawlPredicate(Predicate<PaperCard> brawlPredicate) { this.brawlPredicate = brawlPredicate; }
|
||||
|
||||
public Predicate<PaperCard> getModernPredicate() {
|
||||
return modernPredicate;
|
||||
}
|
||||
public Predicate<PaperCard> getStandardPredicate() { return standardPredicate; }
|
||||
|
||||
public Predicate<PaperCard> getPioneerPredicate() { return pioneerPredicate; }
|
||||
|
||||
public Predicate<PaperCard> getModernPredicate() { return modernPredicate; }
|
||||
|
||||
public Predicate<PaperCard> getCommanderPredicate() { return commanderPredicate; }
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package forge.card;
|
||||
package forge.util;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
import com.google.common.base.Charsets;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.LineReader;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@@ -15,12 +12,12 @@ public class CardTranslation {
|
||||
private static Map <String, String> translatednames;
|
||||
private static Map <String, String> translatedtypes;
|
||||
private static Map <String, String> translatedoracles;
|
||||
private static String languageSelected;
|
||||
private static String languageSelected = "en-US";
|
||||
|
||||
private static void readTranslationFile(String language) {
|
||||
private static void readTranslationFile(String language, String languagesDirectory) {
|
||||
String filename = "cardnames-" + language + ".txt";
|
||||
|
||||
try (LineReader translationFile = new LineReader(new FileInputStream(ForgeConstants.LANG_DIR + filename), Charsets.UTF_8)) {
|
||||
try (LineReader translationFile = new LineReader(new FileInputStream(languagesDirectory + filename), Charsets.UTF_8)) {
|
||||
for (String line : translationFile.readLines()) {
|
||||
String[] matches = line.split("\\|");
|
||||
if (matches.length >= 2) {
|
||||
@@ -34,7 +31,7 @@ public class CardTranslation {
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.error("Error reading translation file: cardnames-" + language + ".txt");
|
||||
System.err.println("Error reading translation file: cardnames-" + language + ".txt");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +63,7 @@ public class CardTranslation {
|
||||
}
|
||||
|
||||
public static HashMap<String, String> getTranslationTexts(String cardname, String altcardname) {
|
||||
HashMap<String, String> translations = new HashMap<String, String>();
|
||||
HashMap<String, String> translations = new HashMap<>();
|
||||
translations.put("name", getTranslatedName(cardname));
|
||||
translations.put("oracle", getTranslatedOracle(cardname));
|
||||
translations.put("altname", getTranslatedName(altcardname));
|
||||
@@ -78,14 +75,14 @@ public class CardTranslation {
|
||||
return !languageSelected.equals("en-US");
|
||||
}
|
||||
|
||||
public static void preloadTranslation(String language) {
|
||||
public static void preloadTranslation(String language, String languagesDirectory) {
|
||||
languageSelected = language;
|
||||
|
||||
if (needsTranslation()) {
|
||||
translatednames = new HashMap<>();
|
||||
translatedtypes = new HashMap<>();
|
||||
translatedoracles = new HashMap<>();
|
||||
readTranslationFile(languageSelected);
|
||||
readTranslationFile(languageSelected, languagesDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.30-SNAPSHOT</version>
|
||||
<version>1.6.30</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-game</artifactId>
|
||||
@@ -32,8 +32,8 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.sentry</groupId>
|
||||
<artifactId>sentry-log4j</artifactId>
|
||||
<version>1.7.5</version>
|
||||
<artifactId>sentry-log4j2</artifactId>
|
||||
<version>1.7.27</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -701,7 +701,9 @@ public class GameAction {
|
||||
// Run triggers
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(c);
|
||||
runParams.put(AbilityKey.Cause, cause);
|
||||
runParams.put(AbilityKey.Origin, origin.getZoneType().name());
|
||||
if (origin != null) { // is generally null when adding via dev mode
|
||||
runParams.put(AbilityKey.Origin, origin.getZoneType().name());
|
||||
}
|
||||
if (params != null) {
|
||||
runParams.putAll(params);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ import java.util.Map.Entry;
|
||||
public class GameFormat implements Comparable<GameFormat> {
|
||||
private final String name;
|
||||
public enum FormatType {Sanctioned, Casual, Historic, Digital, Custom}
|
||||
public enum FormatSubType {Block, Standard, Extended, Modern, Legacy, Vintage, Commander, Planechase, Videogame, MTGO, Custom}
|
||||
public enum FormatSubType {Block, Standard, Extended, Pioneer, Modern, Legacy, Vintage, Commander, Planechase, Videogame, MTGO, Custom}
|
||||
|
||||
// contains allowed sets, when empty allows all sets
|
||||
private FormatType formatType;
|
||||
@@ -290,6 +290,7 @@ public class GameFormat implements Comparable<GameFormat> {
|
||||
private List<String> coreFormats = new ArrayList<>();
|
||||
{
|
||||
coreFormats.add("Standard.txt");
|
||||
coreFormats.add("Pioneer.txt");
|
||||
coreFormats.add("Modern.txt");
|
||||
coreFormats.add("Legacy.txt");
|
||||
coreFormats.add("Vintage.txt");
|
||||
@@ -468,6 +469,10 @@ public class GameFormat implements Comparable<GameFormat> {
|
||||
return this.map.get("Extended");
|
||||
}
|
||||
|
||||
public GameFormat getPioneer() {
|
||||
return this.map.get("Pioneer");
|
||||
}
|
||||
|
||||
public GameFormat getModern() {
|
||||
return this.map.get("Modern");
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ public class ManaPool extends ManaConversionMatrix implements Iterable<Mana> {
|
||||
final Card host = sa.getHostCard();
|
||||
if (mana.addsKeywords(sa) && mana.addsKeywordsType()
|
||||
&& host.getType().hasStringType(mana.getManaAbility().getAddsKeywordsType())) {
|
||||
final long timestamp = sa.getHostCard().getGame().getNextTimestamp();
|
||||
final long timestamp = host.getGame().getNextTimestamp();
|
||||
final List<String> kws = Arrays.asList(mana.getAddedKeywords().split(" & "));
|
||||
host.addChangedCardKeywords(kws, null, false, false, timestamp);
|
||||
if (mana.addsKeywordsUntil()) {
|
||||
@@ -243,14 +243,7 @@ public class ManaPool extends ManaConversionMatrix implements Iterable<Mana> {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!kws.isEmpty()) {
|
||||
for (String kw : kws) {
|
||||
if (kw.startsWith("HIDDEN")) {
|
||||
sa.getHostCard().removeHiddenExtrinsicKeyword(kw);
|
||||
}
|
||||
}
|
||||
host.removeChangedCardKeywords(timestamp);
|
||||
}
|
||||
host.removeChangedCardKeywords(timestamp);
|
||||
host.getGame().fireEvent(new GameEventCardStatsChanged(host));
|
||||
}
|
||||
};
|
||||
@@ -261,10 +254,10 @@ public class ManaPool extends ManaConversionMatrix implements Iterable<Mana> {
|
||||
}
|
||||
}
|
||||
if (mana.addsCounters(sa)) {
|
||||
mana.getManaAbility().createETBCounters(sa.getHostCard());
|
||||
mana.getManaAbility().createETBCounters(host);
|
||||
}
|
||||
if (mana.triggersWhenSpent()) {
|
||||
mana.getManaAbility().addTriggersWhenSpent(sa, sa.getHostCard());
|
||||
mana.getManaAbility().addTriggersWhenSpent(sa, host);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -44,7 +44,16 @@ public enum PhaseType {
|
||||
nameForScripts = name_for_scripts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public final boolean phaseforUpdateField() {
|
||||
boolean result =
|
||||
((ALL_PHASES.indexOf(this) >= ALL_PHASES.indexOf(UNTAP)
|
||||
&& ALL_PHASES.indexOf(this) < ALL_PHASES.indexOf(COMBAT_FIRST_STRIKE_DAMAGE))
|
||||
|| (ALL_PHASES.indexOf(this) >= ALL_PHASES.indexOf(MAIN2)
|
||||
&& ALL_PHASES.indexOf(this) < ALL_PHASES.indexOf(CLEANUP)));
|
||||
return result;
|
||||
}
|
||||
|
||||
public final boolean isAfter(final PhaseType phase) {
|
||||
return ALL_PHASES.indexOf(this) > ALL_PHASES.indexOf(phase);
|
||||
}
|
||||
|
||||
@@ -2430,6 +2430,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
controllerCreator = ctrlr;
|
||||
controller = ctrlr;
|
||||
updateAvatar();
|
||||
updateSleeve();
|
||||
view.updateIsAI(this);
|
||||
view.updateLobbyPlayerName(this);
|
||||
}
|
||||
@@ -2439,6 +2440,10 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
view.updateAvatarCardImageKey(this);
|
||||
}
|
||||
|
||||
public void updateSleeve() {
|
||||
view.updateSleeveIndex(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a procedure using a different controller
|
||||
*/
|
||||
|
||||
@@ -85,6 +85,13 @@ public class PlayerView extends GameEntityView {
|
||||
set(TrackableProperty.AvatarCardImageKey, p.getLobbyPlayer().getAvatarCardImageKey());
|
||||
}
|
||||
|
||||
public int getSleeveIndex() {
|
||||
return get(TrackableProperty.SleeveIndex);
|
||||
}
|
||||
void updateSleeveIndex(Player p) {
|
||||
set(TrackableProperty.SleeveIndex, p.getLobbyPlayer().getSleeveIndex());
|
||||
}
|
||||
|
||||
public String getCurrentPlaneName() { return get(TrackableProperty.CurrentPlane); }
|
||||
void updateCurrentPlaneName( String plane ) {
|
||||
set(TrackableProperty.CurrentPlane, plane);
|
||||
|
||||
@@ -124,7 +124,7 @@ public class StaticAbilityCantTarget {
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return common(st, spellAbility);
|
||||
}
|
||||
|
||||
protected static boolean common(final StaticAbility st, final SpellAbility spellAbility) {
|
||||
|
||||
@@ -122,6 +122,7 @@ public enum TrackableProperty {
|
||||
LobbyPlayerName(TrackableTypes.StringType),
|
||||
AvatarIndex(TrackableTypes.IntegerType),
|
||||
AvatarCardImageKey(TrackableTypes.StringType),
|
||||
SleeveIndex(TrackableTypes.IntegerType),
|
||||
Opponents(TrackableTypes.PlayerViewCollectionType),
|
||||
Life(TrackableTypes.IntegerType),
|
||||
PoisonCounters(TrackableTypes.IntegerType),
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.30-SNAPSHOT</version>
|
||||
<version>1.6.30</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui-android</artifactId>
|
||||
@@ -81,17 +81,17 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>24.1-android</version>
|
||||
<version>28.1-android</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.7</version>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xmlpull</groupId>
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
-dontwarn java.lang.**
|
||||
-dontwarn org.slf4j.**
|
||||
-dontwarn javax.**
|
||||
-dontwarn org.apache.logging.log4j.**
|
||||
-dontwarn module-info
|
||||
|
||||
# mandatory proguard rules for cache2k to keep the core implementation
|
||||
-dontwarn org.cache2k.impl.xmlConfiguration.**
|
||||
@@ -48,6 +50,7 @@
|
||||
-keep class com.google.guava.** { *; }
|
||||
-keep class com.google.common.** { *; }
|
||||
-keep class io.sentry.event.Event { *; }
|
||||
-keep class io.netty.util.internal.logging.** { *; }
|
||||
|
||||
-keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* {
|
||||
<init>(com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration);
|
||||
|
||||
@@ -14,6 +14,7 @@ import android.graphics.BitmapFactory;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.PowerManager;
|
||||
@@ -71,7 +72,8 @@ public class Main extends AndroidApplication {
|
||||
Main.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
||||
}
|
||||
|
||||
initialize(Forge.getApp(new AndroidClipboard(), adapter, assetsDir));
|
||||
boolean value = Build.VERSION.SDK_INT >= 26;
|
||||
initialize(Forge.getApp(new AndroidClipboard(), adapter, assetsDir, value));
|
||||
}
|
||||
|
||||
/*@Override
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.30-SNAPSHOT</version>
|
||||
<version>1.6.30</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui-desktop</artifactId>
|
||||
@@ -142,12 +142,12 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>24.1-android</version>
|
||||
<version>28.1-android</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>1.4.10</version>
|
||||
<version>1.4.11.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
@@ -168,9 +168,14 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.17</version>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>2.11.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.11.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.googlecode</groupId>
|
||||
@@ -180,7 +185,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.7</version>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
|
||||
@@ -202,6 +202,14 @@ public class GuiDesktop implements IGuiBase {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSleevesCount() {
|
||||
if (FSkin.isLoaded()) {
|
||||
return FSkin.getSleeves().size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String showFileDialog(final String title, final String defaultDir) {
|
||||
final JFileChooser fc = new JFileChooser(defaultDir);
|
||||
|
||||
@@ -383,6 +383,11 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
||||
updateMatrix(FModel.getFormats().getStandard());
|
||||
}
|
||||
break;
|
||||
case PIONEER_CARDGEN_DECK:
|
||||
if(FModel.isdeckGenMatrixLoaded()) {
|
||||
updateMatrix(FModel.getFormats().getPioneer());
|
||||
}
|
||||
break;
|
||||
case MODERN_CARDGEN_DECK:
|
||||
if(FModel.isdeckGenMatrixLoaded()) {
|
||||
updateMatrix(FModel.getFormats().getModern());
|
||||
|
||||
@@ -14,6 +14,7 @@ import javax.swing.ButtonGroup;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
|
||||
import forge.screens.home.sanctioned.SleeveSelector;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -66,7 +67,8 @@ public class PlayerPanel extends FPanel {
|
||||
|
||||
private final FLabel nameRandomiser;
|
||||
private final FLabel avatarLabel = new FLabel.Builder().opaque(true).hoverable(true).iconScaleFactor(0.99f).iconInBackground(true).build();
|
||||
private int avatarIndex;
|
||||
private final FLabel sleeveLabel = new FLabel.Builder().opaque(true).hoverable(true).iconScaleFactor(0.99f).iconInBackground(true).build();
|
||||
private int avatarIndex, sleeveIndex;
|
||||
|
||||
private final FTextField txtPlayerName = new FTextField.Builder().build();
|
||||
private FRadioButton radioHuman;
|
||||
@@ -127,6 +129,10 @@ public class PlayerPanel extends FPanel {
|
||||
createAvatar();
|
||||
this.add(avatarLabel, "spany 2, width 80px, height 80px");
|
||||
|
||||
/*TODO Layout and Override for PC*/
|
||||
//createSleeve();
|
||||
//this.add(sleeveLabel, "spany 2, width 60px, height 80px");
|
||||
|
||||
createNameEditor();
|
||||
this.add(lobby.newLabel(localizer.getMessage("lblName") +":"), "w 40px, h 30px, gaptop 5px");
|
||||
this.add(txtPlayerName, "h 30px, pushx, growx");
|
||||
@@ -204,6 +210,10 @@ public class PlayerPanel extends FPanel {
|
||||
avatarLabel.setIcon(FSkin.getAvatars().get(Integer.valueOf(type == LobbySlotType.OPEN ? -1 : avatarIndex)));
|
||||
avatarLabel.repaintSelf();
|
||||
|
||||
sleeveLabel.setEnabled(mayEdit);
|
||||
sleeveLabel.setIcon(FSkin.getSleeves().get(Integer.valueOf(type == LobbySlotType.OPEN ? -1 : sleeveIndex)));
|
||||
sleeveLabel.repaintSelf();
|
||||
|
||||
txtPlayerName.setEnabled(mayEdit);
|
||||
txtPlayerName.setText(type == LobbySlotType.OPEN ? StringUtils.EMPTY : playerName);
|
||||
nameRandomiser.setEnabled(mayEdit);
|
||||
@@ -332,6 +342,62 @@ public class PlayerPanel extends FPanel {
|
||||
}
|
||||
};
|
||||
|
||||
/** Listens to sleeve buttons and gives the appropriate player focus. */
|
||||
private final FocusAdapter sleeveFocusListener = new FocusAdapter() {
|
||||
@Override
|
||||
public void focusGained(final FocusEvent e) {
|
||||
lobby.changePlayerFocus(index);
|
||||
}
|
||||
};
|
||||
|
||||
private final FMouseAdapter sleeveMouseListener = new FMouseAdapter() {
|
||||
@Override public final void onLeftClick(final MouseEvent e) {
|
||||
if (!sleeveLabel.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final FLabel sleeve = (FLabel)e.getSource();
|
||||
|
||||
lobby.changePlayerFocus(index);
|
||||
sleeve.requestFocusInWindow();
|
||||
|
||||
final SleeveSelector sSel = new SleeveSelector(playerName, sleeveIndex, lobby.getUsedSleeves());
|
||||
for (final FLabel lbl : sSel.getSelectables()) {
|
||||
lbl.setCommand(new UiCommand() {
|
||||
@Override
|
||||
public void run() {
|
||||
setSleeveIndex(Integer.valueOf(lbl.getName().substring(11)));
|
||||
sSel.setVisible(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sSel.setVisible(true);
|
||||
sSel.dispose();
|
||||
|
||||
if (index < 2) {
|
||||
lobby.updateSleevePrefs();
|
||||
}
|
||||
|
||||
lobby.firePlayerChangeListener(index);
|
||||
}
|
||||
|
||||
@Override public final void onRightClick(final MouseEvent e) {
|
||||
if (!sleeveLabel.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
lobby.changePlayerFocus(index);
|
||||
sleeveLabel.requestFocusInWindow();
|
||||
|
||||
setRandomSleeve();
|
||||
|
||||
if (index < 2) {
|
||||
lobby.updateSleevePrefs();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void updateVariantControlsVisibility() {
|
||||
final boolean isOathbreaker = lobby.hasVariant(GameType.Oathbreaker);
|
||||
final boolean isTinyLeaders = lobby.hasVariant(GameType.TinyLeaders);
|
||||
@@ -703,6 +769,20 @@ public class PlayerPanel extends FPanel {
|
||||
avatarLabel.addMouseListener(avatarMouseListener);
|
||||
}
|
||||
|
||||
private void createSleeve() {
|
||||
final String[] currentPrefs = FModel.getPreferences().getPref(FPref.UI_SLEEVES).split(",");
|
||||
if (index < currentPrefs.length) {
|
||||
sleeveIndex = Integer.parseInt(currentPrefs[index]);
|
||||
sleeveLabel.setIcon(FSkin.getSleeves().get(sleeveIndex));
|
||||
} else {
|
||||
setRandomSleeve(false);
|
||||
}
|
||||
|
||||
sleeveLabel.setToolTipText("L-click: Select sleeve. R-click: Randomize sleeve.");
|
||||
sleeveLabel.addFocusListener(sleeveFocusListener);
|
||||
sleeveLabel.addMouseListener(sleeveMouseListener);
|
||||
}
|
||||
|
||||
/** Applies a random avatar, avoiding avatars already used. */
|
||||
private void setRandomAvatar() {
|
||||
setRandomAvatar(true);
|
||||
@@ -721,6 +801,24 @@ public class PlayerPanel extends FPanel {
|
||||
}
|
||||
}
|
||||
|
||||
/** Applies a random sleeve, avoiding sleeve already used. */
|
||||
private void setRandomSleeve() {
|
||||
setRandomSleeve(true);
|
||||
}
|
||||
private void setRandomSleeve(final boolean fireListeners) {
|
||||
int random = 0;
|
||||
|
||||
final List<Integer> usedSleeves = lobby.getUsedSleeves();
|
||||
do {
|
||||
random = MyRandom.getRandom().nextInt(FSkin.getSleeves().size());
|
||||
} while (usedSleeves.contains(random));
|
||||
setSleeveIndex(random);
|
||||
|
||||
if (fireListeners) {
|
||||
lobby.firePlayerChangeListener(index);
|
||||
}
|
||||
}
|
||||
|
||||
private final FSkin.LineSkinBorder focusedBorder = new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_BORDERS).alphaColor(255), 3);
|
||||
private final FSkin.LineSkinBorder defaultBorder = new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_THEME).alphaColor(200), 2);
|
||||
|
||||
@@ -746,6 +844,16 @@ public class PlayerPanel extends FPanel {
|
||||
avatarLabel.repaintSelf();
|
||||
}
|
||||
|
||||
public int getSleeveIndex() {
|
||||
return sleeveIndex;
|
||||
}
|
||||
public void setSleeveIndex(final int sleeveIndex0) {
|
||||
sleeveIndex = sleeveIndex0;
|
||||
final SkinImage icon = FSkin.getSleeves().get(sleeveIndex);
|
||||
sleeveLabel.setIcon(icon);
|
||||
sleeveLabel.repaintSelf();
|
||||
}
|
||||
|
||||
public int getTeam() {
|
||||
return teamComboBox.getSelectedIndex();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge.screens.home;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import forge.GuiBase;
|
||||
import forge.UiCommand;
|
||||
import forge.ai.AIOption;
|
||||
import forge.deck.*;
|
||||
@@ -222,6 +223,7 @@ public class VLobby implements ILobbyView {
|
||||
DeckType selectedDeckType = deckChooser.getSelectedDeckType();
|
||||
switch (selectedDeckType){
|
||||
case STANDARD_CARDGEN_DECK:
|
||||
case PIONEER_CARDGEN_DECK:
|
||||
case MODERN_CARDGEN_DECK:
|
||||
case LEGACY_CARDGEN_DECK:
|
||||
case VINTAGE_CARDGEN_DECK:
|
||||
@@ -258,6 +260,9 @@ public class VLobby implements ILobbyView {
|
||||
addPlayerBtn.setEnabled(activePlayersNum < MAX_PLAYERS);
|
||||
|
||||
final boolean allowNetworking = lobby.isAllowNetworking();
|
||||
|
||||
GuiBase.setNetworkplay(allowNetworking);
|
||||
|
||||
ImmutableList<VariantCheckBox> vntBoxes = null;
|
||||
if (allowNetworking) {
|
||||
vntBoxes = vntBoxesNetwork;
|
||||
@@ -397,7 +402,7 @@ public class VLobby implements ILobbyView {
|
||||
|
||||
private UpdateLobbyPlayerEvent getSlot(final int index) {
|
||||
final PlayerPanel panel = playerPanels.get(index);
|
||||
return UpdateLobbyPlayerEvent.create(panel.getType(), panel.getPlayerName(), panel.getAvatarIndex(), panel.getTeam(), panel.isArchenemy(), panel.isReady(), panel.isDevMode(), panel.getAiOptions());
|
||||
return UpdateLobbyPlayerEvent.create(panel.getType(), panel.getPlayerName(), panel.getAvatarIndex(), -1/*TODO panel.getSleeveIndex()*/, panel.getTeam(), panel.isArchenemy(), panel.isReady(), panel.isDevMode(), panel.getAiOptions());
|
||||
}
|
||||
|
||||
/** Builds the actual deck panel layouts for each player.
|
||||
@@ -858,6 +863,15 @@ public class VLobby implements ILobbyView {
|
||||
prefs.save();
|
||||
}
|
||||
|
||||
/** Saves sleeve prefs for players one and two. */
|
||||
void updateSleevePrefs() {
|
||||
final int pOneIndex = playerPanels.get(0).getSleeveIndex();
|
||||
final int pTwoIndex = playerPanels.get(1).getSleeveIndex();
|
||||
|
||||
prefs.setPref(FPref.UI_SLEEVES, pOneIndex + "," + pTwoIndex);
|
||||
prefs.save();
|
||||
}
|
||||
|
||||
/** Adds a pre-styled FLabel component with the specified title. */
|
||||
FLabel newLabel(final String title) {
|
||||
return new FLabel.Builder().text(title).fontSize(14).fontStyle(Font.ITALIC).build();
|
||||
@@ -871,6 +885,14 @@ public class VLobby implements ILobbyView {
|
||||
return usedAvatars;
|
||||
}
|
||||
|
||||
List<Integer> getUsedSleeves() {
|
||||
final List<Integer> usedSleeves = Lists.newArrayListWithCapacity(MAX_PLAYERS);
|
||||
for (final PlayerPanel pp : playerPanels) {
|
||||
usedSleeves.add(pp.getSleeveIndex());
|
||||
}
|
||||
return usedSleeves;
|
||||
}
|
||||
|
||||
|
||||
private static final ImmutableList<String> genderOptions = ImmutableList.of("Male", "Female", "Any"),
|
||||
typeOptions = ImmutableList.of("Fantasy", "Generic", "Any");
|
||||
|
||||
@@ -72,6 +72,7 @@ public enum CSubmenuGauntletQuick implements ICDoc {
|
||||
if (view.getBoxColorDecks().isSelected()) { allowedDeckTypes.add(DeckType.COLOR_DECK); }
|
||||
if (view.getBoxStandardColorDecks().isSelected()) { allowedDeckTypes.add(DeckType.STANDARD_COLOR_DECK); }
|
||||
if (view.getBoxStandardGenDecks().isSelected()) { allowedDeckTypes.add(DeckType.STANDARD_CARDGEN_DECK); }
|
||||
if (view.getBoxPioneerGenDecks().isSelected()) { allowedDeckTypes.add(DeckType.PIONEER_CARDGEN_DECK); }
|
||||
if (view.getBoxModernGenDecks().isSelected()) { allowedDeckTypes.add(DeckType.MODERN_CARDGEN_DECK); }
|
||||
if (view.getBoxLegacyGenDecks().isSelected()) { allowedDeckTypes.add(DeckType.LEGACY_CARDGEN_DECK); }
|
||||
if (view.getBoxVintageGenDecks().isSelected()) { allowedDeckTypes.add(DeckType.VINTAGE_CARDGEN_DECK); }
|
||||
|
||||
@@ -56,6 +56,7 @@ public enum VSubmenuGauntletQuick implements IVSubmenu<CSubmenuGauntletQuick> {
|
||||
private final JCheckBox boxColorDecks = new FCheckBox(DeckType.COLOR_DECK.toString());
|
||||
private final JCheckBox boxStandardColorDecks = new FCheckBox(DeckType.STANDARD_COLOR_DECK.toString());
|
||||
private final JCheckBox boxStandardCardgenDecks = new FCheckBox(DeckType.STANDARD_CARDGEN_DECK.toString());
|
||||
private final JCheckBox boxPioneerCardgenDecks = new FCheckBox(DeckType.PIONEER_CARDGEN_DECK.toString());
|
||||
private final JCheckBox boxModernCardgenDecks = new FCheckBox(DeckType.MODERN_CARDGEN_DECK.toString());
|
||||
private final JCheckBox boxLegacyCardgenDecks = new FCheckBox(DeckType.LEGACY_CARDGEN_DECK.toString());
|
||||
private final JCheckBox boxVintageCardgenDecks = new FCheckBox(DeckType.VINTAGE_CARDGEN_DECK.toString());
|
||||
@@ -88,11 +89,13 @@ public enum VSubmenuGauntletQuick implements IVSubmenu<CSubmenuGauntletQuick> {
|
||||
boxStandardColorDecks.setSelected(true);
|
||||
if(FModel.isdeckGenMatrixLoaded()) {
|
||||
boxStandardCardgenDecks.setSelected(true);
|
||||
boxPioneerCardgenDecks.setSelected(true);
|
||||
boxModernCardgenDecks.setSelected(true);
|
||||
boxLegacyCardgenDecks.setSelected(true);
|
||||
boxVintageCardgenDecks.setSelected(true);
|
||||
}else{
|
||||
boxStandardCardgenDecks.setSelected(false);
|
||||
boxPioneerCardgenDecks.setSelected(false);
|
||||
boxModernCardgenDecks.setSelected(false);
|
||||
boxLegacyCardgenDecks.setSelected(false);
|
||||
boxVintageCardgenDecks.setSelected(false);
|
||||
@@ -121,6 +124,7 @@ public enum VSubmenuGauntletQuick implements IVSubmenu<CSubmenuGauntletQuick> {
|
||||
pnlOptions.add(boxColorDecks, "w 96%!, h 30px!, gap 2% 0 0 5px");
|
||||
if(FModel.isdeckGenMatrixLoaded()) {
|
||||
pnlOptions.add(boxStandardCardgenDecks, "w 96%!, h 30px!, gap 2% 0 0 5px");
|
||||
pnlOptions.add(boxPioneerCardgenDecks, "w 96%!, h 30px!, gap 2% 0 0 5px");
|
||||
pnlOptions.add(boxModernCardgenDecks, "w 96%!, h 30px!, gap 2% 0 0 5px");
|
||||
pnlOptions.add(boxLegacyCardgenDecks, "w 96%!, h 30px!, gap 2% 0 0 5px");
|
||||
pnlOptions.add(boxVintageCardgenDecks, "w 96%!, h 30px!, gap 2% 0 0 5px");
|
||||
@@ -221,6 +225,9 @@ public enum VSubmenuGauntletQuick implements IVSubmenu<CSubmenuGauntletQuick> {
|
||||
public JCheckBox getBoxModernGenDecks() {
|
||||
return boxModernCardgenDecks;
|
||||
}
|
||||
public JCheckBox getBoxPioneerGenDecks() {
|
||||
return boxPioneerCardgenDecks;
|
||||
}
|
||||
public JCheckBox getBoxLegacyGenDecks() {
|
||||
return boxLegacyCardgenDecks;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package forge.screens.home.sanctioned;
|
||||
|
||||
import forge.gui.WrapLayout;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FScrollPane;
|
||||
import forge.toolbox.FSkin;
|
||||
import forge.view.FDialog;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class SleeveSelector extends FDialog {
|
||||
private final List<FLabel> selectables = new ArrayList<>();
|
||||
private final Map<Integer, FSkin.SkinImage> sleeveMap = FSkin.getSleeves();
|
||||
|
||||
public SleeveSelector(final String playerName, final int currentIndex, final Collection<Integer> usedIndices) {
|
||||
this.setTitle("Select Sleeve for " + playerName);
|
||||
|
||||
final JPanel pnlSleevePics = new JPanel(new WrapLayout());
|
||||
|
||||
pnlSleevePics.setOpaque(false);
|
||||
pnlSleevePics.setOpaque(false);
|
||||
|
||||
final FLabel initialSelection = makeSleeveLabel(sleeveMap.get(currentIndex), currentIndex, currentIndex);
|
||||
pnlSleevePics.add(initialSelection);
|
||||
for (final Integer i : sleeveMap.keySet()) {
|
||||
if (currentIndex != i) {
|
||||
pnlSleevePics.add(makeSleeveLabel(sleeveMap.get(i), i, currentIndex));
|
||||
}
|
||||
}
|
||||
|
||||
final int width = this.getOwner().getWidth() * 3 / 4;
|
||||
final int height = this.getOwner().getHeight() * 3 / 4;
|
||||
this.setPreferredSize(new Dimension(width, height));
|
||||
this.setSize(width, height);
|
||||
|
||||
final FScrollPane scroller = new FScrollPane(pnlSleevePics, false);
|
||||
scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
this.add(scroller, "w 100%-24px!, pushy, growy, gap 12px 0 0 0");
|
||||
this.setDefaultFocus(initialSelection);
|
||||
}
|
||||
|
||||
private FLabel makeSleeveLabel(final FSkin.SkinImage img0, final int index0, final int oldIndex) {
|
||||
final FLabel lbl = new FLabel.Builder().icon(img0).iconScaleFactor(0.95).iconAlignX(SwingConstants.CENTER)
|
||||
.iconInBackground(true).hoverable(true).selectable(true).selected(oldIndex == index0)
|
||||
.unhoveredAlpha(oldIndex == index0 ? 0.9f : 0.7f).build();
|
||||
|
||||
final Dimension size = new Dimension(60, 80);
|
||||
lbl.setPreferredSize(size);
|
||||
lbl.setMaximumSize(size);
|
||||
lbl.setMinimumSize(size);
|
||||
lbl.setName("SleeveLabel" + index0);
|
||||
|
||||
if (oldIndex == index0) {
|
||||
lbl.setBorder(new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_BORDERS).alphaColor(255), 3));
|
||||
}
|
||||
|
||||
selectables.add(lbl);
|
||||
|
||||
return lbl;
|
||||
}
|
||||
|
||||
public List<FLabel> getSelectables() {
|
||||
return this.selectables;
|
||||
}
|
||||
}
|
||||
@@ -859,6 +859,7 @@ public class FSkin {
|
||||
}
|
||||
|
||||
private static Map<Integer, SkinImage> avatars;
|
||||
private static Map<Integer, SkinImage> sleeves;
|
||||
private static Map<Integer, Font> fixedFonts = new HashMap<>();
|
||||
|
||||
public static Font getFixedFont() {
|
||||
@@ -1039,7 +1040,7 @@ public class FSkin {
|
||||
private static String preferredDir;
|
||||
private static String preferredName;
|
||||
private static BufferedImage bimDefaultSprite, bimFavIcon, bimPreferredSprite, bimFoils, bimQuestDraftDeck,
|
||||
bimOldFoils, bimDefaultAvatars, bimPreferredAvatars, bimTrophies, bimAbilities, bimManaIcons;
|
||||
bimOldFoils, bimDefaultAvatars, bimPreferredAvatars, bimTrophies, bimAbilities, bimManaIcons, bimDefaultSleeve, bimDefaultSleeve2;
|
||||
private static int x0, y0, w0, h0, newW, newH, preferredW, preferredH;
|
||||
private static int[] tempCoords;
|
||||
private static int defaultFontSize = 12;
|
||||
@@ -1173,6 +1174,8 @@ public class FSkin {
|
||||
final File f9 = new File(defaultDir + ForgeConstants.SPRITE_FAVICONS_FILE);
|
||||
final File f10 = new File(defaultDir + ForgeConstants.SPRITE_ABILITY_FILE);
|
||||
final File f11 = new File(defaultDir + ForgeConstants.SPRITE_MANAICONS_FILE);
|
||||
final File f12 = new File(defaultDir + ForgeConstants.SPRITE_SLEEVES_FILE);
|
||||
final File f13 = new File(defaultDir + ForgeConstants.SPRITE_SLEEVES2_FILE);
|
||||
|
||||
try {
|
||||
int p = 0;
|
||||
@@ -1190,6 +1193,10 @@ public class FSkin {
|
||||
FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
||||
bimDefaultAvatars = ImageIO.read(f4);
|
||||
FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
||||
bimDefaultSleeve = ImageIO.read(f12);
|
||||
FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
||||
bimDefaultSleeve2 = ImageIO.read(f13);
|
||||
FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
||||
bimTrophies = ImageIO.read(f7);
|
||||
FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
||||
bimQuestDraftDeck = ImageIO.read(f8);
|
||||
@@ -1255,6 +1262,8 @@ public class FSkin {
|
||||
|
||||
// Assemble avatar images
|
||||
assembleAvatars();
|
||||
// Sleeves
|
||||
assembleSleeves();
|
||||
|
||||
// Images loaded; can start UI init.
|
||||
FView.SINGLETON_INSTANCE.setSplashProgessBarMessage("Creating display components.");
|
||||
@@ -1266,6 +1275,8 @@ public class FSkin {
|
||||
bimOldFoils.flush();
|
||||
bimPreferredSprite.flush();
|
||||
bimDefaultAvatars.flush();
|
||||
bimDefaultSleeve.flush();
|
||||
bimDefaultSleeve2.flush();
|
||||
bimQuestDraftDeck.flush();
|
||||
bimTrophies.flush();
|
||||
bimAbilities.flush();
|
||||
@@ -1278,6 +1289,8 @@ public class FSkin {
|
||||
bimOldFoils = null;
|
||||
bimPreferredSprite = null;
|
||||
bimDefaultAvatars = null;
|
||||
bimDefaultSleeve = null;
|
||||
bimDefaultSleeve2 = null;
|
||||
bimPreferredAvatars = null;
|
||||
bimQuestDraftDeck = null;
|
||||
bimTrophies = null;
|
||||
@@ -1379,6 +1392,10 @@ public class FSkin {
|
||||
return avatars;
|
||||
}
|
||||
|
||||
public static Map<Integer, SkinImage> getSleeves() {
|
||||
return sleeves;
|
||||
}
|
||||
|
||||
public static boolean isLoaded() { return loaded; }
|
||||
|
||||
/**
|
||||
@@ -1482,6 +1499,34 @@ public class FSkin {
|
||||
}
|
||||
}
|
||||
|
||||
private static void assembleSleeves() {
|
||||
sleeves = new HashMap<>();
|
||||
int counter = 0;
|
||||
Color pxTest;
|
||||
|
||||
final int pw = bimDefaultSleeve.getWidth();
|
||||
final int ph = bimDefaultSleeve.getHeight();
|
||||
|
||||
for (int j = 0; j < ph; j += 500) {
|
||||
for (int i = 0; i < pw; i += 360) {
|
||||
pxTest = getColorFromPixel(bimDefaultSleeve.getRGB(i + 180, j + 250));
|
||||
if (pxTest.getAlpha() == 0) { continue; }
|
||||
sleeves.put(counter++, new SkinImage(bimDefaultSleeve.getSubimage(i, j, 360, 500)));
|
||||
}
|
||||
}
|
||||
//2nd set
|
||||
final int aw = bimDefaultSleeve2.getWidth();
|
||||
final int ah = bimDefaultSleeve2.getHeight();
|
||||
|
||||
for (int j = 0; j < ah; j += 500) {
|
||||
for (int i = 0; i < aw; i += 360) {
|
||||
pxTest = getColorFromPixel(bimDefaultSleeve2.getRGB(i + 180, j + 250));
|
||||
if (pxTest.getAlpha() == 0) { continue; }
|
||||
sleeves.put(counter++, new SkinImage(bimDefaultSleeve2.getSubimage(i, j, 360, 500)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void setImage(final FSkinProp s0, final BufferedImage bim) {
|
||||
tempCoords = s0.getCoords();
|
||||
x0 = tempCoords[0];
|
||||
|
||||
@@ -49,6 +49,9 @@ public final class Main {
|
||||
//setup GUI interface
|
||||
GuiBase.setInterface(new GuiDesktop());
|
||||
|
||||
//set PropertyConfig log4j to true
|
||||
GuiBase.enablePropertyConfig(true);
|
||||
|
||||
//install our error handler
|
||||
ExceptionHandler.registerErrorHandling();
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import forge.CachedCardImage;
|
||||
import forge.FThreads;
|
||||
import forge.StaticData;
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.CardTranslation;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardView;
|
||||
@@ -39,6 +38,7 @@ import forge.screens.match.CMatchUI;
|
||||
import forge.toolbox.CardFaceSymbols;
|
||||
import forge.toolbox.FSkin.SkinnedPanel;
|
||||
import forge.toolbox.IDisposable;
|
||||
import forge.util.CardTranslation;
|
||||
import forge.view.arcane.util.OutlinedLabel;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.30-SNAPSHOT</version>
|
||||
<version>1.6.30</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui-ios</artifactId>
|
||||
|
||||
@@ -29,7 +29,7 @@ public class Main extends IOSApplication.Delegate {
|
||||
final IOSApplicationConfiguration config = new IOSApplicationConfiguration();
|
||||
config.useAccelerometer = false;
|
||||
config.useCompass = false;
|
||||
final ApplicationListener app = Forge.getApp(new IOSClipboard(), new IOSAdapter(), assetsDir);
|
||||
final ApplicationListener app = Forge.getApp(new IOSClipboard(), new IOSAdapter(), assetsDir, false);
|
||||
final IOSApplication iosApp = new IOSApplication(app, config);
|
||||
return iosApp;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.30-SNAPSHOT</version>
|
||||
<version>1.6.30</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui-mobile-dev</artifactId>
|
||||
|
||||
@@ -93,7 +93,7 @@ public class Main {
|
||||
config.useHDPI = desktopMode; // enable HiDPI on Mac OS
|
||||
|
||||
new LwjglApplication(Forge.getApp(new LwjglClipboard(), new DesktopAdapter(switchOrientationFile),
|
||||
desktopMode ? desktopModeAssetsDir : assetsDir), config);
|
||||
desktopMode ? desktopModeAssetsDir : assetsDir, true), config);
|
||||
}
|
||||
|
||||
private static class DesktopAdapter implements IDeviceAdapter {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.30-SNAPSHOT</version>
|
||||
<version>1.6.30</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui-mobile</artifactId>
|
||||
@@ -48,17 +48,17 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>24.1-android</version>
|
||||
<version>28.1-android</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.7</version>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.badlogicgames.gdx</groupId>
|
||||
|
||||
@@ -10,7 +10,6 @@ import forge.assets.AssetsDownloader;
|
||||
import forge.assets.FSkin;
|
||||
import forge.assets.FSkinFont;
|
||||
import forge.assets.ImageCache;
|
||||
import forge.card.CardTranslation;
|
||||
import forge.error.BugReporter;
|
||||
import forge.error.ExceptionHandler;
|
||||
import forge.interfaces.IDeviceAdapter;
|
||||
@@ -31,6 +30,7 @@ import forge.toolbox.FGestureAdapter;
|
||||
import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.FOverlay;
|
||||
import forge.util.Callback;
|
||||
import forge.util.CardTranslation;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.Utils;
|
||||
@@ -67,11 +67,12 @@ public class Forge implements ApplicationListener {
|
||||
public static boolean enablePreloadExtendedArt = false;
|
||||
public static String locale = "en-US";
|
||||
|
||||
public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0) {
|
||||
public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0, boolean value) {
|
||||
if (GuiBase.getInterface() == null) {
|
||||
clipboard = clipboard0;
|
||||
deviceAdapter = deviceAdapter0;
|
||||
GuiBase.setInterface(new GuiMobile(assetDir0));
|
||||
GuiBase.enablePropertyConfig(value);
|
||||
}
|
||||
return app;
|
||||
}
|
||||
@@ -129,13 +130,13 @@ public class Forge implements ApplicationListener {
|
||||
FSkinFont.preloadAll(locale);
|
||||
|
||||
splashScreen.getProgressBar().setDescription(localizer.getMessage("lblLoadingCardTranslations"));
|
||||
CardTranslation.preloadTranslation(locale);
|
||||
CardTranslation.preloadTranslation(locale, ForgeConstants.LANG_DIR);
|
||||
|
||||
splashScreen.getProgressBar().setDescription(localizer.getMessage("lblFinishingStartup"));
|
||||
|
||||
//add reminder to preload
|
||||
if (enablePreloadExtendedArt)
|
||||
splashScreen.getProgressBar().setDescription("Preload Extended Art...");
|
||||
splashScreen.getProgressBar().setDescription(localizer.getMessage("lblPreloadExtendedArt"));
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -244,6 +244,14 @@ public class GuiMobile implements IGuiBase {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSleevesCount() {
|
||||
if (FSkin.isLoaded()) {
|
||||
return FSkin.getSleeves().size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String showFileDialog(final String title, final String defaultDir) {
|
||||
return ForgeConstants.USER_GAMES_DIR + "Test.fgs"; //TODO: Show dialog
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package forge.assets;
|
||||
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.PixmapIO;
|
||||
@@ -25,29 +24,30 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont.Glyph;
|
||||
import com.badlogic.gdx.graphics.g2d.PixmapPacker.Page;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
/** A utility to output BitmapFontData to a FNT file. This can be useful for caching the result from TrueTypeFont, for faster load
|
||||
* times.
|
||||
*
|
||||
* The font format is from the AngelCodeFont BMFont tool.
|
||||
*
|
||||
* @author mattdesl AKA davedes */
|
||||
|
||||
|
||||
/**
|
||||
* This file is 'borrowed' from gdx-tools in the libgdx source
|
||||
*/
|
||||
|
||||
public class BitmapFontWriter {
|
||||
/** A utility to output BitmapFontData to a FNT file. This can be useful for caching the result from TrueTypeFont, for faster load
|
||||
* times.
|
||||
* <p>
|
||||
* The font file format is from the AngelCodeFont BMFont tool.
|
||||
* <p>
|
||||
* Output is nearly identical to the FreeType settting in the Hiero tool {@Link com.badlogic.gdx.tools.hiero.Hiero}. BitmapFontWriter gives more flexibility, eg
|
||||
* borders and shadows can be used. Hiero is able to avoid outputting the same glyph image more than once if multiple character
|
||||
* codes have the exact same glyph.
|
||||
* @author mattdesl AKA davedes */
|
||||
public class BitmapFontWriter {
|
||||
|
||||
/** The output format. */
|
||||
public enum OutputFormat {
|
||||
|
||||
public static enum OutputFormat {
|
||||
|
||||
/** AngelCodeFont text format */
|
||||
Text,
|
||||
/** AngelCodeFont XML format */
|
||||
XML
|
||||
XML;
|
||||
}
|
||||
|
||||
|
||||
/** The output format */
|
||||
private static OutputFormat format = OutputFormat.Text;
|
||||
|
||||
@@ -55,26 +55,25 @@ import com.badlogic.gdx.utils.Array;
|
||||
* Pixi.js).
|
||||
*
|
||||
* @param fmt the output format to use */
|
||||
public static void setOutputFormat(OutputFormat fmt) {
|
||||
if (fmt==null)
|
||||
throw new NullPointerException("format cannot be null");
|
||||
public static void setOutputFormat (OutputFormat fmt) {
|
||||
if (fmt == null) throw new NullPointerException("format cannot be null");
|
||||
format = fmt;
|
||||
}
|
||||
|
||||
/** Returns the currently used output format.
|
||||
* @return the output format */
|
||||
public static OutputFormat getOutputFormat() {
|
||||
public static OutputFormat getOutputFormat () {
|
||||
return format;
|
||||
}
|
||||
|
||||
|
||||
/** The Padding parameter for FontInfo. */
|
||||
public static class Padding {
|
||||
public int up, down, left, right;
|
||||
|
||||
public Padding() {
|
||||
public Padding () {
|
||||
}
|
||||
|
||||
public Padding(int up, int down, int left, int right) {
|
||||
|
||||
public Padding (int up, int down, int left, int right) {
|
||||
this.up = up;
|
||||
this.down = down;
|
||||
this.left = left;
|
||||
@@ -87,8 +86,8 @@ import com.badlogic.gdx.utils.Array;
|
||||
public int horizontal, vertical;
|
||||
}
|
||||
|
||||
/** The font "info" line; this will be ignored by LibGDX's BitmapFont reader,
|
||||
* but useful for clean and organized output. */
|
||||
/** The font "info" line; everything except padding and override metrics are ignored by LibGDX's BitmapFont reader, it is otherwise just useful for
|
||||
* clean and organized output. */
|
||||
public static class FontInfo {
|
||||
/** Face name */
|
||||
public String face;
|
||||
@@ -113,32 +112,55 @@ import com.badlogic.gdx.utils.Array;
|
||||
/** Horizontal/vertical spacing that was applied to font */
|
||||
public Spacing spacing = new Spacing();
|
||||
public int outline = 0;
|
||||
|
||||
public FontInfo() {
|
||||
|
||||
/** Override metrics */
|
||||
public boolean hasOverrideMetrics;
|
||||
public float ascent;
|
||||
public float descent;
|
||||
public float down;
|
||||
public float capHeight;
|
||||
public float lineHeight;
|
||||
public float spaceXAdvance;
|
||||
public float xHeight;
|
||||
|
||||
public FontInfo () {
|
||||
}
|
||||
|
||||
public FontInfo(String face, int size) {
|
||||
|
||||
public FontInfo (String face, int size) {
|
||||
this.face = face;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void overrideMetrics (BitmapFontData data) {
|
||||
hasOverrideMetrics = true;
|
||||
ascent = data.ascent;
|
||||
descent = data.descent;
|
||||
down = data.down;
|
||||
capHeight = data.capHeight;
|
||||
lineHeight = data.lineHeight;
|
||||
spaceXAdvance = data.spaceXadvance;
|
||||
xHeight = data.xHeight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static String quote(Object params) {
|
||||
|
||||
private static String quote (Object params) {
|
||||
return quote(params, false);
|
||||
}
|
||||
|
||||
private static String quote(Object params, boolean spaceAfter) {
|
||||
|
||||
private static String quote (Object params, boolean spaceAfter) {
|
||||
if (BitmapFontWriter.getOutputFormat() == OutputFormat.XML)
|
||||
return "\"" + params.toString().trim() + "\"" + (spaceAfter ? " " : "");
|
||||
else
|
||||
return params.toString();
|
||||
}
|
||||
|
||||
/** Writes the given BitmapFontData to a file, using the specified <tt>pageRefs</tt> strings as the image paths for each texture
|
||||
* page. The glyphs in BitmapFontData have a "page" id, which references the index of the pageRef you specify here.
|
||||
/** Writes the given BitmapFontData to a file, using the specified <tt>pageRefs</tt> strings as the image paths for each
|
||||
* texture page. The glyphs in BitmapFontData have a "page" id, which references the index of the pageRef you specify here.
|
||||
*
|
||||
* The FontInfo parameter is useful for cleaner output; such as including a size and font face name hint. However, it can be
|
||||
* null to use default values. Ultimately, LibGDX ignores the "info" line when reading back fonts.
|
||||
* null to use default values. LibGDX ignores most of the "info" line when reading back fonts, only padding is used. Padding
|
||||
* also affects the size, location, and offset of the glyphs that are output.
|
||||
*
|
||||
* Likewise, the scaleW and scaleH are only for cleaner output. They are currently ignored by LibGDX's reader. For maximum
|
||||
* compatibility with other BMFont tools, you should use the width and height of your texture pages (each page should be the
|
||||
@@ -150,21 +172,22 @@ import com.badlogic.gdx.utils.Array;
|
||||
* @param info the optional info for the file header; can be null
|
||||
* @param scaleW the width of your texture pages
|
||||
* @param scaleH the height of your texture pages */
|
||||
public static void writeFont (BitmapFontData fontData, String[] pageRefs, FileHandle outFntFile, FontInfo info, int scaleW, int scaleH) {
|
||||
if (info==null) {
|
||||
public static void writeFont (BitmapFontData fontData, String[] pageRefs, FileHandle outFntFile, FontInfo info, int scaleW,
|
||||
int scaleH) {
|
||||
if (info == null) {
|
||||
info = new FontInfo();
|
||||
info.face = outFntFile.nameWithoutExtension();
|
||||
}
|
||||
|
||||
|
||||
int lineHeight = (int)fontData.lineHeight;
|
||||
int pages = pageRefs.length;
|
||||
int packed = 0;
|
||||
int base = (int)((fontData.capHeight) + (fontData.flipped ? -fontData.ascent : fontData.ascent));
|
||||
OutputFormat fmt = BitmapFontWriter.getOutputFormat();
|
||||
boolean xml = fmt == OutputFormat.XML;
|
||||
|
||||
boolean xml = fmt == OutputFormat.XML;
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
||||
|
||||
if (xml) {
|
||||
buf.append("<font>\n");
|
||||
}
|
||||
@@ -172,152 +195,129 @@ import com.badlogic.gdx.utils.Array;
|
||||
String xmlCloseSelf = xml ? "/>" : "";
|
||||
String xmlTab = xml ? "\t" : "";
|
||||
String xmlClose = xml ? ">" : "";
|
||||
|
||||
|
||||
String xmlQuote = xml ? "\"" : "";
|
||||
String alphaChnlParams =
|
||||
xml ? " alphaChnl=\"0\" redChnl=\"0\" greenChnl=\"0\" blueChnl=\"0\""
|
||||
: " alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0";
|
||||
//INFO LINE
|
||||
|
||||
buf.append(xmlOpen)
|
||||
.append("info face=\"")
|
||||
.append(info.face==null ? "" : info.face.replaceAll("\"", "'"))
|
||||
.append("\" size=").append( quote(info.size) )
|
||||
.append(" bold=").append( quote(info.bold ? 1 : 0) )
|
||||
.append(" italic=").append( quote(info.italic ? 1 : 0) )
|
||||
.append(" charset=\"").append(info.charset==null ? "" : info.charset)
|
||||
.append("\" unicode=").append( quote(info.unicode ? 1 : 0) )
|
||||
.append(" stretchH=").append( quote(info.stretchH) )
|
||||
.append(" smooth=").append( quote(info.smooth ? 1 : 0) )
|
||||
.append(" aa=").append( quote(info.aa) )
|
||||
.append(" padding=")
|
||||
.append(xmlQuote)
|
||||
.append(info.padding.up).append(",")
|
||||
.append(info.padding.down).append(",")
|
||||
.append(info.padding.left).append(",")
|
||||
.append(info.padding.right)
|
||||
.append(xmlQuote)
|
||||
.append(" spacing=")
|
||||
.append(xmlQuote)
|
||||
.append(info.spacing.horizontal).append(",")
|
||||
.append(info.spacing.vertical)
|
||||
.append(xmlQuote)
|
||||
.append(xmlCloseSelf)
|
||||
String alphaChnlParams = xml ? " alphaChnl=\"0\" redChnl=\"0\" greenChnl=\"0\" blueChnl=\"0\""
|
||||
: " alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0";
|
||||
|
||||
// INFO LINE
|
||||
buf.append(xmlOpen).append("info face=\"").append(info.face == null ? "" : info.face.replaceAll("\"", "'"))
|
||||
.append("\" size=").append(quote(info.size)).append(" bold=").append(quote(info.bold ? 1 : 0)).append(" italic=")
|
||||
.append(quote(info.italic ? 1 : 0)).append(" charset=\"").append(info.charset == null ? "" : info.charset)
|
||||
.append("\" unicode=").append(quote(info.unicode ? 1 : 0)).append(" stretchH=").append(quote(info.stretchH))
|
||||
.append(" smooth=").append(quote(info.smooth ? 1 : 0)).append(" aa=").append(quote(info.aa)).append(" padding=")
|
||||
.append(xmlQuote).append(info.padding.up).append(",").append(info.padding.right).append(",").append(info.padding.down)
|
||||
.append(",").append(info.padding.left).append(xmlQuote).append(" spacing=").append(xmlQuote)
|
||||
.append(info.spacing.horizontal).append(",").append(info.spacing.vertical).append(xmlQuote).append(xmlCloseSelf)
|
||||
.append("\n");
|
||||
|
||||
//COMMON line
|
||||
buf.append(xmlOpen)
|
||||
.append("common lineHeight=").append( quote(lineHeight) )
|
||||
.append(" base=").append( quote(base) )
|
||||
.append(" scaleW=").append( quote(scaleW) )
|
||||
.append(" scaleH=").append( quote(scaleH) )
|
||||
.append(" pages=").append( quote(pages) )
|
||||
.append(" packed=").append( quote(packed) )
|
||||
.append(alphaChnlParams)
|
||||
.append(xmlCloseSelf)
|
||||
.append("\n");
|
||||
|
||||
if (xml)
|
||||
buf.append("\t<pages>\n");
|
||||
|
||||
//PAGES
|
||||
for (int i=0; i<pageRefs.length; i++) {
|
||||
buf.append(xmlTab)
|
||||
.append(xmlOpen)
|
||||
.append("page id=")
|
||||
.append( quote(i) )
|
||||
.append(" file=\"")
|
||||
.append(pageRefs[i])
|
||||
.append("\"")
|
||||
.append(xmlCloseSelf)
|
||||
.append("\n");
|
||||
|
||||
// COMMON line
|
||||
buf.append(xmlOpen).append("common lineHeight=").append(quote(lineHeight)).append(" base=").append(quote(base))
|
||||
.append(" scaleW=").append(quote(scaleW)).append(" scaleH=").append(quote(scaleH)).append(" pages=").append(quote(pages))
|
||||
.append(" packed=").append(quote(packed)).append(alphaChnlParams).append(xmlCloseSelf).append("\n");
|
||||
|
||||
if (xml) buf.append("\t<pages>\n");
|
||||
|
||||
// PAGES
|
||||
for (int i = 0; i < pageRefs.length; i++) {
|
||||
buf.append(xmlTab).append(xmlOpen).append("page id=").append(quote(i)).append(" file=\"").append(pageRefs[i])
|
||||
.append("\"").append(xmlCloseSelf).append("\n");
|
||||
}
|
||||
|
||||
if (xml)
|
||||
buf.append("\t</pages>\n");
|
||||
|
||||
//CHARS
|
||||
Array<Glyph> glyphs = new Array<>(256);
|
||||
for (int i=0; i<fontData.glyphs.length; i++) {
|
||||
if (fontData.glyphs[i]==null)
|
||||
continue;
|
||||
|
||||
for (int j=0; j<fontData.glyphs[i].length; j++) {
|
||||
if (fontData.glyphs[i][j]!=null) {
|
||||
|
||||
if (xml) buf.append("\t</pages>\n");
|
||||
|
||||
// CHARS
|
||||
Array<Glyph> glyphs = new Array<Glyph>(256);
|
||||
for (int i = 0; i < fontData.glyphs.length; i++) {
|
||||
if (fontData.glyphs[i] == null) continue;
|
||||
|
||||
for (int j = 0; j < fontData.glyphs[i].length; j++) {
|
||||
if (fontData.glyphs[i][j] != null) {
|
||||
glyphs.add(fontData.glyphs[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf.append(xmlOpen)
|
||||
.append("chars count=").append(quote(glyphs.size))
|
||||
.append(xmlClose)
|
||||
.append("\n");
|
||||
|
||||
//CHAR definitions
|
||||
for (int i=0; i<glyphs.size; i++) {
|
||||
|
||||
buf.append(xmlOpen).append("chars count=").append(quote(glyphs.size)).append(xmlClose).append("\n");
|
||||
|
||||
int padLeft = 0, padRight = 0, padTop = 0, padX = 0, padY = 0;
|
||||
if (info != null) {
|
||||
padTop = info.padding.up;
|
||||
padLeft = info.padding.left;
|
||||
padRight = info.padding.right;
|
||||
padX = padLeft + padRight;
|
||||
padY = info.padding.up + info.padding.down;
|
||||
}
|
||||
|
||||
// CHAR definitions
|
||||
for (int i = 0; i < glyphs.size; i++) {
|
||||
Glyph g = glyphs.get(i);
|
||||
buf.append(xmlTab)
|
||||
.append(xmlOpen)
|
||||
.append("char id=")
|
||||
.append(quote( String.format("%-5s", g.id), true ))
|
||||
.append("x=").append(quote( String.format("%-5s", g.srcX), true ) )
|
||||
.append("y=").append(quote( String.format("%-5s", g.srcY), true ) )
|
||||
.append("width=").append(quote( String.format("%-5s", g.width), true ) )
|
||||
.append("height=").append(quote( String.format("%-5s", g.height), true ) )
|
||||
.append("xoffset=").append(quote( String.format("%-5s", g.xoffset), true ) )
|
||||
.append("yoffset=").append(quote( String.format("%-5s", fontData.flipped ? g.yoffset : -(g.height + g.yoffset) ), true ) )
|
||||
.append("xadvance=").append(quote( String.format("%-5s", g.xadvance), true ) )
|
||||
.append("page=").append(quote( String.format("%-5s", g.page), true ) )
|
||||
.append("chnl=").append(quote(0, true))
|
||||
.append(xmlCloseSelf)
|
||||
boolean empty = g.width == 0 || g.height == 0;
|
||||
buf.append(xmlTab).append(xmlOpen).append("char id=").append(quote(String.format("%-6s", g.id), true)).append("x=")
|
||||
.append(quote(String.format("%-5s", empty ? 0 : g.srcX), true)).append("y=")
|
||||
.append(quote(String.format("%-5s", empty ? 0 : g.srcY), true)).append("width=")
|
||||
.append(quote(String.format("%-5s", empty ? 0 : g.width), true)).append("height=")
|
||||
.append(quote(String.format("%-5s", empty ? 0 : g.height), true)).append("xoffset=")
|
||||
.append(quote(String.format("%-5s", g.xoffset - padLeft), true)).append("yoffset=")
|
||||
.append(quote(String.format("%-5s", fontData.flipped ? g.yoffset + padTop : -(g.height + (g.yoffset + padTop))), true))
|
||||
.append("xadvance=").append(quote(String.format("%-5s", g.xadvance), true)).append("page=")
|
||||
.append(quote(String.format("%-5s", g.page), true)).append("chnl=").append(quote(0, true)).append(xmlCloseSelf)
|
||||
.append("\n");
|
||||
}
|
||||
|
||||
if (xml)
|
||||
buf.append("\t</chars>\n");
|
||||
|
||||
//KERNINGS
|
||||
|
||||
if (xml) buf.append("\t</chars>\n");
|
||||
|
||||
// KERNINGS
|
||||
int kernCount = 0;
|
||||
StringBuilder kernBuf = new StringBuilder();
|
||||
StringBuilder kernBuf = new StringBuilder();
|
||||
for (int i = 0; i < glyphs.size; i++) {
|
||||
for (int j = 0; j < glyphs.size; j++) {
|
||||
Glyph first = glyphs.get(i);
|
||||
Glyph second = glyphs.get(j);
|
||||
int kern = first.getKerning((char)second.id);
|
||||
if (kern!=0) {
|
||||
if (kern != 0) {
|
||||
kernCount++;
|
||||
kernBuf.append(xmlTab)
|
||||
.append(xmlOpen)
|
||||
.append("kerning first=").append(quote(first.id))
|
||||
.append(" second=").append(quote(second.id))
|
||||
.append(" amount=").append(quote(kern, true))
|
||||
.append(xmlCloseSelf)
|
||||
.append("\n");
|
||||
kernBuf.append(xmlTab).append(xmlOpen).append("kerning first=").append(quote(first.id)).append(" second=")
|
||||
.append(quote(second.id)).append(" amount=").append(quote(kern, true)).append(xmlCloseSelf).append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//KERN info
|
||||
buf.append(xmlOpen)
|
||||
.append("kernings count=").append(quote(kernCount))
|
||||
.append(xmlClose)
|
||||
.append("\n");
|
||||
// KERN info
|
||||
buf.append(xmlOpen).append("kernings count=").append(quote(kernCount)).append(xmlClose).append("\n");
|
||||
buf.append(kernBuf);
|
||||
|
||||
|
||||
if (xml) {
|
||||
buf.append("\t</kernings>\n");
|
||||
}
|
||||
|
||||
// Override metrics
|
||||
if (info.hasOverrideMetrics) {
|
||||
if (xml) buf.append("\t<metrics>\n");
|
||||
|
||||
buf.append(xmlTab).append(xmlOpen)
|
||||
.append("metrics ascent=").append(quote(info.ascent, true))
|
||||
.append(" descent=").append(quote(info.descent, true))
|
||||
.append(" down=").append(quote(info.down, true))
|
||||
.append(" capHeight=").append(quote(info.capHeight, true))
|
||||
.append(" lineHeight=").append(quote(info.lineHeight, true))
|
||||
.append(" spaceXAdvance=").append(quote(info.spaceXAdvance, true))
|
||||
.append(" xHeight=").append(quote(info.xHeight, true))
|
||||
.append(xmlCloseSelf).append("\n");
|
||||
|
||||
if (xml) buf.append("\t</metrics>\n");
|
||||
}
|
||||
|
||||
if (xml) {
|
||||
buf.append("</font>");
|
||||
}
|
||||
|
||||
|
||||
String charset = info.charset;
|
||||
if (charset!=null&&charset.length()==0)
|
||||
charset = null;
|
||||
|
||||
if (charset != null && charset.length() == 0) charset = null;
|
||||
|
||||
outFntFile.writeString(buf.toString(), false, charset);
|
||||
}
|
||||
|
||||
|
||||
/** A utility method which writes the given font data to a file.
|
||||
*
|
||||
* The specified pixmaps are written to the parent directory of <tt>outFntFile</tt>, using that file's name without an
|
||||
@@ -337,8 +337,8 @@ import com.badlogic.gdx.utils.Array;
|
||||
* @param info the optional font info for the header file, can be null */
|
||||
public static void writeFont (BitmapFontData fontData, Pixmap[] pages, FileHandle outFntFile, FontInfo info) {
|
||||
String[] pageRefs = writePixmaps(pages, outFntFile.parent(), outFntFile.nameWithoutExtension());
|
||||
|
||||
//write the font data
|
||||
|
||||
// write the font data
|
||||
writeFont(fontData, pageRefs, outFntFile, info, pages[0].getWidth(), pages[0].getHeight());
|
||||
}
|
||||
|
||||
@@ -357,18 +357,17 @@ import com.badlogic.gdx.utils.Array;
|
||||
* @param fileName the file names for the output images
|
||||
* @return the array of string references to be used with <tt>writeFont</tt> */
|
||||
public static String[] writePixmaps (Pixmap[] pages, FileHandle outputDir, String fileName) {
|
||||
if (pages==null || pages.length==0)
|
||||
throw new IllegalArgumentException("no pixmaps supplied to BitmapFontWriter.write");
|
||||
|
||||
if (pages == null || pages.length == 0) throw new IllegalArgumentException("no pixmaps supplied to BitmapFontWriter.write");
|
||||
|
||||
String[] pageRefs = new String[pages.length];
|
||||
|
||||
for (int i=0; i<pages.length; i++) {
|
||||
String ref = pages.length==1 ? (fileName+".png") : (fileName+"_"+i+".png");
|
||||
|
||||
//the ref for this image
|
||||
|
||||
for (int i = 0; i < pages.length; i++) {
|
||||
String ref = pages.length == 1 ? (fileName + ".png") : (fileName + "_" + i + ".png");
|
||||
|
||||
// the ref for this image
|
||||
pageRefs[i] = ref;
|
||||
|
||||
//write the PNG in that directory
|
||||
|
||||
// write the PNG in that directory
|
||||
PixmapIO.writePNG(outputDir.child(ref), pages[i]);
|
||||
}
|
||||
return pageRefs;
|
||||
@@ -383,9 +382,9 @@ import com.badlogic.gdx.utils.Array;
|
||||
* @return the file refs */
|
||||
public static String[] writePixmaps (Array<Page> pages, FileHandle outputDir, String fileName) {
|
||||
Pixmap[] pix = new Pixmap[pages.size];
|
||||
for (int i=0; i<pages.size; i++) {
|
||||
for (int i = 0; i < pages.size; i++) {
|
||||
pix[i] = pages.get(i).getPixmap();
|
||||
}
|
||||
return writePixmaps(pix, outputDir, fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
package forge.assets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import forge.Forge;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
@@ -30,8 +29,10 @@ import forge.toolbox.FProgressBar;
|
||||
public class FSkin {
|
||||
private static final Map<FSkinProp, FSkinImage> images = new HashMap<>();
|
||||
private static final Map<Integer, TextureRegion> avatars = new HashMap<>();
|
||||
private static final Map<Integer, TextureRegion> sleeves = new HashMap<>();
|
||||
private static final Map<Integer, TextureRegion> borders = new HashMap<>();
|
||||
|
||||
private static List<String> allSkins;
|
||||
private static Array<String> allSkins;
|
||||
private static FileHandle preferredDir;
|
||||
private static String preferredName;
|
||||
private static boolean loaded = false;
|
||||
@@ -98,12 +99,12 @@ public class FSkin {
|
||||
else {
|
||||
if (splashScreen != null) {
|
||||
if (allSkins == null) { //initialize
|
||||
allSkins = new ArrayList<>();
|
||||
final List<String> skinDirectoryNames = getSkinDirectoryNames();
|
||||
allSkins = new Array<>();
|
||||
final Array<String> skinDirectoryNames = getSkinDirectoryNames();
|
||||
for (final String skinDirectoryName : skinDirectoryNames) {
|
||||
allSkins.add(WordUtils.capitalize(skinDirectoryName.replace('_', ' ')));
|
||||
}
|
||||
Collections.sort(allSkins);
|
||||
allSkins.sort();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +173,9 @@ public class FSkin {
|
||||
}
|
||||
|
||||
avatars.clear();
|
||||
sleeves.clear();
|
||||
|
||||
boolean textureFilter = Forge.isTextureFilteringEnabled();
|
||||
|
||||
final Map<String, Texture> textures = new HashMap<>();
|
||||
|
||||
@@ -183,6 +187,9 @@ public class FSkin {
|
||||
final FileHandle f5 = getSkinFile(ForgeConstants.SPRITE_AVATARS_FILE);
|
||||
final FileHandle f6 = getDefaultSkinFile(SourceFile.OLD_FOILS.getFilename());
|
||||
final FileHandle f7 = getDefaultSkinFile(ForgeConstants.SPRITE_MANAICONS_FILE);
|
||||
final FileHandle f8 = getDefaultSkinFile(ForgeConstants.SPRITE_SLEEVES_FILE);
|
||||
final FileHandle f9 = getDefaultSkinFile(ForgeConstants.SPRITE_SLEEVES2_FILE);
|
||||
final FileHandle f10 = getDefaultSkinFile(ForgeConstants.SPRITE_BORDER_FILE);
|
||||
|
||||
try {
|
||||
textures.put(f1.path(), new Texture(f1));
|
||||
@@ -218,16 +225,25 @@ public class FSkin {
|
||||
|
||||
//assemble avatar textures
|
||||
int counter = 0;
|
||||
int scount = 0;
|
||||
Color pxTest;
|
||||
Pixmap pxDefaultAvatars, pxPreferredAvatars;
|
||||
Texture txDefaultAvatars, txPreferredAvatars;
|
||||
Pixmap pxDefaultAvatars, pxPreferredAvatars, pxDefaultSleeves;
|
||||
Texture txDefaultAvatars, txPreferredAvatars, txDefaultSleeves;
|
||||
|
||||
pxDefaultAvatars = new Pixmap(f4);
|
||||
txDefaultAvatars = new Texture(f4);
|
||||
pxDefaultSleeves = new Pixmap(f8);
|
||||
txDefaultAvatars = new Texture(f4, textureFilter);
|
||||
if (textureFilter)
|
||||
txDefaultAvatars.setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear);
|
||||
txDefaultSleeves = new Texture(f8, textureFilter);
|
||||
if (textureFilter)
|
||||
txDefaultSleeves.setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear);
|
||||
|
||||
if (f5.exists()) {
|
||||
pxPreferredAvatars = new Pixmap(f5);
|
||||
txPreferredAvatars = new Texture(f5);
|
||||
txPreferredAvatars = new Texture(f5, textureFilter);
|
||||
if (textureFilter)
|
||||
txPreferredAvatars.setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear);
|
||||
|
||||
final int pw = pxPreferredAvatars.getWidth();
|
||||
final int ph = pxPreferredAvatars.getHeight();
|
||||
@@ -255,8 +271,42 @@ public class FSkin {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final int sw = pxDefaultSleeves.getWidth();
|
||||
final int sh = pxDefaultSleeves.getHeight();
|
||||
|
||||
for (int j = 0; j < sh; j += 500) {
|
||||
for (int i = 0; i < sw; i += 360) {
|
||||
pxTest = new Color(pxDefaultSleeves.getPixel(i + 180, j + 250));
|
||||
if (pxTest.a == 0) { continue; }
|
||||
FSkin.sleeves.put(scount++, new TextureRegion(txDefaultSleeves, i, j, 360, 500));
|
||||
}
|
||||
}
|
||||
|
||||
//re init second set of sleeves
|
||||
pxDefaultSleeves = new Pixmap(f9);
|
||||
txDefaultSleeves = new Texture(f9, textureFilter);
|
||||
if (textureFilter)
|
||||
txDefaultSleeves.setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear);
|
||||
|
||||
final int sw2 = pxDefaultSleeves.getWidth();
|
||||
final int sh2 = pxDefaultSleeves.getHeight();
|
||||
|
||||
for (int j = 0; j < sh2; j += 500) {
|
||||
for (int i = 0; i < sw2; i += 360) {
|
||||
pxTest = new Color(pxDefaultSleeves.getPixel(i + 180, j + 250));
|
||||
if (pxTest.a == 0) { continue; }
|
||||
FSkin.sleeves.put(scount++, new TextureRegion(txDefaultSleeves, i, j, 360, 500));
|
||||
}
|
||||
}
|
||||
|
||||
Texture bordersBW = new Texture(f10);
|
||||
FSkin.borders.put(0, new TextureRegion(bordersBW, 2, 2, 672, 936));
|
||||
FSkin.borders.put(1, new TextureRegion(bordersBW, 676, 2, 672, 936));
|
||||
|
||||
preferredIcons.dispose();
|
||||
pxDefaultAvatars.dispose();
|
||||
pxDefaultSleeves.dispose();;
|
||||
}
|
||||
catch (final Exception e) {
|
||||
System.err.println("FSkin$loadFull: Missing a sprite (default icons, "
|
||||
@@ -314,8 +364,8 @@ public class FSkin {
|
||||
*
|
||||
* @return the skins
|
||||
*/
|
||||
public static List<String> getSkinDirectoryNames() {
|
||||
final List<String> mySkins = new ArrayList<>();
|
||||
public static Array<String> getSkinDirectoryNames() {
|
||||
final Array<String> mySkins = new Array<>();
|
||||
|
||||
final FileHandle dir = Gdx.files.absolute(ForgeConstants.SKINS_DIR);
|
||||
for (FileHandle skinFile : dir.list()) {
|
||||
@@ -340,5 +390,13 @@ public class FSkin {
|
||||
return avatars;
|
||||
}
|
||||
|
||||
public static Map<Integer, TextureRegion> getSleeves() {
|
||||
return sleeves;
|
||||
}
|
||||
|
||||
public static Map<Integer, TextureRegion> getBorders() {
|
||||
return borders;
|
||||
}
|
||||
|
||||
public static boolean isLoaded() { return loaded; }
|
||||
}
|
||||
|
||||
@@ -463,7 +463,7 @@ public class FSkinFont {
|
||||
+ "驽驾驿骁骂骄骆骇验骏骐骑骗骚骤骨骰骷骸骼髅髓高鬃鬓鬣鬼魁魂魄"
|
||||
+ "魅魇魈魏魔鰴鱼鲁鲜鲤鲨鲮鲸鲽鳃鳄鳍鳐鳗鳝鳞鸟鸠鸡鸢鸣鸦鸽鹅鹉"
|
||||
+ "鹊鹏鹗鹞鹤鹦鹫鹭鹰鹿麋麒麟麦麻黄黎黏黑默黛黜點黠黯鼎鼓鼠鼬鼹"
|
||||
+ "鼻齐齑齿龇龙龟!(),/:;?~";
|
||||
+ "鼻齐齑齿龇龙龟伸!(),/:;?~";
|
||||
|
||||
final PixmapPacker packer = new PixmapPacker(pageSize, pageSize, Pixmap.Format.RGBA8888, 2, false);
|
||||
final FreeTypeFontParameter parameter = new FreeTypeFontParameter();
|
||||
|
||||
@@ -214,6 +214,16 @@ public class ImageCache {
|
||||
return Color.valueOf("#fffffd");
|
||||
return Color.valueOf("#171717");
|
||||
}
|
||||
public static int getFSkinBorders(CardView c) {
|
||||
if (c == null)
|
||||
return 0;
|
||||
|
||||
CardView.CardStateView state = c.getCurrentState();
|
||||
CardEdition ed = FModel.getMagicDb().getEditions().get(state.getSetCode());
|
||||
if (ed != null && ed.isWhiteBorder() && state.getFoilIndex() == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
public static boolean isExtendedArt(CardView c) {
|
||||
if (c == null)
|
||||
return false;
|
||||
|
||||
@@ -21,9 +21,10 @@ final class ImageLoader extends CacheLoader<String, Texture> {
|
||||
boolean extendedArt = false;
|
||||
boolean textureFilter = Forge.isTextureFilteringEnabled();
|
||||
if (key.length() > 4){
|
||||
if ((key.substring(0,4).contains("MPS_"))) //TODO add sets to get all extended art???
|
||||
if ((key.substring(0,4).contains("MPS_"))) //MPS_ sets
|
||||
extendedArt = true;
|
||||
else if ((key.substring(0,3).contains("UST"))) //Unstable Set
|
||||
extendedArt = true;
|
||||
//use generated extended art... it will preload the cache at startup so... yeah! :)
|
||||
}
|
||||
File file = ImageKeys.getImageFile(key);
|
||||
if (file != null) {
|
||||
|
||||
@@ -6,7 +6,10 @@ import com.badlogic.gdx.utils.Align;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import forge.Forge;
|
||||
import forge.Graphics;
|
||||
import forge.ImageKeys;
|
||||
import forge.assets.FBufferedImage;
|
||||
import forge.assets.FImage;
|
||||
import forge.assets.FSkin;
|
||||
import forge.assets.FSkinColor;
|
||||
import forge.assets.FSkinFont;
|
||||
import forge.assets.FSkinImage;
|
||||
@@ -25,6 +28,7 @@ import forge.properties.ForgeConstants;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.screens.FScreen;
|
||||
import forge.screens.match.MatchController;
|
||||
import forge.util.CardTranslation;
|
||||
import forge.util.Utils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -326,7 +330,9 @@ public class CardImageRenderer {
|
||||
}
|
||||
|
||||
public static void drawZoom(Graphics g, CardView card, GameView gameView, boolean altState, float x, float y, float w, float h, float dispW, float dispH, boolean isCurrentCard) {
|
||||
boolean canshow = MatchController.instance.mayView(card);
|
||||
final Texture image = ImageCache.getImage(card.getState(altState).getImageKey(MatchController.instance.getLocalPlayers()), true);
|
||||
FImage sleeves = MatchController.getPlayerSleeve(card.getOwner());
|
||||
if (image == null) { //draw details if can't draw zoom
|
||||
drawDetails(g, card, gameView, altState, x, y, w, h);
|
||||
return;
|
||||
@@ -337,8 +343,6 @@ public class CardImageRenderer {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean canLook = MatchController.instance.mayView(card);
|
||||
|
||||
if (image == ImageCache.defaultImage) { //support drawing card image manually if card image not found
|
||||
drawCardImage(g, card, altState, x, y, w, h, CardStackPosition.Top);
|
||||
}
|
||||
@@ -358,47 +362,43 @@ public class CardImageRenderer {
|
||||
if (ImageCache.isExtendedArt(card))
|
||||
g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90);
|
||||
else {
|
||||
if (rotatePlane)
|
||||
g.drawfillBorder(3, ImageCache.borderColor(card), new_xRotate, new_yRotate, new_h, new_w, radius);
|
||||
else
|
||||
g.drawfillBorder(3, ImageCache.borderColor(card), x, y, w, h, radius);
|
||||
|
||||
g.drawRotatedImage(ImageCache.croppedBorderImage(image), new_x+radius/2.3f, new_y+radius/2, new_w*0.96f, new_h*0.96f, (new_x+radius/2.3f) + (new_w*0.96f) / 2, (new_y+radius/2) + (new_h*0.96f) / 2, -90);
|
||||
g.drawRotatedImage(FSkin.getBorders().get(0), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90);
|
||||
g.drawRotatedImage(ImageCache.croppedBorderImage(image), new_x+radius/2, new_y+radius/2, new_w*0.96f, new_h*0.96f, (new_x+radius/2) + (new_w*0.96f) / 2, (new_y+radius/2) + (new_h*0.96f) / 2, -90);
|
||||
}
|
||||
}
|
||||
else
|
||||
g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90);
|
||||
} else if (rotateSplit && isCurrentCard && card.isSplitCard() && canLook) {
|
||||
} else if (rotateSplit && isCurrentCard && card.isSplitCard() && canshow) {
|
||||
boolean isAftermath = card.getText().contains("Aftermath") || card.getAlternateState().getOracleText().contains("Aftermath");
|
||||
if (Forge.enableUIMask) {
|
||||
if (ImageCache.isExtendedArt(card))
|
||||
g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90);
|
||||
else {
|
||||
if (rotateSplit)
|
||||
g.drawfillBorder(3, ImageCache.borderColor(card), new_xRotate, new_yRotate, new_h, new_w, radius);
|
||||
else
|
||||
g.drawfillBorder(3, ImageCache.borderColor(card), x, y, w, h, radius);
|
||||
|
||||
g.drawRotatedImage(ImageCache.croppedBorderImage(image), new_x + radius / 2.3f, new_y + radius / 2, new_w * 0.96f, new_h * 0.96f, (new_x + radius / 2.3f) + (new_w * 0.96f) / 2, (new_y + radius / 2) + (new_h * 0.96f) / 2, isAftermath ? 90 : -90);
|
||||
g.drawRotatedImage(FSkin.getBorders().get(ImageCache.getFSkinBorders(card)), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90);
|
||||
g.drawRotatedImage(ImageCache.croppedBorderImage(image), new_x + radius / 2, new_y + radius / 2, new_w * 0.96f, new_h * 0.96f, (new_x + radius / 2) + (new_w * 0.96f) / 2, (new_y + radius / 2) + (new_h * 0.96f) / 2, isAftermath ? 90 : -90);
|
||||
}
|
||||
}
|
||||
else
|
||||
g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90);
|
||||
}
|
||||
else {
|
||||
if (Forge.enableUIMask) {
|
||||
if (Forge.enableUIMask && canshow && !ImageKeys.getTokenKey(ImageKeys.MORPH_IMAGE).equals(card.getState(altState).getImageKey())) {
|
||||
if (ImageCache.isExtendedArt(card))
|
||||
g.drawImage(image, x, y, w, h);
|
||||
else {
|
||||
g.drawImage(ImageCache.getBorderImage(card, canLook), x, y, w, h);
|
||||
g.drawImage(ImageCache.getBorderImage(card, canshow), x, y, w, h);
|
||||
g.drawImage(ImageCache.croppedBorderImage(image), x + radius / 2.4f, y + radius / 2, w * 0.96f, h * 0.96f);
|
||||
}
|
||||
}
|
||||
else
|
||||
g.drawImage(image, x, y, w, h);
|
||||
else {
|
||||
if (canshow && !ImageKeys.getTokenKey(ImageKeys.MORPH_IMAGE).equals(card.getState(altState).getImageKey()))
|
||||
g.drawImage(image, x, y, w, h);
|
||||
else // sleeve
|
||||
g.drawImage(sleeves, x, y, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
CardRenderer.drawFoilEffect(g, card, x, y, w, h, isCurrentCard && canLook && image != ImageCache.defaultImage);
|
||||
CardRenderer.drawFoilEffect(g, card, x, y, w, h, isCurrentCard && canshow && image != ImageCache.defaultImage);
|
||||
}
|
||||
|
||||
public static void drawDetails(Graphics g, CardView card, GameView gameView, boolean altState, float x, float y, float w, float h) {
|
||||
|
||||
@@ -19,9 +19,12 @@ import forge.CachedCardImage;
|
||||
import forge.Forge;
|
||||
import forge.FThreads;
|
||||
import forge.Graphics;
|
||||
import forge.ImageKeys;
|
||||
import forge.StaticData;
|
||||
import forge.assets.FImage;
|
||||
import forge.assets.FImageComplex;
|
||||
import forge.assets.FRotatedImage;
|
||||
import forge.assets.FSkin;
|
||||
import forge.assets.FSkinColor;
|
||||
import forge.assets.FSkinFont;
|
||||
import forge.assets.FSkinImage;
|
||||
@@ -46,6 +49,7 @@ import forge.properties.ForgePreferences;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.screens.match.MatchController;
|
||||
import forge.toolbox.FList;
|
||||
import forge.util.CardTranslation;
|
||||
import forge.util.Utils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import forge.util.TextBounds;
|
||||
@@ -430,7 +434,9 @@ public class CardRenderer {
|
||||
}
|
||||
}
|
||||
public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean rotate) {
|
||||
boolean canshow = MatchController.instance.mayView(card) && !ImageKeys.getTokenKey(ImageKeys.MORPH_IMAGE).equals(card.getCurrentState().getImageKey());
|
||||
Texture image = new RendererCachedCardImage(card, false).getImage();
|
||||
FImage sleeves = MatchController.getPlayerSleeve(card.getOwner());
|
||||
float radius = (h - w)/8;
|
||||
|
||||
if (image != null) {
|
||||
@@ -444,7 +450,7 @@ public class CardRenderer {
|
||||
if (ImageCache.isExtendedArt(card))
|
||||
g.drawRotatedImage(image, x, y, w, h, x + w / 2, y + h / 2, -90);
|
||||
else {
|
||||
g.drawfillBorder(3, ImageCache.borderColor(card), x, y, w, h, radius);
|
||||
g.drawRotatedImage(FSkin.getBorders().get(0), x, y, w, h, x + w / 2, y + h / 2, -90);
|
||||
g.drawRotatedImage(ImageCache.croppedBorderImage(image), x+radius/2.3f, y+radius/2, w*0.96f, h*0.96f, (x+radius/2.3f) + (w*0.96f) / 2, (y+radius/2) + (h*0.96f) / 2, -90);
|
||||
}
|
||||
}
|
||||
@@ -452,17 +458,21 @@ public class CardRenderer {
|
||||
g.drawRotatedImage(image, x, y, w, h, x + w / 2, y + h / 2, -90);
|
||||
}
|
||||
else {
|
||||
if (Forge.enableUIMask) {
|
||||
if (Forge.enableUIMask && canshow) {
|
||||
if (ImageCache.isExtendedArt(card))
|
||||
g.drawImage(image, x, y, w, h);
|
||||
else {
|
||||
boolean t = (card.getCurrentState().getOriginalColors() != card.getCurrentState().getColors()) || card.getCurrentState().hasChangeColors();
|
||||
g.drawBorderImage(ImageCache.getBorderImage(card, MatchController.instance.mayView(card)), ImageCache.getTint(card), x, y, w, h, t); //tint check for changed colors
|
||||
g.drawBorderImage(ImageCache.getBorderImage(card, canshow), ImageCache.getTint(card), x, y, w, h, t); //tint check for changed colors
|
||||
g.drawImage(ImageCache.croppedBorderImage(image), x + radius / 2.4f, y + radius / 2, w * 0.96f, h * 0.96f);
|
||||
}
|
||||
}
|
||||
else
|
||||
g.drawImage(image, x, y, w, h);
|
||||
else {
|
||||
if (canshow)
|
||||
g.drawImage(image, x, y, w, h);
|
||||
else // draw card back sleeves
|
||||
g.drawImage(sleeves, x, y, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
drawFoilEffect(g, card, x, y, w, h, false);
|
||||
@@ -1113,11 +1123,15 @@ public class CardRenderer {
|
||||
}
|
||||
|
||||
public static void drawFoilEffect(Graphics g, CardView card, float x, float y, float w, float h, boolean inZoomer) {
|
||||
float new_x = x; float new_y = y; float new_w = w; float new_h = h; float radius = (h - w)/8;
|
||||
if (Forge.enableUIMask) {
|
||||
new_x += radius/2.4f; new_y += radius/2; new_w = w * 0.96f; new_h = h * 0.96f;
|
||||
}
|
||||
if (isPreferenceEnabled(FPref.UI_OVERLAY_FOIL_EFFECT) && MatchController.instance.mayView(card)) {
|
||||
boolean rotateSplit = isPreferenceEnabled(FPref.UI_ROTATE_SPLIT_CARDS) && card.isSplitCard() && inZoomer;
|
||||
int foil = card.getCurrentState().getFoilIndex();
|
||||
if (foil > 0) {
|
||||
CardFaceSymbols.drawOther(g, String.format("foil%02d", foil), x, y, w, h, rotateSplit);
|
||||
CardFaceSymbols.drawOther(g, String.format("foil%02d", foil), new_x, new_y, new_w, new_h, rotateSplit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.FTextField;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.util.Callback;
|
||||
import forge.util.Localizer;
|
||||
|
||||
public class GameEntityPicker extends TabPageScreen<GameEntityPicker> {
|
||||
private final FOptionPane optionPane;
|
||||
@@ -73,7 +74,7 @@ public class GameEntityPicker extends TabPageScreen<GameEntityPicker> {
|
||||
super(caption0 + " (" + items.size() + ")", icon0);
|
||||
txtSearch = add(new FTextField());
|
||||
txtSearch.setFont(FSkinFont.get(12));
|
||||
txtSearch.setGhostText("Search");
|
||||
txtSearch.setGhostText(Localizer.getInstance().getMessage("lblSearch"));
|
||||
txtSearch.setChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
|
||||
@@ -149,6 +149,7 @@ public class FDeckChooser extends FScreen {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
if (selectedDeckType != DeckType.STANDARD_COLOR_DECK && selectedDeckType != DeckType.STANDARD_CARDGEN_DECK
|
||||
&& selectedDeckType != DeckType.PIONEER_CARDGEN_DECK
|
||||
&& selectedDeckType != DeckType.MODERN_CARDGEN_DECK && selectedDeckType != DeckType.LEGACY_CARDGEN_DECK
|
||||
&& selectedDeckType != DeckType.VINTAGE_CARDGEN_DECK && selectedDeckType != DeckType.MODERN_COLOR_DECK &&
|
||||
selectedDeckType != DeckType.COLOR_DECK && selectedDeckType != DeckType.THEME_DECK
|
||||
@@ -172,6 +173,9 @@ public class FDeckChooser extends FScreen {
|
||||
else if (selectedDeckType == DeckType.STANDARD_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.PIONEER_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.MODERN_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
@@ -296,6 +300,7 @@ public class FDeckChooser extends FScreen {
|
||||
case RANDOM_CARDGEN_COMMANDER_DECK:
|
||||
case RANDOM_COMMANDER_DECK:
|
||||
case MODERN_CARDGEN_DECK:
|
||||
case PIONEER_CARDGEN_DECK:
|
||||
case LEGACY_CARDGEN_DECK:
|
||||
case VINTAGE_CARDGEN_DECK:
|
||||
case MODERN_COLOR_DECK:
|
||||
@@ -486,6 +491,7 @@ public class FDeckChooser extends FScreen {
|
||||
cmbDeckTypes.addItem(DeckType.STANDARD_COLOR_DECK);
|
||||
if(FModel.isdeckGenMatrixLoaded()) {
|
||||
cmbDeckTypes.addItem(DeckType.STANDARD_CARDGEN_DECK);
|
||||
cmbDeckTypes.addItem(DeckType.PIONEER_CARDGEN_DECK);
|
||||
cmbDeckTypes.addItem(DeckType.MODERN_CARDGEN_DECK);
|
||||
cmbDeckTypes.addItem(DeckType.LEGACY_CARDGEN_DECK);
|
||||
cmbDeckTypes.addItem(DeckType.VINTAGE_CARDGEN_DECK);
|
||||
@@ -698,6 +704,14 @@ public class FDeckChooser extends FScreen {
|
||||
}
|
||||
config = ItemManagerConfig.STRING_ONLY;
|
||||
break;
|
||||
case PIONEER_CARDGEN_DECK:
|
||||
maxSelections = 1;
|
||||
pool= new ArrayList<>();
|
||||
if(FModel.isdeckGenMatrixLoaded()) {
|
||||
pool = ArchetypeDeckGenerator.getMatrixDecks(FModel.getFormats().getPioneer(), isAi);
|
||||
}
|
||||
config = ItemManagerConfig.STRING_ONLY;
|
||||
break;
|
||||
case MODERN_CARDGEN_DECK:
|
||||
maxSelections = 1;
|
||||
pool= new ArrayList<>();
|
||||
@@ -1077,6 +1091,7 @@ public class FDeckChooser extends FScreen {
|
||||
DeckType.STANDARD_COLOR_DECK,
|
||||
DeckType.STANDARD_CARDGEN_DECK,
|
||||
DeckType.MODERN_COLOR_DECK,
|
||||
DeckType.PIONEER_CARDGEN_DECK,
|
||||
DeckType.MODERN_CARDGEN_DECK,
|
||||
DeckType.LEGACY_CARDGEN_DECK,
|
||||
DeckType.VINTAGE_CARDGEN_DECK,
|
||||
@@ -1085,6 +1100,7 @@ public class FDeckChooser extends FScreen {
|
||||
);
|
||||
if (!FModel.isdeckGenMatrixLoaded()) {
|
||||
deckTypes.remove(DeckType.STANDARD_CARDGEN_DECK);
|
||||
deckTypes.remove(DeckType.PIONEER_CARDGEN_DECK);
|
||||
deckTypes.remove(DeckType.MODERN_CARDGEN_DECK);
|
||||
deckTypes.remove(DeckType.LEGACY_CARDGEN_DECK);
|
||||
deckTypes.remove(DeckType.VINTAGE_CARDGEN_DECK);
|
||||
|
||||
@@ -13,6 +13,7 @@ import forge.toolbox.FDisplayObject;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FTextField;
|
||||
import forge.util.Localizer;
|
||||
|
||||
|
||||
public class TextSearchFilter<T extends InventoryItem> extends ItemFilter<T> {
|
||||
@@ -78,10 +79,10 @@ public class TextSearchFilter<T extends InventoryItem> extends ItemFilter<T> {
|
||||
}
|
||||
|
||||
public String getCaption() {
|
||||
return txtSearch.getGhostText().substring("Search ".length());
|
||||
return txtSearch.getGhostText().substring((Localizer.getInstance().getMessage("lblSearch") + " ").length());
|
||||
}
|
||||
public void setCaption(String caption0) {
|
||||
txtSearch.setGhostText("Search " + caption0);
|
||||
txtSearch.setGhostText(Localizer.getInstance().getMessage("lblSearch") + " " + caption0);
|
||||
}
|
||||
|
||||
protected class SearchField extends FTextField {
|
||||
@@ -89,7 +90,7 @@ public class TextSearchFilter<T extends InventoryItem> extends ItemFilter<T> {
|
||||
|
||||
private SearchField() {
|
||||
setFont(FONT);
|
||||
setGhostText("Search");
|
||||
setGhostText(Localizer.getInstance().getMessage("lblSearch"));
|
||||
setHeight(getDefaultHeight(DEFAULT_FONT)); //set height based on default filter font
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class AvatarSelector extends FScreen {
|
||||
}
|
||||
|
||||
private static final float PADDING = Utils.scale(5);
|
||||
private static final int COLUMNS = 4;
|
||||
private static final int COLUMNS = 5;
|
||||
|
||||
private final int currentIndex;
|
||||
private final List<Integer> usedAvatars;
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckSection;
|
||||
@@ -301,13 +302,20 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
}
|
||||
|
||||
/** Saves avatar prefs for players one and two. */
|
||||
void updateAvatarPrefs() {
|
||||
void updateAvatarPrefs() {
|
||||
int pOneIndex = playerPanels.get(0).getAvatarIndex();
|
||||
int pTwoIndex = playerPanels.get(1).getAvatarIndex();
|
||||
|
||||
prefs.setPref(FPref.UI_AVATARS, pOneIndex + "," + pTwoIndex);
|
||||
prefs.save();
|
||||
}
|
||||
void updateSleevePrefs() {
|
||||
int pOneIndex = playerPanels.get(0).getSleeveIndex();
|
||||
int pTwoIndex = playerPanels.get(1).getSleeveIndex();
|
||||
|
||||
prefs.setPref(FPref.UI_SLEEVES, pOneIndex + "," + pTwoIndex);
|
||||
prefs.save();
|
||||
}
|
||||
|
||||
/** Updates the avatars from preferences on update. */
|
||||
private void updatePlayersFromPrefs() {
|
||||
@@ -320,6 +328,13 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
playerPanels.get(i).setAvatarIndex(avatarIndex);
|
||||
}
|
||||
|
||||
// Sleeves
|
||||
String[] sleevePrefs = prefs.getPref(FPref.UI_SLEEVES).split(",");
|
||||
for (int i = 0; i < sleevePrefs.length; i++) {
|
||||
int sleeveIndex = Integer.parseInt(sleevePrefs[i]);
|
||||
playerPanels.get(i).setSleeveIndex(sleeveIndex);
|
||||
}
|
||||
|
||||
// Name
|
||||
String prefName = prefs.getPref(FPref.PLAYER_NAME);
|
||||
playerPanels.get(0).setPlayerName(StringUtils.isBlank(prefName) ? Localizer.getInstance().getMessage("lblHuman") : prefName);
|
||||
@@ -334,6 +349,15 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
return usedAvatars;
|
||||
}
|
||||
|
||||
List<Integer> getUsedSleeves() {
|
||||
List<Integer> usedSleeves = Arrays.asList(-1,-1,-1,-1,-1,-1,-1,-1);
|
||||
int i = 0;
|
||||
for (PlayerPanel pp : playerPanels) {
|
||||
usedSleeves.set(i++, pp.getSleeveIndex());
|
||||
}
|
||||
return usedSleeves;
|
||||
}
|
||||
|
||||
List<String> getPlayerNames() {
|
||||
List<String> names = new ArrayList<>();
|
||||
for (PlayerPanel pp : playerPanels) {
|
||||
@@ -350,6 +374,10 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
return playerPanels.get(i).getAvatarIndex();
|
||||
}
|
||||
|
||||
public int getPlayerSleeve(int i) {
|
||||
return playerPanels.get(i).getSleeveIndex();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//========== Various listeners in build order
|
||||
|
||||
@@ -448,6 +476,7 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
DeckType selectedDeckType = deckChooser.getSelectedDeckType();
|
||||
switch (selectedDeckType){
|
||||
case STANDARD_CARDGEN_DECK:
|
||||
case PIONEER_CARDGEN_DECK:
|
||||
case MODERN_CARDGEN_DECK:
|
||||
case LEGACY_CARDGEN_DECK:
|
||||
case VINTAGE_CARDGEN_DECK:
|
||||
@@ -498,6 +527,9 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
updateVariantSelection();
|
||||
|
||||
final boolean allowNetworking = lobby.isAllowNetworking();
|
||||
|
||||
GuiBase.setNetworkplay(allowNetworking);
|
||||
|
||||
for (int i = 0; i < cbPlayerCount.getSelectedItem(); i++) {
|
||||
final boolean hasPanel = i < playerPanels.size();
|
||||
if (i < playerCount) {
|
||||
@@ -527,8 +559,18 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
|
||||
final LobbySlotType type = slot.getType();
|
||||
panel.setType(type);
|
||||
panel.setPlayerName(slot.getName());
|
||||
panel.setAvatarIndex(slot.getAvatarIndex());
|
||||
if (type != LobbySlotType.AI) {
|
||||
panel.setPlayerName(slot.getName());
|
||||
panel.setAvatarIndex(slot.getAvatarIndex());
|
||||
panel.setSleeveIndex(slot.getSleeveIndex());
|
||||
} else {
|
||||
//AI: this one overrides the setplayername if blank
|
||||
if (panel.getPlayerName().isEmpty())
|
||||
panel.setPlayerName(slot.getName());
|
||||
//AI: override settings if somehow player changes it for AI
|
||||
slot.setAvatarIndex(panel.getAvatarIndex());
|
||||
slot.setSleeveIndex(panel.getSleeveIndex());
|
||||
}
|
||||
panel.setTeam(slot.getTeam());
|
||||
panel.setIsReady(slot.isReady());
|
||||
panel.setIsDevMode(slot.isDevMode());
|
||||
@@ -631,6 +673,18 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
}
|
||||
}
|
||||
|
||||
void updateAvatar(final int index, final int avatarIndex) {
|
||||
if (playerChangeListener != null) {
|
||||
playerChangeListener.update(index, UpdateLobbyPlayerEvent.avatarUpdate(avatarIndex));
|
||||
}
|
||||
}
|
||||
|
||||
void updateSleeve(final int index, final int sleeveIndex) {
|
||||
if (playerChangeListener != null) {
|
||||
playerChangeListener.update(index, UpdateLobbyPlayerEvent.sleeveUpdate(sleeveIndex));
|
||||
}
|
||||
}
|
||||
|
||||
void setReady(final int index, final boolean ready) {
|
||||
if (ready) {
|
||||
updateDeck(index);
|
||||
@@ -667,7 +721,7 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
|
||||
private UpdateLobbyPlayerEvent getSlot(final int index) {
|
||||
final PlayerPanel panel = playerPanels.get(index);
|
||||
return UpdateLobbyPlayerEvent.create(panel.getType(), panel.getPlayerName(), panel.getAvatarIndex(), panel.getTeam(), panel.isArchenemy(), panel.isReady(), panel.isDevMode(), panel.getAiOptions());
|
||||
return UpdateLobbyPlayerEvent.create(panel.getType(), panel.getPlayerName(), panel.getAvatarIndex(), panel.getSleeveIndex(), panel.getTeam(), panel.isArchenemy(), panel.isReady(), panel.isDevMode(), panel.getAiOptions());
|
||||
}
|
||||
|
||||
public List<PlayerPanel> getPlayerPanels() {
|
||||
|
||||
@@ -59,7 +59,8 @@ public class PlayerPanel extends FContainer {
|
||||
|
||||
private final FLabel nameRandomiser;
|
||||
private final FLabel avatarLabel = new FLabel.Builder().opaque(true).iconScaleFactor(0.99f).alphaComposite(1).iconInBackground(true).build();
|
||||
private int avatarIndex;
|
||||
private final FLabel sleeveLabel = new FLabel.Builder().opaque(true).iconScaleFactor(0.99f).alphaComposite(1).iconInBackground(true).build();
|
||||
private int avatarIndex, sleeveIndex;
|
||||
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
private final FTextField txtPlayerName = new FTextField(localizer.getMessage("lblPlayerName"));
|
||||
@@ -98,6 +99,7 @@ public class PlayerPanel extends FContainer {
|
||||
setType(slot.getType());
|
||||
setPlayerName(slot.getName());
|
||||
setAvatarIndex(slot.getAvatarIndex());
|
||||
setSleeveIndex(slot.getSleeveIndex());
|
||||
|
||||
devModeSwitch = new FToggleSwitch(localizer.getMessage("lblNormal"), localizer.getMessage("lblDevMode"));
|
||||
devModeSwitch.setVisible(isNetworkHost());
|
||||
@@ -189,6 +191,9 @@ public class PlayerPanel extends FContainer {
|
||||
createAvatar();
|
||||
add(avatarLabel);
|
||||
|
||||
createSleeve();
|
||||
add(sleeveLabel);
|
||||
|
||||
createNameEditor();
|
||||
add(newLabel(localizer.getMessage("lblName") + ":"));
|
||||
add(txtPlayerName);
|
||||
@@ -299,12 +304,16 @@ public class PlayerPanel extends FContainer {
|
||||
float y = PADDING;
|
||||
float fieldHeight = txtPlayerName.getHeight();
|
||||
float avatarSize = 2 * fieldHeight + PADDING;
|
||||
float sleeveSize = 2 * fieldHeight + PADDING;
|
||||
float sleeveSizeW = (sleeveSize/4)*3;
|
||||
float dy = fieldHeight + PADDING;
|
||||
|
||||
avatarLabel.setBounds(x, y, avatarSize, avatarSize);
|
||||
x += avatarSize + PADDING;
|
||||
sleeveLabel.setBounds(x, y, sleeveSizeW, sleeveSize);
|
||||
x += sleeveSizeW + PADDING;
|
||||
float w = width - x - fieldHeight - 2 * PADDING;
|
||||
txtPlayerName.setBounds(x, y, w, fieldHeight);
|
||||
txtPlayerName.setBounds(x, y, w, fieldHeight); //add space for card back
|
||||
x += w + PADDING;
|
||||
nameRandomiser.setBounds(x, y, fieldHeight, fieldHeight);
|
||||
|
||||
@@ -312,8 +321,8 @@ public class PlayerPanel extends FContainer {
|
||||
humanAiSwitch.setSize(humanAiSwitch.getAutoSizeWidth(fieldHeight), fieldHeight);
|
||||
x = width - humanAiSwitch.getWidth() - PADDING;
|
||||
humanAiSwitch.setPosition(x, y);
|
||||
w = x - avatarSize - 3 * PADDING;
|
||||
x = avatarSize + 2 * PADDING;
|
||||
w = x - (avatarSize+sleeveSizeW+PADDING) - 3 * PADDING;
|
||||
x = (avatarSize+sleeveSizeW+PADDING) + 2 * PADDING;
|
||||
if (cbArchenemyTeam.isVisible()) {
|
||||
cbArchenemyTeam.setBounds(x, y, w, fieldHeight);
|
||||
}
|
||||
@@ -411,6 +420,7 @@ public class PlayerPanel extends FContainer {
|
||||
//update may edit in-case it changed as a result of the AI change
|
||||
setMayEdit(screen.getLobby().mayEdit(index));
|
||||
setAvatarIndex(slot.getAvatarIndex());
|
||||
setSleeveIndex(slot.getSleeveIndex());
|
||||
setPlayerName(slot.getName());
|
||||
}
|
||||
}
|
||||
@@ -470,6 +480,7 @@ public class PlayerPanel extends FContainer {
|
||||
setAvatarIndex(result);
|
||||
|
||||
if (index < 2) {
|
||||
screen.updateAvatar(index, result);
|
||||
screen.updateAvatarPrefs();
|
||||
}
|
||||
if (allowNetworking) {
|
||||
@@ -480,6 +491,26 @@ public class PlayerPanel extends FContainer {
|
||||
}
|
||||
};
|
||||
|
||||
private FEventHandler sleeveCommand = new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
SleevesSelector.show(getPlayerName(), sleeveIndex, screen.getUsedSleeves(), new Callback<Integer>() {
|
||||
@Override
|
||||
public void run(Integer result) {
|
||||
setSleeveIndex(result);
|
||||
|
||||
if (index < 2) {
|
||||
screen.updateSleeve(index, result);
|
||||
screen.updateSleevePrefs();
|
||||
}
|
||||
if (allowNetworking) {
|
||||
screen.firePlayerChangeListener(index);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
public void setDeckSelectorButtonText(String text) {
|
||||
btnDeck.setText(text);
|
||||
}
|
||||
@@ -664,6 +695,17 @@ public class PlayerPanel extends FContainer {
|
||||
avatarLabel.setCommand(avatarCommand);
|
||||
}
|
||||
|
||||
private void createSleeve() {
|
||||
String[] currentPrefs = prefs.getPref(FPref.UI_SLEEVES).split(",");
|
||||
if (index < currentPrefs.length) {
|
||||
setSleeveIndex(Integer.parseInt(currentPrefs[index]));
|
||||
}
|
||||
else {
|
||||
setSleeveIndex(SleevesSelector.getRandomSleeves(screen.getUsedSleeves()));
|
||||
}
|
||||
sleeveLabel.setCommand(sleeveCommand);
|
||||
}
|
||||
|
||||
public void setAvatarIndex(int newAvatarIndex) {
|
||||
avatarIndex = newAvatarIndex;
|
||||
if (avatarIndex != -1) {
|
||||
@@ -674,10 +716,24 @@ public class PlayerPanel extends FContainer {
|
||||
}
|
||||
}
|
||||
|
||||
public void setSleeveIndex(int newSleeveIndex) {
|
||||
sleeveIndex = newSleeveIndex;
|
||||
if (sleeveIndex != -1) {
|
||||
sleeveLabel.setIcon(new FTextureRegionImage(FSkin.getSleeves().get(newSleeveIndex)));
|
||||
}
|
||||
else {
|
||||
sleeveLabel.setIcon(null);
|
||||
}
|
||||
}
|
||||
|
||||
public int getAvatarIndex() {
|
||||
return avatarIndex;
|
||||
}
|
||||
|
||||
public int getSleeveIndex() {
|
||||
return sleeveIndex;
|
||||
}
|
||||
|
||||
public void setPlayerName(String string) {
|
||||
txtPlayerName.setText(string);
|
||||
}
|
||||
@@ -759,6 +815,7 @@ public class PlayerPanel extends FContainer {
|
||||
if (mayEdit == mayEdit0) { return; }
|
||||
mayEdit = mayEdit0;
|
||||
avatarLabel.setEnabled(mayEdit);
|
||||
sleeveLabel.setEnabled(mayEdit);
|
||||
txtPlayerName.setEnabled(mayEdit);
|
||||
nameRandomiser.setEnabled(mayEdit);
|
||||
humanAiSwitch.setEnabled(mayEdit);
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
package forge.screens.constructed;
|
||||
|
||||
import forge.Forge;
|
||||
import forge.assets.FImage;
|
||||
import forge.assets.FSkin;
|
||||
import forge.assets.FSkinImage;
|
||||
import forge.assets.FTextureRegionImage;
|
||||
import forge.screens.FScreen;
|
||||
import forge.toolbox.FDisplayObject;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FScrollPane;
|
||||
import forge.util.Callback;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.Utils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
|
||||
public class SleevesSelector extends FScreen {
|
||||
public static int getRandomSleeves(List<Integer> usedSleeves) {
|
||||
int random = 0;
|
||||
do {
|
||||
random = MyRandom.getRandom().nextInt(FSkin.getSleeves().size());
|
||||
} while (usedSleeves.contains(random));
|
||||
return random;
|
||||
}
|
||||
|
||||
public static void show(final String playerName, final int currentIndex0, final List<Integer> usedSleeves0, final Callback<Integer> callback0) {
|
||||
SleevesSelector selector = new SleevesSelector(playerName, currentIndex0, usedSleeves0, callback0);
|
||||
Forge.openScreen(selector);
|
||||
}
|
||||
|
||||
private static final float PADDING = Utils.scale(5);
|
||||
private static final int COLUMNS = 5;
|
||||
|
||||
private final int currentIndex;
|
||||
private final List<Integer> usedSleeves;
|
||||
private final Callback<Integer> callback;
|
||||
private final FScrollPane scroller = new FScrollPane() {
|
||||
@Override
|
||||
protected ScrollBounds layoutAndGetScrollBounds(float visibleWidth, float visibleHeight) {
|
||||
int rowCount = 0;
|
||||
float x = PADDING;
|
||||
float y = PADDING;
|
||||
float labelSize = (visibleWidth - (COLUMNS + 1) * PADDING) / COLUMNS;
|
||||
for (FDisplayObject lbl : scroller.getChildren()) {
|
||||
if (rowCount == COLUMNS) { //wrap to next line
|
||||
x = PADDING;
|
||||
y += labelSize + PADDING;
|
||||
rowCount = 0;
|
||||
}
|
||||
lbl.setBounds(x, y, labelSize, labelSize);
|
||||
x += labelSize + PADDING;
|
||||
rowCount++;
|
||||
}
|
||||
return new ScrollBounds(visibleWidth, y + labelSize + PADDING);
|
||||
}
|
||||
};
|
||||
|
||||
private SleevesSelector(final String playerName, final int currentIndex0, final List<Integer> usedSleeves0, final Callback<Integer> callback0) {
|
||||
super("Select Sleeves for " + playerName);
|
||||
|
||||
currentIndex = currentIndex0;
|
||||
usedSleeves = usedSleeves0;
|
||||
callback = callback0;
|
||||
|
||||
//add label for selecting random sleeves first
|
||||
addSleevesLabel(FSkinImage.UNKNOWN, -1);
|
||||
|
||||
//add label for currently selected sleeves next
|
||||
final Map<Integer, TextureRegion> sleeveMap = FSkin.getSleeves();
|
||||
addSleevesLabel(new FTextureRegionImage(sleeveMap.get(currentIndex)), currentIndex);
|
||||
|
||||
//add label for remaining sleeves
|
||||
for (final Integer i : sleeveMap.keySet()) {
|
||||
if (currentIndex != i) {
|
||||
addSleevesLabel(new FTextureRegionImage(sleeveMap.get(i)), i);
|
||||
}
|
||||
}
|
||||
|
||||
add(scroller);
|
||||
}
|
||||
|
||||
private void addSleevesLabel(final FImage img, final int index) {
|
||||
final FLabel lbl = new FLabel.Builder().icon(img).iconScaleFactor(0.99f).align(Align.center)
|
||||
.iconInBackground(true).selectable(true).selected(currentIndex == index)
|
||||
.build();
|
||||
|
||||
if (index == -1) {
|
||||
lbl.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
callback.run(getRandomSleeves(usedSleeves));
|
||||
Forge.back();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
lbl.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
callback.run(index);
|
||||
Forge.back();
|
||||
}
|
||||
});
|
||||
}
|
||||
scroller.add(lbl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLayout(float startY, float width, float height) {
|
||||
scroller.setBounds(0, startY, width, height - startY);
|
||||
}
|
||||
}
|
||||
@@ -23,15 +23,18 @@ import forge.toolbox.FTextArea;
|
||||
import forge.toolbox.GuiChoose;
|
||||
import forge.toolbox.ListChooser;
|
||||
import forge.util.Callback;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.Utils;
|
||||
|
||||
public class NewGauntletScreen extends LaunchScreen {
|
||||
private static final float PADDING = Utils.scale(10);
|
||||
|
||||
private final Localizer localizer = Localizer.getInstance();
|
||||
|
||||
private final FTextArea lblDesc = add(new FTextArea(false,
|
||||
"In Gauntlet mode, you select a deck and play against multiple opponents.\n\n" +
|
||||
"Configure how many opponents you wish to face and what decks or types of decks they will play.\n\n" +
|
||||
"Then, try to beat all AI opponents without losing a match."));
|
||||
localizer.getMessage("lblGauntletText1") + "\n\n" +
|
||||
localizer.getMessage("lblGauntletText2") + "\n\n" +
|
||||
localizer.getMessage("lblGauntletText3")));
|
||||
|
||||
public NewGauntletScreen() {
|
||||
super(null, NewGameMenu.getMenu());
|
||||
@@ -51,44 +54,41 @@ public class NewGauntletScreen extends LaunchScreen {
|
||||
|
||||
@Override
|
||||
protected void startMatch() {
|
||||
GuiChoose.oneOrNone("Select a Gauntlet Type", new String[] {
|
||||
"Quick Gauntlet",
|
||||
"Custom Gauntlet",
|
||||
"Gauntlet Contest",
|
||||
GuiChoose.oneOrNone(localizer.getMessage("lblSelectGauntletType"), new String[] {
|
||||
localizer.getMessage("lblQuickGauntlet"),
|
||||
localizer.getMessage("lblCustomGauntlet"),
|
||||
localizer.getMessage("lblGauntletContest"),
|
||||
}, new Callback<String>() {
|
||||
@Override
|
||||
public void run(String result) {
|
||||
if (result == null) { return; }
|
||||
|
||||
switch (result) {
|
||||
case "Quick Gauntlet":
|
||||
if (localizer.getMessage("lblQuickGauntlet").equals(result)) {
|
||||
createQuickGauntlet();
|
||||
break;
|
||||
case "Custom Gauntlet":
|
||||
} else if(localizer.getMessage("lblCustomGauntlet").equals(result)) {
|
||||
createCustomGauntlet();
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
createGauntletContest();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createQuickGauntlet() {
|
||||
GuiChoose.getInteger("How many opponents are you willing to face?", 3, 50, new Callback<Integer>() {
|
||||
GuiChoose.getInteger(localizer.getMessage("lblHowManyOpponents"), 3, 50, new Callback<Integer>() {
|
||||
@Override
|
||||
public void run(final Integer numOpponents) {
|
||||
if (numOpponents == null) { return; }
|
||||
|
||||
ListChooser<DeckType> chooser = new ListChooser<>(
|
||||
"Choose allowed deck types for opponents", 0, 11, Arrays.asList(DeckType.CUSTOM_DECK,
|
||||
localizer.getMessage("lblChooseAllowedDeckTypeOpponents"), 0, 11, Arrays.asList(DeckType.CUSTOM_DECK,
|
||||
DeckType.PRECONSTRUCTED_DECK,
|
||||
DeckType.QUEST_OPPONENT_DECK,
|
||||
DeckType.COLOR_DECK,
|
||||
DeckType.STANDARD_COLOR_DECK,
|
||||
DeckType.STANDARD_CARDGEN_DECK,
|
||||
DeckType.MODERN_COLOR_DECK,
|
||||
DeckType.PIONEER_CARDGEN_DECK,
|
||||
DeckType.MODERN_CARDGEN_DECK,
|
||||
DeckType.LEGACY_CARDGEN_DECK,
|
||||
DeckType.VINTAGE_CARDGEN_DECK,
|
||||
@@ -99,7 +99,7 @@ public class NewGauntletScreen extends LaunchScreen {
|
||||
return;
|
||||
}
|
||||
|
||||
FDeckChooser.promptForDeck("Select Your Deck", GameType.Gauntlet, false, new Callback<Deck>() {
|
||||
FDeckChooser.promptForDeck(localizer.getMessage("lblSelectYourDeck"), GameType.Gauntlet, false, new Callback<Deck>() {
|
||||
@Override
|
||||
public void run(Deck userDeck) {
|
||||
if (userDeck == null) {
|
||||
@@ -118,7 +118,7 @@ public class NewGauntletScreen extends LaunchScreen {
|
||||
}
|
||||
|
||||
private void createCustomGauntlet() {
|
||||
GuiChoose.getInteger("How many opponents are you willing to face?", 3, 50, new Callback<Integer>() {
|
||||
GuiChoose.getInteger(localizer.getMessage("lblHowManyOpponents"), 3, 50, new Callback<Integer>() {
|
||||
@Override
|
||||
public void run(final Integer numOpponents) {
|
||||
if (numOpponents == null) { return; }
|
||||
@@ -132,7 +132,7 @@ public class NewGauntletScreen extends LaunchScreen {
|
||||
|
||||
private void promptForAiDeck(final GauntletData gauntlet, final int numOpponents) {
|
||||
final int opponentNum = gauntlet.getDecks().size() + 1;
|
||||
FDeckChooser.promptForDeck("Select Deck for Opponent " + opponentNum + " / " + numOpponents, GameType.Gauntlet, true, new Callback<Deck>() {
|
||||
FDeckChooser.promptForDeck(localizer.getMessage("lblSelectDeckForOpponent") + " " + opponentNum + " / " + numOpponents, GameType.Gauntlet, true, new Callback<Deck>() {
|
||||
@Override
|
||||
public void run(Deck aiDeck) {
|
||||
if (aiDeck == null) { return; }
|
||||
@@ -145,7 +145,7 @@ public class NewGauntletScreen extends LaunchScreen {
|
||||
}
|
||||
else {
|
||||
//once all ai decks have been selected, prompt for user deck
|
||||
FDeckChooser.promptForDeck("Select Your Deck", GameType.Gauntlet, false, new Callback<Deck>() {
|
||||
FDeckChooser.promptForDeck(localizer.getMessage("lblSelectYourDeck"), GameType.Gauntlet, false, new Callback<Deck>() {
|
||||
@Override
|
||||
public void run(Deck userDeck) {
|
||||
if (userDeck == null) { return; }
|
||||
@@ -170,12 +170,12 @@ public class NewGauntletScreen extends LaunchScreen {
|
||||
}
|
||||
}
|
||||
|
||||
GuiChoose.oneOrNone("Select Gauntlet Contest", contests, new Callback<GauntletData>() {
|
||||
GuiChoose.oneOrNone(localizer.getMessage("lblSelectGauntletContest"), contests, new Callback<GauntletData>() {
|
||||
@Override
|
||||
public void run(final GauntletData contest) {
|
||||
if (contest == null) { return; }
|
||||
|
||||
FDeckChooser.promptForDeck("Select Your Deck", GameType.Gauntlet, false, new Callback<Deck>() {
|
||||
FDeckChooser.promptForDeck(localizer.getMessage("lblSelectYourDeck"), GameType.Gauntlet, false, new Callback<Deck>() {
|
||||
@Override
|
||||
public void run(final Deck userDeck) {
|
||||
if (userDeck == null) { return; }
|
||||
|
||||
@@ -19,15 +19,13 @@ import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.util.Localizer;
|
||||
|
||||
public class LoadGameMenu extends FPopupMenu {
|
||||
final static Localizer localizer = Localizer.getInstance();
|
||||
|
||||
public enum LoadGameScreen {
|
||||
BoosterDraft(localizer.getMessage("lblBoosterDraft"), FSkinImage.HAND, LoadDraftScreen.class),
|
||||
SealedDeck(localizer.getMessage("lblSealedDeck"), FSkinImage.PACK, LoadSealedScreen.class),
|
||||
QuestMode(localizer.getMessage("lblQuestMode"), FSkinImage.QUEST_ZEP, LoadQuestScreen.class),
|
||||
PlanarConquest(localizer.getMessage("lblPlanarConquest"), FSkinImage.MULTIVERSE, LoadConquestScreen.class),
|
||||
Gauntlet(localizer.getMessage("lblGauntlet"), FSkinImage.ALPHASTRIKE, LoadGauntletScreen.class);
|
||||
|
||||
BoosterDraft("Booster Draft", FSkinImage.HAND, LoadDraftScreen.class),
|
||||
SealedDeck("Sealed Deck", FSkinImage.PACK, LoadSealedScreen.class),
|
||||
QuestMode("Quest Mode", FSkinImage.QUEST_ZEP, LoadQuestScreen.class),
|
||||
PlanarConquest("Planar Conquest", FSkinImage.MULTIVERSE, LoadConquestScreen.class),
|
||||
Gauntlet("Gauntlet", FSkinImage.ALPHASTRIKE, LoadGauntletScreen.class);
|
||||
|
||||
private final FMenuItem item;
|
||||
private final Class<? extends FScreen> screenClass;
|
||||
private FScreen screen;
|
||||
@@ -47,7 +45,7 @@ public class LoadGameMenu extends FPopupMenu {
|
||||
if (screen == null) { //don't initialize screen until it's opened the first time
|
||||
try {
|
||||
screen = screenClass.newInstance();
|
||||
screen.setHeaderCaption(localizer.getMessage("lblLoadGame") + " - " + item.getText());
|
||||
screen.setHeaderCaption(Localizer.getInstance().getMessage("lblLoadGame") + " - " + item.getText());
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -18,6 +18,7 @@ import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.FTextArea;
|
||||
import forge.toolbox.GuiChoose;
|
||||
import forge.util.Callback;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.Utils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -28,10 +29,9 @@ public class PuzzleScreen extends LaunchScreen {
|
||||
private static final float PADDING = Utils.scale(10);
|
||||
|
||||
private final FTextArea lblDesc = add(new FTextArea(false,
|
||||
"Puzzle Mode loads in a puzzle that you have to win in a predetermined time/way.\n\n" +
|
||||
"To begin, press the Start button below, then select a puzzle from a list.\n\n" +
|
||||
"Your objective will be displayed in a pop-up window when the puzzle starts and also " +
|
||||
"specified on a special effect card which will be placed in your command zone."));
|
||||
Localizer.getInstance().getMessage("lblPuzzleText1") + "\n\n" +
|
||||
Localizer.getInstance().getMessage("lblPuzzleText2") + "\n\n" +
|
||||
Localizer.getInstance().getMessage("lblPuzzleText3")));
|
||||
|
||||
public PuzzleScreen() {
|
||||
super(null, NewGameMenu.getMenu());
|
||||
@@ -54,10 +54,10 @@ public class PuzzleScreen extends LaunchScreen {
|
||||
final ArrayList<Puzzle> puzzles = PuzzleIO.loadPuzzles();
|
||||
Collections.sort(puzzles);
|
||||
|
||||
GuiChoose.one("Choose a puzzle", puzzles, new Callback<Puzzle>() {
|
||||
GuiChoose.one(Localizer.getInstance().getMessage("lblChooseAPuzzle"), puzzles, new Callback<Puzzle>() {
|
||||
@Override
|
||||
public void run(final Puzzle chosen) {
|
||||
LoadingOverlay.show("Loading the puzzle...", new Runnable() {
|
||||
LoadingOverlay.show(Localizer.getInstance().getMessage("lblLoadingThePuzzle"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Load selected puzzle
|
||||
|
||||
@@ -30,6 +30,7 @@ import forge.match.HostedMatch;
|
||||
import forge.model.FModel;
|
||||
import forge.player.GamePlayerUtil;
|
||||
import forge.toolbox.FComboBox;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.gui.SGuiChoose;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -37,20 +38,20 @@ import java.util.List;
|
||||
public class LoadDraftScreen extends LaunchScreen {
|
||||
private final DeckManager lstDecks = add(new DeckManager(GameType.Draft));
|
||||
private final FLabel lblTip = add(new FLabel.Builder()
|
||||
.text("Double-tap to edit deck (Long-press to view)")
|
||||
.text(Localizer.getInstance().getMessage("lblDoubleTapToEditDeck"))
|
||||
.textColor(FLabel.INLINE_LABEL_COLOR)
|
||||
.align(Align.center).font(FSkinFont.get(12)).build());
|
||||
|
||||
private final FSkinFont GAME_MODE_FONT= FSkinFont.get(12);
|
||||
private final FLabel lblMode = add(new FLabel.Builder().text("Mode:").font(GAME_MODE_FONT).build());
|
||||
private final FLabel lblMode = add(new FLabel.Builder().text(Localizer.getInstance().getMessage("lblMode")).font(GAME_MODE_FONT).build());
|
||||
private final FComboBox<String> cbMode = add(new FComboBox<>());
|
||||
|
||||
public LoadDraftScreen() {
|
||||
super(null, LoadGameMenu.getMenu());
|
||||
|
||||
cbMode.setFont(GAME_MODE_FONT);
|
||||
cbMode.addItem("Gauntlet");
|
||||
cbMode.addItem("Single Match");
|
||||
cbMode.addItem(Localizer.getInstance().getMessage("lblGauntlet"));
|
||||
cbMode.addItem(Localizer.getInstance().getMessage("lblSingleMatch"));
|
||||
|
||||
lstDecks.setup(ItemManagerConfig.DRAFT_DECKS);
|
||||
lstDecks.setItemActivateHandler(new FEventHandler() {
|
||||
@@ -98,17 +99,18 @@ public class LoadDraftScreen extends LaunchScreen {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Localizer localizer = Localizer.getInstance();
|
||||
final DeckProxy humanDeck = lstDecks.getSelectedItem();
|
||||
if (humanDeck == null) {
|
||||
FOptionPane.showErrorDialog("You must select an existing deck or build a deck from a new booster draft game.", "No Deck");
|
||||
FOptionPane.showErrorDialog(localizer.getMessage("lblYouMustSelectExistingDeck"), localizer.getMessage("lblNoDeck"));
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: if booster draft tournaments are supported in the future, add the possibility to choose them here
|
||||
final boolean gauntlet = cbMode.getSelectedItem().equals("Gauntlet");
|
||||
final boolean gauntlet = cbMode.getSelectedItem().equals(localizer.getMessage("lblGauntlet"));
|
||||
|
||||
if (gauntlet) {
|
||||
final Integer rounds = SGuiChoose.getInteger("How many opponents are you willing to face?",
|
||||
final Integer rounds = SGuiChoose.getInteger(localizer.getMessage("lblHowManyOpponents"),
|
||||
1, FModel.getDecks().getDraft().get(humanDeck.getName()).getAiDecks().size());
|
||||
if (rounds == null) {
|
||||
return;
|
||||
@@ -121,7 +123,7 @@ public class LoadDraftScreen extends LaunchScreen {
|
||||
return;
|
||||
}
|
||||
|
||||
LoadingOverlay.show("Loading new game...", new Runnable() {
|
||||
LoadingOverlay.show(localizer.getMessage("lblLoadingNewGame"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FModel.getGauntletMini().resetGauntletDraft();
|
||||
@@ -131,7 +133,7 @@ public class LoadDraftScreen extends LaunchScreen {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final Integer aiIndex = SGuiChoose.getInteger("Which opponent would you like to face?",
|
||||
final Integer aiIndex = SGuiChoose.getInteger(localizer.getMessage("lblWhichOpponentWouldYouLikeToFace"),
|
||||
1, FModel.getDecks().getDraft().get(humanDeck.getName()).getAiDecks().size());
|
||||
if (aiIndex == null) {
|
||||
return; // Cancel was pressed
|
||||
@@ -146,7 +148,7 @@ public class LoadDraftScreen extends LaunchScreen {
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show("Loading new game...", new Runnable() {
|
||||
LoadingOverlay.show(localizer.getMessage("lblLoadingNewGame"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!checkDeckLegality(humanDeck)) {
|
||||
@@ -177,7 +179,7 @@ public class LoadDraftScreen extends LaunchScreen {
|
||||
if (FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) {
|
||||
String errorMessage = GameType.Draft.getDeckFormat().getDeckConformanceProblem(humanDeck.getDeck());
|
||||
if (errorMessage != null) {
|
||||
FOptionPane.showErrorDialog("Your deck " + errorMessage + "\nPlease edit or choose a different deck.", "Invalid Deck");
|
||||
FOptionPane.showErrorDialog(Localizer.getInstance().getMessage("lblInvalidDeckDesc").replace("%n", errorMessage), Localizer.getInstance().getMessage("lblInvalidDeck"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import forge.screens.LoadingOverlay;
|
||||
import forge.screens.home.NewGameMenu;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FTextArea;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.ThreadUtil;
|
||||
import forge.util.Utils;
|
||||
import forge.util.gui.SGuiChoose;
|
||||
@@ -19,9 +20,9 @@ public class NewDraftScreen extends LaunchScreen {
|
||||
private static final float PADDING = Utils.scale(10);
|
||||
|
||||
private final FTextArea lblDesc = add(new FTextArea(false,
|
||||
"In Draft mode, three booster packs are rotated around eight players.\n\n" +
|
||||
"Build a deck from the cards you choose. The AI will do the same.\n\n" +
|
||||
"Then, play against any number of the AI opponents."));
|
||||
Localizer.getInstance().getMessage("lblDraftText1") + "\n\n" +
|
||||
Localizer.getInstance().getMessage("lblDraftText2") + "\n\n" +
|
||||
Localizer.getInstance().getMessage("lblDraftText3")));
|
||||
|
||||
public NewDraftScreen() {
|
||||
super(null, NewGameMenu.getMenu());
|
||||
@@ -44,7 +45,7 @@ public class NewDraftScreen extends LaunchScreen {
|
||||
ThreadUtil.invokeInGameThread(new Runnable() { //must run in game thread to prevent blocking UI thread
|
||||
@Override
|
||||
public void run() {
|
||||
final LimitedPoolType poolType = SGuiChoose.oneOrNone("Choose Draft Format", LimitedPoolType.values());
|
||||
final LimitedPoolType poolType = SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblChooseDraftFormat"), LimitedPoolType.values());
|
||||
if (poolType == null) { return; }
|
||||
|
||||
final BoosterDraft draft = BoosterDraft.createDraft(poolType);
|
||||
@@ -53,7 +54,7 @@ public class NewDraftScreen extends LaunchScreen {
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show("Loading new draft...", new Runnable() {
|
||||
LoadingOverlay.show(Localizer.getInstance().getMessage("lblLoadingNewDraft"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Forge.openScreen(new DraftingProcessScreen(draft, EditorType.Draft, null));
|
||||
|
||||
@@ -12,6 +12,7 @@ import forge.screens.LaunchScreen;
|
||||
import forge.screens.home.NewGameMenu;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FTextArea;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.ThreadUtil;
|
||||
import forge.util.Utils;
|
||||
|
||||
@@ -19,9 +20,9 @@ public class NewSealedScreen extends LaunchScreen {
|
||||
private static final float PADDING = Utils.scale(10);
|
||||
|
||||
private final FTextArea lblDesc = add(new FTextArea(false,
|
||||
"In Sealed mode, you build a deck from booster packs (maximum 10).\n\n" +
|
||||
"Build a deck from the cards you receive. A number of AI opponents will do the same.\n\n" +
|
||||
"Then, play against each of the AI opponents."));
|
||||
Localizer.getInstance().getMessage("lblSealedText2") + "\n\n" +
|
||||
Localizer.getInstance().getMessage("lblSealedText3") + "\n\n" +
|
||||
Localizer.getInstance().getMessage("lblSealedText4")));
|
||||
|
||||
public NewSealedScreen() {
|
||||
super(null, NewGameMenu.getMenu());
|
||||
|
||||
@@ -7,6 +7,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.assets.FSkinImage;
|
||||
import forge.util.Localizer;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -68,6 +70,8 @@ public class MatchController extends AbstractGuiGame {
|
||||
|
||||
private static final Map<String, FImage> avatarImages = new HashMap<>();
|
||||
|
||||
private static final Map<String, FImage> sleeveImages = new HashMap<>();
|
||||
|
||||
private static HostedMatch hostedMatch;
|
||||
private static MatchScreen view;
|
||||
|
||||
@@ -100,12 +104,34 @@ public class MatchController extends AbstractGuiGame {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public static FImage getPlayerSleeve(final PlayerView p) {
|
||||
if (p == null)
|
||||
return FSkinImage.UNKNOWN;
|
||||
final String lp = p.getLobbyPlayerName();
|
||||
FImage sleeve = sleeveImages.get(lp);
|
||||
if (sleeve == null) {
|
||||
sleeve = new FTextureRegionImage(FSkin.getSleeves().get(p.getSleeveIndex()));
|
||||
}
|
||||
return sleeve;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshCardDetails(final Iterable<CardView> cards) {
|
||||
//ensure cards appear in the correct row of the field
|
||||
/*//ensure cards appear in the correct row of the field
|
||||
for (final VPlayerPanel pnl : view.getPlayerPanels().values()) {
|
||||
pnl.getField().update();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshField() {
|
||||
if(getGameView() == null)
|
||||
return;
|
||||
if(getGameView().getPhase() == null)
|
||||
return;
|
||||
if (getGameView().getPhase().phaseforUpdateField())
|
||||
for (final VPlayerPanel pnl : view.getPlayerPanels().values())
|
||||
pnl.getField().update();
|
||||
}
|
||||
|
||||
public boolean hotSeatMode() {
|
||||
@@ -363,6 +389,42 @@ public class MatchController extends AbstractGuiGame {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectables(final Iterable<CardView> cards) {
|
||||
super.setSelectables(cards);
|
||||
// update zones on tabletop and floating zones - non-selectable cards may be rendered differently
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
for (final PlayerView p : getGameView().getPlayers()) {
|
||||
if ( p.getCards(ZoneType.Battlefield) != null ) {
|
||||
updateCards(p.getCards(ZoneType.Battlefield));
|
||||
}
|
||||
if ( p.getCards(ZoneType.Hand) != null ) {
|
||||
updateCards(p.getCards(ZoneType.Hand));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSelectables() {
|
||||
super.clearSelectables();
|
||||
// update zones on tabletop and floating zones - non-selectable cards may be rendered differently
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
for (final PlayerView p : getGameView().getPlayers()) {
|
||||
if ( p.getCards(ZoneType.Battlefield) != null ) {
|
||||
updateCards(p.getCards(ZoneType.Battlefield));
|
||||
}
|
||||
if ( p.getCards(ZoneType.Hand) != null ) {
|
||||
updateCards(p.getCards(ZoneType.Hand));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterGameEnd() {
|
||||
Forge.back();
|
||||
|
||||
@@ -376,6 +376,14 @@ public class MatchScreen extends FScreen {
|
||||
TargetingOverlay.drawArrow(g, blocker, attacker);
|
||||
}
|
||||
}
|
||||
//player
|
||||
if (is4Player() || is3Player()) {
|
||||
int numplayers = is3Player() ? 3 : 4;
|
||||
for (final PlayerView p : game.getPlayers()) {
|
||||
if (combat.getAttackersOf(p).contains(attacker))
|
||||
TargetingOverlay.drawArrow(g, attacker, p, numplayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,7 +403,7 @@ public class MatchScreen extends FScreen {
|
||||
return getActivePrompt().getBtnCancel().trigger(); //trigger Cancel if can't trigger OK
|
||||
case Keys.ESCAPE:
|
||||
if (!FModel.getPreferences().getPrefBoolean(FPref.UI_ALLOW_ESC_TO_END_TURN)) {
|
||||
if (getActivePrompt().getBtnCancel().getText().equals("End Turn")) {
|
||||
if (getActivePrompt().getBtnCancel().getText().equals(Localizer.getInstance().getMessage("lblEndTurn"))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,11 @@ public class TargetingOverlay {
|
||||
CardAreaPanel.get(endCard).getTargetingArrowOrigin(),
|
||||
connects);
|
||||
}
|
||||
public static void drawArrow(Graphics g, CardView startCard, PlayerView targetPlayer, int numplayers) {
|
||||
drawArrow(g, CardAreaPanel.get(startCard).getTargetingArrowOrigin(),
|
||||
MatchController.getView().getPlayerPanel(targetPlayer).getAvatar().getTargetingArrowOrigin(numplayers),
|
||||
ArcConnection.FoesAttacking);
|
||||
}
|
||||
public static void drawArrow(Graphics g, Vector2 start, CardView targetCard, ArcConnection connects) {
|
||||
drawArrow(g, start,
|
||||
CardAreaPanel.get(targetCard).getTargetingArrowOrigin(),
|
||||
|
||||
@@ -45,10 +45,15 @@ public class VAvatar extends FDisplayObject {
|
||||
}
|
||||
|
||||
public Vector2 getTargetingArrowOrigin() {
|
||||
return getTargetingArrowOrigin(2);
|
||||
}
|
||||
public Vector2 getTargetingArrowOrigin(int numplayers) {
|
||||
Vector2 origin = new Vector2(screenPos.x, screenPos.y);
|
||||
|
||||
origin.x += WIDTH * 0.75f;
|
||||
if (origin.y < MatchController.getView().getHeight() / 2) {
|
||||
float modx = numplayers > 2 ? 0.25f : 0.75f;
|
||||
|
||||
origin.x += WIDTH * modx;
|
||||
if (origin.y < MatchController.getView().getHeight() / numplayers) {
|
||||
origin.y += HEIGHT * 0.75f; //target bottom right corner if on top half of screen
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -53,21 +53,24 @@ public class ControlWinLose {
|
||||
view.hide();
|
||||
saveOptions();
|
||||
|
||||
MatchController.getHostedMatch().continueMatch();
|
||||
try { MatchController.getHostedMatch().continueMatch();
|
||||
} catch (NullPointerException e) {}
|
||||
}
|
||||
|
||||
/** Action performed when "restart" button is pressed in default win/lose UI. */
|
||||
public void actionOnRestart() {
|
||||
view.hide();
|
||||
saveOptions();
|
||||
MatchController.getHostedMatch().restartMatch();
|
||||
try { MatchController.getHostedMatch().restartMatch();
|
||||
} catch (NullPointerException e) {}
|
||||
}
|
||||
|
||||
/** Action performed when "quit" button is pressed in default win/lose UI. */
|
||||
public void actionOnQuit() {
|
||||
// Reset other stuff
|
||||
saveOptions();
|
||||
MatchController.getHostedMatch().endCurrentGame();
|
||||
try { MatchController.getHostedMatch().endCurrentGame();
|
||||
} catch (NullPointerException e) {}
|
||||
view.hide();
|
||||
}
|
||||
|
||||
|
||||
@@ -302,8 +302,8 @@ public class SettingsPage extends TabPage<SettingsScreen> {
|
||||
localizer.getMessage("nlDisableCardEffect")),
|
||||
4);
|
||||
lstSettings.addItem(new BooleanSetting(FPref.UI_ENABLE_BORDER_MASKING,
|
||||
"Enable Round Border Mask",
|
||||
"When enabled, the card corners are rounded (Preferably Card with Full Borders)."){
|
||||
localizer.getMessage("lblEnableRoundBorder"),
|
||||
localizer.getMessage("nlEnableRoundBorder")){
|
||||
@Override
|
||||
public void select() {
|
||||
super.select();
|
||||
@@ -312,8 +312,8 @@ public class SettingsPage extends TabPage<SettingsScreen> {
|
||||
}
|
||||
},4);
|
||||
lstSettings.addItem(new BooleanSetting(FPref.UI_ENABLE_PRELOAD_EXTENDED_ART,
|
||||
"Preload Extended Art Cards",
|
||||
"When enabled, Preloads Extended Art Cards to Cache on Startup."){
|
||||
localizer.getMessage("lblPreloadExtendedArtCards"),
|
||||
localizer.getMessage("nlPreloadExtendedArtCards")){
|
||||
@Override
|
||||
public void select() {
|
||||
super.select();
|
||||
@@ -322,8 +322,8 @@ public class SettingsPage extends TabPage<SettingsScreen> {
|
||||
}
|
||||
},4);
|
||||
lstSettings.addItem(new BooleanSetting(FPref.UI_SHOW_FPS,
|
||||
"Show FPS Display",
|
||||
"When enabled, show the FPS Display (Experimental)."){
|
||||
localizer.getMessage("lblShowFPSDisplay"),
|
||||
localizer.getMessage("nlShowFPSDisplay")){
|
||||
@Override
|
||||
public void select() {
|
||||
super.select();
|
||||
|
||||
@@ -1 +1,84 @@
|
||||
This file is automatically updated by our release bot on Discord, Blacksmith. It is created from the files present in the 'release-files' directory. Please do not hand-edit this file if using the bot to perform a release, as your changes will be overwritten.
|
||||
Forge: 11/11/2019 ver 1.6.30
|
||||
|
||||
19439 cards in total.
|
||||
|
||||
|
||||
--------------
|
||||
Release Notes:
|
||||
--------------
|
||||
|
||||
- Bug fixes -
|
||||
As always, this release of Forge features an assortment of bug fixes and improvements based on user feedback during the previous release run.
|
||||
|
||||
-------------
|
||||
Known Issues:
|
||||
-------------
|
||||
|
||||
Known issues are here: https://git.cardforge.org/core-developers/forge/issues
|
||||
|
||||
Feel free to report your own there if you have any.
|
||||
|
||||
-------------
|
||||
Installation:
|
||||
-------------
|
||||
|
||||
The Forge archive includes a MANUAL.txt file and we ask that you spend a few minutes reading this file as it contains some information that may prove useful. We do tend to update this file at times and you should quickly read this file and look for new information for each and every new release. Thank you.
|
||||
|
||||
The archive format used for the Forge distribution is ".tar.bz2". There are utilities for Windows, Mac OS and the various *nix's that can be used to extract/decompress these ".tar.bz2" archives. We recommend that you extract/decompress the Forge archive into a new and unused folder.
|
||||
|
||||
Some people use the Windows application 7zip. This utility can be found at http://www.7-zip.org/download.html. Mac users can double click on the archive and the application Archive Utility will launch and extract the archive. Mac users do not need to download a separate utility.
|
||||
|
||||
Once the Forge archive has been decompressed you should then be able to launch Forge by using the included launcher. Launching Forge by double clicking on the forge jar file in the past caused a java heap space error. Forge's memory requirements have increased over time and the launchers increase the java heap space available to Forge. Currently you can launch Forge by double clicking on the forge jar file without a java heap space error but this is likely to change as we add in more sounds, icons, etc.
|
||||
|
||||
- The Mac OS application version -
|
||||
We provide separate macOS builds of desktop and mobile (backported) Forge packaged as native Mac applications. Please check the relevant thread for details and download links.
|
||||
|
||||
|
||||
- Online Multiplayer -
|
||||
For local network play you should only need two systems running Forge. One to host and one to join and play. For remote (over the Internet) play you will need to ensure that the port used (36743 by default) is forwarded to the hosting machine.
|
||||
|
||||
--------------------
|
||||
Active Contributors:
|
||||
--------------------
|
||||
|
||||
Agetian
|
||||
apantel
|
||||
Austinio7116
|
||||
Churrufli
|
||||
DrDev
|
||||
excessum
|
||||
Flair
|
||||
Gos
|
||||
Hanmac
|
||||
Indigo Dragon
|
||||
Jamin Collins
|
||||
kevlahnota
|
||||
klaxnek
|
||||
KrazyTheFox
|
||||
leriomaggio
|
||||
Luke
|
||||
Marek14
|
||||
mcrawford620
|
||||
Meerkov
|
||||
Myrd
|
||||
nefigah
|
||||
OgreBattlecruiser
|
||||
pfps
|
||||
Ryan1729
|
||||
Seravy
|
||||
Sirspud
|
||||
Sloth
|
||||
slyfox7777777
|
||||
Sol
|
||||
Swordshine
|
||||
tjtillman
|
||||
tojammot
|
||||
torridus
|
||||
Xyx
|
||||
Zuchinni
|
||||
|
||||
(If you think your name should be on this list, add it with your next contribution)
|
||||
|
||||
(Quest icons used created by Teekatas, from his Legendora set http://raindropmemory.deviantart.com)
|
||||
(Thanks to the XMage team for permission to use their targeting arrows.)
|
||||
(Thanks to http://www.freesound.org/browse/ for providing some sound files.)
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.6.30-SNAPSHOT</version>
|
||||
<version>1.6.30</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-gui</artifactId>
|
||||
@@ -39,28 +39,33 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>24.1-android</version>
|
||||
<version>28.1-android</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>1.4.10</version>
|
||||
<version>1.4.11.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.7</version>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.0.25.Final</version>
|
||||
<version>4.1.43.Final</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.17</version>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>2.11.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.11.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.fourthline.cling</groupId>
|
||||
@@ -72,6 +77,11 @@
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>1.7.22</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapdb</groupId>
|
||||
<artifactId>elsa</artifactId>
|
||||
<version>3.0.0-M7</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#Add one announcement per line
|
||||
Throne of Eldraine pre-release!
|
||||
Updated Libgdx from 1.5.5 to 1.9.10 ([url=https://github.com/libgdx/libgdx/blob/master/CHANGES]detailed changes are here[/url]).
|
||||
Throne of Eldraine fixes
|
||||
Pioneer is here!
|
||||
Some fancy looking UI stuff was added. Card Sleeves and Keyword Icons
|
||||
Continued work on Translations
|
||||
[b]Forge now requires Java 8 (or newer). You will not be able to start the game if you are not yet running Java 8.[/b]
|
||||
For some reason Oracle hates Forge and version 1.8.0_211 does bad things with Forge for unknown reasons. Downgrade to 202 for a beter time.
|
||||
https://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8-2177648.html
|
||||
|
||||
@@ -10,6 +10,7 @@ Hanmac
|
||||
Indigo Dragon
|
||||
Jamin Collins
|
||||
kevlahnota
|
||||
klaxnek
|
||||
KrazyTheFox
|
||||
leriomaggio
|
||||
Luke
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Name:Dread Warlock
|
||||
ManaCost:1 B B
|
||||
Types:Creature Human Wizard
|
||||
Types:Creature Human Wizard Warlock
|
||||
PT:2/2
|
||||
K:CantBeBlockedBy Creature.nonBlack
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/dread_warlock.jpg
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Name:Memory Theft
|
||||
ManaCost:2 B
|
||||
Types:Sorcery
|
||||
A:SP$ Discard | Cost$ 2 B | ValidTgts$ Opponent | Mode$ RevealYouChoose | NumCards$ 1 | SubAbility$ DBChangeZone | SpellDescription$ Target opponent reveals their hand. You choose a nonland card from it. That player discards that card. You may put a card that has an Adventure that player owns from exile into that player's graveyard.
|
||||
A:SP$ Discard | Cost$ 2 B | ValidTgts$ Opponent | Mode$ RevealYouChoose | NumCards$ 1 | DiscardValid$ Card.nonLand | SubAbility$ DBChangeZone | SpellDescription$ Target opponent reveals their hand. You choose a nonland card from it. That player discards that card. You may put a card that has an Adventure that player owns from exile into that player's graveyard.
|
||||
SVar:DBChangeZone:DB$ ChangeZone | ChangeType$ Card.AdventureCard+TargetedPlayerCtrl | Origin$ Exile | Destination$ Graveyard | Hidden$ True
|
||||
Oracle:Target opponent reveals their hand. You choose a nonland card from it. That player discards that card. You may put a card that has an Adventure that player owns from exile into that player's graveyard.
|
||||
|
||||
@@ -7,7 +7,7 @@ K:Deathtouch
|
||||
K:Haste
|
||||
K:CantBeBlockedBy Creature.powerLE2
|
||||
S:Mode$ CantPreventDamage | IsCombat$ True | ValidSource$ Creature.YouCtrl | Description$ Combat damage that would be dealt by creatures you control can’t be prevented.
|
||||
T:Mode$ DamageDone | ValidSource$ Creature.YouCtrl | ValidTarget$ Opponent | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ MoreDamage | TriggerDescription$ Whenever CARDNAME deals combat damage to an opponent, it deals that much damage to target planeswalker that player controls.
|
||||
T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Opponent | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ MoreDamage | TriggerDescription$ Whenever CARDNAME deals combat damage to an opponent, it deals that much damage to target planeswalker that player controls.
|
||||
SVar:MoreDamage:DB$ DealDamage | ValidTgts$ Planeswalker.ControlledBy TriggeredTarget | TgtPrompt$ Select target planeswalker that player controls | NumDmg$ X | References$ X
|
||||
SVar:X:TriggerCount$DamageAmount
|
||||
Oracle:Vigilance, deathtouch, haste\nQuesting Beast can’t be blocked by creatures with power 2 or less.\nCombat damage that would be dealt by creatures you control can’t be prevented.\nWhenever Questing Beast deals combat damage to an opponent, it deals that much damage to target planeswalker that player controls.
|
||||
@@ -3,6 +3,6 @@ ManaCost:W/B W/B W/B W/B
|
||||
Types:Creature Human Knight
|
||||
PT:4/2
|
||||
A:AB$ Pump | Cost$ W/B W/B | KW$ Lifelink | Defined$ Self | SpellDescription$ CARDNAME gains lifelink until end of turn.
|
||||
A:AB$ Pump | Cost$ W/B W/B W/B W/B | KW$ Indestructible | Defined$ Self | SpellDescription$ CARDNAME gains indestructible until end of turn.
|
||||
A:AB$ Pump | Cost$ W/B W/B W/B | KW$ Indestructible | Defined$ Self | SpellDescription$ CARDNAME gains indestructible until end of turn.
|
||||
DeckHas:Ability$LifeGain
|
||||
Oracle:{W/B}{W/B}: Resolute Rider gains lifelink until end of turn.\n{W/B}{W/B}{W/B}{W/B}: Resolute Rider gains indestructible until end of turn.
|
||||
Oracle:{W/B}{W/B}: Resolute Rider gains lifelink until end of turn.\n{W/B}{W/B}{W/B}: Resolute Rider gains indestructible until end of turn.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
BIN
forge-gui/res/deckgendecks/Pioneer.lda.dat
Normal file
BIN
forge-gui/res/deckgendecks/Pioneer.lda.dat
Normal file
Binary file not shown.
BIN
forge-gui/res/deckgendecks/Pioneer.raw.dat
Normal file
BIN
forge-gui/res/deckgendecks/Pioneer.raw.dat
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,4 +4,4 @@ Order:108
|
||||
Subtype:Custom
|
||||
Type:Casual
|
||||
Rarities:L, C
|
||||
Banned:Gush;Gitaxian Probe;Daze
|
||||
Banned:Gush;Gitaxian Probe;Daze;Arcum's Astrolabe
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[format]
|
||||
Name:Modern
|
||||
Order:102
|
||||
Order:103
|
||||
Subtype:Modern
|
||||
Type:Sanctioned
|
||||
Sets:8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, LRW, EVE, SHM, MOR, ALA, CFX, ARB, M10, ZEN, WWK, ROE, M11, SOM, MBS, NPH, M12, ISD, DKA, AVR, M13, RTR, GTC, DGM, M14, THS, BNG, JOU, M15, KTK, FRF, DTK, MM2, ORI, BFZ, OGW, SOI, EMN, KLD, AER, AKH, W17, HOU, XLN, RIX, DOM, M19, G18, GRN, RNA, WAR, MH1, M20, ELD
|
||||
|
||||
7
forge-gui/res/formats/Sanctioned/Pioneer.txt
Normal file
7
forge-gui/res/formats/Sanctioned/Pioneer.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
[format]
|
||||
Name:Pioneer
|
||||
Order:102
|
||||
Subtype:Pioneer
|
||||
Type:Sanctioned
|
||||
Sets:RTR, GTC, DGM, M14, THS, BNG, JOU, M15, KTK, FRF, DTK, ORI, BFZ, OGW, SOI, EMN, KLD, AER, AKH, HOU, XLN, RIX, DOM, M19, GRN, RNA, WAR, M20, ELD
|
||||
Banned:Bloodstained Mire; Flooded Strand; Polluted Delta; Windswept Heath; Wooded Foothills; Felidar Guardian; Leyline of Abundance; Oath of Nissa
|
||||
@@ -4,4 +4,4 @@ Order:101
|
||||
Subtype:Standard
|
||||
Type:Sanctioned
|
||||
Sets:GRN, RNA, WAR, M20, ELD
|
||||
Banned:
|
||||
Banned:Field of the Dead
|
||||
|
||||
@@ -41,7 +41,7 @@ txerrFailedtodeletelayoutfile=Fehler beim Löschen der Layout-Datei.
|
||||
#VSubmenuPreferences.java
|
||||
Preferences=Einstellungen
|
||||
btnReset=Alles zurücksetzen
|
||||
btnDeleteMatchUI=SpielfeldLayout zurücksetzen
|
||||
btnDeleteMatchUI=Spielfeld-Layout zurücksetzen
|
||||
btnDeleteEditorUI=Editor-Layout zurücksetzen
|
||||
btnDeleteWorkshopUI=Workshop-Layout zurücksetzen
|
||||
btnUserProfileUI=Öffne Benutzer-Verzeichnis
|
||||
@@ -179,8 +179,8 @@ KeyboardShortcuts=Tastenkombinationen
|
||||
lblAchievements=Errungenschaften
|
||||
# VSubmenuDownloaders.java
|
||||
btnDownloadSetPics=Bilder(LQ) Sets herunterladen
|
||||
btnDownloadPics=Bilder(LQ) Karten herunterladen
|
||||
btnDownloadPicsHQ=Bilder(HQ) Karten herunterladen (Sehr langsam!)
|
||||
btnDownloadPics=Bilder(LQ) Karten herunterladen
|
||||
btnDownloadQuestImages=Bilder für Quests herunterladen
|
||||
btnDownloadAchievementImages=Bilder für Erfolge herunterladen
|
||||
btnReportBug=Einen Fehler melden
|
||||
@@ -548,6 +548,7 @@ lblPreconstructedDecks=Vorkonstruiertes Deck
|
||||
lblQuestOpponentDecks=Quest-Gegner-Deck
|
||||
lblRandomColorDecks=Decks - zufällige Farben
|
||||
lblRandomStandardArchetypeDecks=Decks - zufälliger Standard-Archetyp
|
||||
lblRandomPioneerArchetypeDecks=Decks - zufälliger Pioneer-Archetyp
|
||||
lblRandomModernArchetypeDecks=Decks - zufälliger Modern-Archetyp
|
||||
lblRandomLegacyArchetypeDecks=Decks - zufälliger Legacy-Archetyp
|
||||
lblRandomVintageArchetypeDecks=Decks - zufälliger Vintage-Archetyp
|
||||
@@ -628,7 +629,7 @@ titleUnlocked=%n freigeschaltet!
|
||||
lblStartADuel=Starte eine Duell.
|
||||
lblSelectAQuestDeck=Wähle ein Quest-Deck
|
||||
lblInvalidDeck=Unzulässiges Deck
|
||||
lblInvalidDeckDesc=Dein Deck %n. Bitte ändern oder anderes Deck wählen.
|
||||
lblInvalidDeckDesc=Dein Deck %n\nBitte ändern oder anderes Deck wählen.
|
||||
#VSubmenuQuestPrefs.java
|
||||
lblQuestPreferences=Quest-Einstellungen
|
||||
lblRewardsError=Fehler bei Belohnungen
|
||||
@@ -795,7 +796,7 @@ lbltodeck=zum Deck
|
||||
lblfromdeck=vom Deck
|
||||
lbltosideboard=zum Sideboard
|
||||
lblfromsideboard=vom Sideboard
|
||||
lblascommander=als Kommandeur
|
||||
lblascommander=als General
|
||||
lblasoathbreaker=als "Eidbrecher"
|
||||
lblassignaturespell=als "Signatur"-Spruch
|
||||
lblasavatar=als Avatar
|
||||
@@ -950,6 +951,12 @@ nlShowMatchBackground=Zeige Bilder im Spielfeldhintergrund.
|
||||
nlTheme=Wähle ein Thema um die Bildschirmanzeigen anzupassen.
|
||||
nlVibrateAfterLongPress=Aktiviert Vibration bei langen Druck, z.B. beim Zoomen.
|
||||
nlVibrateWhenLosingLife=Aktiviert Vibration bei Lebenspunktverlust.
|
||||
lblEnableRoundBorder=Aktiviere Maske mit runden Ränder
|
||||
nlEnableRoundBorder=Wenn aktiviert, werden Kartenecken abgerundet. Vorzugsweise bei Karten mit vollem Rand.
|
||||
lblPreloadExtendedArtCards=Erw. Kartenbilder bei Start laden
|
||||
nlPreloadExtendedArtCards=Wenn aktiviert, werden erweiterte Kartenbilder bereits beim Start in den Speicher geladen.
|
||||
lblShowFPSDisplay=FPS-Anzeige
|
||||
nlShowFPSDisplay=Aktiviert die Frames-per-second-Anzeige (Experimentell).
|
||||
#MatchScreen.java
|
||||
lblPlayers=Spieler
|
||||
lblLog=Bericht
|
||||
@@ -980,12 +987,13 @@ lblToMainDeck=zum Haupt-Deck
|
||||
lblHowMany=wie viel?
|
||||
lblInventory=Inhaltsverzeichnis
|
||||
lblCollection=Sammlung
|
||||
lblCommanders=Komandeure
|
||||
lblCommanders=Generäle
|
||||
lblOathbreakers=Eidbrecher
|
||||
#Forge.java
|
||||
lblLoadingFonts=Lade Schriftarten...
|
||||
lblLoadingCardTranslations=Lade Karten-Übersetzungen...
|
||||
lblFinishingStartup=Letzte Vorbereitungen...
|
||||
lblPreloadExtendedArt=Lade erweiterte Bilder...
|
||||
#LobbyScreen.java
|
||||
lblMore=Mehr...
|
||||
lblLoadingNewGame=Lade neues Spiel...
|
||||
@@ -1088,7 +1096,7 @@ lblStormCount=Sturmzähler
|
||||
#PlayerControllerHuman.java
|
||||
lblYouHaveWonTheCoinToss=%s, du hast den Münzwurf gewonnen.
|
||||
lblYouLostTheLastGame=%s, du hast das letzte Spiel verloren.
|
||||
lblWouldYouLiketoPlayorDraw=Willst du lieber zuerst spielen oder ziehen.
|
||||
lblWouldYouLiketoPlayorDraw=Willst du lieber zuerst spielen oder ziehen?
|
||||
lblWhoWouldYouLiketoStartthisGame=Wer soll das Spiel beginnen? (Klicke auf das Portrait.)
|
||||
lblPlay=Spielen
|
||||
lblDraw=Ziehen
|
||||
@@ -1140,6 +1148,28 @@ lblArrangeCardsToBePutOnTopOfYourLibrary=Ordne Karten, welche unter die Biblioth
|
||||
lblTopOfLibrary=Oben auf Bibliothek
|
||||
lblSelectCardsToBePutIntoTheGraveyard=Wähle Karten, welche auf den Friedhof gelegt werden sollen
|
||||
lblCardsToPutInTheGraveyard=Karten, welche auf den Friedhof gelegt werden sollen
|
||||
lblDiscardUpToNCards=Werfe bis zu %d Karte(n) ab
|
||||
lblDiscardNCards=Werfe %d Karte(n) ab
|
||||
lblSelectNCardsToDiscardUnlessDiscarduType=Wähle bis zu %d Karte(n) zum abwerfen, außer du wirfst eine %s ab.
|
||||
lblCleanupPhase=Aufräumphase
|
||||
lblSelectCardsToDiscardHandDownMaximum=Werfe %d Karte(n) ab um dein Handmaximum von %max Karte(n) zu erfüllen.
|
||||
lblChooseMinCardToDiscard=Wähle %d Karte(n) zm Abwerfen
|
||||
lblDiscarded=Abgeworfen
|
||||
lblChooseDamageOrderFor=Wähle Schadensreihenfolge für %s
|
||||
lblDamagedFirst=Zuerst geschädigt
|
||||
lblChooseBlockerAfterWhichToPlaceAttackert=Wähle Blocker für Platz %s in der Schadensreihenfolge; Abbrechen für ersten Platz
|
||||
lblPutCardOnTopOrBottomLibrary=Lege %s auf oder unter deine Bibliothek?
|
||||
lblChooseOrderCardsPutIntoLibrary=Wähle die Reihenfolge der Karten, in der sie in die Bibliothek gelegt werden
|
||||
lblClosestToTop=Zuoberst
|
||||
lblChooseOrderCardsPutOntoBattlefield=Wähle die Reihenfolge der Karten, in der sie auf das Spielfeld gebracht werden
|
||||
lblPutFirst=Lege zuerst
|
||||
lblChooseOrderCardsPutIntoGraveyard=Wähle die Reihenfolge der Karten, in der sie in den Friedhof gelegt werden
|
||||
lblClosestToBottom=Zuunterst
|
||||
lblChooseOrderCardsPutIntoPlanarDeck=Wähle die Reihenfolge der Karten, in der sie in das Weltendeck gelegt werden
|
||||
lblChooseOrderCardsPutIntoSchemeDeck=Wähle die Reihenfolge der Karten, in der sie in den Verschwörungsdeck gelegt werden
|
||||
lblChooseOrderCopiesCast=Wähle die Reihenfolge für die Kopien
|
||||
lblDelveHowManyCards=Wühlen - Wie viele Karten?
|
||||
lblExileWhichCard=Schicke welche Karte ins Exil?
|
||||
#AbstractGuiGame.java
|
||||
lblConcedeCurrentGame=Das Spiel wird als verloren gewertet.\n\nTrotzdem aufgeben?
|
||||
lblConcedeTitle=Spiel verloren geben?
|
||||
@@ -1171,4 +1201,41 @@ btnQuitMatch=Beende Partie
|
||||
lblItsADraw=Es ist ein Unentschieden!
|
||||
lblTeamWon=Team %s hat gewonnen!
|
||||
lblWinnerWon=%s hat gewonnen!
|
||||
lblGameLog=Spiel-Aufzeichnung
|
||||
lblGameLog=Spiel-Bericht
|
||||
#NewDraftScreen.java
|
||||
lblLoadingNewDraft=Lade neuen Draft...
|
||||
#LoadDraftScreen.java
|
||||
lblDoubleTapToEditDeck=Doppelklick zum Bearbeiten. Lange drücken für Anzeige.
|
||||
lblMode=Modus:
|
||||
lblYouMustSelectExistingDeck=Du mußt eine bestehendes Deck wählen oder ein neues Draft-Deck erstellen.
|
||||
lblWhichOpponentWouldYouLikeToFace=Wähle deinen Gegner!
|
||||
lblSingleMatch=Einzelnes Spiel
|
||||
#NewGauntletScreen.java
|
||||
lblGauntletText1=Beim Spießrutenlauf wählst du ein Deck und tritts gegen mehrer Gegner an.
|
||||
lblGauntletText2=Wähle die Anzahl der Gegener und welche Art Deck sie spielen sollen.
|
||||
lblGauntletText3=Dann versuche alle Gegner zu besiegen auche ein Spiel zu verlieren.
|
||||
lblSelectGauntletType=Wähle die Art des Spießrutenlaufs
|
||||
lblCustomGauntlet=angepaßter Spießrutenlauf
|
||||
lblGauntletContest=Wettbewerb
|
||||
lblSelectYourDeck=Wähle dein Deck
|
||||
lblSelectDeckForOpponent=Wähle Deck für Gegner
|
||||
lblSelectGauntletContest=Wähle Wettbewerb
|
||||
#PuzzleScreen.java
|
||||
lblPuzzleText1=Der puzzle-Modus lädt ein Puzzle, welches du auf eine bestimmte Art zu gewinnen hast.
|
||||
lblPuzzleText2=Drücke Start und wähle ein Puzzle aus der Liste.
|
||||
lblPuzzleText3=Zu Beginn wird dir in einem Fenster dein Ziel erklärt, und auch eventuelle spezielle Karten in deiner Kommandozone.
|
||||
lblChooseAPuzzle=Wähle ein Puzzle
|
||||
lblLoadingThePuzzle=Lade das Puzzle...
|
||||
#InputPassPriority.java
|
||||
lblCastSpell=Einen Zauberspruch sprechen
|
||||
lblPlayLand=Spiele ein Land
|
||||
lblActivateAbility=Aktiviere Fähigkeit
|
||||
lblYouHaveManaFloatingInYourManaPoolCouldBeLostIfPassPriority=Du hast noch unverbrauchtes Mana, welches verloren geht, wenn du die Priorität abgibst.
|
||||
lblYouWillTakeManaBurnDamageEqualAmountFloatingManaLostThisWay=Du wirst Manabrand erleiden, in Höhe des verlorenen Manas.
|
||||
lblManaFloating=Unverbrauchtes Mana
|
||||
#InputPayManaOfCostPayment.java
|
||||
lblPayManaCost=Zahle die Spruchkosten:
|
||||
lblLifePaidForPhyrexianMana=(%d Leben wurde bezahlt für phyrexianisches Mana)
|
||||
lblClickOnYourLifeTotalToPayLifeForPhyrexianMana=Klicke auf deine Lebenspunkte um phyrexianisches Mana zu bezahlen.
|
||||
lblClickOnYourLifeTotalToPayLifeForBlackMana=Klicke auf deine Lebenspunkte um schwarzes Mana zu bezahlen.
|
||||
lblClickOnYourLifeTotalToPayLifeForPhyrexianOrBlackMana=Klicke auf deine Lebenspunkte um phyrexianisches oder schwarzes Mana zu bezahlen.
|
||||
|
||||
@@ -548,6 +548,7 @@ lblPreconstructedDecks=Preconstructed Decks
|
||||
lblQuestOpponentDecks=Quest Opponent Decks
|
||||
lblRandomColorDecks=Random Color Decks
|
||||
lblRandomStandardArchetypeDecks=Random Standard Archetype Decks
|
||||
lblRandomPioneerArchetypeDecks=Random Pioneer Archetype Decks
|
||||
lblRandomModernArchetypeDecks=Random Modern Archetype Decks
|
||||
lblRandomLegacyArchetypeDecks=Random Legacy Archetype Decks
|
||||
lblRandomVintageArchetypeDecks=Random Vintage Archetype Decks
|
||||
@@ -628,7 +629,7 @@ titleUnlocked=%n unlocked!
|
||||
lblStartADuel=Start a duel.
|
||||
lblSelectAQuestDeck=Please select a Quest Deck.
|
||||
lblInvalidDeck=Invalid Deck
|
||||
lblInvalidDeckDesc=Your deck %n Please edit or choose a different deck.
|
||||
lblInvalidDeckDesc=Your deck %n\nPlease edit or choose a different deck.
|
||||
#VSubmenuQuestPrefs.java
|
||||
lblQuestPreferences=Quest Preferences
|
||||
lblRewardsError=Rewards Error
|
||||
@@ -950,6 +951,12 @@ nlShowMatchBackground=Show match background image on battlefield, otherwise back
|
||||
nlTheme=Sets the theme that determines how display components are skinned.
|
||||
nlVibrateAfterLongPress=Enable quick vibration to signify a long press, such as for card zooming.
|
||||
nlVibrateWhenLosingLife=Enable vibration when your player loses life or takes damage during a game.
|
||||
lblEnableRoundBorder=Enable Round Border Mask
|
||||
nlEnableRoundBorder=When enabled, the card corners are rounded (Preferably Card with Full Borders).
|
||||
lblPreloadExtendedArtCards=Preload Extended Art Cards
|
||||
nlPreloadExtendedArtCards=When enabled, Preloads Extended Art Cards to Cache on Startup.
|
||||
lblShowFPSDisplay=Show FPS Display
|
||||
nlShowFPSDisplay=When enabled, show the FPS Display (Experimental).
|
||||
#MatchScreen.java
|
||||
lblPlayers=Players
|
||||
lblLog=Log
|
||||
@@ -986,6 +993,7 @@ lblOathbreakers=Oathbreakers
|
||||
lblLoadingFonts=Loading fonts...
|
||||
lblLoadingCardTranslations=Loading card translations...
|
||||
lblFinishingStartup=Finishing startup...
|
||||
lblPreloadExtendedArt=Preload Extended Art...
|
||||
#LobbyScreen.java
|
||||
lblMore=More...
|
||||
lblLoadingNewGame=Loading new game...
|
||||
@@ -1140,6 +1148,28 @@ lblArrangeCardsToBePutOnTopOfYourLibrary=Arrange cards to be put on top of your
|
||||
lblTopOfLibrary=Top of Library
|
||||
lblSelectCardsToBePutIntoTheGraveyard=Select cards to be put into the graveyard
|
||||
lblCardsToPutInTheGraveyard=Cards to put in the graveyard
|
||||
lblDiscardUpToNCards=Discard up to %d card(s)
|
||||
lblDiscardNCards=Discard %d card(s)
|
||||
lblSelectNCardsToDiscardUnlessDiscarduType=Select %d card(s) to discard, unless you discard a %s.
|
||||
lblCleanupPhase=Cleanup Phase
|
||||
lblSelectCardsToDiscardHandDownMaximum=Select %d card(s) to discard to bring your hand down to the maximum of %max cards.
|
||||
lblChooseMinCardToDiscard=Choose %d card(s) to discard
|
||||
lblDiscarded=Discarded
|
||||
lblChooseDamageOrderFor=Choose Damage Order for %s
|
||||
lblDamagedFirst=Damaged First
|
||||
lblChooseBlockerAfterWhichToPlaceAttackert=Choose blocker after which to place %s in damage order; cancel to place it first
|
||||
lblPutCardOnTopOrBottomLibrary=Put %s on the top or bottom of your library?
|
||||
lblChooseOrderCardsPutIntoLibrary=Choose order of cards to put into the library
|
||||
lblClosestToTop=Closest to top
|
||||
lblChooseOrderCardsPutOntoBattlefield=Choose order of cards to put onto the battlefield
|
||||
lblPutFirst=Put first
|
||||
lblChooseOrderCardsPutIntoGraveyard=Choose order of cards to put into the graveyard
|
||||
lblClosestToBottom=Closest to bottom
|
||||
lblChooseOrderCardsPutIntoPlanarDeck=Choose order of cards to put into the planar deck
|
||||
lblChooseOrderCardsPutIntoSchemeDeck=Choose order of cards to put into the scheme deck
|
||||
lblChooseOrderCopiesCast=Choose order of copies to cast
|
||||
lblDelveHowManyCards=Delve how many cards?
|
||||
lblExileWhichCard=Exile which card?
|
||||
#AbstractGuiGame.java
|
||||
lblConcedeCurrentGame=This will concede the current game and you will lose.\n\nConcede anyway?
|
||||
lblConcedeTitle=Concede Game?
|
||||
@@ -1171,4 +1201,41 @@ btnQuitMatch=Quit Match
|
||||
lblItsADraw=It's a draw!
|
||||
lblTeamWon=Team %s won!
|
||||
lblWinnerWon=%s won!
|
||||
lblGameLog=Game Log
|
||||
lblGameLog=Game Log
|
||||
#NewDraftScreen.java
|
||||
lblLoadingNewDraft=Loading new draft...
|
||||
#LoadDraftScreen.java
|
||||
lblDoubleTapToEditDeck=Double-tap to edit deck (Long-press to view)
|
||||
lblMode=Mode:
|
||||
lblYouMustSelectExistingDeck=You must select an existing deck or build a deck from a new booster draft game.
|
||||
lblWhichOpponentWouldYouLikeToFace=Which opponent would you like to face?
|
||||
lblSingleMatch=Single Match
|
||||
#NewGauntletScreen.java
|
||||
lblGauntletText1=In Gauntlet mode, you select a deck and play against multiple opponents.
|
||||
lblGauntletText2=Configure how many opponents you wish to face and what decks or types of decks they will play.
|
||||
lblGauntletText3=Then, try to beat all AI opponents without losing a match.
|
||||
lblSelectGauntletType=Select a Gauntlet Type
|
||||
lblCustomGauntlet=Custom Gauntlet
|
||||
lblGauntletContest=Gauntlet Contest
|
||||
lblSelectYourDeck=Select Your Deck
|
||||
lblSelectDeckForOpponent=Select Deck for Opponent
|
||||
lblSelectGauntletContest=Select Gauntlet Contest
|
||||
#PuzzleScreen.java
|
||||
lblPuzzleText1=Puzzle Mode loads in a puzzle that you have to win in a predetermined time/way.
|
||||
lblPuzzleText2=To begin, press the Start button below, then select a puzzle from a list.
|
||||
lblPuzzleText3=Your objective will be displayed in a pop-up window when the puzzle starts and also specified on a special effect card which will be placed in your command zone.
|
||||
lblChooseAPuzzle=Choose a puzzle
|
||||
lblLoadingThePuzzle=Loading the puzzle...
|
||||
#InputPassPriority.java
|
||||
lblCastSpell=cast spell
|
||||
lblPlayLand=play land
|
||||
lblActivateAbility=activate ability
|
||||
lblYouHaveManaFloatingInYourManaPoolCouldBeLostIfPassPriority=You have mana floating in your mana pool that could be lost if you pass priority now.
|
||||
lblYouWillTakeManaBurnDamageEqualAmountFloatingManaLostThisWay=You will take mana burn damage equal to the amount of floating mana lost this way.
|
||||
lblManaFloating=Mana Floating
|
||||
#InputPayManaOfCostPayment.java
|
||||
lblPayManaCost=Pay Mana Cost:
|
||||
lblLifePaidForPhyrexianMana=(%d life paid for phyrexian mana)
|
||||
lblClickOnYourLifeTotalToPayLifeForPhyrexianMana=Click on your life total to pay life for phyrexian mana.
|
||||
lblClickOnYourLifeTotalToPayLifeForBlackMana=Click on your life total to pay life for black mana.
|
||||
lblClickOnYourLifeTotalToPayLifeForPhyrexianOrBlackMana=Click on your life total to pay life for phyrexian mana or black mana.
|
||||
@@ -548,6 +548,7 @@ lblPreconstructedDecks=Mazos Preconstruidos
|
||||
lblQuestOpponentDecks=Mazos de los Oponentes de la Aventura
|
||||
lblRandomColorDecks=Mazos Aleatorios por Color
|
||||
lblRandomStandardArchetypeDecks=Mazos Standard por Arquetipo
|
||||
lblRandomPioneerArchetypeDecks=Random Pioneer Archetype Decks
|
||||
lblRandomModernArchetypeDecks=Mazos Modern por Arquetipo
|
||||
lblRandomLegacyArchetypeDecks=Mazos Legacy por Arquetipo
|
||||
lblRandomVintageArchetypeDecks=Mazos Vintage por Arquetipo
|
||||
@@ -628,7 +629,7 @@ titleUnlocked=%n desbloqueado!
|
||||
lblStartADuel=Comienza un duelo.
|
||||
lblSelectAQuestDeck=Por favor, seleccione un mazo de aventura.
|
||||
lblInvalidDeck=Mazo no válido
|
||||
lblInvalidDeckDesc=Su mazo %n Por favor, edite o elija un mazo diferente.
|
||||
lblInvalidDeckDesc=Su mazo %n\nPor favor, edite o elija un mazo diferente.
|
||||
#VSubmenuQuestPrefs.java
|
||||
lblQuestPreferences=Preferencias de la Aventura
|
||||
lblRewardsError=Error de recompensas
|
||||
@@ -950,6 +951,12 @@ nlShowMatchBackground=Muestra la imagen de fondo de la partida en el campo de ba
|
||||
nlTheme=Establece el tema que determina el aspecto global del juego.
|
||||
nlVibrateAfterLongPress=Habilita la vibración rápida cuando se realice una pulsación prolongada, como p.ej. al realizar zoom de la carta.
|
||||
nlVibrateWhenLosingLife=Habilita la vibración cuando tu jugador pierde vida o sufre daños durante un juego.
|
||||
lblEnableRoundBorder=Habilitar máscara de bordes redondeados
|
||||
nlEnableRoundBorder=Cuando está habilitado, las esquinas de las cartas se redondean (Preferiblemente Cartas con bordes completos).
|
||||
lblPreloadExtendedArtCards=Precargar Cartas de Arte Extendido
|
||||
nlPreloadExtendedArtCards=Cuando está habilitado, carga previamente las cartas de arte ampliadas en la caché al iniciar el programa.
|
||||
lblShowFPSDisplay=Mostrar FPS
|
||||
nlShowFPSDisplay=Cuando está habilitado, muestra los FPS (Experimental).
|
||||
#MatchScreen.java
|
||||
lblPlayers=Jugadores
|
||||
lblLog=Log
|
||||
@@ -986,6 +993,7 @@ lblOathbreakers=Oathbreakers
|
||||
lblLoadingFonts=Cargando fuentes...
|
||||
lblLoadingCardTranslations=Cargando traducciones de cartas...
|
||||
lblFinishingStartup=Finalizando el arranque...
|
||||
lblPreloadExtendedArt=Precargando Arte Extendido...
|
||||
#LobbyScreen.java
|
||||
lblMore=Más...
|
||||
lblLoadingNewGame=Cargando nueva partida...
|
||||
@@ -1140,6 +1148,28 @@ lblArrangeCardsToBePutOnTopOfYourLibrary=Organizar las cartas para colocarlas en
|
||||
lblTopOfLibrary=Parte Superior de la Biblioteca
|
||||
lblSelectCardsToBePutIntoTheGraveyard=Selecciona las cartas para ponerlas en el Cementerio
|
||||
lblCardsToPutInTheGraveyard=Cartas para poner en el Cementerio
|
||||
lblDiscardUpToNCards=Descarta hasta %d carta(s)
|
||||
lblDiscardNCards=Descarta %d carta(s)
|
||||
lblSelectNCardsToDiscardUnlessDiscarduType=Selecciona %d carta(s) para descartar, a menos que descartes un %s.
|
||||
lblCleanupPhase=Fase de Limpieza
|
||||
lblSelectCardsToDiscardHandDownMaximum=Selecciona %d carta(s) a descartar para reducir tu mano al máximo de %max cartas.
|
||||
lblChooseMinCardToDiscard=Elige %d carta(s) para descartar
|
||||
lblDiscarded=Descartado
|
||||
lblChooseDamageOrderFor=Selecciona el Orden de Daños para %s
|
||||
lblDamagedFirst=Dañado Primero
|
||||
lblChooseBlockerAfterWhichToPlaceAttackert=Elige un bloqueador después del cual colocar %s en el orden de daño; cancela para colocarlo primero.
|
||||
lblPutCardOnTopOrBottomLibrary=¿Poner %s en la parte superior o inferior de tu biblioteca?
|
||||
lblChooseOrderCardsPutIntoLibrary=Elige el orden de las cartas para poner en la biblioteca
|
||||
lblClosestToTop=Más cerca de la parte superior
|
||||
lblChooseOrderCardsPutOntoBattlefield=Elige el orden de las cartas que quieres poner en el campo de batalla
|
||||
lblPutFirst=Poner en primer lugar
|
||||
lblChooseOrderCardsPutIntoGraveyard=Elige el orden de las cartas para poner en el cementerio
|
||||
lblClosestToBottom=Más cerca de la parte inferior
|
||||
lblChooseOrderCardsPutIntoPlanarDeck=Elige el orden de las cartas que quieres poner en el mazo planar
|
||||
lblChooseOrderCardsPutIntoSchemeDeck=Elige el orden de las cartas que quieres poner en el mazo scheme
|
||||
lblChooseOrderCopiesCast=Elige el orden de las copias que se van a invocar
|
||||
lblDelveHowManyCards=¿Excavar cuántas cartas?
|
||||
lblExileWhichCard=¿Exiliar qué carta?
|
||||
#AbstractGuiGame.java
|
||||
lblConcedeCurrentGame=Esto concederá la partida actual y perderás.\n\n¿Conceder de todos modos?
|
||||
lblConcedeTitle=¿Conceder Partida?
|
||||
@@ -1171,4 +1201,41 @@ btnQuitMatch=Salir de la Partida
|
||||
lblItsADraw=¡Es un empate!
|
||||
lblTeamWon=¡El equipo %s ha ganado!
|
||||
lblWinnerWon=¡%s ha ganado!
|
||||
lblGameLog=Registro del Juego
|
||||
lblGameLog=Registro del Juego
|
||||
#NewDraftScreen.java
|
||||
lblLoadingNewDraft=Cargando nuevo Draft...
|
||||
#LoadDraftScreen.java
|
||||
lblDoubleTapToEditDeck=Pulsa 2 veces para editar el mazo (Pulsación prologanda para ver)
|
||||
lblMode=Modo:
|
||||
lblYouMustSelectExistingDeck=Debes seleccionar un mazo existente o construir un mazo a partir de un nuevo juego de booster draft.
|
||||
lblWhichOpponentWouldYouLikeToFace=¿A qué oponente te gustaría enfrentarte?
|
||||
lblSingleMatch=Partida individual
|
||||
#NewGauntletScreen.java
|
||||
lblGauntletText1=En el modo Desafío, selecciona un mazo y juega contra varios oponentes.
|
||||
lblGauntletText2=Configura a cuántos oponentes deseas enfrentarte y qué mazos o tipos de mazos jugarán.
|
||||
lblGauntletText3=Luego, intenta derrotar a todos los oponentes de la IA sin perder una partida.
|
||||
lblSelectGauntletType=Seleccione el Tipo de Desafío
|
||||
lblCustomGauntlet=Desafío Personalizado
|
||||
lblGauntletContest=Concurso de Desafío
|
||||
lblSelectYourDeck=Seleccciona Tu Mazo
|
||||
lblSelectDeckForOpponent=Seleccionar Mazo para el Oponente
|
||||
lblSelectGauntletContest=Seleccionar Concurso de Desafío
|
||||
#PuzzleScreen.java
|
||||
lblPuzzleText1=En el Modo Puzzle se carga un rompecabezas que tienes que ganar en un tiempo/forma predeterminados.
|
||||
lblPuzzleText2=Para comenzar, pulsa el botón Inicio y selecciona un puzzle de una lista.
|
||||
lblPuzzleText3=Tu objetivo se mostrará en una ventana emergente cuando se inicie el puzzle y también se especificará en una carta de efectos especiales que se colocará en tu zona de comandos.
|
||||
lblChooseAPuzzle=Elige un puzzle
|
||||
lblLoadingThePuzzle=Cargando el puzzle...
|
||||
#InputPassPriority.java
|
||||
lblCastSpell=lanzar hechizo
|
||||
lblPlayLand=jugar tierra
|
||||
lblActivateAbility=activar abilidad
|
||||
lblYouHaveManaFloatingInYourManaPoolCouldBeLostIfPassPriority=Tienes maná flotando en tu pool de maná que podría perderse si pasas la prioridad ahora.
|
||||
lblYouWillTakeManaBurnDamageEqualAmountFloatingManaLostThisWay=Recibirás un daño por quemadura de maná igual a la cantidad de maná flotante perdido de esta manera.
|
||||
lblManaFloating=Maná Flotante
|
||||
#InputPayManaOfCostPayment.java
|
||||
lblPayManaCost=Paga el coste de maná:
|
||||
lblLifePaidForPhyrexianMana=(%d de vida pagado por el maná filaxiano)
|
||||
lblClickOnYourLifeTotalToPayLifeForPhyrexianMana=Haga clic en el total de su vida para pagar la vida por el maná filaxiano.
|
||||
lblClickOnYourLifeTotalToPayLifeForBlackMana=Haga clic en el total de su vida para pagar la vida de maná negro.
|
||||
lblClickOnYourLifeTotalToPayLifeForPhyrexianOrBlackMana=Haga clic en el total de su vida para pagar la vida por maná filoxiano o maná negro.
|
||||
@@ -1,21 +1,21 @@
|
||||
language.name=Chinese (CN)
|
||||
#SplashScreen.java
|
||||
splash.loading.examining-cards=加载牌张,检查文件夹
|
||||
splash.loading.cards-folders=从文件夹加载牌张
|
||||
splash.loading.cards-archive=从存档中加载牌张
|
||||
splash.loading.examining-cards=加载卡牌,检查文件夹
|
||||
splash.loading.cards-folders=从文件夹加载卡牌
|
||||
splash.loading.cards-archive=从存档中加载卡牌
|
||||
splash.loading.decks=加载套牌
|
||||
splash.loading.processingimagesprites=处理精灵图
|
||||
#FControl.java
|
||||
lblOpeningMainWindow=打开主窗口中
|
||||
lblCloseScreen=关闭屏幕
|
||||
txCloseAction1=Forge现在支持选项卡导航,可以轻松关闭和切换不同屏幕。因此,您不再需要使用右上角X按钮关闭当前屏幕并返回
|
||||
txCloseAction2=请选择右上角的X按钮选择接下来将要进行的操作。此选项保留给未来使用,您将不会再看到此消息,您可以随时在“首选项”中更改此行为
|
||||
titCloseAction=选择您的关闭行动
|
||||
txCloseAction1=Forge现在支持选项卡导航,可以轻松关闭和切换不同屏幕。因此,你不再需要使用右上角X按钮关闭当前屏幕并返回
|
||||
txCloseAction2=请通过右上角的X按钮选择将要进行的动作。此选项保留给未来使用,你将不会再看到此消息,你可以随时在“首选项”中更改此行为
|
||||
titCloseAction=选择你的关闭动作
|
||||
lblAreYouSureYouWishRestartForge=你确定要重启Forge吗?
|
||||
lblAreYouSureYouWishExitForge=你确定要退出Forge吗?
|
||||
lblOneOrMoreGamesActive=一个或多个游戏正处于活动状态
|
||||
lblerrLoadingLayoutFile=无法读取您的布局文件:%s。按OK然后删除。\n游戏将以默认布局进行。
|
||||
lblLoadingQuest=加载时空竞逐中...
|
||||
lblerrLoadingLayoutFile=无法读取你的布局文件:%s。按OK然后删除。\n游戏将以默认布局进行。
|
||||
lblLoadingQuest=加载冒险之旅...
|
||||
#FScreen.java
|
||||
lblHome=主页
|
||||
lblWorkshop=作坊页面
|
||||
@@ -30,13 +30,13 @@ lblDraftDeckEditor=轮抓套牌编辑器
|
||||
lblSealedDeckEditor=现开套牌编辑器
|
||||
lblTokenViewer=衍生物查看器
|
||||
lblCloseViewer=关闭查看器
|
||||
lblQuestDeckEditor=竞逐套牌编辑器
|
||||
lblQuestTournamentDeckEditor=竞逐比赛套牌编辑器
|
||||
lblSpellShop=轮替商店
|
||||
lblQuestDeckEditor=冒险套牌编辑器
|
||||
lblQuestTournamentDeckEditor=冒险比赛套牌编辑器
|
||||
lblSpellShop=卡牌商店
|
||||
lblLeaveShop=离开商店
|
||||
lblLeaveDraft=离开轮抓
|
||||
lblBazaar=珍宝集市
|
||||
lblConcedeGame=让出这场游戏
|
||||
lblConcedeGame=这场游戏认输
|
||||
txerrFailedtodeletelayoutfile=删除布局文件失败。
|
||||
#VSubmenuPreferences.java
|
||||
Preferences=偏好
|
||||
@@ -62,7 +62,7 @@ cbEnableAICheats=允许人工智能作弊
|
||||
cbManaBurn=法术力灼烧
|
||||
cbManaLostPrompt=提示法术力池将要清空
|
||||
cbDevMode=开发人员模式
|
||||
cbLoadCardsLazily=惰性加载牌张脚本
|
||||
cbLoadCardsLazily=惰性加载卡牌脚本
|
||||
cbLoadHistoricFormats=加载史记赛制
|
||||
cbWorkshopSyntax=作坊语法检查
|
||||
cbEnforceDeckLegality=套牌一致性
|
||||
@@ -74,7 +74,7 @@ cbCloneImgSource=复制使用原始的图片
|
||||
cbScaleLarger=将图像缩放的更大
|
||||
cbRenderBlackCardBorders=渲染黑卡边框
|
||||
cbLargeCardViewers=使用大图查看器
|
||||
cbSmallDeckViewer=使用小套牌查看器
|
||||
cbSmallDeckViewer=使用小图查看器
|
||||
cbDisplayFoil=显示闪卡
|
||||
cbRandomFoil=随机闪卡
|
||||
cbRandomArtInPools=在生成的卡池中随机加入闪卡
|
||||
@@ -102,7 +102,7 @@ cbpGameLogEntryType=游戏日志详细程度
|
||||
cbpCloseAction=关闭动作
|
||||
cbpDefaultFontSize=默认字体大小
|
||||
cbpAiProfiles=人工智能强度
|
||||
cbpDisplayCurrentCardColors=显示牌张颜色详情
|
||||
cbpDisplayCurrentCardColors=显示卡牌颜色详情
|
||||
cbpAutoYieldMode=自动让过
|
||||
cbpCounterDisplayType=计数器显示类型
|
||||
cbpCounterDisplayLocation=计数器显示区域
|
||||
@@ -141,13 +141,13 @@ nlSingletons=禁止在生成的套牌中非地牌重复出现
|
||||
nlRemoveArtifacts=在生成的套牌中禁用神器牌
|
||||
nlCardBased=构建具有更多协同效应的套牌(需要重启)
|
||||
DeckEditorOptions=套牌编辑器选项
|
||||
nlFilterLandsByColorId=当使用牌张颜色筛选器时,过滤地可以更容易找到产数相关法术力的地
|
||||
nlFilterLandsByColorId=当使用卡牌颜色筛选器时,过滤地可以更容易找到产数相关法术力的地
|
||||
AdvancedSettings=高级设置
|
||||
nlDevMode=启用在开发期间进行测试的功能菜单
|
||||
nlWorkshopSyntax=在作坊中启用牌张脚本检查。注意:该功能任在测试阶段。
|
||||
nlWorkshopSyntax=在作坊中启用卡牌脚本检查。注意:该功能任在测试阶段。
|
||||
nlGameLogEntryType=更改游戏中日志显示的信息量。排序为最少到最详细。
|
||||
nlCloseAction=更改单击右上角X按钮时的行为
|
||||
nlLoadCardsLazily=如果打开该选项Forge将在使用到牌张脚本时才加载(警告:实验状态)。
|
||||
nlCloseAction=更改单击右上角X按钮时的动作
|
||||
nlLoadCardsLazily=如果打开该选项Forge将在使用到卡牌脚本时才加载(警告:实验状态)。
|
||||
nlLoadHistoricFormats=如果打开,Forge将加载史记赛制,这个能会导致游戏载入时间变长。
|
||||
GraphicOptions=图形选项
|
||||
nlDefaultFontSize=UI中字体的默认大小。所有字体元素都相对于此缩放。(需要重启)
|
||||
@@ -155,21 +155,21 @@ cbpMulliganRule = 调度规则
|
||||
nlImageFetcher=允许从在线资源中实时获取缺失的图片
|
||||
nlDisplayFoil=显示闪卡
|
||||
nlRandomFoil=随机将牌设置为闪卡
|
||||
nlScaleLarger=允许牌张图片缩放为初始大小
|
||||
nlScaleLarger=允许卡牌图片缩放为初始大小
|
||||
nlRenderBlackCardBorders=为牌周围渲染黑色边框
|
||||
nlLargeCardViewers=是所有牌看起来更大以便高分辨率图片看起来更舒适,不适合低分辨率设备使用
|
||||
nlSmallDeckViewer=将套牌查看器设置为800X600而不是按屏幕大小等比缩放
|
||||
nlRandomArtInPools=限制赛生成的卡池中带有闪卡。
|
||||
nlUiForTouchScreen=增加一些UI元素以提高触屏体验(需要重启)。
|
||||
nlCompactPrompt=隐藏标题并在“提示”窗格中使用较小的字体使其更紧凑。
|
||||
nlHideReminderText=在“牌张详情“窗格中隐藏提醒文本
|
||||
nlHideReminderText=在“卡牌详情“窗格中隐藏提醒文本
|
||||
nlOpenPacksIndiv=打开肥包或者补充盒的时候一包一包开。
|
||||
nlTokensInSeparateRow=生物与衍生物分不同的行显示。
|
||||
nlStackCreatures=在战场上如同地、神器、结界一般堆叠一样的生物。
|
||||
nlTimedTargOverlay=启用基于限制目标的覆盖优化以减少CPU使用率(仅在旧设备上需要使用,需要重启游戏)。
|
||||
nlCounterDisplayType=选择指示物的样式。基于文本还是基于图片还是二者混合。
|
||||
nlCounterDisplayLocation=确定牌张上指示物的位置:靠近底部还是顶部
|
||||
nlDisplayCurrentCardColors=在牌张详情窗格中显示当前牌的颜色
|
||||
nlCounterDisplayLocation=确定卡牌上指示物的位置:靠近底部还是顶部
|
||||
nlDisplayCurrentCardColors=在卡牌详情窗格中显示当前牌的颜色
|
||||
SoundOptions=声音选项
|
||||
nlEnableSounds=在游戏中启用声音效果
|
||||
nlEnableMusic=在游戏中启用背景音乐
|
||||
@@ -188,18 +188,18 @@ btnListImageData=统计牌和图片数据
|
||||
lblListImageData=统计Forge实现且缺少的图片的牌
|
||||
btnImportPictures=导入数据
|
||||
btnHowToPlay=如何玩
|
||||
btnDownloadPrices=下载牌张价格
|
||||
btnDownloadPrices=下载卡牌价格
|
||||
btnLicensing=许可证详情
|
||||
lblDownloadPics=下载缺省牌的图片
|
||||
lblDownloadPicsHQ=下载缺省牌的高清图片
|
||||
lblDownloadSetPics=下载每张牌的图片(每张牌出现一次)
|
||||
lblDownloadQuestImages=下载冒险之旅里使用的衍生物与图标
|
||||
lblDownloadAchievementImages=下载成就图片,让你的奖杯更引人注目。
|
||||
lblDownloadPrices=下载牌张商店最新的价格表
|
||||
lblDownloadPrices=下载卡牌商店最新的价格表
|
||||
lblYourVersionOfJavaIsTooOld=你的Java版本太旧无法开始下载内容
|
||||
lblPleaseUpdateToTheLatestVersionOfJava=请更新到最新版本的JRE
|
||||
lblYoureRunning=你在运行
|
||||
lblYouNeedAtLeastJavaVersion=您的JRE版本至少需要为1.8.0_101。
|
||||
lblYouNeedAtLeastJavaVersion=你的JRE版本至少需要为1.8.0_101。
|
||||
lblImportPictures=从本地目录导入数据
|
||||
lblReportBug=什么东西坏了?
|
||||
lblHowToPlay=游戏规则。
|
||||
@@ -230,7 +230,7 @@ lblGameSettings=游戏设置
|
||||
#VLobby.java
|
||||
lblHeaderConstructedMode=游戏模式:构筑
|
||||
lblGetNewRandomName=获取一个随机名称
|
||||
lbltypeofName=您想要生成什么类型的名称?
|
||||
lbltypeofName=你想要生成什么类型的名称?
|
||||
lblconfirmName=你想使用名称%s,还是想重试
|
||||
lblUseThisName=使用这个名称
|
||||
lblTryAgain=再试一次
|
||||
@@ -299,7 +299,7 @@ lblAlphaStrike=先攻
|
||||
lblEndTurn=结束回合
|
||||
lblTargetingArcs=瞄准弧
|
||||
lblOff=关闭
|
||||
lblCardMouseOver=牌张悬停
|
||||
lblCardMouseOver=卡牌悬停
|
||||
lblAlwaysOn=总是打开
|
||||
lblAutoYields=自动让过
|
||||
lblDeckList=套牌列表
|
||||
@@ -357,7 +357,7 @@ lblDraftText3=然后对抗一个或多个人工智能对手
|
||||
lblNewBoosterDraftGame=新的补充包轮抓
|
||||
lblDraftDecks=轮抓套牌
|
||||
#CSubmenuDraft.java
|
||||
lblNoDeckSelected=没有为人类选择套牌。\n(您可能要建立一个新的套牌)
|
||||
lblNoDeckSelected=没有为人类选择套牌。\n(你可能要建立一个新的套牌)
|
||||
lblNoDeck=没有套牌
|
||||
lblChooseDraftFormat=选择轮抓模式
|
||||
#VSubmenuSealed.java
|
||||
@@ -365,7 +365,7 @@ lblSealedDeck=现开
|
||||
lblSealedDecks=现开套牌
|
||||
lblHeaderSealed=游戏模式:现开
|
||||
lblSealedText1=构建或选择一个套牌
|
||||
lblSealedText2=在现开模式中,您可以从补充包里(最多10个)构建一套牌
|
||||
lblSealedText2=在现开模式中,你可以从补充包里(最多10个)构建一套牌
|
||||
lblSealedText3=从你得到的牌中组一套牌。人工智能也会这样做
|
||||
lblSealedText4=然后对抗一个或多个人工智能对手
|
||||
btnBuildNewSealedDeck=构建新的现开套牌
|
||||
@@ -392,7 +392,7 @@ lblGauntlet=决斗
|
||||
lblTournament=锦标赛
|
||||
lblQuest=冒险
|
||||
lblQuestDraft=冒险轮抓
|
||||
lblPlanarConquest=时空竞逐征服
|
||||
lblPlanarConquest=时空征服
|
||||
lblPuzzle=谜题
|
||||
lblPuzzleDesc=从给定的游戏状态解谜
|
||||
lblDeckManager=套牌管理
|
||||
@@ -425,7 +425,7 @@ lblNextChallengeNotYet=没有确定下次胜利后的挑战
|
||||
btnUnlockSets=解锁系列
|
||||
btnTravel=时空旅行
|
||||
btnBazaar=珍宝集市
|
||||
btnSpellShop=牌张商店
|
||||
btnSpellShop=卡牌商店
|
||||
cbSummonPlant=召唤植物
|
||||
cbLaunchZeppelin=启动飞艇
|
||||
#VSubmenuQuest.java
|
||||
@@ -448,7 +448,7 @@ lblCustomdeck=自定义套牌
|
||||
lblDefineCustomFormat=定义自定义赛制
|
||||
lblSelectFormat=选择赛制
|
||||
lblStartWithAllCards=从所选系列的所有牌开始
|
||||
lblAllowDuplicateCards=允许重复的牌张
|
||||
lblAllowDuplicateCards=允许重复的卡牌
|
||||
lblStartingPoolDistribution=初始牌池分配
|
||||
lblChooseDistribution=选择分配
|
||||
lblPrizedCards=奖励卡
|
||||
@@ -505,9 +505,9 @@ lblColors=颜色
|
||||
lblnoSettings=没有可用于此选择的设置
|
||||
lblDistribution=分配
|
||||
lblHoverforDescription=将鼠标悬停在每个选项上以获得更详细的说明
|
||||
lblradBalanced=“均衡”将在每种选定的颜色中提供数量均衡的牌张。
|
||||
lblradRandom=“随机”将随机分配牌张和颜色。
|
||||
lblradSurpriseMe=随机挑选颜色并提供数量均衡的随机牌张。
|
||||
lblradBalanced=“均衡”将在每种选定的颜色中提供数量均衡的卡牌。
|
||||
lblradRandom=“随机”将随机分配卡牌和颜色。
|
||||
lblradSurpriseMe=随机挑选颜色并提供数量均衡的随机卡牌。
|
||||
lblradBoosters=忽略所有颜色设置,从指定数量的补充包中生成牌池
|
||||
lblcbxArtifacts=选择后无论选择的颜色如何,神器都包涵在牌池中,这模拟了旧牌池的行为。
|
||||
#VSubmenuChallenges.java
|
||||
@@ -548,6 +548,7 @@ lblPreconstructedDecks=预组套牌
|
||||
lblQuestOpponentDecks=冒险之旅套牌
|
||||
lblRandomColorDecks=随机颜色套牌
|
||||
lblRandomStandardArchetypeDecks=随机标准原型套牌
|
||||
lblRandomPioneerArchetypeDecks=随机先驱原型套牌
|
||||
lblRandomModernArchetypeDecks=随机摩登原型套牌
|
||||
lblRandomLegacyArchetypeDecks=随机薪传原型套牌
|
||||
lblRandomVintageArchetypeDecks=随机特选原型套牌
|
||||
@@ -620,7 +621,7 @@ lblBuildAndSelectaDeck=构建,然后在“冒险套牌”子菜单中选择一
|
||||
lblCurrentDeck=你现在的套牌是%n
|
||||
PleaseCreateAQuestBefore=请在%n之前创建套牌。
|
||||
lblNoQuest=没有探索
|
||||
lblVisitTheSpellShop=参观牌张商店
|
||||
lblVisitTheSpellShop=进入卡牌商店
|
||||
lblVisitTheBazaar=参观珍宝集市
|
||||
lblUnlockEditions=解锁新的时空
|
||||
lblUnlocked=你已经成功解锁%n
|
||||
@@ -628,7 +629,7 @@ titleUnlocked=%n解锁!
|
||||
lblStartADuel=开始决斗!
|
||||
lblSelectAQuestDeck=请选择一个冒险套牌。
|
||||
lblInvalidDeck=错误的套牌
|
||||
lblInvalidDeckDesc=您的套牌%n请编辑或者选择其他套牌
|
||||
lblInvalidDeckDesc=你的套牌%n请编辑或者选择其他套牌
|
||||
#VSubmenuQuestPrefs.java
|
||||
lblQuestPreferences=冒险偏好
|
||||
lblRewardsError=奖励错误
|
||||
@@ -672,7 +673,7 @@ lblStartingCredits=初始积分
|
||||
lblWinsforNewChallenge=新挑战所需的胜利
|
||||
lblStartingSnowLands=初始雪境地
|
||||
lblColorBias=颜色偏差(1-100%)
|
||||
ttColorBias=初始卡池中您选择的颜色的百分比
|
||||
ttColorBias=初始卡池中的颜色百分比
|
||||
lblPenaltyforLoss=失败补偿
|
||||
lblMoreDuelChoices=更多决斗选择
|
||||
lblCommon=铁
|
||||
@@ -695,11 +696,11 @@ lblCardSalePercentageCap=出售牌的系数上限
|
||||
lblCardSalePriceCap=出售牌的价格上限
|
||||
lblWinstoUncapSalePrice=胜利解锁价格系数
|
||||
lblPlaysetSize=玩家收藏大小
|
||||
ttPlaysetSize=在售卖牌张时要保留的牌张数量
|
||||
ttPlaysetSize=在售卖卡牌时要保留的卡牌数量
|
||||
lblPlaysetSizeBasicLand=玩家收藏大小:基本地
|
||||
ttPlaysetSizeBasicLand=在售卖牌张时要保留的基本地数量
|
||||
ttPlaysetSizeBasicLand=在售卖卡牌时要保留的基本地数量
|
||||
lblPlaysetSizeAnyNumber=玩家收藏大小:任意数量
|
||||
ttPlaysetSizeAnyNumber=售卖牌张时不保留牌张
|
||||
ttPlaysetSizeAnyNumber=售卖卡牌时不保留
|
||||
lblItemLevelRestriction=物品等级限制
|
||||
lblFoilfilterAlwaysOn=闪卡过滤器始终开启
|
||||
lblRatingsfilterAlwaysOn=评级过滤器始终开启。
|
||||
@@ -767,7 +768,7 @@ lblRemove4ofcard=移除4张牌
|
||||
ttRemove4ofcard=最多可以将4张所选牌从当前套牌移除
|
||||
lblAddBasicLands=添加基本地
|
||||
ttAddBasicLands=添加基本地到套牌
|
||||
lblCardCatalog=牌张目录
|
||||
lblCardCatalog=卡牌目录
|
||||
lblJumptoprevioustable=跳转到上一个表格
|
||||
lblJumptopnexttable=跳转到下一个表格
|
||||
lblJumptotextfilter=跳转到文本筛选器
|
||||
@@ -883,7 +884,7 @@ lblQty=数量
|
||||
lblQuantity=数量
|
||||
lblSide=备牌
|
||||
lblSideboard=备牌
|
||||
lblNew=新建
|
||||
lblNew=新获得
|
||||
lblOwned=拥有
|
||||
lblPower=力量
|
||||
ttPower=力量
|
||||
@@ -904,8 +905,8 @@ lblAutomaticBugReports=自动报告BUG
|
||||
lblBattlefieldTextureFiltering=战场纹理过滤
|
||||
lblCompactListItems=紧凑的项目列表
|
||||
lblCompactTabs=紧凑标签
|
||||
lblCardOverlays=牌张叠加层
|
||||
lblDisableCardEffect=禁用牌张“效果”图
|
||||
lblCardOverlays=卡牌叠加层
|
||||
lblDisableCardEffect=禁用卡牌“效果”图
|
||||
lblDynamicBackgroundPlanechase=动态时空背景
|
||||
lblGameplayOptions=游戏选项
|
||||
lblGeneralSettings=常规设置
|
||||
@@ -915,14 +916,14 @@ lblLater=以后
|
||||
lblMinimizeScreenLock=锁屏时最小化
|
||||
lblOrderGraveyard=坟场顺序
|
||||
lblRestartForge=重启Forge
|
||||
lblRestartForgeDescription=您必须重启Forge才能使此更改生效
|
||||
lblRestartForgeDescription=你必须重启Forge才能使此更改生效
|
||||
lblRotateZoomPlanesPhenomena=旋转缩放时空/异象图
|
||||
lblRotateZoomSplit=旋转缩放连体牌
|
||||
lblShowAbilityIconsOverlays=显示异能图标
|
||||
lblShowCardIDOverlays=显示牌张ID叠加层
|
||||
lblShowCardManaCostOverlays=显示牌张法术力费用叠加层
|
||||
lblShowCardNameOverlays=显示牌张名称叠加层
|
||||
lblShowCardOverlays=显示牌张叠加层
|
||||
lblShowCardIDOverlays=显示卡牌ID叠加层
|
||||
lblShowCardManaCostOverlays=显示卡牌法术力费用叠加层
|
||||
lblShowCardNameOverlays=显示卡牌名称叠加层
|
||||
lblShowCardOverlays=显示卡牌叠加层
|
||||
lblShowCardPTOverlays=显示攻击/防御叠加层
|
||||
lblShowMatchBackground=显示比赛背景
|
||||
lblVibrateAfterLongPress=长按后震动
|
||||
@@ -930,26 +931,32 @@ lblVibrateWhenLosingLife=失去生命时震动
|
||||
lblVibrationOptions=振动选项
|
||||
nlAutomaticBugReports=在没有提示的情况下自动向开发人员报告错误
|
||||
nlBattlefieldTextureFiltering=在战场上过滤闪卡特效,使其在大屏幕上不像素化(需要重启,可能会降低性能)。
|
||||
nlCompactListItems=默认情况下,在所有视图列表中只显示牌张和套牌的单行文本。
|
||||
nlCompactListItems=默认情况下,在所有视图列表中只显示卡牌和套牌的单行文本。
|
||||
nlCompactTabs=在标签页屏幕顶部显示较小的标签(例如此屏幕)。
|
||||
nlDisableCardEffect=禁用“效果”卡的缩放图片。
|
||||
nlDynamicBackgroundPlanechase=使用当前时空图片作为背景(时空图片必须位于cache/pics/planechase文件夹中)。
|
||||
nlHotSeatMode=当用两个人类玩家开始游戏的时候,用单个提示控制两个玩家。
|
||||
nlLandscapeMode=使用横向(水平)而不是纵向(垂直)。
|
||||
nlMinimizeScreenLock=锁定屏幕时最小化Forge(锁屏以后出现图形故障使用)。
|
||||
nlOrderGraveyard=确定何时让玩家确定同时进入坟场的牌的顺序(绝不/总是/只对有关牌张)。
|
||||
nlOrderGraveyard=确定何时让玩家确定同时进入坟场的牌的顺序(绝不/总是/只对有关卡牌)。
|
||||
nlRotateZoomPlanesPhenomena=旋转缩放时空或异象图片。
|
||||
nlRotateZoomSplit=旋转缩放连体牌图片。
|
||||
nlShowAbilityIconsOverlays=在牌张上显示异能图标,否则他们被隐藏。
|
||||
nlShowCardIDOverlays=显示牌张的ID叠加层,否则他们被隐藏。
|
||||
nlShowCardManaCostOverlays=显示牌张的法术力费用叠加层,否则他们被隐藏。
|
||||
nlShowCardNameOverlays=显示牌张的名称费用叠加层,否则他们被隐藏。
|
||||
nlShowCardOverlays=显示牌张名称,法术力费用,力量/防御和ID叠加层,否则他们被隐藏。
|
||||
nlShowAbilityIconsOverlays=在卡牌上显示异能图标,否则他们被隐藏。
|
||||
nlShowCardIDOverlays=显示卡牌的ID叠加层,否则他们被隐藏。
|
||||
nlShowCardManaCostOverlays=显示卡牌的法术力费用叠加层,否则他们被隐藏。
|
||||
nlShowCardNameOverlays=显示卡牌的名称费用叠加层,否则他们被隐藏。
|
||||
nlShowCardOverlays=显示卡牌名称,法术力费用,力量/防御和ID叠加层,否则他们被隐藏。
|
||||
nlShowCardPTOverlays=显示力量/防御/忠诚叠加层,否则他们被隐藏。
|
||||
nlShowMatchBackground=在战场显示背景图片,否则显示背景纹理。
|
||||
nlTheme=设置显示的组件使用的外观主题。
|
||||
nlVibrateAfterLongPress=启用长按触发震动,例如长按缩放牌张图片。
|
||||
nlVibrateAfterLongPress=启用长按触发震动,例如长按缩放卡牌图片。
|
||||
nlVibrateWhenLosingLife=启用当玩家在游戏中失去生命或收到伤害时震动。
|
||||
lblEnableRoundBorder=启用圆角边框掩码
|
||||
nlEnableRoundBorder=启用后,卡牌边框会变成圆角(带有完整边框的卡牌图片效果最好)。
|
||||
lblPreloadExtendedArtCards=预加载拉伸卡图
|
||||
nlPreloadExtendedArtCards=启用后,拉伸卡图将在启动时加载到缓存。
|
||||
lblShowFPSDisplay=显示当前的FPS值
|
||||
nlShowFPSDisplay=启用后,将在画面左上角显示当前Forge的FPS(实验性特性)。
|
||||
#MatchScreen.java
|
||||
lblPlayers=玩家列表
|
||||
lblLog=日志
|
||||
@@ -973,7 +980,7 @@ lblChangePreferredArt=改变首选卡图
|
||||
lblSelectPreferredArt=选择首选的卡图版本
|
||||
lblTo=到
|
||||
lblAvatar=头像
|
||||
lblCards=牌张
|
||||
lblCards=卡牌
|
||||
lblPlanes=时空
|
||||
lblSchemes=阴谋
|
||||
lblToMainDeck=到主牌
|
||||
@@ -984,8 +991,9 @@ lblCommanders=指挥官
|
||||
lblOathbreakers=破誓者
|
||||
#Forge.java
|
||||
lblLoadingFonts=加载字体中
|
||||
lblLoadingCardTranslations=加载牌张翻译中
|
||||
lblLoadingCardTranslations=加载卡牌翻译中
|
||||
lblFinishingStartup=完成启动
|
||||
lblPreloadExtendedArt=预加载拉伸卡图
|
||||
#LobbyScreen.java
|
||||
lblMore=更多
|
||||
lblLoadingNewGame=载入新游戏中
|
||||
@@ -1038,11 +1046,11 @@ lblNoPlayerPriorityNoDeckListViewed=现在玩家没有优先权,因此无法
|
||||
#FilesPage.java
|
||||
lblFiles=文件
|
||||
lblStorageLocations=储存位置
|
||||
lblCardPicsLocation=牌张图片位置
|
||||
lblCardPicsLocation=卡牌图片位置
|
||||
lblDecksLocation=套牌位置
|
||||
lblDataLocation=数据位置(例如 设置和探索模式)
|
||||
lblImageCacheLocation=图片缓存位置
|
||||
lblRestartForgeMoveFilesNewLocation=您必须重启Forge才能使此更改生效。执行此操作之前,请确保将所有必要的文件移动到新的位置。
|
||||
lblRestartForgeMoveFilesNewLocation=你必须重启Forge才能使此更改生效。执行此操作之前,请确保将所有必要的文件移动到新的位置。
|
||||
lblRestartRequired=需要重启
|
||||
lblSelect=选择%s
|
||||
#AddBasicLandsDialog.java
|
||||
@@ -1050,17 +1058,17 @@ lblLandSet=地牌的系列
|
||||
lblAddBasicLandsAutoSuggest=添加基本地到%s\n(双击自动添加)
|
||||
lblAssortedArt=各种画
|
||||
lblCardArt=卡图%d
|
||||
lblNonLandCount=%d张非地
|
||||
lblOldLandCount=%d张地
|
||||
lblNewLandCount=添加%d张地
|
||||
lblNonLandCount=%d张非地牌
|
||||
lblOldLandCount=%d张地牌
|
||||
lblNewLandCount=添加%d张地牌
|
||||
lblNewTotalCount=%d张牌
|
||||
#FDeckImportDialog.java
|
||||
lblImportLatestVersionCard=导入牌张的最新版本
|
||||
lblImportLatestVersionCard=导入卡牌的最新版本
|
||||
lblUseOnlySetsReleasedBefore=只用之前上市系列的版本:
|
||||
lblUseOnlyCoreAndExpansionSets=只使用核心系列和拓展系列
|
||||
lblFollowingCardsCannotBeImported=由于拼写错误,系列限制或forge尚未实现,以下牌张没有被导入:
|
||||
lblFollowingCardsCannotBeImported=由于拼写错误,系列限制或forge尚未实现,以下卡牌没有被导入:
|
||||
lblImportRemainingCards=导入剩余的卡?
|
||||
lblNoKnownCardsOnClipboard=在剪切板找不到已知的牌张。\n\n将套牌列表复制到剪切板,然后重新打开此对话框。
|
||||
lblNoKnownCardsOnClipboard=在剪切板找不到已知的卡牌。\n\n将套牌列表复制到剪切板,然后重新打开此对话框。
|
||||
#FDeckViewer.java
|
||||
lblDeckListCopiedClipboard=套牌列表'%s'已经复制到剪切板
|
||||
#FSideboardDialog.java
|
||||
@@ -1092,11 +1100,11 @@ lblWouldYouLiketoPlayorDraw=你想先手还是后手?
|
||||
lblWhoWouldYouLiketoStartthisGame=你想谁先开始游戏?(单击头像)
|
||||
lblPlay=先手
|
||||
lblDraw=后手
|
||||
lblTooFewCardsMainDeck=主牌中牌张数过少(最少为%s),请重新修改套牌。
|
||||
lblTooManyCardsSideboard=备牌中牌张数过多(最多为%s),请重新修改套牌。
|
||||
lblTooFewCardsMainDeck=主牌中卡牌数过少(最少为%s),请重新修改套牌。
|
||||
lblTooManyCardsSideboard=备牌中卡牌数过多(最多为%s),请重新修改套牌。
|
||||
lblAssignCombatDamageWerentBlocked=是否要像没有被阻挡一样分配战斗伤害?
|
||||
lblChosenCards=选择牌
|
||||
lblAttacker=攻击者
|
||||
lblAttacker=进攻者
|
||||
lblTriggeredby=触发者
|
||||
lblChooseWhichCardstoReveal=选择要展示的牌
|
||||
lblChooseCardsActivateOpeningHandandOrder=选择要展示的手牌和顺序
|
||||
@@ -1110,16 +1118,16 @@ lblPleaseDefineanActionSequenceFirst=请先定义一个动作序列。
|
||||
lblRememberActionSequence=记住动作序列
|
||||
lblYouMustHavePrioritytoUseThisFeature=你必须有使用此功能的优先权。
|
||||
lblNameTheCard=命名牌
|
||||
lblWhichPlayerShouldRoll=那个玩家掷骰子?
|
||||
lblWhichPlayerShouldRoll=哪位玩家掷骰子?
|
||||
lblChooseResult=选择结果
|
||||
lblChosenCardNotPermanentorCantExistIndependentlyontheBattleground=选择的牌不是永久物,也不能在战场单独存在。\n如果你想释放费永久物咒语或者你想释放永久物咒语并将之放于堆叠上,请按"Cast Spell/Play Land"按钮。
|
||||
lblError=错误
|
||||
lblWinGame=赢得这局游戏
|
||||
lblSetLifetoWhat=设定生命值为多少?
|
||||
lblSetLifeforWhichPlayer=设定哪个牌手的生命值?
|
||||
lblSetLifeforWhichPlayer=设定哪位牌手的生命值?
|
||||
lblChoosePermanentstoTap=选择要横置的永久物
|
||||
lblChoosePermanentstoUntap=选择要重置的永久物
|
||||
lblWhichTypeofCounter=那种指示物?
|
||||
lblWhichTypeofCounter=哪种指示物?
|
||||
lblHowManyCounters=多少指示物?
|
||||
lblRemoveCountersFromWhichCard=从哪张牌移除指示物?
|
||||
lblAddCountersToWhichCard=添加指示物到哪张牌?
|
||||
@@ -1127,23 +1135,45 @@ lblChooseaCard=选择一张牌
|
||||
lblNoPlayerPriorityDeckCantBeTutoredFrom=目前没有玩家拥有优先权,因此无法从其套牌导师。
|
||||
lblNoPlayerPriorityGameStateCannotBeSetup=目前没有玩家拥有优先权,因此无法设置游戏状态。
|
||||
lblErrorLoadingBattleSetupFile=加载战场设置文件出错!
|
||||
lblSelectCardstoAddtoYourDeck=选择要添加到套牌的牌张。
|
||||
lblSelectCardstoAddtoYourDeck=选择要添加到套牌的卡牌。
|
||||
lblAddTheseToMyDeck=添加这些到我的套牌
|
||||
lblChooseaPile=选择一堆
|
||||
lblSelectOrderForSimultaneousAbilities=选择同时触发的异能的结算顺序
|
||||
lblReorderSimultaneousAbilities=重新对同时触发异能的结算顺序进行排序
|
||||
lblResolveFirst=先结算
|
||||
lblMoveCardstoToporBbottomofLibrary=将牌张移动到牌库顶或底
|
||||
lblSelectCardsToBeOutOnTheBottomOfYourLibrary=选择要放到牌库底的牌张
|
||||
lblCardsToPutOnTheBottom=放到底部的牌张
|
||||
lblArrangeCardsToBePutOnTopOfYourLibrary=为放于牌库顶的牌张排序
|
||||
lblMoveCardstoToporBbottomofLibrary=将卡牌移动到牌库顶或底
|
||||
lblSelectCardsToBeOutOnTheBottomOfYourLibrary=选择要放到牌库底的卡牌
|
||||
lblCardsToPutOnTheBottom=放到底部的卡牌
|
||||
lblArrangeCardsToBePutOnTopOfYourLibrary=为放于牌库顶的卡牌排序
|
||||
lblTopOfLibrary=牌库顶
|
||||
lblSelectCardsToBePutIntoTheGraveyard=选择要放于坟场的牌张
|
||||
lblCardsToPutInTheGraveyard=放于坟场的牌张
|
||||
lblSelectCardsToBePutIntoTheGraveyard=选择要放于坟场的卡牌
|
||||
lblCardsToPutInTheGraveyard=放于坟场的卡牌
|
||||
lblDiscardUpToNCards=最多弃%d张牌
|
||||
lblDiscardNCards=弃%d张牌
|
||||
lblSelectNCardsToDiscardUnlessDiscarduType=选择要丢弃的%d张牌,除非你丢弃%s。
|
||||
lblCleanupPhase=清除步骤
|
||||
lblSelectCardsToDiscardHandDownMaximum=选择要丢弃的%d张牌,以使你的手牌数量减少到%max张。
|
||||
lblChooseMinCardToDiscard=选择%d张牌弃掉
|
||||
lblDiscarded=弃牌
|
||||
lblChooseDamageOrderFor=选择%s造成伤害的顺序
|
||||
lblDamagedFirst=先造成伤害
|
||||
lblChooseBlockerAfterWhichToPlaceAttackert=选择%s后造成伤害的阻挡者; cancel to place it first
|
||||
lblPutCardOnTopOrBottomLibrary=将%s放到牌库顶还是底?
|
||||
lblChooseOrderCardsPutIntoLibrary=选择要放入牌库中的牌的顺序
|
||||
lblClosestToTop=最接近顶部
|
||||
lblChooseOrderCardsPutOntoBattlefield=选择要放入战场中的牌的顺序
|
||||
lblPutFirst=放在最前
|
||||
lblChooseOrderCardsPutIntoGraveyard=选择要放入坟场中的牌的顺序
|
||||
lblClosestToBottom=最接近底部
|
||||
lblChooseOrderCardsPutIntoPlanarDeck=选择要放入时空竞逐套牌中的牌的顺序
|
||||
lblChooseOrderCardsPutIntoSchemeDeck=选择要放入魔王套牌中的牌的顺序
|
||||
lblChooseOrderCopiesCast=选择要复制品的释放顺序。
|
||||
lblDelveHowManyCards=掘穴多少张牌?
|
||||
lblExileWhichCard=放逐哪张牌?
|
||||
#AbstractGuiGame.java
|
||||
lblConcedeCurrentGame=这将让出这局游戏,而你将输掉。\n\n一定要让出吗?
|
||||
lblConcedeTitle=让出这局游戏?
|
||||
lblConcede=让出
|
||||
lblConcedeCurrentGame=这局游戏认输。\n\n确认吗?
|
||||
lblConcedeTitle=这局游戏认输?
|
||||
lblConcede=认输
|
||||
lblCloseGameSpectator=这将关闭游戏,你将无法继续观看它。\n\n一定要关闭吗?
|
||||
lblCloseGame=关闭游戏?
|
||||
lblWaitingForOpponent=等待对手中
|
||||
@@ -1153,16 +1183,16 @@ lblEnterNumberBetweenMinAndMax=输入介于%min到%max之间的数字:
|
||||
lblEnterNumberGreaterThanOrEqualsToMin=输入一个大于等于%min的数字:
|
||||
lblEnterNumberLessThanOrEqualsToMax=输入一个小于等于%max的数字:
|
||||
#PlayerOutcome.java
|
||||
lblWonBecauseAllOpponentsHaveLost=由于所有对手都输了所以你赢了
|
||||
lblWonDueToEffectOf=受'%s'的影响而获胜了
|
||||
lblConceded=已经让出
|
||||
lblWonBecauseAllOpponentsHaveLost=因所有对手都输了而赢得胜利
|
||||
lblWonDueToEffectOf=受'%s'的影响赢得胜利
|
||||
lblConceded=已经认输
|
||||
lblLostTryingToDrawCardsFromEmptyLibrary=尝试从为空的牌库中抓牌而输
|
||||
lblLostBecauseLifeTotalReachedZero=生命值为0而输
|
||||
lblLostBecauseOfObtainingTenPoisonCounters=中毒指示物达到10而输
|
||||
lblLostBecauseAnOpponentHasWonBySpell=因对手用咒语'%s'获胜而输
|
||||
lblLostDueToEffectOfSpell=受咒语'%s'的影响而输
|
||||
lblLostDueToAccumulationOf21DamageFromGenerals=受到大于21点主将伤害而输
|
||||
lblAcceptedThatTheGameIsADraw=已经接受此局游戏平局
|
||||
lblAcceptedThatTheGameIsADraw=此局游戏平局
|
||||
lblLostForUnknownReasonBug=由于未知错误而输(这是一个错误)
|
||||
#ViewWinLose.java
|
||||
btnNextGame=下一局游戏
|
||||
@@ -1171,4 +1201,41 @@ btnQuitMatch=退出比赛
|
||||
lblItsADraw=平局!
|
||||
lblTeamWon=队伍%s胜利了!
|
||||
lblWinnerWon=%s胜利了!
|
||||
lblGameLog=游戏日志
|
||||
lblGameLog=游戏日志
|
||||
#NewDraftScreen.java
|
||||
lblLoadingNewDraft=加载新的轮抽中
|
||||
#LoadDraftScreen.java
|
||||
lblDoubleTapToEditDeck=双击以编辑套牌(长按可以查看)
|
||||
lblMode=模式:
|
||||
lblYouMustSelectExistingDeck=你必须选择一个已有的卡组或者从新的补充包轮抽游戏中构筑一个卡组。
|
||||
lblWhichOpponentWouldYouLikeToFace=你想面对哪个对手?
|
||||
lblSingleMatch=单场比赛
|
||||
#NewGauntletScreen.java
|
||||
lblGauntletText1=在决斗模式下,你可以选择一套牌与多个对手进行对战。
|
||||
lblGauntletText2=设置你想面对的对手数量以及他们所使用的套牌类型或者套牌。
|
||||
lblGauntletText3=然后,尝试击败所有人工智能对手而不输掉一场比赛。
|
||||
lblSelectGauntletType=选择一个决斗类型
|
||||
lblCustomGauntlet=自定义决斗
|
||||
lblGauntletContest=决斗竞赛
|
||||
lblSelectYourDeck=选择你的套牌
|
||||
lblSelectDeckForOpponent=选择对手的套牌
|
||||
lblSelectGauntletContest=选择决斗竞赛
|
||||
#PuzzleScreen.java
|
||||
lblPuzzleText1=解谜模式会加载一个谜题,你必须在预定的时间/方式中获胜。
|
||||
lblPuzzleText2=首先,按下面的开始按钮,然后从列表中选择一个谜题。
|
||||
lblPuzzleText3=当解谜开始的时候,该谜题的要求将会显示在弹窗中,并且还会在指挥官区域放置一张特殊效应卡指示这个谜题的要求。
|
||||
lblChooseAPuzzle=选择一个谜题
|
||||
lblLoadingThePuzzle=加载新的谜题中
|
||||
#InputPassPriority.java
|
||||
lblCastSpell=释放咒语
|
||||
lblPlayLand=使用地
|
||||
lblActivateAbility=启动式异能
|
||||
lblYouHaveManaFloatingInYourManaPoolCouldBeLostIfPassPriority=你的法术力池中还有剩余的法术力,如果现在让过优先权,这些法术力可能会丢失。
|
||||
lblYouWillTakeManaBurnDamageEqualAmountFloatingManaLostThisWay=你将受到等同于通过这种方式失去的剩余法术力数量的法术力灼烧伤害。
|
||||
lblManaFloating=剩余法术力
|
||||
#InputPayManaOfCostPayment.java
|
||||
lblPayManaCost=支付法术力:
|
||||
lblLifePaidForPhyrexianMana=(以%d生命支付了非瑞克西亚法术力)
|
||||
lblClickOnYourLifeTotalToPayLifeForPhyrexianMana=单击你的总生命,以生命值支付非瑞克西亚法术力。
|
||||
lblClickOnYourLifeTotalToPayLifeForBlackMana=单击你的总生命,以生命值支付黑色法术力。
|
||||
lblClickOnYourLifeTotalToPayLifeForPhyrexianOrBlackMana=单击你的总生命,以生命值支付黑色或非瑞克西亚法术力。
|
||||
@@ -33,4 +33,5 @@ Genetic Algorithm AI Decks | https://downloads.cardforge.org/decks/geneticalgori
|
||||
Current Standard Metagame | https://downloads.cardforge.org/decks/currentstandardmetagame.zip
|
||||
Current Modern Metagame | https://downloads.cardforge.org/decks/currentmodernmetagame.zip
|
||||
Current Legacy Metagame | https://downloads.cardforge.org/decks/currentlegacymetagame.zip
|
||||
Current Pauper Metagame | https://downloads.cardforge.org/decks/currentpaupermetagame.zip
|
||||
Current Pauper Metagame | https://downloads.cardforge.org/decks/currentpaupermetagame.zip
|
||||
Current Pioneer Decks | https://downloads.cardforge.org/decks/currentpioneerdecks.zip
|
||||
16
forge-gui/res/puzzle/PS_ELD2.pzl
Normal file
16
forge-gui/res/puzzle/PS_ELD2.pzl
Normal file
@@ -0,0 +1,16 @@
|
||||
[metadata]
|
||||
Name:Possibility Storm - Throne of Eldraine #02
|
||||
URL:http://www.possibilitystorm.com/wp-content/uploads/2019/10/133.-ELD2-1.jpg
|
||||
Goal:Win
|
||||
Turns:1
|
||||
Difficulty:Uncommon
|
||||
Description:Win this turn. Your Sentinel's Mark is attached to your Tajic, Legion's Edge, and your opponent's Sentinel Mark is attached to their Harmonious Archon. Neither was cast this turn. Remember that your solution must satisfy all possible blocking scenarios!
|
||||
[state]
|
||||
humanlife=20
|
||||
ailife=8
|
||||
turn=1
|
||||
activeplayer=human
|
||||
activephase=MAIN1
|
||||
humanhand=Silverflame Squire;Arrester's Zeal;Burn Bright;Torch Courier
|
||||
humanbattlefield=Ferocity of the Wilds;Torbran, Thane of Red Fell;Tajic, Legion's Edge|Id:1;Sentinel's Mark|AttachedTo:1;Sacred Foundry|NoETBTrigs;Mountain;Mountain;Plains
|
||||
aibattlefield=Harmonious Archon|Id:2;Sentinel's Mark|AttachedTo:2;t:Human,P:1,T:1,Cost:no cost,Color:W,Types:Creature-Human,Keywords:,Image:w_1_1_human_eld;t:Human,P:1,T:1,Cost:no cost,Color:W,Types:Creature-Human,Keywords:,Image:w_1_1_human_eld
|
||||
18
forge-gui/res/puzzle/PS_ELD3.pzl
Normal file
18
forge-gui/res/puzzle/PS_ELD3.pzl
Normal file
@@ -0,0 +1,18 @@
|
||||
[metadata]
|
||||
Name:Possibility Storm - Throne of Eldraine #03
|
||||
URL:http://www.possibilitystorm.com/wp-content/uploads/2019/10/134.-ELD3.jpg
|
||||
Goal:Win
|
||||
Turns:1
|
||||
Difficulty:Mythic
|
||||
Description:Win this turn. Your opponent owns a Beanstalk Giant in exile. You have a Cryptic Caves in your graveyard.
|
||||
[state]
|
||||
humanlife=1
|
||||
ailife=7
|
||||
turn=1
|
||||
activeplayer=human
|
||||
activephase=MAIN1
|
||||
humanhand=Giant Opportunity;Overgrown Tomb;Shepherd of the Flock;Overcome;Outmuscle
|
||||
humangraveyard=Cryptic Caves
|
||||
humanbattlefield=Wandermare;Kaya, Orzhov Usurper|Counters:LOYALTY=5;Vengeful Warchief;Trollbred Guardian;Jiang Yanggu, Wildcrafter|Counters:LOYALTY=1;Overgrown Tomb|NoETBTrigs;Overgrown Tomb|NoETBTrigs;Godless Shrine|NoETBTrigs;Godless Shrine|NoETBTrigs
|
||||
aibattlefield=End-Raze Forerunners;Wardscale Crocodile
|
||||
aiexile=Beanstalk Giant
|
||||
20
forge-gui/res/puzzle/PS_ELD4.pzl
Normal file
20
forge-gui/res/puzzle/PS_ELD4.pzl
Normal file
@@ -0,0 +1,20 @@
|
||||
[metadata]
|
||||
Name:Possibility Storm - Throne of Eldraine #04
|
||||
URL:http://www.possibilitystorm.com/wp-content/uploads/2019/10/135.-ELD4-1.jpg
|
||||
Goal:Win
|
||||
Turns:1
|
||||
Difficulty:Uncommon
|
||||
Description:Win this turn. You have not played a land yet this turn. You own an Animating Faerie "on an adventure" in exile. Note that Bring to Life turned Enchanted Carriage into a 0/0 with four +1/+1 counters.
|
||||
[state]
|
||||
humanlife=20
|
||||
ailife=10
|
||||
humanlandsplayed=0
|
||||
turn=1
|
||||
activeplayer=human
|
||||
activephase=MAIN1
|
||||
humanhand=Witch's Oven;Island;Taste of Death;Undercity Uprising
|
||||
humanbattlefield=Wicked Wolf;Oko, Thief of Crowns|Counters:LOYALTY=1;Nullhide Ferox;Enchanted Carriage|Id:1;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs;Watery Grave|NoETBTrigs;Watery Grave|NoETBTrigs
|
||||
humanexile=Animating Faerie|OnAdventure
|
||||
aibattlefield=Loyal Pegasus;Gate Colossus;Dawning Angel
|
||||
humanprecast=Enchanted Carriage:TrigToken;Bring To Life:1->1
|
||||
removesummoningsickness=true
|
||||
@@ -1,5 +1,6 @@
|
||||
Name:Main world
|
||||
Name:Random Standard
|
||||
Name:Random Pioneer
|
||||
Name:Random Modern
|
||||
Name:Random Commander
|
||||
Name:Amonkhet|Dir:Amonkhet|Sets:AKH, HOU
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 32 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 565 KiB After Width: | Height: | Size: 687 KiB |
BIN
forge-gui/res/skins/default/sprite_sleeves.png
Normal file
BIN
forge-gui/res/skins/default/sprite_sleeves.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
BIN
forge-gui/res/skins/default/sprite_sleeves2.png
Normal file
BIN
forge-gui/res/skins/default/sprite_sleeves2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 697 KiB |
@@ -13,6 +13,8 @@ public class FThreads {
|
||||
* @param mustBeEDT   boolean: true = exception if not EDT, false = exception if EDT
|
||||
*/
|
||||
public static void assertExecutedByEdt(final boolean mustBeEDT) {
|
||||
if (GuiBase.isNetworkplay())
|
||||
return; //don't check for networkplay
|
||||
if (isGuiThread() != mustBeEDT) {
|
||||
final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
||||
final String methodName = trace[2].getClassName() + "." + trace[2].getMethodName();
|
||||
|
||||
@@ -4,6 +4,8 @@ import forge.interfaces.IGuiBase;
|
||||
|
||||
public class GuiBase {
|
||||
private static IGuiBase guiInterface;
|
||||
private static boolean propertyConfig = true;
|
||||
private static boolean networkplay = false;
|
||||
|
||||
public static IGuiBase getInterface() {
|
||||
return guiInterface;
|
||||
@@ -11,4 +13,16 @@ public class GuiBase {
|
||||
public static void setInterface(IGuiBase i0) {
|
||||
guiInterface = i0;
|
||||
}
|
||||
public static void enablePropertyConfig(boolean value) {
|
||||
propertyConfig = value;
|
||||
}
|
||||
public static boolean isNetworkplay() {
|
||||
return networkplay;
|
||||
}
|
||||
public static void setNetworkplay(boolean value) {
|
||||
networkplay = value;
|
||||
}
|
||||
public static boolean hasPropertyConfig() {
|
||||
return propertyConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import forge.item.SealedProduct;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.util.CardTranslation;
|
||||
import forge.util.Lang;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user