mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
Merge branch 'Card-Forge:master' into master
This commit is contained in:
@@ -131,10 +131,9 @@ public class ComputerUtil {
|
||||
|
||||
sa = GameActionUtil.addExtraKeywordCost(sa);
|
||||
|
||||
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
||||
if (!CharmEffect.makeChoices(sa)) {
|
||||
return false;
|
||||
}
|
||||
if (sa.getApi() == ApiType.Charm && !CharmEffect.makeChoices(sa)) {
|
||||
// 603.3c If no mode is chosen, the ability is removed from the stack.
|
||||
return false;
|
||||
}
|
||||
if (chooseTargets != null) {
|
||||
chooseTargets.run();
|
||||
@@ -250,6 +249,13 @@ public class ComputerUtil {
|
||||
return false;
|
||||
|
||||
final Card source = sa.getHostCard();
|
||||
|
||||
Zone fromZone = game.getZoneOf(source);
|
||||
int zonePosition = 0;
|
||||
if (fromZone != null) {
|
||||
zonePosition = fromZone.getCards().indexOf(source);
|
||||
}
|
||||
|
||||
if (sa.isSpell() && !source.isCopiedSpell()) {
|
||||
sa.setHostCard(game.getAction().moveToStack(source, sa));
|
||||
}
|
||||
@@ -257,11 +263,18 @@ public class ComputerUtil {
|
||||
sa = GameActionUtil.addExtraKeywordCost(sa);
|
||||
|
||||
final Cost cost = sa.getPayCosts();
|
||||
final CostPayment pay = new CostPayment(cost, sa);
|
||||
|
||||
// do this after card got added to stack
|
||||
if (!sa.checkRestrictions(ai)) {
|
||||
GameActionUtil.rollbackAbility(sa, fromZone, zonePosition, pay, source);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cost == null) {
|
||||
ComputerUtilMana.payManaCost(ai, sa, false);
|
||||
game.getStack().add(sa);
|
||||
} else {
|
||||
final CostPayment pay = new CostPayment(cost, sa);
|
||||
if (pay.payComputerCosts(new AiCostDecision(ai, sa, false))) {
|
||||
game.getStack().add(sa);
|
||||
}
|
||||
@@ -292,17 +305,30 @@ public class ComputerUtil {
|
||||
newSA = GameActionUtil.addExtraKeywordCost(newSA);
|
||||
|
||||
final Card source = newSA.getHostCard();
|
||||
|
||||
Zone fromZone = game.getZoneOf(source);
|
||||
int zonePosition = 0;
|
||||
if (fromZone != null) {
|
||||
zonePosition = fromZone.getCards().indexOf(source);
|
||||
}
|
||||
|
||||
if (newSA.isSpell() && !source.isCopiedSpell()) {
|
||||
newSA.setHostCard(game.getAction().moveToStack(source, newSA));
|
||||
|
||||
if (newSA.getApi() == ApiType.Charm && !newSA.isWrapper()) {
|
||||
if (!CharmEffect.makeChoices(newSA)) {
|
||||
return false;
|
||||
}
|
||||
if (newSA.getApi() == ApiType.Charm && !CharmEffect.makeChoices(newSA)) {
|
||||
// 603.3c If no mode is chosen, the ability is removed from the stack.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final CostPayment pay = new CostPayment(newSA.getPayCosts(), newSA);
|
||||
|
||||
// do this after card got added to stack
|
||||
if (!sa.checkRestrictions(ai)) {
|
||||
GameActionUtil.rollbackAbility(sa, fromZone, zonePosition, pay, source);
|
||||
return false;
|
||||
}
|
||||
|
||||
pay.payComputerCosts(new AiCostDecision(ai, newSA, false));
|
||||
|
||||
game.getStack().add(newSA);
|
||||
@@ -2798,7 +2824,7 @@ public class ComputerUtil {
|
||||
}
|
||||
|
||||
return type.is(CounterEnumType.AWAKENING) || type.is(CounterEnumType.MANIFESTATION) || type.is(CounterEnumType.PETRIFICATION)
|
||||
|| type.is(CounterEnumType.TRAINING);
|
||||
|| type.is(CounterEnumType.TRAINING) || type.is(CounterEnumType.GHOSTFORM);
|
||||
}
|
||||
|
||||
public static Player evaluateBoardPosition(final List<Player> listToEvaluate) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import forge.ai.AiCardMemory.MemorySet;
|
||||
import forge.ai.ability.AnimateAi;
|
||||
import forge.ai.ability.TokenAi;
|
||||
import forge.card.ColorSet;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
@@ -14,6 +15,7 @@ import forge.game.ability.ApiType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -692,6 +694,72 @@ public class ComputerUtilCost {
|
||||
return false;
|
||||
} else if ("LowPriority".equals(aiLogic) && MyRandom.getRandom().nextInt(100) < 67) {
|
||||
return false;
|
||||
} else if (aiLogic != null && aiLogic.startsWith("Fabricate")) {
|
||||
final int n = Integer.valueOf(aiLogic.substring("Fabricate".length()));
|
||||
|
||||
// if host would leave the play or if host is useless, create tokens
|
||||
if (source.hasSVar("EndOfTurnLeavePlay") || ComputerUtilCard.isUselessCreature(payer, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// need a copy for one with extra +1/+1 counter boost,
|
||||
// without causing triggers to run
|
||||
final Card copy = CardUtil.getLKICopy(source);
|
||||
copy.setCounters(CounterEnumType.P1P1, copy.getCounters(CounterEnumType.P1P1) + n);
|
||||
copy.setZone(source.getZone());
|
||||
|
||||
// if host would put into the battlefield attacking
|
||||
Combat combat = source.getGame().getCombat();
|
||||
if (combat != null && combat.isAttacking(source)) {
|
||||
final Player defender = combat.getDefenderPlayerByAttacker(source);
|
||||
if (defender.canLoseLife() && !ComputerUtilCard.canBeBlockedProfitably(defender, copy, true)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the host has haste and can attack
|
||||
if (CombatUtil.canAttack(copy)) {
|
||||
for (final Player opp : payer.getOpponents()) {
|
||||
if (CombatUtil.canAttack(copy, opp) &&
|
||||
opp.canLoseLife() &&
|
||||
!ComputerUtilCard.canBeBlockedProfitably(opp, copy, true))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO check for trigger to turn token ETB into +1/+1 counter for host
|
||||
// TODO check for trigger to turn token ETB into damage or life loss for opponent
|
||||
// in this cases Token might be prefered even if they would not survive
|
||||
final Card tokenCard = TokenAi.spawnToken(payer, sa);
|
||||
|
||||
// Token would not survive
|
||||
if (!tokenCard.isCreature() || tokenCard.getNetToughness() < 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Special Card logic, this one try to median its power with the number of artifacts
|
||||
if ("Marionette Master".equals(source.getName())) {
|
||||
CardCollection list = CardLists.filter(payer.getCardsIn(ZoneType.Battlefield), Presets.ARTIFACTS);
|
||||
return list.size() >= copy.getNetPower();
|
||||
} else if ("Cultivator of Blades".equals(source.getName())) {
|
||||
// Cultivator does try to median with number of Creatures
|
||||
CardCollection list = payer.getCreaturesInPlay();
|
||||
return list.size() >= copy.getNetPower();
|
||||
}
|
||||
|
||||
// evaluate Creature with +1/+1
|
||||
int evalCounter = ComputerUtilCard.evaluateCreature(copy);
|
||||
|
||||
final CardCollection tokenList = new CardCollection(source);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
tokenList.add(TokenAi.spawnToken(payer, sa));
|
||||
}
|
||||
|
||||
// evaluate Host with Tokens
|
||||
int evalToken = ComputerUtilCard.evaluateCreatureList(tokenList);
|
||||
|
||||
return evalToken < evalCounter;
|
||||
}
|
||||
|
||||
// Check for shocklands and similar ETB replacement effects
|
||||
|
||||
@@ -45,7 +45,7 @@ public class CreatureEvaluator implements Function<Card, Integer> {
|
||||
value += addValue(toughness * 10, "toughness: " + toughness);
|
||||
|
||||
// because backside is always stronger the potential makes it better than a single faced card
|
||||
if (c.hasKeyword(Keyword.DAYBOUND)) {
|
||||
if (c.hasKeyword(Keyword.DAYBOUND) && c.hasBackSide()) {
|
||||
value += addValue(power * 10, "transforming");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import forge.game.GameObject;
|
||||
import forge.game.GameType;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.ability.effects.CharmEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
@@ -1045,16 +1046,14 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: the new implementation (below) requires implementing setupNewTargets in the AI controller, among other possible changes, otherwise breaks AI
|
||||
if (sa.isMayChooseNewTargets()) {
|
||||
sa.setupNewTargets(player);
|
||||
}
|
||||
*/
|
||||
if (sa.isMayChooseNewTargets() && !sa.setupTargets()) {
|
||||
if (sa.isSpell()) {
|
||||
getGame().getAction().ceaseToExist(sa.getHostCard(), false);
|
||||
TargetChoices tc = sa.getTargets();
|
||||
if (!sa.setupTargets()) {
|
||||
// if AI can't choose targets need to keep old one even if illegal
|
||||
sa.setTargets(tc);
|
||||
}
|
||||
continue;
|
||||
// FIXME: the new implementation (below) requires implementing setupNewTargets in the AI controller, among other possible changes, otherwise breaks AI
|
||||
// sa.setupNewTargets(player);
|
||||
}
|
||||
}
|
||||
// need finally add the new spell to the stack
|
||||
@@ -1064,6 +1063,9 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
private boolean prepareSingleSa(final Card host, final SpellAbility sa, boolean isMandatory) {
|
||||
if (sa.getApi() == ApiType.Charm) {
|
||||
return CharmEffect.makeChoices(sa);
|
||||
}
|
||||
if (sa.hasParam("TargetingPlayer")) {
|
||||
Player targetingPlayer = AbilityUtils.getDefinedPlayers(host, sa.getParam("TargetingPlayer"), sa).get(0);
|
||||
sa.setTargetingPlayer(targetingPlayer);
|
||||
@@ -1087,7 +1089,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
if (tgtSA instanceof Spell) { // Isn't it ALWAYS a spell?
|
||||
Spell spell = (Spell) tgtSA;
|
||||
// TODO if mandatory AI is only forced to use mana when it's already in the pool
|
||||
if (tgtSA.checkRestrictions(brains.getPlayer()) && (brains.canPlayFromEffectAI(spell, !optional, noManaCost) == AiPlayDecision.WillPlay || !optional)) {
|
||||
if (brains.canPlayFromEffectAI(spell, !optional, noManaCost) == AiPlayDecision.WillPlay || !optional) {
|
||||
if (noManaCost) {
|
||||
return ComputerUtil.playSpellAbilityWithoutPayingManaCost(player, tgtSA, getGame());
|
||||
}
|
||||
|
||||
@@ -89,7 +89,6 @@ public class CharmAi extends SpellAbilityAi {
|
||||
// First pass using standard canPlayAi() for good choices
|
||||
for (AbilitySub sub : choices) {
|
||||
sub.setActivatingPlayer(ai);
|
||||
sub.getRestrictions().setZone(sub.getParent().getRestrictions().getZone());
|
||||
if (AiPlayDecision.WillPlay == aic.canPlaySa(sub)) {
|
||||
chosenList.add(sub);
|
||||
if (chosenList.size() == num) {
|
||||
@@ -101,8 +100,6 @@ public class CharmAi extends SpellAbilityAi {
|
||||
// Second pass using doTrigger(false) to fulfill minimum choice
|
||||
choices.removeAll(chosenList);
|
||||
for (AbilitySub sub : choices) {
|
||||
sub.setActivatingPlayer(ai);
|
||||
sub.getRestrictions().setZone(sub.getParent().getRestrictions().getZone());
|
||||
if (aic.doTrigger(sub, false)) {
|
||||
chosenList.add(sub);
|
||||
if (chosenList.size() == min) {
|
||||
@@ -114,8 +111,6 @@ public class CharmAi extends SpellAbilityAi {
|
||||
if (chosenList.size() < min) {
|
||||
choices.removeAll(chosenList);
|
||||
for (AbilitySub sub : choices) {
|
||||
sub.setActivatingPlayer(ai);
|
||||
sub.getRestrictions().setZone(sub.getParent().getRestrictions().getZone());
|
||||
if (aic.doTrigger(sub, true)) {
|
||||
chosenList.add(sub);
|
||||
if (chosenList.size() == min) {
|
||||
@@ -231,7 +226,6 @@ public class CharmAi extends SpellAbilityAi {
|
||||
} else {
|
||||
// Standard canPlayAi()
|
||||
sub.setActivatingPlayer(ai);
|
||||
sub.getRestrictions().setZone(sub.getParent().getRestrictions().getZone());
|
||||
if (AiPlayDecision.WillPlay == aic.canPlaySa(sub)) {
|
||||
chosenList.add(sub);
|
||||
if (chosenList.size() == min) {
|
||||
@@ -255,15 +249,6 @@ public class CharmAi extends SpellAbilityAi {
|
||||
return Aggregates.random(opponents);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doTriggerAINoCost(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) {
|
||||
// already done by chooseOrderOfSimultaneousStackEntry
|
||||
if (sa.getChosenList() != null) {
|
||||
return true;
|
||||
}
|
||||
return super.doTriggerAINoCost(aiPlayer, sa, mandatory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chkDrawbackWithSubs(Player aiPlayer, AbilitySub ab) {
|
||||
// choices were already targeted
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
@@ -19,12 +18,9 @@ import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
@@ -43,7 +39,7 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
protected boolean checkAiLogic(final Player ai, final SpellAbility sa, final String aiLogic) {
|
||||
if ("Khans".equals(aiLogic) || "Dragons".equals(aiLogic)) {
|
||||
return true;
|
||||
} else if (aiLogic.startsWith("Fabricate") || "Riot".equals(aiLogic)) {
|
||||
} else if ("Riot".equals(aiLogic)) {
|
||||
return true;
|
||||
} else if ("Pump".equals(aiLogic) || "BestOption".equals(aiLogic)) {
|
||||
for (AbilitySub sb : sa.getAdditionalAbilityList("Choices")) {
|
||||
@@ -265,83 +261,6 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
}
|
||||
// if unsure, random?
|
||||
return Aggregates.random(spells);
|
||||
} else if (logic.startsWith("Fabricate")) {
|
||||
final int n = Integer.valueOf(logic.substring("Fabricate".length()));
|
||||
if(spells.size() < 2) {
|
||||
// If the creature is no longer on the battlefield, the option
|
||||
// to add counters is already removed at this point. Return the
|
||||
// only available option: create servo tokens.
|
||||
return spells.get(0);
|
||||
}
|
||||
SpellAbility counterSA = spells.get(0), tokenSA = spells.get(1);
|
||||
|
||||
// check for something which might prevent the counters to be placed on host
|
||||
if (!host.canReceiveCounters(CounterEnumType.P1P1)) {
|
||||
return tokenSA;
|
||||
}
|
||||
|
||||
// if host would leave the play or if host is useless, create tokens
|
||||
if (host.hasSVar("EndOfTurnLeavePlay") || ComputerUtilCard.isUselessCreature(player, host)) {
|
||||
return tokenSA;
|
||||
}
|
||||
|
||||
// need a copy for one with extra +1/+1 counter boost,
|
||||
// without causing triggers to run
|
||||
final Card copy = CardUtil.getLKICopy(host);
|
||||
copy.setCounters(CounterEnumType.P1P1, copy.getCounters(CounterEnumType.P1P1) + n);
|
||||
copy.setZone(host.getZone());
|
||||
|
||||
// if host would put into the battlefield attacking
|
||||
if (combat != null && combat.isAttacking(host)) {
|
||||
final Player defender = combat.getDefenderPlayerByAttacker(host);
|
||||
if (defender.canLoseLife() && !ComputerUtilCard.canBeBlockedProfitably(defender, copy, true)) {
|
||||
return counterSA;
|
||||
}
|
||||
return tokenSA;
|
||||
}
|
||||
|
||||
// if the host has haste and can attack
|
||||
if (CombatUtil.canAttack(copy)) {
|
||||
for (final Player opp : player.getOpponents()) {
|
||||
if (CombatUtil.canAttack(copy, opp) &&
|
||||
opp.canLoseLife() &&
|
||||
!ComputerUtilCard.canBeBlockedProfitably(opp, copy, true))
|
||||
return counterSA;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO check for trigger to turn token ETB into +1/+1 counter for host
|
||||
// TODO check for trigger to turn token ETB into damage or life loss for opponent
|
||||
// in this cases Token might be prefered even if they would not survive
|
||||
final Card tokenCard = TokenAi.spawnToken(player, tokenSA);
|
||||
|
||||
// Token would not survive
|
||||
if (!tokenCard.isCreature() || tokenCard.getNetToughness() < 1) {
|
||||
return counterSA;
|
||||
}
|
||||
|
||||
// Special Card logic, this one try to median its power with the number of artifacts
|
||||
if ("Marionette Master".equals(sourceName)) {
|
||||
CardCollection list = CardLists.filter(player.getCardsIn(ZoneType.Battlefield), Presets.ARTIFACTS);
|
||||
return list.size() >= copy.getNetPower() ? counterSA : tokenSA;
|
||||
} else if ("Cultivator of Blades".equals(sourceName)) {
|
||||
// Cultivator does try to median with number of Creatures
|
||||
CardCollection list = player.getCreaturesInPlay();
|
||||
return list.size() >= copy.getNetPower() ? counterSA : tokenSA;
|
||||
}
|
||||
|
||||
// evaluate Creature with +1/+1
|
||||
int evalCounter = ComputerUtilCard.evaluateCreature(copy);
|
||||
|
||||
final CardCollection tokenList = new CardCollection(host);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
tokenList.add(TokenAi.spawnToken(player, tokenSA));
|
||||
}
|
||||
|
||||
// evaluate Host with Tokens
|
||||
int evalToken = ComputerUtilCard.evaluateCreatureList(tokenList);
|
||||
|
||||
return evalToken >= evalCounter ? tokenSA : counterSA;
|
||||
} else if ("CombustibleGearhulk".equals(logic)) {
|
||||
Player controller = sa.getActivatingPlayer();
|
||||
List<ZoneType> zones = ZoneType.listValueOf("Graveyard, Battlefield, Exile");
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge;
|
||||
import forge.item.PaperCard;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.ThreadUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
@@ -30,6 +31,7 @@ public final class ImageKeys {
|
||||
private static Map<String, String> CACHE_CARD_PICS_SUBDIR;
|
||||
|
||||
private static Map<String, Boolean> editionImageLookup = new HashMap<>();
|
||||
private static Set<String> toFind = new HashSet<>();
|
||||
|
||||
private static boolean isLibGDXPort = false;
|
||||
|
||||
@@ -109,7 +111,8 @@ public final class ImageKeys {
|
||||
filename = key;
|
||||
dir = CACHE_CARD_PICS_DIR;
|
||||
}
|
||||
|
||||
if (toFind.contains(filename))
|
||||
return null;
|
||||
if (missingCards.contains(filename))
|
||||
return null;
|
||||
|
||||
@@ -171,10 +174,20 @@ public final class ImageKeys {
|
||||
return file;
|
||||
}
|
||||
//setlookup
|
||||
file = setLookUpFile(filename, fullborderFile);
|
||||
if (file != null) {
|
||||
cachedCards.put(filename, file);
|
||||
return file;
|
||||
if (hasSetLookup(filename)) {
|
||||
toFind.add(filename);
|
||||
try {
|
||||
ThreadUtil.getServicePool().submit(() -> {
|
||||
File f = setLookUpFile(filename, fullborderFile);
|
||||
if (f != null)
|
||||
cachedCards.put(filename, f);
|
||||
else //is null
|
||||
missingCards.add(filename);
|
||||
toFind.remove(filename);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
toFind.remove(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
//if an image, like phenomenon or planes is missing .full in their filenames but you have an existing images that have .full/.fullborder
|
||||
@@ -250,7 +263,7 @@ public final class ImageKeys {
|
||||
|
||||
// System.out.println("File not found, no image created: " + key);
|
||||
//add missing cards - disable for desktop version for compatibility reasons with autodownloader
|
||||
if (isLibGDXPort)
|
||||
if (isLibGDXPort && !hasSetLookup(filename)) //missing cards with setlookup is handled differently
|
||||
missingCards.add(filename);
|
||||
return null;
|
||||
}
|
||||
@@ -260,34 +273,44 @@ public final class ImageKeys {
|
||||
? StaticData.instance().getEditions().getCode2ByCode(edition) // by default 2-letter codes from MWS are used
|
||||
: CACHE_CARD_PICS_SUBDIR.get(edition); // may use custom paths though
|
||||
}
|
||||
private static File setLookUpFile(String filename, String fullborderFile) {
|
||||
public static boolean hasSetLookup(String filename) {
|
||||
if (!StaticData.instance().getSetLookup().isEmpty()) {
|
||||
return StaticData.instance().getSetLookup().keySet().stream().anyMatch(setKey -> filename.startsWith(setKey));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
public static File setLookUpFile(String filename, String fullborderFile) {
|
||||
if (!StaticData.instance().getSetLookup().isEmpty()) {
|
||||
for (String setKey : StaticData.instance().getSetLookup().keySet()) {
|
||||
if (filename.startsWith(setKey)) {
|
||||
for (String setLookup : StaticData.instance().getSetLookup().get(setKey)) {
|
||||
String lookupDirectory = CACHE_CARD_PICS_DIR + setLookup;
|
||||
File f = new File(lookupDirectory);
|
||||
String[] cardNames = f.list();
|
||||
if (cardNames != null) {
|
||||
Set<String> cardList = new HashSet<>(Arrays.asList(cardNames));
|
||||
if (f.exists() && f.isDirectory()) {
|
||||
for (String ext : FILE_EXTENSIONS) {
|
||||
if (ext.equals(""))
|
||||
continue;
|
||||
File placeholder;
|
||||
String fb1 = fullborderFile.replace(setKey+"/","")+ext;
|
||||
if (cardList.contains(fb1)) {
|
||||
return new File(lookupDirectory+"/"+fb1);
|
||||
placeholder = new File(lookupDirectory+"/"+fb1);
|
||||
if (placeholder.exists()) {
|
||||
return placeholder;
|
||||
}
|
||||
String fb2 = fullborderFile.replace(setKey+"/","").replaceAll("[0-9]*.fullborder", "1.fullborder")+ext;
|
||||
if (cardList.contains(fb2)) {
|
||||
return new File(lookupDirectory+"/"+fb2);
|
||||
placeholder = new File(lookupDirectory+"/"+fb2);
|
||||
if (placeholder.exists()) {
|
||||
return placeholder;
|
||||
}
|
||||
String f1 = filename.replace(setKey+"/","")+ext;
|
||||
if (cardList.contains(f1)) {
|
||||
return new File(lookupDirectory+"/"+f1);
|
||||
placeholder = new File(lookupDirectory+"/"+f1);
|
||||
if (placeholder.exists()) {
|
||||
return placeholder;
|
||||
}
|
||||
String f2 = filename.replace(setKey+"/","").replaceAll("[0-9]*.full", "1.full")+ext;
|
||||
if (cardList.contains(f2)) {
|
||||
return new File(lookupDirectory+"/"+f2);
|
||||
placeholder = new File(lookupDirectory+"/"+f2);
|
||||
if (placeholder.exists()) {
|
||||
return placeholder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,11 @@ import forge.card.PrintSheet;
|
||||
import forge.item.*;
|
||||
import forge.token.TokenDb;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.ImageUtil;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.storage.IStorage;
|
||||
import forge.util.storage.StorageBase;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
@@ -45,6 +47,7 @@ public class StaticData {
|
||||
|
||||
private boolean allowCustomCardsInDecksConformance;
|
||||
private boolean enableSmartCardArtSelection;
|
||||
private boolean loadNonLegalCards;
|
||||
|
||||
// Loaded lazily:
|
||||
private IStorage<SealedProduct.Template> boosters;
|
||||
@@ -74,6 +77,7 @@ public class StaticData {
|
||||
this.customCardReader = customCardReader;
|
||||
this.allowCustomCardsInDecksConformance = allowCustomCardsInDecksConformance;
|
||||
this.enableSmartCardArtSelection = enableSmartCardArtSelection;
|
||||
this.loadNonLegalCards = loadNonLegalCards;
|
||||
lastInstance = this;
|
||||
List<String> funnyCards = new ArrayList<>();
|
||||
List<String> filtered = new ArrayList<>();
|
||||
@@ -752,6 +756,129 @@ public class StaticData {
|
||||
preferences_avails[i] = prettifyCardArtPreferenceName(preferences[i]);
|
||||
return preferences_avails;
|
||||
}
|
||||
public Pair<Integer, Integer> audit(StringBuffer noImageFound, StringBuffer cardNotImplemented) {
|
||||
int missingCount = 0;
|
||||
int notImplementedCount = 0;
|
||||
for (CardEdition e : editions) {
|
||||
if (CardEdition.Type.FUNNY.equals(e.getType()))
|
||||
continue;
|
||||
boolean nifHeader = false;
|
||||
boolean cniHeader = false;
|
||||
boolean tokenHeader = false;
|
||||
|
||||
String imagePath;
|
||||
int artIndex = 1;
|
||||
|
||||
HashMap<String, Pair<Boolean, Integer>> cardCount = new HashMap<>();
|
||||
for (CardEdition.CardInSet c : e.getAllCardsInSet()) {
|
||||
if (cardCount.containsKey(c.name)) {
|
||||
cardCount.put(c.name, Pair.of(c.collectorNumber.startsWith("F"), cardCount.get(c.name).getRight() + 1));
|
||||
} else {
|
||||
cardCount.put(c.name, Pair.of(c.collectorNumber.startsWith("F"), 1));
|
||||
}
|
||||
}
|
||||
|
||||
// loop through the cards in this edition, considering art variations...
|
||||
for (Map.Entry<String, Pair<Boolean, Integer>> entry : cardCount.entrySet()) {
|
||||
String c = entry.getKey();
|
||||
artIndex = entry.getValue().getRight();
|
||||
|
||||
PaperCard cp = getCommonCards().getCard(c, e.getCode(), artIndex);
|
||||
if (cp == null) {
|
||||
cp = getVariantCards().getCard(c, e.getCode(), artIndex);
|
||||
}
|
||||
|
||||
if (cp == null) {
|
||||
if (entry.getValue().getLeft()) //skip funny cards
|
||||
continue;
|
||||
if (!loadNonLegalCards && CardEdition.Type.FUNNY.equals(e.getType()))
|
||||
continue;
|
||||
if (!cniHeader) {
|
||||
cardNotImplemented.append("Edition: ").append(e.getName()).append(" ").append("(").append(e.getCode()).append("/").append(e.getCode2()).append(")\n");
|
||||
cniHeader = true;
|
||||
}
|
||||
cardNotImplemented.append(" ").append(c).append("\n");
|
||||
notImplementedCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check the front image
|
||||
imagePath = ImageUtil.getImageRelativePath(cp, false, true, false);
|
||||
if (imagePath != null) {
|
||||
File file = ImageKeys.getImageFile(imagePath);
|
||||
if (file == null && ImageKeys.hasSetLookup(imagePath))
|
||||
file = ImageKeys.setLookUpFile(imagePath, imagePath+"border");
|
||||
if (file == null) {
|
||||
if (!nifHeader) {
|
||||
noImageFound.append("Edition: ").append(e.getName()).append(" ").append("(").append(e.getCode()).append("/").append(e.getCode2()).append(")\n");
|
||||
nifHeader = true;
|
||||
}
|
||||
noImageFound.append(" ").append(imagePath).append("\n");
|
||||
missingCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// check the back face
|
||||
if (cp.hasBackFace()) {
|
||||
imagePath = ImageUtil.getImageRelativePath(cp, true, true, false);
|
||||
if (imagePath != null) {
|
||||
File file = ImageKeys.getImageFile(imagePath);
|
||||
if (file == null && ImageKeys.hasSetLookup(imagePath))
|
||||
file = ImageKeys.setLookUpFile(imagePath, imagePath+"border");
|
||||
if (file == null) {
|
||||
if (!nifHeader) {
|
||||
noImageFound.append("Edition: ").append(e.getName()).append(" ").append("(").append(e.getCode()).append("/").append(e.getCode2()).append(")\n");
|
||||
nifHeader = true;
|
||||
}
|
||||
noImageFound.append(" ").append(imagePath).append("\n");
|
||||
missingCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Audit token images here...
|
||||
for(Map.Entry<String, Integer> tokenEntry : e.getTokens().entrySet()) {
|
||||
String name = tokenEntry.getKey();
|
||||
artIndex = tokenEntry.getValue();
|
||||
try {
|
||||
PaperToken token = getAllTokens().getToken(name, e.getCode());
|
||||
if (token == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(int i = 0; i < artIndex; i++) {
|
||||
String imgKey = token.getImageKey(i);
|
||||
File file = ImageKeys.getImageFile(imgKey);
|
||||
if (file == null) {
|
||||
if (!nifHeader) {
|
||||
noImageFound.append("Edition: ").append(e.getName()).append(" ").append("(").append(e.getCode()).append("/").append(e.getCode2()).append(")\n");
|
||||
nifHeader = true;
|
||||
}
|
||||
if (!tokenHeader) {
|
||||
noImageFound.append("\nTOKENS\n");
|
||||
tokenHeader = true;
|
||||
}
|
||||
noImageFound.append(" ").append(token.getImageFilename(i + 1)).append("\n");
|
||||
missingCount++;
|
||||
}
|
||||
}
|
||||
} catch(Exception ex) {
|
||||
System.out.println("No Token found: " + name + " in " + e.getName());
|
||||
}
|
||||
}
|
||||
if (nifHeader)
|
||||
noImageFound.append("\n");
|
||||
}
|
||||
|
||||
String totalStats = "Missing images: " + missingCount + "\nUnimplemented cards: " + notImplementedCount + "\n";
|
||||
cardNotImplemented.append("\n-----------\n");
|
||||
cardNotImplemented.append(totalStats);
|
||||
cardNotImplemented.append("-----------\n\n");
|
||||
|
||||
noImageFound.append(cardNotImplemented); // combine things together...
|
||||
return Pair.of(missingCount, notImplementedCount);
|
||||
}
|
||||
|
||||
private String prettifyCardArtPreferenceName(CardDb.CardArtPreference preference) {
|
||||
StringBuilder label = new StringBuilder();
|
||||
|
||||
@@ -53,6 +53,27 @@ public class ThreadUtil {
|
||||
return Thread.currentThread().getName().startsWith("Game");
|
||||
}
|
||||
|
||||
private static ExecutorService service = Executors.newWorkStealingPool();
|
||||
public static ExecutorService getServicePool() {
|
||||
return service;
|
||||
}
|
||||
public static void refreshServicePool() {
|
||||
service = Executors.newWorkStealingPool();
|
||||
}
|
||||
public static <T> T limit(Callable<T> task, long millis){
|
||||
Future<T> future = null;
|
||||
T result;
|
||||
try {
|
||||
future = service.submit(task);
|
||||
result = future.get(millis, TimeUnit.MILLISECONDS);
|
||||
} catch (Exception e) {
|
||||
result = null;
|
||||
} finally {
|
||||
if (future != null)
|
||||
future.cancel(true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static <T> T executeWithTimeout(Callable<T> task, int milliseconds) {
|
||||
ExecutorService executor = Executors.newCachedThreadPool();
|
||||
Future<T> future = executor.submit(task);
|
||||
|
||||
@@ -53,6 +53,7 @@ import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.card.CardZoneTable;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.event.Event;
|
||||
@@ -120,6 +121,8 @@ public class Game {
|
||||
private CardCollection lastStateBattlefield = new CardCollection();
|
||||
private CardCollection lastStateGraveyard = new CardCollection();
|
||||
|
||||
private CardZoneTable untilHostLeavesPlayTriggerList = new CardZoneTable();
|
||||
|
||||
private Table<CounterType, Player, List<Pair<Card, Integer>>> countersAddedThisTurn = HashBasedTable.create();
|
||||
|
||||
private FCollection<CardDamageHistory> globalDamageHistory = new FCollection<>();
|
||||
@@ -187,6 +190,10 @@ public class Game {
|
||||
initiative = p;
|
||||
}
|
||||
|
||||
public CardZoneTable getUntilHostLeavesPlayTriggerList() {
|
||||
return untilHostLeavesPlayTriggerList;
|
||||
}
|
||||
|
||||
public CardCollectionView getLastStateBattlefield() {
|
||||
return lastStateBattlefield;
|
||||
}
|
||||
|
||||
@@ -162,14 +162,32 @@ public class GameAction {
|
||||
// need to check before it enters
|
||||
if (c.isAura() && !c.isAttachedToEntity() && toBattlefield && (zoneFrom == null || !zoneFrom.is(ZoneType.Stack))) {
|
||||
boolean found = false;
|
||||
if (Iterables.any(game.getPlayers(), PlayerPredicates.canBeAttached(c, null))) {
|
||||
found = true;
|
||||
try {
|
||||
if (Iterables.any(game.getPlayers(), PlayerPredicates.canBeAttached(c, null))) {
|
||||
found = true;
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
found = false;
|
||||
}
|
||||
else if (Iterables.any((CardCollectionView) params.get(AbilityKey.LastStateBattlefield), CardPredicates.canBeAttached(c, null))) {
|
||||
found = true;
|
||||
|
||||
if (!found) {
|
||||
try {
|
||||
if (Iterables.any((CardCollectionView) params.get(AbilityKey.LastStateBattlefield), CardPredicates.canBeAttached(c, null))) {
|
||||
found = true;
|
||||
}
|
||||
} catch (Exception e2) {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
else if (Iterables.any((CardCollectionView) params.get(AbilityKey.LastStateGraveyard), CardPredicates.canBeAttached(c, null))) {
|
||||
found = true;
|
||||
|
||||
if (!found) {
|
||||
try {
|
||||
if (Iterables.any((CardCollectionView) params.get(AbilityKey.LastStateGraveyard), CardPredicates.canBeAttached(c, null))) {
|
||||
found = true;
|
||||
}
|
||||
} catch (Exception e3) {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
c.clearControllers();
|
||||
@@ -341,8 +359,10 @@ public class GameAction {
|
||||
if (commanderEffect != null) break;
|
||||
}
|
||||
// Disable the commander replacement effect
|
||||
for (final ReplacementEffect re : commanderEffect.getReplacementEffects()) {
|
||||
re.setSuppressed(true);
|
||||
if (commanderEffect != null) {
|
||||
for (final ReplacementEffect re : commanderEffect.getReplacementEffects()) {
|
||||
re.setSuppressed(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2315,14 +2335,16 @@ public class GameAction {
|
||||
final Player p = e.getKey();
|
||||
final CardCollection toTop = e.getValue().getLeft();
|
||||
final CardCollection toBottom = e.getValue().getRight();
|
||||
final int numLookedAt = toTop.size() + toBottom.size();
|
||||
int numLookedAt = 0;
|
||||
if (toTop != null) {
|
||||
numLookedAt += toTop.size();
|
||||
Collections.reverse(toTop); // reverse to get the correct order
|
||||
for (Card c : toTop) {
|
||||
moveToLibrary(c, cause, null);
|
||||
}
|
||||
}
|
||||
if (toBottom != null) {
|
||||
numLookedAt += toBottom.size();
|
||||
for (Card c : toBottom) {
|
||||
moveToBottomOfLibrary(c, cause, null);
|
||||
}
|
||||
@@ -2390,6 +2412,9 @@ public class GameAction {
|
||||
}
|
||||
}
|
||||
|
||||
// for Zangief do this before runWaitingTriggers DamageDone
|
||||
damageMap.triggerExcessDamage(isCombat, lethalDamage, game);
|
||||
|
||||
// lose life simultaneously
|
||||
if (isCombat) {
|
||||
for (Player p : game.getPlayers()) {
|
||||
@@ -2418,7 +2443,6 @@ public class GameAction {
|
||||
preventMap.clear();
|
||||
|
||||
damageMap.triggerDamageDoneOnce(isCombat, game);
|
||||
damageMap.triggerExcessDamage(isCombat, lethalDamage, game);
|
||||
damageMap.clear();
|
||||
|
||||
counterTable.replaceCounterEffect(game, cause, !isCombat);
|
||||
|
||||
@@ -34,6 +34,7 @@ import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.CardPlayOption.PayManaCost;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostPayment;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.keyword.KeywordInterface;
|
||||
import forge.game.player.Player;
|
||||
@@ -842,4 +843,46 @@ public final class GameActionUtil {
|
||||
c.getGame().getTriggerHandler().resetActiveTriggers();
|
||||
}
|
||||
|
||||
public static void rollbackAbility(SpellAbility ability, final Zone fromZone, final int zonePosition, CostPayment payment, Card oldCard) {
|
||||
// cancel ability during target choosing
|
||||
final Game game = ability.getActivatingPlayer().getGame();
|
||||
|
||||
if (fromZone != null) { // and not a copy
|
||||
oldCard.setCastSA(null);
|
||||
oldCard.setCastFrom(null);
|
||||
// add back to where it came from, hopefully old state
|
||||
// skip GameAction
|
||||
oldCard.getZone().remove(oldCard);
|
||||
fromZone.add(oldCard, zonePosition >= 0 ? Integer.valueOf(zonePosition) : null);
|
||||
ability.setHostCard(oldCard);
|
||||
ability.setXManaCostPaid(null);
|
||||
ability.setSpendPhyrexianMana(false);
|
||||
if (ability.hasParam("Announce")) {
|
||||
for (final String aVar : ability.getParam("Announce").split(",")) {
|
||||
final String varName = aVar.trim();
|
||||
if (!varName.equals("X")) {
|
||||
ability.setSVar(varName, "0");
|
||||
}
|
||||
}
|
||||
}
|
||||
// better safe than sorry approach in case rolled back ability was copy (from addExtraKeywordCost)
|
||||
for (SpellAbility sa : oldCard.getSpells()) {
|
||||
sa.setHostCard(oldCard);
|
||||
}
|
||||
//for Chorus of the Conclave
|
||||
ability.rollback();
|
||||
|
||||
oldCard.setBackSide(false);
|
||||
oldCard.setState(oldCard.getFaceupCardStateName(), true);
|
||||
oldCard.unanimateBestow();
|
||||
}
|
||||
|
||||
ability.clearTargets();
|
||||
|
||||
ability.resetOnceResolved();
|
||||
payment.refundPayment();
|
||||
game.getStack().clearFrozen();
|
||||
game.getTriggerHandler().clearWaitingTriggers();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ public final class AbilityFactory {
|
||||
}
|
||||
}
|
||||
|
||||
if (api == ApiType.Charm || api == ApiType.GenericChoice || api == ApiType.AssignGroup) {
|
||||
if (api == ApiType.Charm || api == ApiType.GenericChoice || api == ApiType.AssignGroup) {
|
||||
final String key = "Choices";
|
||||
if (mapParams.containsKey(key)) {
|
||||
List<String> names = Lists.newArrayList(mapParams.get(key).split(","));
|
||||
@@ -426,7 +426,9 @@ public final class AbilityFactory {
|
||||
private static final void makeRestrictions(final SpellAbility sa) {
|
||||
// SpellAbilityRestrictions should be added in here
|
||||
final SpellAbilityRestriction restrict = sa.getRestrictions();
|
||||
restrict.setRestrictions(sa.getMapParams());
|
||||
if (restrict != null) {
|
||||
restrict.setRestrictions(sa.getMapParams());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -438,7 +440,7 @@ public final class AbilityFactory {
|
||||
* a {@link forge.game.spellability.SpellAbility} object.
|
||||
*/
|
||||
private static final void makeConditions(final SpellAbility sa) {
|
||||
// SpellAbilityRestrictions should be added in here
|
||||
// SpellAbilityConditions should be added in here
|
||||
final SpellAbilityCondition condition = sa.getConditions();
|
||||
condition.setConditions(sa.getMapParams());
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ public enum AbilityKey {
|
||||
Blockers("Blockers"),
|
||||
CanReveal("CanReveal"),
|
||||
CastSA("CastSA"),
|
||||
CastSACMC("CastSACMC"),
|
||||
Card("Card"),
|
||||
Cards("Cards"),
|
||||
CardLKI("CardLKI"),
|
||||
|
||||
@@ -163,17 +163,15 @@ public class AbilityUtils {
|
||||
return cards;
|
||||
}
|
||||
}
|
||||
else if (defined.equals("Targeted") && sa instanceof SpellAbility) {
|
||||
else if ((defined.equals("Targeted") || defined.equals("TargetedCard")) && sa instanceof SpellAbility) {
|
||||
for (TargetChoices tc : ((SpellAbility)sa).getAllTargetChoices()) {
|
||||
Iterables.addAll(cards, tc.getTargetCards());
|
||||
}
|
||||
}
|
||||
else if (defined.equals("TargetedSource") && sa instanceof SpellAbility) {
|
||||
for (TargetChoices tc : ((SpellAbility)sa).getAllTargetChoices()) {
|
||||
for (SpellAbility s : tc.getTargetSpells()) {
|
||||
for (TargetChoices tc : ((SpellAbility)sa).getAllTargetChoices()) for (SpellAbility s : tc.getTargetSpells()) {
|
||||
cards.add(s.getHostCard());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (defined.equals("ThisTargetedCard") && sa instanceof SpellAbility) { // do not add parent targeted
|
||||
if (((SpellAbility)sa).getTargets() != null) {
|
||||
@@ -285,7 +283,7 @@ public class AbilityUtils {
|
||||
System.err.println("Warning: couldn't find trigger SA in the chain of SpellAbility " + sa);
|
||||
}
|
||||
} else if (defined.equals("FirstRemembered")) {
|
||||
Object o = Iterables.getFirst(hostCard.getRemembered(), null);
|
||||
Object o = hostCard.getFirstRemembered();
|
||||
if (o != null && o instanceof Card) {
|
||||
cards.add(game.getCardState((Card) o));
|
||||
}
|
||||
@@ -544,6 +542,9 @@ public class AbilityUtils {
|
||||
}
|
||||
} else if (calcX[0].equals("OriginalHost")) {
|
||||
val = xCount(ability.getOriginalHost(), calcX[1], ability);
|
||||
} else if (calcX[0].equals("LastStateBattlefield") && ability instanceof SpellAbility) {
|
||||
Card c = ((SpellAbility) ability).getLastStateBattlefield().get(card);
|
||||
val = c == null ? 0 : xCount(c, calcX[1], ability);
|
||||
} else if (calcX[0].startsWith("Remembered")) {
|
||||
// Add whole Remembered list to handlePaid
|
||||
final CardCollection list = new CardCollection();
|
||||
@@ -687,10 +688,9 @@ public class AbilityUtils {
|
||||
Object o = root.getTriggeringObject(AbilityKey.fromString(calcX[0].substring(9)));
|
||||
val = o instanceof Player ? playerXProperty((Player) o, calcX[1], card, ability) : 0;
|
||||
}
|
||||
else if (calcX[0].equals("TriggeredSpellAbility")) {
|
||||
final SpellAbility root = sa.getRootAbility();
|
||||
SpellAbility sat = (SpellAbility) root.getTriggeringObject(AbilityKey.SpellAbility);
|
||||
val = calculateAmount(sat.getHostCard(), calcX[1], sat);
|
||||
else if (calcX[0].equals("TriggeredSpellAbility") || calcX[0].equals("TriggeredStackInstance") || calcX[0].equals("SpellTargeted")) {
|
||||
final SpellAbility sat = getDefinedSpellAbilities(card, calcX[0], sa).get(0);
|
||||
val = xCount(sat.getHostCard(), calcX[1], sat);
|
||||
}
|
||||
else if (calcX[0].startsWith("TriggerCount")) {
|
||||
// TriggerCount is similar to a regular Count, but just
|
||||
@@ -730,7 +730,7 @@ public class AbilityUtils {
|
||||
else if (calcX[0].startsWith("Discarded")) {
|
||||
final SpellAbility root = sa.getRootAbility();
|
||||
list = root.getPaidList("Discarded");
|
||||
if ((null == list) && root.isTrigger()) {
|
||||
if (null == list && root.isTrigger()) {
|
||||
list = root.getHostCard().getSpellPermanent().getPaidList("Discarded");
|
||||
}
|
||||
}
|
||||
@@ -973,7 +973,7 @@ public class AbilityUtils {
|
||||
|
||||
final Player player = sa instanceof SpellAbility ? ((SpellAbility)sa).getActivatingPlayer() : card.getController();
|
||||
|
||||
if (defined.equals("Self") || defined.equals("ThisTargetedCard") || defined.startsWith("Valid") || getPaidCards(sa, defined) != null) {
|
||||
if (defined.equals("Self") || defined.equals("TargetedCard") || defined.equals("ThisTargetedCard") || defined.startsWith("Valid") || getPaidCards(sa, defined) != null) {
|
||||
// do nothing, Self is for Cards, not Players
|
||||
} else if (defined.equals("TargetedOrController")) {
|
||||
players.addAll(getDefinedPlayers(card, "Targeted", sa));
|
||||
@@ -1849,7 +1849,7 @@ public class AbilityUtils {
|
||||
return doXMath(0, expr, c, ctb);
|
||||
}
|
||||
}
|
||||
list = CardLists.getValidCards(list, k[1], sa.getActivatingPlayer(), c, sa);
|
||||
list = CardLists.getValidCards(list, k[1], player, c, sa);
|
||||
return doXMath(list.size(), expr, c, ctb);
|
||||
}
|
||||
|
||||
@@ -1873,7 +1873,7 @@ public class AbilityUtils {
|
||||
return doXMath(0, expr, c, ctb);
|
||||
}
|
||||
}
|
||||
list = CardLists.getValidCards(list, k[1], sa.getActivatingPlayer(), c, sa);
|
||||
list = CardLists.getValidCards(list, k[1], player, c, sa);
|
||||
return doXMath(list.size(), expr, c, ctb);
|
||||
}
|
||||
|
||||
@@ -1901,14 +1901,14 @@ public class AbilityUtils {
|
||||
// fallback if ctb isn't a spellability
|
||||
if (sq[0].startsWith("LastStateBattlefield")) {
|
||||
final String[] k = l[0].split(" ");
|
||||
CardCollection list = new CardCollection(game.getLastStateBattlefield());
|
||||
CardCollectionView list = game.getLastStateBattlefield();
|
||||
list = CardLists.getValidCards(list, k[1], player, c, ctb);
|
||||
return doXMath(list.size(), expr, c, ctb);
|
||||
}
|
||||
|
||||
if (sq[0].startsWith("LastStateGraveyard")) {
|
||||
final String[] k = l[0].split(" ");
|
||||
CardCollection list = new CardCollection(game.getLastStateGraveyard());
|
||||
CardCollectionView list = game.getLastStateGraveyard();
|
||||
list = CardLists.getValidCards(list, k[1], player, c, ctb);
|
||||
return doXMath(list.size(), expr, c, ctb);
|
||||
}
|
||||
@@ -2167,17 +2167,22 @@ public class AbilityUtils {
|
||||
// Count$CardManaCost
|
||||
if (sq[0].contains("CardManaCost")) {
|
||||
Card ce;
|
||||
if (sq[0].contains("Equipped") && c.isEquipping()) {
|
||||
ce = c.getEquipping();
|
||||
}
|
||||
else if (sq[0].contains("Remembered")) {
|
||||
if (sq[0].contains("Remembered")) {
|
||||
ce = (Card) c.getFirstRemembered();
|
||||
}
|
||||
else {
|
||||
ce = c;
|
||||
}
|
||||
|
||||
return doXMath(ce == null ? 0 : ce.getCMC(), expr, c, ctb);
|
||||
int cmc = ce == null ? 0 : ce.getCMC();
|
||||
|
||||
if (sq[0].contains("LKI") && ctb instanceof SpellAbility && ce != null && !ce.isInZone(ZoneType.Stack) && ce.getManaCost() != null) {
|
||||
if (((SpellAbility) ctb).getXManaCostPaid() != null) {
|
||||
cmc += ((SpellAbility) ctb).getXManaCostPaid() * ce.getManaCost().countX();
|
||||
}
|
||||
}
|
||||
|
||||
return doXMath(cmc, expr, c, ctb);
|
||||
}
|
||||
|
||||
if (sq[0].startsWith("RememberedSize")) {
|
||||
@@ -3481,7 +3486,8 @@ public class AbilityUtils {
|
||||
}
|
||||
|
||||
if (value.equals("OpponentsAttackedThisCombat")) {
|
||||
return doXMath(game.getCombat().getAttackedOpponents(player).size(), m, source, ctb);
|
||||
int amount = game.getCombat() == null ? 0 : game.getCombat().getAttackedOpponents(player).size();
|
||||
return doXMath(amount, m, source, ctb);
|
||||
}
|
||||
|
||||
if (value.equals("DungeonsCompleted")) {
|
||||
|
||||
@@ -657,7 +657,6 @@ public abstract class SpellAbilityEffect {
|
||||
if (untilCards.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
CardZoneTable untilTable = new CardZoneTable();
|
||||
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
|
||||
moveParams.put(AbilityKey.LastStateBattlefield, game.copyLastStateBattlefield());
|
||||
moveParams.put(AbilityKey.LastStateGraveyard, game.copyLastStateGraveyard());
|
||||
@@ -697,10 +696,9 @@ public abstract class SpellAbilityEffect {
|
||||
}
|
||||
// no cause there?
|
||||
Card movedCard = game.getAction().moveTo(cell.getRowKey(), newCard, 0, null, moveParams);
|
||||
untilTable.put(cell.getColumnKey(), cell.getRowKey(), movedCard);
|
||||
game.getUntilHostLeavesPlayTriggerList().put(cell.getColumnKey(), cell.getRowKey(), movedCard);
|
||||
}
|
||||
}
|
||||
untilTable.triggerChangesZoneAll(game, null);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -154,8 +154,6 @@ public class AnimateEffect extends AnimateEffectBase {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
List<Card> tgts = getCardsfromTargets(sa);
|
||||
|
||||
if (sa.hasParam("Optional")) {
|
||||
|
||||
@@ -1,41 +1,18 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.game.*;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.GameCommand;
|
||||
import forge.card.CardStateName;
|
||||
import forge.card.CardType;
|
||||
import forge.game.*;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardState;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.card.CardZoneTable;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.event.GameEventCombatChanged;
|
||||
import forge.game.player.DelayedReveal;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.player.PlayerCollection;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.player.*;
|
||||
import forge.game.replacement.ReplacementEffect;
|
||||
import forge.game.replacement.ReplacementType;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
@@ -43,13 +20,13 @@ import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.CardTranslation;
|
||||
import forge.util.Lang;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.MessageUtil;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.*;
|
||||
import forge.util.collect.FCollectionView;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
|
||||
@@ -689,7 +666,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
// need to be facedown before it hits the battlefield in case of Replacement Effects or Trigger
|
||||
if (sa.hasParam("FaceDown")) {
|
||||
gameCard.turnFaceDown(true);
|
||||
setFaceDownState(gameCard, sa);
|
||||
CardFactoryUtil.setFaceDownState(gameCard, sa);
|
||||
}
|
||||
|
||||
movedCard = game.getAction().moveTo(gameCard.getController().getZone(destination), gameCard, sa, moveParams);
|
||||
@@ -1345,7 +1322,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
// need to be facedown before it hits the battlefield in case of Replacement Effects or Trigger
|
||||
if (sa.hasParam("FaceDown")) {
|
||||
c.turnFaceDown(true);
|
||||
setFaceDownState(c, sa);
|
||||
CardFactoryUtil.setFaceDownState(c, sa);
|
||||
}
|
||||
movedCard = game.getAction().moveToPlay(c, c.getController(), sa, moveParams);
|
||||
|
||||
@@ -1448,6 +1425,13 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ZoneType.Exile.equals(destination) && sa.hasParam("WithCountersType")) {
|
||||
CounterType cType = CounterType.getType(sa.getParam("WithCountersType"));
|
||||
int cAmount = AbilityUtils.calculateAmount(sa.getOriginalHost(), sa.getParamOrDefault("WithCountersAmount", "1"), sa);
|
||||
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||
movedCard.addCounter(cType, cAmount, player, table);
|
||||
table.replaceCounterEffect(game, sa, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (((!ZoneType.Battlefield.equals(destination) && changeType != null && !defined && !changeType.equals("Card"))
|
||||
@@ -1496,39 +1480,6 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
&& sa.getParam("WithTotalCMC") == null;
|
||||
}
|
||||
|
||||
private static void setFaceDownState(Card c, SpellAbility sa) {
|
||||
final Card source = sa.getHostCard();
|
||||
CardState faceDown = c.getFaceDownState();
|
||||
|
||||
// set New Pt doesn't work because this values need to be copyable for clone effects
|
||||
if (sa.hasParam("FaceDownPower")) {
|
||||
faceDown.setBasePower(AbilityUtils.calculateAmount(
|
||||
source, sa.getParam("FaceDownPower"), sa));
|
||||
}
|
||||
if (sa.hasParam("FaceDownToughness")) {
|
||||
faceDown.setBaseToughness(AbilityUtils.calculateAmount(
|
||||
source, sa.getParam("FaceDownToughness"), sa));
|
||||
}
|
||||
|
||||
if (sa.hasParam("FaceDownSetType")) {
|
||||
faceDown.setType(new CardType(Arrays.asList(sa.getParam("FaceDownSetType").split(" & ")), false));
|
||||
}
|
||||
|
||||
if (sa.hasParam("FaceDownPower") || sa.hasParam("FaceDownToughness")
|
||||
|| sa.hasParam("FaceDownSetType")) {
|
||||
final GameCommand unanimate = new GameCommand() {
|
||||
private static final long serialVersionUID = 8853789549297846163L;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
c.clearStates(CardStateName.FaceDown, true);
|
||||
}
|
||||
};
|
||||
|
||||
c.addFaceupCommand(unanimate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* removeFromStack.
|
||||
|
||||
@@ -156,6 +156,11 @@ public class CharmEffect extends SpellAbilityEffect {
|
||||
}
|
||||
|
||||
public static boolean makeChoices(SpellAbility sa) {
|
||||
// CR 700.2g
|
||||
if (sa.isCopied()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//this resets all previous choices
|
||||
sa.setSubAbility(null);
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import forge.game.player.DelayedReveal;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.util.CardTranslation;
|
||||
@@ -119,6 +118,23 @@ public class ChooseCardEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (sa.hasParam("ChooseParty")) {
|
||||
Set<String> partyTypes = Sets.newHashSet("Cleric", "Rogue", "Warrior", "Wizard");
|
||||
for (final String type : partyTypes) {
|
||||
CardCollection valids = CardLists.filter(p.getCardsIn(ZoneType.Battlefield),
|
||||
CardPredicates.isType(type));
|
||||
for (Card alreadyChosen : chosen) {
|
||||
valids.remove(alreadyChosen);
|
||||
}
|
||||
if (!valids.isEmpty()) {
|
||||
final String prompt = Localizer.getInstance().getMessage("lblChoose") + " " +
|
||||
Lang.nounWithNumeralExceptOne(1, type);
|
||||
Card c = p.getController().chooseSingleEntityForEffect(valids, sa, prompt, true, null);
|
||||
if (c != null) {
|
||||
chosen.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (sa.hasParam("WithTotalPower")) {
|
||||
final int totP = AbilityUtils.calculateAmount(host, sa.getParam("WithTotalPower"), sa);
|
||||
CardCollection negativeCreats = CardLists.filterLEPower(p.getCreaturesInPlay(), -1);
|
||||
@@ -187,6 +203,18 @@ public class ChooseCardEffect extends SpellAbilityEffect {
|
||||
chosenPool.add(choice);
|
||||
}
|
||||
chosen.addAll(chosenPool);
|
||||
} else if (sa.hasParam("ControlAndNot")) {
|
||||
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : Localizer.getInstance().getMessage("lblChooseCreature");
|
||||
// Targeted player (p) chooses N creatures that belongs to them
|
||||
CardCollection tgtPlayerCtrl = CardLists.filterControlledBy(choices, p);
|
||||
chosen.addAll(p.getController().chooseCardsForEffect(tgtPlayerCtrl, sa, title + " " + "you control", minAmount, validAmount,
|
||||
!sa.hasParam("Mandatory"), null));
|
||||
// Targeted player (p) chooses N creatures that don't belong to them
|
||||
CardCollection notTgtPlayerCtrl = new CardCollection(choices);
|
||||
notTgtPlayerCtrl.removeAll(tgtPlayerCtrl);
|
||||
chosen.addAll(p.getController().chooseCardsForEffect(notTgtPlayerCtrl, sa, title + " " + "you don't control", minAmount, validAmount,
|
||||
!sa.hasParam("Mandatory"), null));
|
||||
|
||||
} else if ((tgt == null) || p.canBeTargetedBy(sa)) {
|
||||
if (sa.hasParam("AtRandom") && !choices.isEmpty()) {
|
||||
Aggregates.random(choices, validAmount, chosen);
|
||||
@@ -217,8 +245,13 @@ public class ChooseCardEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sa.hasParam("Reveal")) {
|
||||
game.getAction().reveal(chosen, p, true, Localizer.getInstance().getMessage("lblChosenCards") + " ");
|
||||
if (sa.hasParam("Reveal") && !sa.hasParam("SecretlyChoose")) {
|
||||
game.getAction().reveal(chosen, p, true, sa.hasParam("RevealTitle") ? sa.getParam("RevealTitle") : Localizer.getInstance().getMessage("lblChosenCards") + " ");
|
||||
}
|
||||
}
|
||||
if(sa.hasParam("Reveal") && sa.hasParam("SecretlyChoose")) {
|
||||
for (final Player p : tgtPlayers) {
|
||||
game.getAction().reveal(chosen, p, true, sa.hasParam("RevealTitle") ? sa.getParam("RevealTitle") : Localizer.getInstance().getMessage("lblChosenCards") + " ");
|
||||
}
|
||||
}
|
||||
host.setChosenCards(chosen);
|
||||
|
||||
@@ -50,7 +50,7 @@ public class ChooseGenericEffect extends SpellAbilityEffect {
|
||||
List<SpellAbility> saToRemove = Lists.newArrayList();
|
||||
|
||||
for (SpellAbility saChoice : abilities) {
|
||||
if (!saChoice.getRestrictions().checkOtherRestrictions(host, saChoice, sa.getActivatingPlayer()) ) {
|
||||
if (saChoice.getRestrictions() != null && !saChoice.getRestrictions().checkOtherRestrictions(host, saChoice, sa.getActivatingPlayer())) {
|
||||
saToRemove.add(saChoice);
|
||||
} else if (saChoice.hasParam("UnlessCost")) {
|
||||
// generic check for if the cost can be paid
|
||||
|
||||
@@ -124,11 +124,12 @@ public class ControlGainEffect extends SpellAbilityEffect {
|
||||
sa.getParam("Chooser"), sa).get(0) : activator;
|
||||
CardCollectionView choices = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield),
|
||||
sa.getParam("Choices"), activator, source, sa);
|
||||
if (!choices.isEmpty()) {
|
||||
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") :
|
||||
Localizer.getInstance().getMessage("lblChooseaCard") +" ";
|
||||
tgtCards = chooser.getController().chooseCardsForEffect(choices, sa, title, 1, 1, false, null);
|
||||
if (choices.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") :
|
||||
Localizer.getInstance().getMessage("lblChooseaCard") +" ";
|
||||
tgtCards = chooser.getController().chooseCardsForEffect(choices, sa, title, 1, 1, false, null);
|
||||
} else {
|
||||
tgtCards = getDefinedCards(sa);
|
||||
}
|
||||
|
||||
@@ -122,8 +122,9 @@ public class CounterEffect extends SpellAbilityEffect {
|
||||
CardZoneTable table = new CardZoneTable();
|
||||
for (final SpellAbility tgtSA : sas) {
|
||||
final Card tgtSACard = tgtSA.getHostCard();
|
||||
// should remember even that spell cannot be countered, e.g. Dovescape
|
||||
// TODO use LKI in case the spell gets countered before (else X amounts would be missing)
|
||||
// should remember even that spell cannot be countered
|
||||
// currently all effects using this are targeted in case the spell gets countered before
|
||||
// so don't need to worry about LKI (else X amounts would be missing)
|
||||
if (sa.hasParam("RememberCounteredCMC")) {
|
||||
sa.getHostCard().addRemembered(Integer.valueOf(tgtSACard.getCMC()));
|
||||
}
|
||||
|
||||
@@ -67,8 +67,9 @@ public class CountersPutEffect extends SpellAbilityEffect {
|
||||
|
||||
stringBuilder.append(pronoun ? "they" : who).append(" ");
|
||||
|
||||
String desc = sa.getDescription();
|
||||
boolean forEach = desc.contains("for each");
|
||||
if (sa.hasParam("CounterTypes")) {
|
||||
String desc = sa.getDescription();
|
||||
if (desc.contains("Put ") && desc.contains(" on ")) {
|
||||
desc = desc.substring(desc.indexOf("Put "), desc.indexOf(" on ") + 4)
|
||||
.replaceFirst("Put ", "puts ");
|
||||
@@ -84,8 +85,8 @@ public class CountersPutEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
|
||||
final int amount = AbilityUtils.calculateAmount(card,
|
||||
sa.getParamOrDefault("CounterNum", "1"), sa);
|
||||
final String key = forEach ? "ForEachNum" : "CounterNum";
|
||||
final int amount = AbilityUtils.calculateAmount(card, sa.getParamOrDefault(key, "1"), sa);
|
||||
|
||||
if (sa.hasParam("Bolster")) {
|
||||
stringBuilder.append("bolsters ").append(amount).append(".");
|
||||
@@ -155,7 +156,7 @@ public class CountersPutEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
}
|
||||
stringBuilder.append(".");
|
||||
stringBuilder.append(forEach ? desc.substring(desc.indexOf(" for each")) : ".");
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
@@ -495,7 +496,7 @@ public class CountersPutEffect extends SpellAbilityEffect {
|
||||
// need to unfreeze tracker
|
||||
game.getTracker().unfreeze();
|
||||
|
||||
// check if it can recive the Tribute
|
||||
// check if it can receive the Tribute
|
||||
if (abort) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public class DigUntilEffect extends SpellAbilityEffect {
|
||||
if (revealed.equals(ZoneType.Exile)) {
|
||||
sb.append("and exile all other cards revealed this way.");
|
||||
}
|
||||
} else {
|
||||
} else if (revealed != null) {
|
||||
if (revealed.equals(ZoneType.Hand)) {
|
||||
sb.append("all cards revealed this way into their hand");
|
||||
}
|
||||
@@ -209,7 +209,9 @@ public class DigUntilEffect extends SpellAbilityEffect {
|
||||
Collections.shuffle(revealed, MyRandom.getRandom());
|
||||
}
|
||||
|
||||
if (sa.hasParam("NoneFoundDestination") && found.size() < untilAmount) {
|
||||
if (sa.hasParam("NoMoveRevealed")) {
|
||||
//don't do anything
|
||||
} else if (sa.hasParam("NoneFoundDestination") && found.size() < untilAmount) {
|
||||
// Allow ordering the revealed cards
|
||||
if (noneFoundDest.isKnown() && revealed.size() >= 2) {
|
||||
revealed = (CardCollection)p.getController().orderMoveToZoneList(revealed, noneFoundDest, sa);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -144,6 +145,9 @@ public class RollDiceEffect extends SpellAbilityEffect {
|
||||
sa.setSVar(sa.getParam("OtherSVar"), Integer.toString(other));
|
||||
}
|
||||
}
|
||||
if (sa.hasParam("UseHighestRoll")) {
|
||||
total = Collections.max(rolls);
|
||||
}
|
||||
|
||||
Map<String, SpellAbility> diceAbilities = sa.getAdditionalAbilities();
|
||||
SpellAbility resultAbility = null;
|
||||
|
||||
@@ -162,6 +162,10 @@ public class SetStateEffect extends SpellAbilityEffect {
|
||||
hasTransformed = gameCard.turnFaceUp(true, true, sa);
|
||||
} else {
|
||||
hasTransformed = gameCard.changeCardState(mode, sa.getParam("NewState"), sa);
|
||||
if (gameCard.isFaceDown() && (sa.hasParam("FaceDownPower") || sa.hasParam("FaceDownToughness")
|
||||
|| sa.hasParam("FaceDownSetType"))) {
|
||||
CardFactoryUtil.setFaceDownState(gameCard, sa);
|
||||
}
|
||||
}
|
||||
if (hasTransformed) {
|
||||
if (sa.isMorphUp()) {
|
||||
|
||||
@@ -256,6 +256,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
|
||||
private Map<Integer, Integer> damage = Maps.newHashMap();
|
||||
private boolean hasBeenDealtDeathtouchDamage;
|
||||
private boolean hasBeenDealtExcessDamageThisTurn;
|
||||
|
||||
// regeneration
|
||||
private FCollection<Card> shields = new FCollection<>();
|
||||
@@ -3016,7 +3017,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
public final FCollectionView<SpellAbility> getBasicSpells() {
|
||||
return getBasicSpells(currentState);
|
||||
}
|
||||
|
||||
public final FCollectionView<SpellAbility> getBasicSpells(CardState state) {
|
||||
final FCollection<SpellAbility> res = new FCollection<>();
|
||||
for (final SpellAbility sa : state.getNonManaAbilities()) {
|
||||
@@ -5361,6 +5361,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
this.hasBeenDealtDeathtouchDamage = hasBeenDealtDeatchtouchDamage;
|
||||
}
|
||||
|
||||
public final boolean hasBeenDealtExcessDamageThisTurn() {
|
||||
return hasBeenDealtExcessDamageThisTurn;
|
||||
}
|
||||
public final void setHasBeenDealtExcessDamageThisTurn(final boolean bool) {
|
||||
this.hasBeenDealtExcessDamageThisTurn = bool;
|
||||
}
|
||||
|
||||
public final Map<Card, Integer> getAssignedDamageMap() {
|
||||
return assignedDamageMap;
|
||||
}
|
||||
@@ -5515,7 +5522,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
}
|
||||
// Defending player at the time the damage was dealt
|
||||
runParams.put(AbilityKey.DefendingPlayer, game.getCombat() != null ? game.getCombat().getDefendingPlayerRelatedTo(source) : null);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams, false);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams, true);
|
||||
|
||||
DamageType damageType = DamageType.Normal;
|
||||
if (isPlaneswalker()) { // 120.3c
|
||||
@@ -6158,6 +6165,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
setDamage(0);
|
||||
}
|
||||
setHasBeenDealtDeathtouchDamage(false);
|
||||
setHasBeenDealtExcessDamageThisTurn(false);
|
||||
setRegeneratedThisTurn(0);
|
||||
resetShield();
|
||||
setBecameTargetThisTurn(false);
|
||||
|
||||
@@ -113,6 +113,7 @@ public class CardDamageMap extends ForwardingTable<Card, GameEntity, Integer> {
|
||||
|
||||
int excess = sum - (damaged.getKey().hasBeenDealtDeathtouchDamage() ? 1 : damaged.getValue());
|
||||
if (excess > 0) {
|
||||
damaged.getKey().setHasBeenDealtExcessDamageThisTurn(true);
|
||||
// Run triggers
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||
runParams.put(AbilityKey.DamageTarget, damaged.getKey());
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import forge.GameCommand;
|
||||
import forge.game.event.GameEventCardForetold;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -1147,29 +1148,21 @@ public class CardFactoryUtil {
|
||||
+ " | ValidCard$ Card.Self | Secondary$ True"
|
||||
+ " | TriggerDescription$ Fabricate " + n + " (" + inst.getReminderText() + ")";
|
||||
|
||||
final String choose = "DB$ GenericChoice | AILogic$ " + name;
|
||||
final String counter = "DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ " + n +
|
||||
" | IsPresent$ Card.StrictlySelf | SpellDescription$ Put "
|
||||
+ Lang.nounWithNumeral(n, "+1/+1 counter") + " on it.";
|
||||
final String token = "DB$ Token | TokenAmount$ " + n + " | TokenScript$ c_1_1_a_servo | TokenOwner$ You "
|
||||
+ " | SpellDescription$ Create "
|
||||
final String token = "DB$ Token | TokenAmount$ " + n + " | TokenScript$ c_1_1_a_servo"
|
||||
+ " | UnlessCost$ AddCounter<" + n + "/P1P1> | UnlessPayer$ You | UnlessAI$ " + name
|
||||
+ " | SpellDescription$ Fabricate - Create "
|
||||
+ Lang.nounWithNumeral(n, "1/1 colorless Servo artifact creature token") + ".";
|
||||
|
||||
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic);
|
||||
|
||||
SpellAbility saChoose = AbilityFactory.getAbility(choose, card);
|
||||
|
||||
List<AbilitySub> list = Lists.newArrayList();
|
||||
list.add((AbilitySub)AbilityFactory.getAbility(counter, card));
|
||||
list.add((AbilitySub)AbilityFactory.getAbility(token, card));
|
||||
saChoose.setAdditionalAbilityList("Choices", list);
|
||||
SpellAbility saChoose = AbilityFactory.getAbility(token, card);
|
||||
saChoose.setIntrinsic(intrinsic);
|
||||
|
||||
trigger.setOverridingAbility(saChoose);
|
||||
|
||||
inst.addTrigger(trigger);
|
||||
} else if (keyword.startsWith("Fading")) {
|
||||
String upkeepTrig = "Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Secondary$ True " +
|
||||
String upkeepTrig = "Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Secondary$ True" +
|
||||
" | TriggerDescription$ At the beginning of your upkeep, remove a fade counter from CARDNAME. If you can't, sacrifice CARDNAME.";
|
||||
|
||||
final String removeCounterStr = "DB$ RemoveCounter | Defined$ Self | CounterType$ FADE | CounterNum$ 1 | RememberRemoved$ True";
|
||||
@@ -3748,4 +3741,37 @@ public class CardFactoryUtil {
|
||||
re.setOverridingAbility(saExile);
|
||||
card.addReplacementEffect(re);
|
||||
}
|
||||
|
||||
public static void setFaceDownState(Card c, SpellAbility sa) {
|
||||
final Card source = sa.getHostCard();
|
||||
CardState faceDown = c.getFaceDownState();
|
||||
|
||||
// set New Pt doesn't work because this values need to be copyable for clone effects
|
||||
if (sa.hasParam("FaceDownPower")) {
|
||||
faceDown.setBasePower(AbilityUtils.calculateAmount(
|
||||
source, sa.getParam("FaceDownPower"), sa));
|
||||
}
|
||||
if (sa.hasParam("FaceDownToughness")) {
|
||||
faceDown.setBaseToughness(AbilityUtils.calculateAmount(
|
||||
source, sa.getParam("FaceDownToughness"), sa));
|
||||
}
|
||||
|
||||
if (sa.hasParam("FaceDownSetType")) {
|
||||
faceDown.setType(new CardType(Arrays.asList(sa.getParam("FaceDownSetType").split(" & ")), false));
|
||||
}
|
||||
|
||||
if (sa.hasParam("FaceDownPower") || sa.hasParam("FaceDownToughness")
|
||||
|| sa.hasParam("FaceDownSetType")) {
|
||||
final GameCommand unanimate = new GameCommand() {
|
||||
private static final long serialVersionUID = 8853789549297846163L;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
c.clearStates(CardStateName.FaceDown, true);
|
||||
}
|
||||
};
|
||||
|
||||
c.addFaceupCommand(unanimate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -607,7 +607,7 @@ public class CardProperty {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("Cloned")) {
|
||||
if ((card.getCloneOrigin() == null) || !card.getCloneOrigin().equals(source)) {
|
||||
if (card.getCloneOrigin() == null || !card.getCloneOrigin().equals(source)) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("SharesCMCWith")) {
|
||||
@@ -1180,6 +1180,10 @@ public class CardProperty {
|
||||
if (card.getAssignedDamage(false, null) == 0) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("wasDealtExcessDamageThisTurn")) {
|
||||
if (!card.hasBeenDealtExcessDamageThisTurn()) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("wasDealtDamageByThisGame")) {
|
||||
int idx = source.getDamageHistory().getThisGameDamaged().indexOf(card);
|
||||
if (idx == -1) {
|
||||
@@ -1475,6 +1479,14 @@ public class CardProperty {
|
||||
if (!card.getManaCost().getShortString().equals(property.substring(8))) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("HasCounters")) {
|
||||
if (!card.hasCounters()) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("NoCounters")) {
|
||||
if (card.hasCounters()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// syntax example: countersGE9 P1P1 or countersLT12TIME (greater number
|
||||
@@ -1691,7 +1703,7 @@ public class CardProperty {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("hadToAttackThisCombat")) {
|
||||
AttackRequirement e = game.getCombat().getAttackConstraints().getRequirements().get(card);
|
||||
AttackRequirement e = combat.getAttackConstraints().getRequirements().get(card);
|
||||
if (e == null || !e.hasCreatureRequirement() || !e.getAttacker().equalsWithTimestamp(card)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1807,14 +1819,6 @@ public class CardProperty {
|
||||
if (!card.hasNoAbilities()) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("HasCounters")) {
|
||||
if (!card.hasCounters()) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("NoCounters")) {
|
||||
if (card.hasCounters()) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("castKeyword")) {
|
||||
SpellAbility castSA = card.getCastSA();
|
||||
if (castSA == null) {
|
||||
@@ -1937,8 +1941,16 @@ public class CardProperty {
|
||||
} else if (property.startsWith("Triggered")) {
|
||||
if (spellAbility instanceof SpellAbility) {
|
||||
final String key = property.substring(9);
|
||||
CardCollection cc = (CardCollection) ((SpellAbility)spellAbility).getTriggeringObject(AbilityKey.fromString(key));
|
||||
if (cc == null || !cc.contains(card)) {
|
||||
Object o = ((SpellAbility)spellAbility).getTriggeringObject(AbilityKey.fromString(key));
|
||||
boolean found = false;
|
||||
if (o != null) {
|
||||
if (o instanceof CardCollection) {
|
||||
found = ((CardCollection) o).contains(card);
|
||||
} else {
|
||||
found = card.equals(o);
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -56,7 +56,12 @@ public class CardZoneTable extends ForwardingTable<ZoneType, ZoneType, CardColle
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||
runParams.put(AbilityKey.Cards, new CardZoneTable(this));
|
||||
runParams.put(AbilityKey.Cause, cause);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.ChangesZoneAll, AbilityKey.newMap(runParams), false);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.ChangesZoneAll, runParams, false);
|
||||
}
|
||||
final CardZoneTable untilTable = game.getUntilHostLeavesPlayTriggerList();
|
||||
if (this != untilTable) {
|
||||
untilTable.triggerChangesZoneAll(game, null);
|
||||
untilTable.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,16 +141,16 @@ public class CostPutCounter extends CostPartWithList {
|
||||
public final boolean canPay(final SpellAbility ability, final Player payer, final boolean effect) {
|
||||
final Card source = ability.getHostCard();
|
||||
if (this.payCostFromSource()) {
|
||||
return source.canReceiveCounters(this.counter);
|
||||
} else {
|
||||
// 3 Cards have Put a -1/-1 Counter on a Creature you control.
|
||||
List<Card> typeList = CardLists.getValidCards(source.getGame().getCardsIn(ZoneType.Battlefield),
|
||||
this.getType().split(";"), payer, source, ability);
|
||||
|
||||
typeList = CardLists.filter(typeList, CardPredicates.canReceiveCounters(this.counter));
|
||||
|
||||
return !typeList.isEmpty();
|
||||
return source.isInPlay() && source.canReceiveCounters(this.counter);
|
||||
}
|
||||
|
||||
// 3 Cards have Put a -1/-1 Counter on a Creature you control.
|
||||
List<Card> typeList = CardLists.getValidCards(source.getGame().getCardsIn(ZoneType.Battlefield),
|
||||
this.getType().split(";"), payer, source, ability);
|
||||
|
||||
typeList = CardLists.filter(typeList, CardPredicates.canReceiveCounters(this.counter));
|
||||
|
||||
return !typeList.isEmpty();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -836,7 +836,6 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
game.getStack().onNextTurn();
|
||||
|
||||
game.getTriggerHandler().clearThisTurnDelayedTrigger();
|
||||
game.getTriggerHandler().resetTurnTriggerState();
|
||||
|
||||
Player next = getNextActivePlayer();
|
||||
while (next.hasLost()) {
|
||||
|
||||
@@ -1603,6 +1603,12 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
}
|
||||
}
|
||||
|
||||
// MilledAll trigger
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||
runParams.put(AbilityKey.Cards, milled);
|
||||
runParams.put(AbilityKey.Player, this);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.MilledAll, runParams, false);
|
||||
|
||||
return milled;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -44,6 +45,7 @@ import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardDamageMap;
|
||||
import forge.game.card.CardState;
|
||||
import forge.game.card.CardTraitChanges;
|
||||
@@ -175,9 +177,17 @@ public class ReplacementHandler {
|
||||
final Card c = preList.get(crd);
|
||||
|
||||
for (final ReplacementEffect replacementEffect : c.getReplacementEffects()) {
|
||||
// Use "CheckLKIZone" parameter to test for effects that care abut where the card was last (e.g. Kalitas, Traitor of Ghet
|
||||
Zone cardZone;
|
||||
// Use "CheckLKIZone" parameter to test for effects that care about where the card was last (e.g. Kalitas, Traitor of Ghet
|
||||
// getting hit by mass removal should still produce tokens).
|
||||
Zone cardZone = "True".equals(replacementEffect.getParam("CheckSelfLKIZone")) ? game.getChangeZoneLKIInfo(c).getLastKnownZone() : game.getZoneOf(c);
|
||||
if ("True".equals(replacementEffect.getParam("CheckSelfLKIZone"))) {
|
||||
cardZone = game.getChangeZoneLKIInfo(c).getLastKnownZone();
|
||||
if (cardZone.is(ZoneType.Battlefield) && runParams.containsKey(AbilityKey.LastStateBattlefield) && runParams.get(AbilityKey.LastStateBattlefield) != null && !((CardCollectionView) runParams.get(AbilityKey.LastStateBattlefield)).contains(crd)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
cardZone = game.getZoneOf(c);
|
||||
}
|
||||
|
||||
// Replacement effects that are tied to keywords (e.g. damage prevention effects - if the keyword is removed, the replacement
|
||||
// effect should be inactive)
|
||||
@@ -351,8 +361,8 @@ public class ReplacementHandler {
|
||||
tailend = tailend.getSubAbility();
|
||||
} while(tailend != null);
|
||||
|
||||
effectSA.setLastStateBattlefield(game.getLastStateBattlefield());
|
||||
effectSA.setLastStateGraveyard(game.getLastStateGraveyard());
|
||||
effectSA.setLastStateBattlefield((CardCollectionView) ObjectUtils.firstNonNull(runParams.get(AbilityKey.LastStateBattlefield), game.getLastStateBattlefield()));
|
||||
effectSA.setLastStateGraveyard((CardCollectionView) ObjectUtils.firstNonNull(runParams.get(AbilityKey.LastStateGraveyard), game.getLastStateGraveyard()));
|
||||
if (replacementEffect.isIntrinsic()) {
|
||||
effectSA.setIntrinsic(true);
|
||||
effectSA.changeText();
|
||||
|
||||
@@ -179,7 +179,7 @@ public class AbilityManaPart implements java.io.Serializable {
|
||||
if (source.isLand() && root.isManaAbility() && root.getPayCosts() != null && root.getPayCosts().hasTapCost()) {
|
||||
player.setTappedLandForManaThisTurn(true);
|
||||
}
|
||||
} // end produceMana(String)
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -348,7 +348,7 @@ public class AbilityManaPart implements java.io.Serializable {
|
||||
|
||||
// "can't" zone restriction – shouldn't be mixed with other restrictions
|
||||
if (restriction.startsWith("CantCastSpellFrom")) {
|
||||
if (!sa.isSpell()) { //
|
||||
if (!sa.isSpell()) {
|
||||
return true;
|
||||
}
|
||||
final ZoneType badZone = ZoneType.smartValueOf(restriction.substring(17));
|
||||
|
||||
@@ -138,7 +138,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
|
||||
/** The pay costs. */
|
||||
private Cost payCosts;
|
||||
private SpellAbilityRestriction restrictions = new SpellAbilityRestriction();
|
||||
private SpellAbilityRestriction restrictions;
|
||||
private SpellAbilityCondition conditions = new SpellAbilityCondition();
|
||||
private AbilitySub subAbility;
|
||||
|
||||
@@ -179,8 +179,8 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
|
||||
private StaticAbility mayPlay;
|
||||
|
||||
private CardCollection lastStateBattlefield = null;
|
||||
private CardCollection lastStateGraveyard = null;
|
||||
private CardCollection lastStateBattlefield;
|
||||
private CardCollection lastStateGraveyard;
|
||||
|
||||
private CardCollection rollbackEffects = new CardCollection();
|
||||
|
||||
@@ -214,6 +214,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
view0 = new SpellAbilityView(this);
|
||||
}
|
||||
view = view0;
|
||||
if (!(this instanceof AbilitySub)) {
|
||||
restrictions = new SpellAbilityRestriction();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -443,7 +443,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
|
||||
if (getPresentDefined() != null) {
|
||||
list = AbilityUtils.getDefinedObjects(sa.getHostCard(), getPresentDefined(), sa);
|
||||
} else {
|
||||
list = new FCollection<GameObject>(game.getCardsIn(getPresentZone()));
|
||||
list = new FCollection<>(game.getCardsIn(getPresentZone()));
|
||||
}
|
||||
|
||||
final int left = Iterables.size(Iterables.filter(list, GameObjectPredicates.restriction(getIsPresent().split(","), activator, c, sa)));
|
||||
|
||||
@@ -214,7 +214,6 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView {
|
||||
public final int getXManaPaid() {
|
||||
return xManaPaid;
|
||||
}
|
||||
|
||||
public final void setXManaPaid(int x) {
|
||||
xManaPaid = x;
|
||||
}
|
||||
@@ -341,7 +340,6 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView {
|
||||
public Player getActivatingPlayer() {
|
||||
return activatingPlayer;
|
||||
}
|
||||
|
||||
public void setActivatingPlayer(Player activatingPlayer0) {
|
||||
if (activatingPlayer == activatingPlayer0) { return; }
|
||||
activatingPlayer = activatingPlayer0;
|
||||
|
||||
@@ -45,6 +45,7 @@ import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.CardTranslation;
|
||||
import forge.util.Expressions;
|
||||
import forge.util.FileSection;
|
||||
import forge.util.Lang;
|
||||
import forge.util.TextUtil;
|
||||
|
||||
@@ -89,41 +90,12 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
|
||||
* @return a {@link java.util.HashMap} object.
|
||||
*/
|
||||
private static Map<String, String> parseParams(final String abString, final Card hostCard) {
|
||||
final Map<String, String> mapParameters = Maps.newHashMap();
|
||||
|
||||
if (!(abString.length() > 0)) {
|
||||
throw new RuntimeException("StaticEffectFactory : getAbility -- abString too short in "
|
||||
+ hostCard.getName() + ": [" + abString + "]");
|
||||
}
|
||||
|
||||
final String[] a = abString.split("\\|");
|
||||
|
||||
for (int aCnt = 0; aCnt < a.length; aCnt++) {
|
||||
a[aCnt] = a[aCnt].trim();
|
||||
}
|
||||
|
||||
if (!(a.length > 0)) {
|
||||
throw new RuntimeException("StaticEffectFactory : getAbility -- a[] too short in " + hostCard.getName());
|
||||
}
|
||||
|
||||
for (final String element : a) {
|
||||
final String[] aa = element.split("\\$");
|
||||
|
||||
for (int aaCnt = 0; aaCnt < aa.length; aaCnt++) {
|
||||
aa[aaCnt] = aa[aaCnt].trim();
|
||||
}
|
||||
|
||||
if (aa.length != 2) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("StaticEffectFactory Parsing Error: Split length of ");
|
||||
sb.append(element).append(" in ").append(hostCard.getName()).append(" is not 2.");
|
||||
throw new RuntimeException(sb.toString());
|
||||
}
|
||||
|
||||
mapParameters.put(aa[0], aa[1]);
|
||||
}
|
||||
|
||||
return mapParameters;
|
||||
return FileSection.parseToMap(abString, FileSection.DOLLAR_SIGN_KV_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -111,12 +111,18 @@ public final class StaticAbilityContinuous {
|
||||
final List<Player> affectedPlayers = StaticAbilityContinuous.getAffectedPlayers(stAb);
|
||||
final Game game = hostCard.getGame();
|
||||
|
||||
final StaticEffect se = game.getStaticEffects().getStaticEffect(stAb);
|
||||
final StaticEffects effects = game.getStaticEffects();
|
||||
final StaticEffect se = effects.getStaticEffect(stAb);
|
||||
se.setAffectedCards(affectedCards);
|
||||
se.setAffectedPlayers(affectedPlayers);
|
||||
se.setParams(params);
|
||||
se.setTimestamp(hostCard.getTimestamp());
|
||||
|
||||
// nothing more to do
|
||||
if (stAb.hasParam("Affected") && affectedPlayers.isEmpty() && affectedCards.isEmpty()) {
|
||||
return affectedCards;
|
||||
}
|
||||
|
||||
String addP = "";
|
||||
int powerBonus = 0;
|
||||
String addT = "";
|
||||
@@ -161,7 +167,6 @@ public final class StaticAbilityContinuous {
|
||||
|
||||
//Global rules changes
|
||||
if (layer == StaticAbilityLayer.RULES && params.containsKey("GlobalRule")) {
|
||||
final StaticEffects effects = game.getStaticEffects();
|
||||
effects.setGlobalRuleChange(GlobalRuleChange.fromString(params.get("GlobalRule")));
|
||||
}
|
||||
|
||||
@@ -197,8 +202,6 @@ public final class StaticAbilityContinuous {
|
||||
// update keywords with Chosen parts
|
||||
final String hostCardUID = Integer.toString(hostCard.getId()); // Protection with "doesn't remove" effect
|
||||
|
||||
final ColorSet colorsYouCtrl = CardUtil.getColorsYouCtrl(controller);
|
||||
|
||||
Iterables.removeIf(addKeywords, new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
@@ -246,6 +249,8 @@ public final class StaticAbilityContinuous {
|
||||
}
|
||||
// two variants for Red vs. red in keyword
|
||||
if (input.contains("ColorsYouCtrl") || input.contains("colorsYouCtrl")) {
|
||||
final ColorSet colorsYouCtrl = CardUtil.getColorsYouCtrl(controller);
|
||||
|
||||
for (byte color : colorsYouCtrl) {
|
||||
final String colorWord = MagicColor.toLongString(color);
|
||||
String y = input.replaceAll("ColorsYouCtrl", StringUtils.capitalize(colorWord));
|
||||
@@ -718,6 +723,7 @@ public final class StaticAbilityContinuous {
|
||||
// add P/T bonus
|
||||
if (layer == StaticAbilityLayer.MODIFYPT) {
|
||||
if (addP.contains("Affected")) {
|
||||
// TODO don't calculate these above if this gets used instead
|
||||
powerBonus = AbilityUtils.calculateAmount(affectedCard, addP, stAb, true);
|
||||
}
|
||||
if (addT.contains("Affected")) {
|
||||
|
||||
@@ -77,10 +77,6 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
|
||||
private List<Object> triggerRemembered = Lists.newArrayList();
|
||||
|
||||
// number of times this trigger was activated this this turn
|
||||
// used to handle once-per-turn triggers like Crawling Sensation
|
||||
private int numberTurnActivations = 0;
|
||||
|
||||
private Set<PhaseType> validPhases;
|
||||
|
||||
private SpellAbility spawningAbility;
|
||||
@@ -388,7 +384,8 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
for (Player opp : this.getHostCard().getController().getOpponents()) {
|
||||
if (opp.equals(attackedP)) {
|
||||
continue;
|
||||
} else if (opp.getLife() > life) {
|
||||
}
|
||||
if (opp.getLife() > life) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -536,16 +533,13 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
}
|
||||
|
||||
public int getActivationsThisTurn() {
|
||||
return this.numberTurnActivations;
|
||||
return hostCard.getAbilityActivatedThisTurn(this.getOverridingAbility());
|
||||
}
|
||||
|
||||
public void triggerRun() {
|
||||
this.numberTurnActivations++;
|
||||
}
|
||||
|
||||
// Resets the state stored each turn for per-turn and per-instance restriction
|
||||
public void resetTurnState() {
|
||||
this.numberTurnActivations = 0;
|
||||
if (this.getOverridingAbility() != null) {
|
||||
hostCard.addAbilityActivated(this.getOverridingAbility());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
||||
@@ -346,15 +346,6 @@ public class TriggerHandler {
|
||||
waitingTriggers.clear();
|
||||
}
|
||||
|
||||
public void resetTurnTriggerState() {
|
||||
for (final Trigger t : activeTriggers) {
|
||||
t.resetTurnState();
|
||||
}
|
||||
for (final Trigger t : delayedTriggers) {
|
||||
t.resetTurnState();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean runNonStaticTriggersForPlayer(final Player player, final TriggerWaiting wt, final List<Trigger> delayedTriggersWorkingCopy) {
|
||||
final TriggerType mode = wt.getMode();
|
||||
final Map<AbilityKey, Object> runParams = wt.getParams();
|
||||
@@ -568,24 +559,11 @@ public class TriggerHandler {
|
||||
sa.setActivatingPlayer(p);
|
||||
}
|
||||
|
||||
if (regtrig.hasParam("RememberController")) {
|
||||
host.addRemembered(sa.getActivatingPlayer());
|
||||
}
|
||||
|
||||
if (regtrig.hasParam("RememberTriggeringCard")) {
|
||||
Card triggeredCard = ((Card) sa.getTriggeringObject(AbilityKey.Card));
|
||||
host.addRemembered(triggeredCard);
|
||||
}
|
||||
|
||||
if (regtrig.hasParam("RememberKey")) {
|
||||
host.addRemembered(runParams.get(AbilityKey.fromString(regtrig.getParam("RememberKey"))));
|
||||
}
|
||||
|
||||
if (regtrig.hasParam("RememberAmount")) {
|
||||
Integer amount = (Integer) sa.getTriggeringObject(AbilityKey.fromString(regtrig.getParam("RememberAmount")));
|
||||
host.addRemembered(amount);
|
||||
}
|
||||
|
||||
sa.setStackDescription(sa.toString());
|
||||
|
||||
Player decider = null;
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package forge.game.trigger;
|
||||
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.util.Localizer;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* TriggerMilledAll class.
|
||||
* </p>
|
||||
*/
|
||||
public class TriggerMilledAll extends Trigger {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for TriggerMilledAll
|
||||
* </p>
|
||||
*
|
||||
* @param params
|
||||
* a {@link java.util.HashMap} object.
|
||||
* @param host
|
||||
* a {@link forge.game.card.Card} object.
|
||||
* @param intrinsic
|
||||
* the intrinsic
|
||||
*/
|
||||
public TriggerMilledAll (final Map<String, String> params, final Card host, final boolean intrinsic) {
|
||||
super(params, host, intrinsic);
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* @param runParams*/
|
||||
@Override
|
||||
public final boolean performTest(final Map<AbilityKey, Object> runParams) {
|
||||
|
||||
if (!matchesValidParam("ValidPlayer", runParams.get(AbilityKey.Player))) {
|
||||
return false;
|
||||
}
|
||||
if (!matchesValidParam("ValidCard", runParams.get(AbilityKey.Cards))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final void setTriggeringObjects(final SpellAbility sa, Map<AbilityKey, Object> runParams) {
|
||||
CardCollection cards = (CardCollection) runParams.get(AbilityKey.Cards);
|
||||
|
||||
if (hasParam("ValidCard")) {
|
||||
cards = CardLists.getValidCards(cards, getParam("ValidCard"), getHostCard().getController(),
|
||||
getHostCard(), this);
|
||||
}
|
||||
|
||||
sa.setTriggeringObject(AbilityKey.Cards, cards);
|
||||
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImportantStackObjects(SpellAbility sa) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(Localizer.getInstance().getMessage("lblPlayer")).append(": ");
|
||||
sb.append(sa.getTriggeringObject(AbilityKey.Player));
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -64,8 +64,7 @@ public class TriggerScry extends Trigger {
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final void setTriggeringObjects(final SpellAbility sa, Map<AbilityKey, Object> runParams) {
|
||||
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Player);
|
||||
sa.setTriggeringObjectsFrom(runParams, AbilityKey.ScryNum);
|
||||
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Player, AbilityKey.ScryNum);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -313,8 +313,7 @@ public class TriggerSpellAbilityCastOrCopy extends Trigger {
|
||||
AbilityKey.Player,
|
||||
AbilityKey.Activator,
|
||||
AbilityKey.CurrentStormCount,
|
||||
AbilityKey.CurrentCastSpells,
|
||||
AbilityKey.CastSACMC
|
||||
AbilityKey.CurrentCastSpells
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ public enum TriggerType {
|
||||
LifeGained(TriggerLifeGained.class),
|
||||
LifeLost(TriggerLifeLost.class),
|
||||
LosesGame(TriggerLosesGame.class),
|
||||
MilledAll(TriggerMilledAll.class),
|
||||
Mutates(TriggerMutates.class),
|
||||
NewGame(TriggerNewGame.class),
|
||||
PayCumulativeUpkeep(TriggerPayCumulativeUpkeep.class),
|
||||
|
||||
@@ -175,21 +175,6 @@ public class WrappedAbility extends Ability {
|
||||
return sa.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getActivatingPlayer() {
|
||||
return sa.getActivatingPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return sa.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManaCost getMultiKickerManaCost() {
|
||||
return sa.getMultiKickerManaCost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAbilityRestriction getRestrictions() {
|
||||
return sa.getRestrictions();
|
||||
@@ -249,14 +234,18 @@ public class WrappedAbility extends Ability {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilitySub getSubAbility() {
|
||||
return sa.getSubAbility();
|
||||
public void setStackDescription(final String s) {
|
||||
sa.setStackDescription(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetRestrictions getTargetRestrictions() {
|
||||
return sa.getTargetRestrictions();
|
||||
}
|
||||
@Override
|
||||
public void setTargetRestrictions(final TargetRestrictions tgt) {
|
||||
sa.setTargetRestrictions(tgt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Card getTargetCard() {
|
||||
@@ -267,6 +256,10 @@ public class WrappedAbility extends Ability {
|
||||
public TargetChoices getTargets() {
|
||||
return sa.getTargets();
|
||||
}
|
||||
@Override
|
||||
public void setTargets(TargetChoices targets) {
|
||||
sa.setTargets(targets);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAbility() {
|
||||
@@ -327,16 +320,28 @@ public class WrappedAbility extends Ability {
|
||||
// sa.resetOnceResolved();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getActivatingPlayer() {
|
||||
return sa.getActivatingPlayer();
|
||||
}
|
||||
@Override
|
||||
public void setActivatingPlayer(final Player player) {
|
||||
sa.setActivatingPlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return sa.getDescription();
|
||||
}
|
||||
@Override
|
||||
public void setDescription(final String s) {
|
||||
sa.setDescription(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManaCost getMultiKickerManaCost() {
|
||||
return sa.getMultiKickerManaCost();
|
||||
}
|
||||
@Override
|
||||
public void setMultiKickerManaCost(final ManaCost cost) {
|
||||
sa.setMultiKickerManaCost(cost);
|
||||
@@ -358,25 +363,14 @@ public class WrappedAbility extends Ability {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStackDescription(final String s) {
|
||||
sa.setStackDescription(s);
|
||||
public AbilitySub getSubAbility() {
|
||||
return sa.getSubAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSubAbility(final AbilitySub subAbility) {
|
||||
sa.setSubAbility(subAbility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargetRestrictions(final TargetRestrictions tgt) {
|
||||
sa.setTargetRestrictions(tgt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargets(TargetChoices targets) {
|
||||
sa.setTargets(targets);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargetCard(final Card card) {
|
||||
sa.setTargetCard(card);
|
||||
|
||||
@@ -41,7 +41,6 @@ import forge.game.GameObject;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.ability.effects.CharmEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardUtil;
|
||||
@@ -72,6 +71,7 @@ import forge.util.TextUtil;
|
||||
*/
|
||||
public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbilityStackInstance> {
|
||||
private final List<SpellAbility> simultaneousStackEntryList = Lists.newArrayList();
|
||||
private final List<SpellAbility> activePlayerSAs = Lists.newArrayList();
|
||||
|
||||
// They don't provide a LIFO queue, so had to use a deque
|
||||
private final Deque<SpellAbilityStackInstance> stack = new LinkedBlockingDeque<>();
|
||||
@@ -308,7 +308,6 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
||||
runParams.put(AbilityKey.Cost, sp.getPayCosts());
|
||||
runParams.put(AbilityKey.Activator, sp.getActivatingPlayer());
|
||||
runParams.put(AbilityKey.CastSA, si.getSpellAbility(true));
|
||||
runParams.put(AbilityKey.CastSACMC, si.getSpellAbility(true).getHostCard().getCMC());
|
||||
runParams.put(AbilityKey.CurrentStormCount, thisTurnCast.size());
|
||||
runParams.put(AbilityKey.CurrentCastSpells, Lists.newArrayList(thisTurnCast));
|
||||
|
||||
@@ -825,38 +824,26 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
||||
return false;
|
||||
}
|
||||
|
||||
final List<SpellAbility> activePlayerSAs = Lists.newArrayList();
|
||||
final List<SpellAbility> failedSAs = Lists.newArrayList();
|
||||
activePlayerSAs.clear();
|
||||
for (int i = 0; i < simultaneousStackEntryList.size(); i++) {
|
||||
SpellAbility sa = simultaneousStackEntryList.get(i);
|
||||
Player activator = sa.getActivatingPlayer();
|
||||
|
||||
if (sa.getApi() == ApiType.Charm) {
|
||||
if (!CharmEffect.makeChoices(sa)) {
|
||||
// 603.3c If no mode is chosen, the ability is removed from the stack.
|
||||
failedSAs.add(sa);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (activator == null) {
|
||||
if (sa.getHostCard().getController().equals(activePlayer)) {
|
||||
activePlayerSAs.add(sa);
|
||||
}
|
||||
} else {
|
||||
if (activator.equals(activePlayer)) {
|
||||
activePlayerSAs.add(sa);
|
||||
}
|
||||
activator = sa.getHostCard().getController();
|
||||
}
|
||||
if (activator.equals(activePlayer)) {
|
||||
activePlayerSAs.add(sa);
|
||||
}
|
||||
}
|
||||
simultaneousStackEntryList.removeAll(activePlayerSAs);
|
||||
simultaneousStackEntryList.removeAll(failedSAs);
|
||||
|
||||
if (activePlayerSAs.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
activePlayer.getController().orderAndPlaySimultaneousSa(activePlayerSAs);
|
||||
activePlayerSAs.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -878,6 +865,12 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (final SpellAbility sa : activePlayerSAs) {
|
||||
if (sa.getSourceTrigger() == triggerID) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -212,8 +212,7 @@ public class GuiChoose {
|
||||
|
||||
if (selected != null) {
|
||||
c.show(selected);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
c.show();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,6 @@ import java.awt.Toolkit;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JPanel;
|
||||
@@ -17,24 +14,17 @@ import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import forge.ImageKeys;
|
||||
import forge.StaticData;
|
||||
import forge.card.CardDb;
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.CardEdition.CardInSet;
|
||||
import forge.gui.SOverlayUtils;
|
||||
import forge.gui.UiCommand;
|
||||
import forge.gui.framework.DragCell;
|
||||
import forge.gui.framework.DragTab;
|
||||
import forge.gui.framework.EDocID;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.PaperToken;
|
||||
import forge.localinstance.properties.ForgeConstants;
|
||||
import forge.localinstance.skin.FSkinProp;
|
||||
import forge.screens.home.EMenuGroup;
|
||||
import forge.screens.home.IVSubmenu;
|
||||
import forge.screens.home.VHomeUI;
|
||||
import forge.token.TokenDb;
|
||||
import forge.toolbox.FButton;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FOverlay;
|
||||
@@ -43,7 +33,6 @@ import forge.toolbox.FScrollPane;
|
||||
import forge.toolbox.FSkin;
|
||||
import forge.toolbox.FTextArea;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.ImageUtil;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.RuntimeVersion;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
@@ -232,17 +221,8 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
||||
* @param scr
|
||||
*/
|
||||
public void auditUpdate(FTextArea tar, FScrollPane scr) {
|
||||
// Get top-level Forge objects
|
||||
CardDb cardDb = StaticData.instance().getCommonCards();
|
||||
CardDb variantDb = StaticData.instance().getVariantCards();
|
||||
TokenDb tokenDb = StaticData.instance().getAllTokens();
|
||||
CardEdition.Collection editions = StaticData.instance().getEditions();
|
||||
|
||||
int missingCount = 0;
|
||||
int notImplementedCount = 0;
|
||||
|
||||
final StringBuffer nifSB = new StringBuffer(); // NO IMAGE FOUND BUFFER
|
||||
final StringBuffer cniSB = new StringBuffer(); // CARD NOT IMPLEMENTED BUFFER
|
||||
StringBuffer nifSB = new StringBuffer(); // NO IMAGE FOUND BUFFER
|
||||
StringBuffer cniSB = new StringBuffer(); // CARD NOT IMPLEMENTED BUFFER
|
||||
|
||||
nifSB.append("\n\n-------------------\n");
|
||||
nifSB.append("NO IMAGE FOUND LIST\n");
|
||||
@@ -252,118 +232,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
||||
cniSB.append("UNIMPLEMENTED CARD LIST\n");
|
||||
cniSB.append("-------------------\n\n");
|
||||
|
||||
for (CardEdition e : editions) {
|
||||
if (CardEdition.Type.FUNNY.equals(e.getType()))
|
||||
continue;
|
||||
boolean nifHeader = false;
|
||||
boolean cniHeader = false;
|
||||
boolean tokenHeader = false;
|
||||
|
||||
String imagePath;
|
||||
int artIndex = 1;
|
||||
|
||||
HashMap<String, Pair<Boolean, Integer>> cardCount = new HashMap<>();
|
||||
for (CardInSet c : e.getAllCardsInSet()) {
|
||||
if (cardCount.containsKey(c.name)) {
|
||||
cardCount.put(c.name, Pair.of(c.collectorNumber.startsWith("F"), cardCount.get(c.name).getRight() + 1));
|
||||
} else {
|
||||
cardCount.put(c.name, Pair.of(c.collectorNumber.startsWith("F"), 1));
|
||||
}
|
||||
}
|
||||
|
||||
// loop through the cards in this edition, considering art variations...
|
||||
for (Entry<String, Pair<Boolean, Integer>> entry : cardCount.entrySet()) {
|
||||
String c = entry.getKey();
|
||||
artIndex = entry.getValue().getRight();
|
||||
|
||||
PaperCard cp = cardDb.getCard(c, e.getCode(), artIndex);
|
||||
if (cp == null) {
|
||||
cp = variantDb.getCard(c, e.getCode(), artIndex);
|
||||
}
|
||||
|
||||
if (cp == null) {
|
||||
if (entry.getValue().getLeft()) //skip funny cards
|
||||
continue;
|
||||
if (!cniHeader) {
|
||||
cniSB.append("Edition: ").append(e.getName()).append(" ").append("(").append(e.getCode()).append("/").append(e.getCode2()).append(")\n");
|
||||
cniHeader = true;
|
||||
}
|
||||
cniSB.append(" ").append(c).append("\n");
|
||||
notImplementedCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check the front image
|
||||
imagePath = ImageUtil.getImageRelativePath(cp, false, true, false);
|
||||
if (imagePath != null) {
|
||||
File file = ImageKeys.getImageFile(imagePath);
|
||||
if (file == null) {
|
||||
if (!nifHeader) {
|
||||
nifSB.append("Edition: ").append(e.getName()).append(" ").append("(").append(e.getCode()).append("/").append(e.getCode2()).append(")\n");
|
||||
nifHeader = true;
|
||||
}
|
||||
nifSB.append(" ").append(imagePath).append("\n");
|
||||
missingCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// check the back face
|
||||
if (cp.hasBackFace()) {
|
||||
imagePath = ImageUtil.getImageRelativePath(cp, true, true, false);
|
||||
if (imagePath != null) {
|
||||
File file = ImageKeys.getImageFile(imagePath);
|
||||
if (file == null) {
|
||||
if (!nifHeader) {
|
||||
nifSB.append("Edition: ").append(e.getName()).append(" ").append("(").append(e.getCode()).append("/").append(e.getCode2()).append(")\n");
|
||||
nifHeader = true;
|
||||
}
|
||||
nifSB.append(" ").append(imagePath).append("\n");
|
||||
missingCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Audit token images here...
|
||||
for(Entry<String, Integer> tokenEntry : e.getTokens().entrySet()) {
|
||||
String name = tokenEntry.getKey();
|
||||
artIndex = tokenEntry.getValue();
|
||||
try {
|
||||
PaperToken token = tokenDb.getToken(name, e.getCode());
|
||||
if (token == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(int i = 0; i < artIndex; i++) {
|
||||
String imgKey = token.getImageKey(i);
|
||||
File file = ImageKeys.getImageFile(imgKey);
|
||||
if (file == null) {
|
||||
if (!nifHeader) {
|
||||
nifSB.append("Edition: ").append(e.getName()).append(" ").append("(").append(e.getCode()).append("/").append(e.getCode2()).append(")\n");
|
||||
nifHeader = true;
|
||||
}
|
||||
if (!tokenHeader) {
|
||||
nifSB.append("\nTOKENS\n");
|
||||
tokenHeader = true;
|
||||
}
|
||||
nifSB.append(" ").append(token.getImageFilename(i + 1)).append("\n");
|
||||
missingCount++;
|
||||
}
|
||||
}
|
||||
} catch(Exception ex) {
|
||||
System.out.println("No Token found: " + name + " in " + e.getName());
|
||||
}
|
||||
}
|
||||
if (nifHeader)
|
||||
nifSB.append("\n");
|
||||
}
|
||||
|
||||
String totalStats = "Missing images: " + missingCount + "\nUnimplemented cards: " + notImplementedCount + "\n";
|
||||
cniSB.append("\n-----------\n");
|
||||
cniSB.append(totalStats);
|
||||
cniSB.append("-----------\n\n");
|
||||
|
||||
nifSB.append(cniSB); // combine things together...
|
||||
Pair<Integer, Integer> totalAudit = StaticData.instance().audit(nifSB, cniSB);
|
||||
|
||||
tar.setText(nifSB.toString());
|
||||
tar.setCaretPosition(0); // this will move scroll view to the top...
|
||||
@@ -378,7 +247,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
||||
});
|
||||
scr.getParent().add(btnClipboardCopy, "w 200!, h pref+12!, center, gaptop 10");
|
||||
|
||||
String labelText = "<html>Missing images: " + missingCount + "<br>Unimplemented cards: " + notImplementedCount + "<br>";
|
||||
String labelText = "<html>Missing images: " + totalAudit.getLeft() + "<br>Unimplemented cards: " + totalAudit.getRight() + "<br>";
|
||||
final FLabel statsLabel = new FLabel.Builder().text(labelText).fontSize(15).build();
|
||||
scr.getParent().add(statsLabel);
|
||||
|
||||
|
||||
@@ -55,9 +55,7 @@ import java.io.File;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Forge implements ApplicationListener {
|
||||
public static final String CURRENT_VERSION = "1.6.53.001";
|
||||
@@ -81,6 +79,7 @@ public class Forge implements ApplicationListener {
|
||||
protected static TransitionScreen transitionScreen;
|
||||
public static KeyInputAdapter keyInputAdapter;
|
||||
private static boolean exited;
|
||||
public boolean needsUpdate = false;
|
||||
public static boolean safeToClose = true;
|
||||
public static boolean magnify = false;
|
||||
public static boolean magnifyToggle = true;
|
||||
@@ -104,15 +103,14 @@ public class Forge implements ApplicationListener {
|
||||
public static boolean enablePreloadExtendedArt = false;
|
||||
public static boolean isTabletDevice = false;
|
||||
public static String locale = "en-US";
|
||||
public Assets cardAssets;
|
||||
public Assets otherAssets;
|
||||
public Assets assets;
|
||||
public static boolean hdbuttons = false;
|
||||
public static boolean hdstart = false;
|
||||
public static boolean isPortraitMode = false;
|
||||
public static boolean gameInProgress = false;
|
||||
public static boolean disposeTextures = false;
|
||||
public static boolean isMobileAdventureMode = false;
|
||||
public static int cacheSize = 400;
|
||||
public static int cacheSize = 300;
|
||||
public static int totalDeviceRAM = 0;
|
||||
public static int androidVersion = 0;
|
||||
public static boolean autoCache = false;
|
||||
@@ -126,7 +124,6 @@ public class Forge implements ApplicationListener {
|
||||
public static boolean forcedEnglishonCJKMissing = false;
|
||||
public static boolean adventureLoaded = false;
|
||||
private static Localizer localizer;
|
||||
static Map<Integer, Texture> misc = new HashMap<>();
|
||||
|
||||
public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0, boolean value, boolean androidOrientation, int totalRAM, boolean isTablet, int AndroidAPI, String AndroidRelease, String deviceName) {
|
||||
app = new Forge();
|
||||
@@ -166,8 +163,7 @@ public class Forge implements ApplicationListener {
|
||||
// don't allow to read and process
|
||||
ForgeConstants.SPRITE_CARDBG_FILE = "";
|
||||
}
|
||||
cardAssets = new Assets();
|
||||
otherAssets = new Assets();
|
||||
assets = new Assets();
|
||||
graphics = new Graphics();
|
||||
splashScreen = new SplashScreen();
|
||||
frameRate = new FrameRate();
|
||||
@@ -212,9 +208,9 @@ public class Forge implements ApplicationListener {
|
||||
CJK_Font = prefs.getPref(FPref.UI_CJK_FONT);
|
||||
|
||||
if (autoCache) {
|
||||
//increase cacheSize for devices with RAM more than 5GB, default is 400. Some phones have more than 10GB RAM (Mi 10, OnePlus 8, S20, etc..)
|
||||
if (totalDeviceRAM > 5000) //devices with more than 10GB RAM will have 800 Cache size, 600 Cache size for morethan 5GB RAM
|
||||
cacheSize = totalDeviceRAM > 10000 ? 800 : 600;
|
||||
//increase cacheSize for devices with RAM more than 5GB, default is 300. Some phones have more than 10GB RAM (Mi 10, OnePlus 8, S20, etc..)
|
||||
if (totalDeviceRAM > 5000) //devices with more than 10GB RAM will have 600 Cache size, 400 Cache size for morethan 5GB RAM
|
||||
cacheSize = totalDeviceRAM > 10000 ? 600 : 400;
|
||||
}
|
||||
//init cache
|
||||
ImageCache.initCache(cacheSize);
|
||||
@@ -345,22 +341,6 @@ public class Forge implements ApplicationListener {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public static Texture getTitleBG() {
|
||||
if (misc.get(0) == null) {
|
||||
misc.put(0, new Texture(GuiBase.isAndroid()
|
||||
? Gdx.files.internal("fallback_skin").child("title_bg_lq.png")
|
||||
: Gdx.files.classpath("fallback_skin").child("title_bg_lq.png")));
|
||||
}
|
||||
return misc.get(0);
|
||||
}
|
||||
public static Texture getTransitionBG() {
|
||||
if (misc.get(1) == null) {
|
||||
misc.put(1, new Texture(GuiBase.isAndroid()
|
||||
? Gdx.files.internal("fallback_skin").child("transition.png")
|
||||
: Gdx.files.classpath("fallback_skin").child("transition.png")));
|
||||
}
|
||||
return misc.get(1);
|
||||
}
|
||||
protected void afterDbLoaded() {
|
||||
destroyThis = false; //Allow back()
|
||||
Gdx.input.setCatchKey(Keys.MENU, true);
|
||||
@@ -801,7 +781,7 @@ public class Forge implements ApplicationListener {
|
||||
@Override
|
||||
public void render() {
|
||||
if (showFPS)
|
||||
frameRate.update();
|
||||
frameRate.update(ImageCache.counter, Forge.getAssets().manager().getMemoryInMegabytes());
|
||||
|
||||
try {
|
||||
ImageCache.allowSingleLoad();
|
||||
@@ -837,8 +817,8 @@ public class Forge implements ApplicationListener {
|
||||
animationBatch.setColor(1, 1, 1, 1);
|
||||
animationBatch.draw(lastScreenTexture, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
animationBatch.setColor(1, 1, 1, 1 - (1 / transitionTime) * animationTimeout);
|
||||
animationBatch.draw(getTransitionBG(), 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
animationBatch.draw(getTransitionBG(), 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
animationBatch.draw(getAssets().fallback_skins().get(1), 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
animationBatch.draw(getAssets().fallback_skins().get(1), 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
animationBatch.end();
|
||||
if (animationTimeout < 0) {
|
||||
currentScene.render();
|
||||
@@ -857,8 +837,8 @@ public class Forge implements ApplicationListener {
|
||||
animationBatch.setColor(1, 1, 1, 1);
|
||||
animationBatch.draw(lastScreenTexture, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
animationBatch.setColor(1, 1, 1, (1 / transitionTime) * (animationTimeout + transitionTime));
|
||||
animationBatch.draw(getTransitionBG(), 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
animationBatch.draw(getTransitionBG(), 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
animationBatch.draw(getAssets().fallback_skins().get(1), 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
animationBatch.draw(getAssets().fallback_skins().get(1), 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
animationBatch.end();
|
||||
return;
|
||||
}
|
||||
@@ -896,6 +876,11 @@ public class Forge implements ApplicationListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
//update here
|
||||
if (needsUpdate) {
|
||||
if (getAssets().manager().update())
|
||||
needsUpdate = false;
|
||||
}
|
||||
graphics.end();
|
||||
} catch (Exception ex) {
|
||||
graphics.end();
|
||||
@@ -942,6 +927,15 @@ public class Forge implements ApplicationListener {
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
try {
|
||||
Texture.setAssetManager(getAssets().manager());
|
||||
needsUpdate = true;
|
||||
} catch (Exception e) {
|
||||
//the application context must have been recreated from its last state.
|
||||
//it could be triggered by the low memory on heap on android.
|
||||
needsUpdate = false;
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (MatchController.getHostedMatch() != null) {
|
||||
MatchController.getHostedMatch().resume();
|
||||
}
|
||||
@@ -954,8 +948,7 @@ public class Forge implements ApplicationListener {
|
||||
currentScreen.onClose(null);
|
||||
currentScreen = null;
|
||||
}
|
||||
cardAssets.dispose();
|
||||
otherAssets.dispose();
|
||||
assets.dispose();
|
||||
Dscreens.clear();
|
||||
graphics.dispose();
|
||||
SoundSystem.instance.dispose();
|
||||
@@ -967,11 +960,8 @@ public class Forge implements ApplicationListener {
|
||||
/** Retrieve assets.
|
||||
* @param other if set to true returns otherAssets otherwise returns cardAssets
|
||||
*/
|
||||
public static Assets getAssets(boolean other) {
|
||||
if (other)
|
||||
return ((Forge)Gdx.app.getApplicationListener()).otherAssets;
|
||||
else
|
||||
return ((Forge)Gdx.app.getApplicationListener()).cardAssets;
|
||||
public static Assets getAssets() {
|
||||
return ((Forge)Gdx.app.getApplicationListener()).assets;
|
||||
}
|
||||
public static boolean switchScene(Scene newScene) {
|
||||
if (currentScene != null) {
|
||||
|
||||
@@ -16,6 +16,8 @@ import com.badlogic.gdx.utils.TimeUtils;
|
||||
|
||||
public class FrameRate implements Disposable{
|
||||
long lastTimeCounted;
|
||||
int cardsLoaded = 0;
|
||||
int allocT = 0;
|
||||
private float sinceChange;
|
||||
private float frameRate;
|
||||
private BitmapFont font;
|
||||
@@ -38,7 +40,10 @@ public class FrameRate implements Disposable{
|
||||
batch.setProjectionMatrix(cam.combined);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
public void update(int loadedCardSize, float toAlloc) {
|
||||
if (toAlloc > 300f)
|
||||
allocT = (int) toAlloc;
|
||||
cardsLoaded = loadedCardSize;
|
||||
long delta = TimeUtils.timeSinceMillis(lastTimeCounted);
|
||||
lastTimeCounted = TimeUtils.millis();
|
||||
sinceChange += delta;
|
||||
@@ -50,7 +55,7 @@ public class FrameRate implements Disposable{
|
||||
|
||||
public void render() {
|
||||
batch.begin();
|
||||
font.draw(batch, (int)frameRate + " fps", 3, Gdx.graphics.getHeight() - 3);
|
||||
font.draw(batch, (int)frameRate + " FPS | " + cardsLoaded + " cards re/loaded - " + allocT + " vMem", 3, Gdx.graphics.getHeight() - 3);
|
||||
batch.end();
|
||||
}
|
||||
|
||||
|
||||
@@ -661,8 +661,10 @@ public class Graphics {
|
||||
drawRoundRect(2f, borderLining(borderColor.toString()), x, y, w, h, (h-w)/12);
|
||||
fillRoundRect(tintColor, x, y, w, h, (h-w)/12);
|
||||
} else {
|
||||
image.draw(this, x, y, w, h);
|
||||
fillRoundRect(borderColor, x, y, w, h, (h-w)/10);//show corners edges
|
||||
if (image != null) {
|
||||
image.draw(this, x, y, w, h);
|
||||
fillRoundRect(borderColor, x, y, w, h, (h - w) / 10);//show corners edges
|
||||
}
|
||||
}
|
||||
setAlphaComposite(oldalpha);
|
||||
}
|
||||
@@ -672,10 +674,14 @@ public class Graphics {
|
||||
setAlphaComposite(oldalpha);
|
||||
}
|
||||
public void drawImage(FImage image, Color borderColor, float x, float y, float w, float h) {
|
||||
if (image == null)
|
||||
return;
|
||||
image.draw(this, x, y, w, h);
|
||||
fillRoundRect(borderColor, x+1, y+1, w-1.5f, h-1.5f, (h-w)/10);//used by zoom let some edges show...
|
||||
}
|
||||
public void drawAvatarImage(FImage image, float x, float y, float w, float h, boolean drawGrayscale) {
|
||||
if (image == null)
|
||||
return;
|
||||
if (!drawGrayscale) {
|
||||
image.draw(this, x, y, w, h);
|
||||
} else {
|
||||
@@ -693,6 +699,8 @@ public class Graphics {
|
||||
}
|
||||
}
|
||||
public void drawCardImage(FImage image, TextureRegion damage_overlay, float x, float y, float w, float h, boolean drawGrayscale, boolean damaged) {
|
||||
if (image == null)
|
||||
return;
|
||||
if (!drawGrayscale) {
|
||||
image.draw(this, x, y, w, h);
|
||||
if (damage_overlay != null && damaged)
|
||||
@@ -752,6 +760,8 @@ public class Graphics {
|
||||
}
|
||||
}
|
||||
public void drawGrayTransitionImage(FImage image, float x, float y, float w, float h, boolean withDarkOverlay, float percentage) {
|
||||
if (image == null)
|
||||
return;
|
||||
batch.end();
|
||||
shaderGrayscale.bind();
|
||||
shaderGrayscale.setUniformf("u_grayness", percentage);
|
||||
@@ -839,6 +849,8 @@ public class Graphics {
|
||||
batch.begin();
|
||||
}
|
||||
public void drawWarpImage(FImage image, float x, float y, float w, float h, float time) {
|
||||
if (image == null)
|
||||
return;
|
||||
batch.end();
|
||||
shaderWarp.bind();
|
||||
shaderWarp.setUniformf("u_amount", 0.2f);
|
||||
@@ -854,6 +866,8 @@ public class Graphics {
|
||||
batch.begin();
|
||||
}
|
||||
public void drawUnderWaterImage(FImage image, float x, float y, float w, float h, float time, boolean withDarkOverlay) {
|
||||
if (image == null)
|
||||
return;
|
||||
batch.end();
|
||||
shaderUnderwater.bind();
|
||||
shaderUnderwater.setUniformf("u_amount", 10f*time);
|
||||
@@ -893,6 +907,8 @@ public class Graphics {
|
||||
drawImage(image, x, y, w, h, false);
|
||||
}
|
||||
public void drawImage(FImage image, float x, float y, float w, float h, boolean withDarkOverlay) {
|
||||
if (image == null)
|
||||
return;
|
||||
image.draw(this, x, y, w, h);
|
||||
if(withDarkOverlay){
|
||||
float oldalpha = alphaComposite;
|
||||
|
||||
@@ -8,7 +8,6 @@ import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.google.common.base.Predicates;
|
||||
import forge.Forge;
|
||||
import forge.adventure.data.DialogData;
|
||||
import forge.adventure.data.EffectData;
|
||||
@@ -19,8 +18,6 @@ import forge.adventure.util.Current;
|
||||
import forge.adventure.util.MapDialog;
|
||||
import forge.adventure.util.Reward;
|
||||
import forge.card.CardRarity;
|
||||
import forge.card.CardRulesPredicates;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.item.PaperCard;
|
||||
import forge.util.Aggregates;
|
||||
@@ -106,10 +103,11 @@ public class EnemySprite extends CharacterSprite {
|
||||
ret.add(new Reward(Reward.Type.Life, 1));
|
||||
} else {
|
||||
if(data.rewards != null) { //Collect standard rewards.
|
||||
Deck enemyDeck = Current.latestDeck(); // By popular demand, remove basic lands from the reward pool.
|
||||
CardPool deckNoBasicLands = enemyDeck.getMain().getFilteredPool(Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND), PaperCard.FN_GET_RULES));
|
||||
Deck enemyDeck = Current.latestDeck();
|
||||
/*// By popular demand, remove basic lands from the reward pool.
|
||||
CardPool deckNoBasicLands = enemyDeck.getMain().getFilteredPool(Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND), PaperCard.FN_GET_RULES));*/
|
||||
for (RewardData rdata : data.rewards) {
|
||||
ret.addAll(rdata.generate(false, deckNoBasicLands.toFlatList() ));
|
||||
ret.addAll(rdata.generate(false, enemyDeck == null ? null : enemyDeck.getMain().toFlatList() ));
|
||||
}
|
||||
}
|
||||
if(rewards != null) { //Collect additional rewards.
|
||||
|
||||
@@ -457,7 +457,8 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
||||
onLifeTotalChangeList.emit();
|
||||
}
|
||||
public void defeated() {
|
||||
gold=gold/2;
|
||||
int percentLoss = 10;
|
||||
gold=gold-(gold*percentLoss/100);
|
||||
life=Math.max(1,(int)(life-(maxLife*0.2f)));
|
||||
onLifeTotalChangeList.emit();
|
||||
onGoldChangeList.emit();
|
||||
|
||||
@@ -177,7 +177,17 @@ public class SaveLoadScene extends UIScene {
|
||||
updateFiles();
|
||||
//ensure the dialog is hidden before switching
|
||||
dialog.getColor().a = 0f;
|
||||
Forge.switchScene(SceneType.GameScene.instance);
|
||||
|
||||
Scene restoreScene = Forge.switchToLast();
|
||||
if (restoreScene != null) {
|
||||
restoreScene = Forge.switchToLast();
|
||||
}
|
||||
|
||||
if (restoreScene == null) {
|
||||
restoreScene = SceneType.GameScene.instance;
|
||||
}
|
||||
|
||||
Forge.switchScene(restoreScene);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,8 @@ public class SettingsScene extends UIScene {
|
||||
Label label = Controls.newLabel(name);
|
||||
label.setWrap(true);
|
||||
settingGroup.row().space(5);
|
||||
settingGroup.add(label).align(Align.left).pad(2, 2, 2, 5).width(100).expand();
|
||||
int w = Forge.isLandscapeMode() ? 160 : 80;
|
||||
settingGroup.add(label).align(Align.left).pad(2, 2, 2, 5).width(w).expand();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -83,8 +83,10 @@ public class StartScene extends UIScene {
|
||||
@Override
|
||||
public void enter() {
|
||||
boolean hasSaveButton = WorldSave.getCurrentSave().getWorld().getData() != null;
|
||||
if (hasSaveButton)
|
||||
hasSaveButton = !((TileMapScene) SceneType.TileMapScene.instance).currentMap().isInMap();
|
||||
if (hasSaveButton) {
|
||||
TileMapScene scene = (TileMapScene) SceneType.TileMapScene.instance;
|
||||
hasSaveButton = !scene.currentMap().isInMap() || scene.inTown();
|
||||
}
|
||||
saveButton.setVisible(hasSaveButton);
|
||||
|
||||
boolean hasResumeButton = WorldSave.getCurrentSave().getWorld().getData() != null;
|
||||
|
||||
@@ -92,6 +92,10 @@ public class TileMapScene extends HudScene {
|
||||
tiledMapRenderer.loadMap(map, "");
|
||||
}
|
||||
|
||||
public boolean inTown() {
|
||||
return "town".equalsIgnoreCase(rootPoint.getData().type);
|
||||
}
|
||||
|
||||
PointOfInterest rootPoint;
|
||||
String oldMap;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.badlogic.gdx.Input;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage;
|
||||
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Image;
|
||||
@@ -192,7 +193,8 @@ public class GameHUD extends Stage {
|
||||
}
|
||||
//auto follow touchpad
|
||||
if (GuiBase.isAndroid() && !MapStage.getInstance().getDialogOnlyInput() && !console.isVisible()) {
|
||||
if (!(Controls.actorContainsVector(miniMap,touch)) // not inside map bounds
|
||||
if (!(Controls.actorContainsVector(avatar,touch)) // not inside avatar bounds
|
||||
&& !(Controls.actorContainsVector(miniMap,touch)) // not inside map bounds
|
||||
&& !(Controls.actorContainsVector(gamehud,touch)) //not inside gamehud bounds
|
||||
&& !(Controls.actorContainsVector(menuActor,touch)) //not inside menu button
|
||||
&& !(Controls.actorContainsVector(deckActor,touch)) //not inside deck button
|
||||
@@ -251,23 +253,25 @@ public class GameHUD extends Stage {
|
||||
mapborder.setVisible(visible);
|
||||
miniMapPlayer.setVisible(visible);
|
||||
gamehud.setVisible(visible);
|
||||
avatarborder.setVisible(visible);
|
||||
avatar.setVisible(visible);
|
||||
lifePoints.setVisible(visible);
|
||||
money.setVisible(visible);
|
||||
blank.setVisible(visible);
|
||||
if (visible) {
|
||||
avatarborder.getColor().a = 1f;
|
||||
avatar.getColor().a = 1f;
|
||||
deckActor.getColor().a = 1f;
|
||||
menuActor.getColor().a = 1f;
|
||||
statsActor.getColor().a = 1f;
|
||||
inventoryActor.getColor().a = 1f;
|
||||
opacity = 1f;
|
||||
} else {
|
||||
deckActor.getColor().a = 0.5f;
|
||||
menuActor.getColor().a = 0.5f;
|
||||
statsActor.getColor().a = 0.5f;
|
||||
inventoryActor.getColor().a = 0.5f;
|
||||
opacity = 0.5f;
|
||||
avatarborder.getColor().a = 0.4f;
|
||||
avatar.getColor().a = 0.4f;
|
||||
deckActor.getColor().a = 0.4f;
|
||||
menuActor.getColor().a = 0.4f;
|
||||
statsActor.getColor().a = 0.4f;
|
||||
inventoryActor.getColor().a = 0.4f;
|
||||
opacity = 0.4f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,7 +321,7 @@ public class GameHUD extends Stage {
|
||||
}
|
||||
class ConsoleToggleListener extends ActorGestureListener {
|
||||
public ConsoleToggleListener() {
|
||||
getGestureDetector().setLongPressSeconds(0.5f);
|
||||
getGestureDetector().setLongPressSeconds(0.6f);
|
||||
}
|
||||
@Override
|
||||
public boolean longPress(Actor actor, float x, float y) {
|
||||
@@ -325,5 +329,12 @@ public class GameHUD extends Stage {
|
||||
console.toggle();
|
||||
return super.longPress(actor, x, y);
|
||||
}
|
||||
@Override
|
||||
public void tap(InputEvent event, float x, float y, int count, int button) {
|
||||
super.tap(event, x, y, count, button);
|
||||
//show menu buttons if double tapping the avatar, for android devices without visible navigation buttons
|
||||
if (count > 1)
|
||||
showButtons();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.Image;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import com.badlogic.gdx.utils.Scaling;
|
||||
import forge.Forge;
|
||||
import forge.adventure.character.*;
|
||||
@@ -43,6 +42,7 @@ import forge.sound.SoundEffectType;
|
||||
import forge.sound.SoundSystem;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static forge.adventure.util.Paths.MANA_ATLAS;
|
||||
@@ -69,7 +69,7 @@ public class MapStage extends GameStage {
|
||||
private final Vector2 oldPosition3 = new Vector2();
|
||||
private final Vector2 oldPosition4 = new Vector2();
|
||||
private boolean isLoadingMatch = false;
|
||||
private ObjectMap<String, Byte> mapFlags = new ObjectMap<>(); //Stores local map flags. These aren't available outside this map.
|
||||
private HashMap<String, Byte> mapFlags = new HashMap<>(); //Stores local map flags. These aren't available outside this map.
|
||||
|
||||
private Dialog dialog;
|
||||
private Stage dialogStage;
|
||||
|
||||
@@ -120,11 +120,11 @@ public class Config {
|
||||
|
||||
public TextureAtlas getAtlas(String spriteAtlas) {
|
||||
String fileName = getFile(spriteAtlas).path();
|
||||
if (!Forge.getAssets(true).manager.contains(fileName, TextureAtlas.class)) {
|
||||
Forge.getAssets(true).manager.load(fileName, TextureAtlas.class);
|
||||
Forge.getAssets(true).manager.finishLoadingAsset(fileName);
|
||||
if (!Forge.getAssets().manager().contains(fileName, TextureAtlas.class)) {
|
||||
Forge.getAssets().manager().load(fileName, TextureAtlas.class);
|
||||
Forge.getAssets().manager().finishLoadingAsset(fileName);
|
||||
}
|
||||
return Forge.getAssets(true).manager.get(fileName);
|
||||
return Forge.getAssets().manager().get(fileName);
|
||||
}
|
||||
public SettingData getSettingData()
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.*;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import forge.Forge;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -18,15 +19,10 @@ import java.util.function.Function;
|
||||
* Class to create ui elements in the correct style
|
||||
*/
|
||||
public class Controls {
|
||||
private static Skin SelectedSkin = null;
|
||||
private static BitmapFont defaultfont, bigfont;
|
||||
|
||||
static public TextButton newTextButton(String text) {
|
||||
|
||||
return new TextButton(text, GetSkin());
|
||||
}
|
||||
static public Rectangle getBoundingRect(Actor actor) {
|
||||
|
||||
return new Rectangle(actor.getX(),actor.getY(),actor.getWidth(),actor.getHeight());
|
||||
}
|
||||
static public boolean actorContainsVector (Actor actor, Vector2 point) {
|
||||
@@ -56,8 +52,6 @@ public class Controls {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static public TextField newTextField(String text) {
|
||||
return new TextField(text, GetSkin());
|
||||
}
|
||||
@@ -108,32 +102,28 @@ public class Controls {
|
||||
switch (fontName) {
|
||||
case "blackbig":
|
||||
case "big":
|
||||
return bigfont;
|
||||
return Forge.getAssets().advBigFont;
|
||||
default:
|
||||
return defaultfont;
|
||||
return Forge.getAssets().advDefaultFont;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public Skin GetSkin() {
|
||||
|
||||
if (SelectedSkin == null) {
|
||||
SelectedSkin = new Skin();
|
||||
|
||||
if (Forge.getAssets().skin == null) {
|
||||
Forge.getAssets().skin = new Skin();
|
||||
FileHandle skinFile = Config.instance().getFile(Paths.SKIN);
|
||||
FileHandle atlasFile = skinFile.sibling(skinFile.nameWithoutExtension() + ".atlas");
|
||||
TextureAtlas atlas = new TextureAtlas(atlasFile);
|
||||
//font
|
||||
defaultfont = new BitmapFont(Config.instance().getFile(Paths.SKIN).sibling("LanaPixel.fnt"));
|
||||
bigfont = new BitmapFont(Config.instance().getFile(Paths.SKIN).sibling("LanaPixel.fnt"));
|
||||
bigfont.getData().setScale(2, 2);
|
||||
SelectedSkin.add("default", defaultfont);
|
||||
SelectedSkin.add("big", bigfont);
|
||||
SelectedSkin.addRegions(atlas);
|
||||
SelectedSkin.load(skinFile);
|
||||
|
||||
Forge.getAssets().advDefaultFont = new BitmapFont(Config.instance().getFile(Paths.SKIN).sibling("LanaPixel.fnt"));
|
||||
Forge.getAssets().advBigFont = new BitmapFont(Config.instance().getFile(Paths.SKIN).sibling("LanaPixel.fnt"));
|
||||
Forge.getAssets().advBigFont.getData().setScale(2, 2);
|
||||
Forge.getAssets().skin.add("default", Forge.getAssets().advDefaultFont);
|
||||
Forge.getAssets().skin.add("big", Forge.getAssets().advBigFont);
|
||||
Forge.getAssets().skin.addRegions(atlas);
|
||||
Forge.getAssets().skin.load(skinFile);
|
||||
}
|
||||
return SelectedSkin;
|
||||
return Forge.getAssets().skin;
|
||||
}
|
||||
|
||||
public static Label newLabel(String name) {
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import com.badlogic.gdx.utils.SerializationException;
|
||||
import com.badlogic.gdx.utils.XmlReader;
|
||||
import forge.Forge;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -34,17 +35,15 @@ public class TemplateTmxMapLoader extends TmxMapLoader {
|
||||
|
||||
this.root = xml.parse(tmxFile);
|
||||
|
||||
ObjectMap<String, Texture> textures = new ObjectMap<String, Texture>();
|
||||
|
||||
final Array<FileHandle> textureFiles = getDependencyFileHandles(tmxFile);
|
||||
for (FileHandle textureFile : textureFiles) {
|
||||
Texture texture = new Texture(textureFile, parameter.generateMipMaps);
|
||||
texture.setFilter(parameter.textureMinFilter, parameter.textureMagFilter);
|
||||
textures.put(textureFile.path(), texture);
|
||||
Forge.getAssets().tmxMap().put(textureFile.path(), texture);
|
||||
}
|
||||
|
||||
TiledMap map = loadTiledMap(tmxFile, parameter, new ImageResolver.DirectImageResolver(textures));
|
||||
map.setOwnedResources(textures.values().toArray());
|
||||
TiledMap map = loadTiledMap(tmxFile, parameter, new ImageResolver.DirectImageResolver(Forge.getAssets().tmxMap()));
|
||||
map.setOwnedResources(Forge.getAssets().tmxMap().values().toArray());
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,234 @@
|
||||
package forge.assets;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.assets.AssetLoaderParameters;
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.assets.loaders.FileHandleResolver;
|
||||
import com.badlogic.gdx.assets.loaders.TextureLoader;
|
||||
import com.badlogic.gdx.assets.loaders.resolvers.AbsoluteFileHandleResolver;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.TextureData;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
import com.badlogic.gdx.utils.Disposable;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import forge.Forge;
|
||||
import forge.gui.GuiBase;
|
||||
import forge.localinstance.skin.FSkinProp;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Assets implements Disposable {
|
||||
public AssetManager manager = new AssetManager(new AbsoluteFileHandleResolver());
|
||||
private MemoryTrackingAssetManager manager = new MemoryTrackingAssetManager(new AbsoluteFileHandleResolver());
|
||||
private HashMap<Integer, FSkinFont> fonts = new HashMap<>();
|
||||
private HashMap<String, FImageComplex> cardArtCache = new HashMap<>(1024);
|
||||
private HashMap<String, FImage> avatarImages = new HashMap<>();
|
||||
private HashMap<String, FSkinImage> manaImages = new HashMap<>(128);
|
||||
private HashMap<String, FSkinImage> symbolLookup = new HashMap<>(64);
|
||||
private HashMap<FSkinProp, FSkinImage> images = new HashMap<>(512);
|
||||
private HashMap<Integer, TextureRegion> avatars = new HashMap<>(150);
|
||||
private HashMap<Integer, TextureRegion> sleeves = new HashMap<>(64);
|
||||
private HashMap<Integer, TextureRegion> cracks = new HashMap<>(16);
|
||||
private HashMap<Integer, TextureRegion> borders = new HashMap<>();
|
||||
private HashMap<Integer, TextureRegion> deckbox = new HashMap<>();
|
||||
private HashMap<Integer, TextureRegion> cursor = new HashMap<>();
|
||||
private ObjectMap<Integer, BitmapFont> counterFonts = new ObjectMap<>();
|
||||
private ObjectMap<String, Texture> generatedCards = new ObjectMap<>(512);
|
||||
private ObjectMap<Integer, Texture> fallback_skins = new ObjectMap<>();
|
||||
private ObjectMap<String, Texture> tmxMap = new ObjectMap<>();
|
||||
public Skin skin;
|
||||
public BitmapFont advDefaultFont, advBigFont;
|
||||
public Assets() {
|
||||
//init titlebg fallback
|
||||
fallback_skins.put(0, new Texture(GuiBase.isAndroid()
|
||||
? Gdx.files.internal("fallback_skin").child("title_bg_lq.png")
|
||||
: Gdx.files.classpath("fallback_skin").child("title_bg_lq.png")));
|
||||
//init transition fallback
|
||||
fallback_skins.put(1, new Texture(GuiBase.isAndroid()
|
||||
? Gdx.files.internal("fallback_skin").child("transition.png")
|
||||
: Gdx.files.classpath("fallback_skin").child("transition.png")));
|
||||
}
|
||||
@Override
|
||||
public void dispose() {
|
||||
manager.dispose();
|
||||
for (BitmapFont bitmapFont : counterFonts.values())
|
||||
bitmapFont.dispose();
|
||||
for (Texture texture : generatedCards.values())
|
||||
texture.dispose();
|
||||
for (FSkinFont fSkinFont : fonts.values())
|
||||
fSkinFont.font.dispose();
|
||||
for (Texture texture : fallback_skins.values())
|
||||
texture.dispose();
|
||||
for (Texture texture : tmxMap.values())
|
||||
texture.dispose();
|
||||
if (advDefaultFont != null)
|
||||
advDefaultFont.dispose();
|
||||
if (advBigFont != null)
|
||||
advBigFont.dispose();
|
||||
if (skin != null)
|
||||
skin.dispose();
|
||||
}
|
||||
public MemoryTrackingAssetManager manager() {
|
||||
if (manager == null)
|
||||
manager = new MemoryTrackingAssetManager(new AbsoluteFileHandleResolver());
|
||||
return manager;
|
||||
}
|
||||
public HashMap<Integer, FSkinFont> fonts() {
|
||||
if (fonts == null)
|
||||
fonts = new HashMap<>();
|
||||
return fonts;
|
||||
}
|
||||
public HashMap<String, FImageComplex> cardArtCache() {
|
||||
if (cardArtCache == null)
|
||||
cardArtCache = new HashMap<>(1024);
|
||||
return cardArtCache;
|
||||
}
|
||||
public HashMap<String, FImage> avatarImages() {
|
||||
if (avatarImages == null)
|
||||
avatarImages = new HashMap<>();
|
||||
return avatarImages;
|
||||
}
|
||||
public HashMap<String, FSkinImage> manaImages() {
|
||||
if (manaImages == null)
|
||||
manaImages = new HashMap<>(128);
|
||||
return manaImages;
|
||||
}
|
||||
public HashMap<String, FSkinImage> symbolLookup() {
|
||||
if (symbolLookup == null)
|
||||
symbolLookup = new HashMap<>(64);
|
||||
return symbolLookup;
|
||||
}
|
||||
public HashMap<FSkinProp, FSkinImage> images() {
|
||||
if (images == null)
|
||||
images = new HashMap<>(512);
|
||||
return images;
|
||||
}
|
||||
public HashMap<Integer, TextureRegion> avatars() {
|
||||
if (avatars == null)
|
||||
avatars = new HashMap<>(150);
|
||||
return avatars;
|
||||
}
|
||||
public HashMap<Integer, TextureRegion> sleeves() {
|
||||
if (sleeves == null)
|
||||
sleeves = new HashMap<>(64);
|
||||
return sleeves;
|
||||
}
|
||||
public HashMap<Integer, TextureRegion> cracks() {
|
||||
if (cracks == null)
|
||||
cracks = new HashMap<>(16);
|
||||
return cracks;
|
||||
}
|
||||
public HashMap<Integer, TextureRegion> borders() {
|
||||
if (borders == null)
|
||||
borders = new HashMap<>();
|
||||
return borders;
|
||||
}
|
||||
public HashMap<Integer, TextureRegion> deckbox() {
|
||||
if (deckbox == null)
|
||||
deckbox = new HashMap<>();
|
||||
return deckbox;
|
||||
}
|
||||
public HashMap<Integer, TextureRegion> cursor() {
|
||||
if (cursor == null)
|
||||
cursor = new HashMap<>();
|
||||
return cursor;
|
||||
}
|
||||
public ObjectMap<Integer, BitmapFont> counterFonts() {
|
||||
if (counterFonts == null)
|
||||
counterFonts = new ObjectMap<>();
|
||||
return counterFonts;
|
||||
}
|
||||
public ObjectMap<String, Texture> generatedCards() {
|
||||
if (generatedCards == null)
|
||||
generatedCards = new ObjectMap<>(512);
|
||||
return generatedCards;
|
||||
}
|
||||
public ObjectMap<Integer, Texture> fallback_skins() {
|
||||
if (fallback_skins == null)
|
||||
fallback_skins = new ObjectMap<>();
|
||||
return fallback_skins;
|
||||
}
|
||||
public ObjectMap<String, Texture> tmxMap() {
|
||||
if (tmxMap == null)
|
||||
tmxMap = new ObjectMap<>();
|
||||
return tmxMap;
|
||||
}
|
||||
public class MemoryTrackingAssetManager extends AssetManager {
|
||||
private int currentMemory;
|
||||
private Map<String, Integer> memoryPerFile;
|
||||
|
||||
public MemoryTrackingAssetManager(FileHandleResolver resolver) {
|
||||
super(resolver);
|
||||
|
||||
currentMemory = 0;
|
||||
memoryPerFile = new HashMap<String, Integer>();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private int calculateTextureSize(AssetManager assetManager, String fileName, Class type) {
|
||||
if (memoryPerFile.containsKey(fileName)) {
|
||||
return memoryPerFile.get(fileName);
|
||||
}
|
||||
|
||||
Texture texture = (Texture) assetManager.get(fileName, type);
|
||||
TextureData textureData = texture.getTextureData();
|
||||
int textureSize = textureData.getWidth() * textureData.getHeight();
|
||||
if (Forge.isTextureFilteringEnabled())
|
||||
textureSize = textureSize + (textureSize/3);
|
||||
switch (textureData.getFormat()) {
|
||||
case RGB565:
|
||||
textureSize *= 2;
|
||||
break;
|
||||
case RGB888:
|
||||
textureSize *= 3;
|
||||
break;
|
||||
case RGBA4444:
|
||||
textureSize *= 2;
|
||||
break;
|
||||
case RGBA8888:
|
||||
textureSize *= 4;
|
||||
break;
|
||||
}
|
||||
|
||||
memoryPerFile.put(fileName, textureSize);
|
||||
|
||||
return textureSize;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public synchronized <T> void load(String fileName, Class<T> type, AssetLoaderParameters<T> parameter) {
|
||||
if (type.equals(Texture.class)) {
|
||||
if (parameter == null) {
|
||||
parameter = (AssetLoaderParameters<T>) new TextureLoader.TextureParameter();
|
||||
}
|
||||
|
||||
final AssetLoaderParameters.LoadedCallback prevCallback = parameter.loadedCallback;
|
||||
parameter.loadedCallback = (assetManager, fileName1, type1) -> {
|
||||
if (prevCallback != null) {
|
||||
prevCallback.finishedLoading(assetManager, fileName1, type1);
|
||||
}
|
||||
|
||||
currentMemory += calculateTextureSize(assetManager, fileName1, type1);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
super.load(fileName, type, parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void unload(String fileName) {
|
||||
super.unload(fileName);
|
||||
if (memoryPerFile.containsKey(fileName)) {
|
||||
currentMemory -= memoryPerFile.get(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
public float getMemoryInMegabytes() {
|
||||
return (float) currentMemory / 1024f / 1024f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,18 +25,9 @@ import forge.screens.TransitionScreen;
|
||||
import forge.toolbox.FProgressBar;
|
||||
import forge.util.WordUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class FSkin {
|
||||
private static final Map<FSkinProp, FSkinImage> images = new HashMap<>(512);
|
||||
private static final Map<Integer, TextureRegion> avatars = new HashMap<>(150);
|
||||
private static final Map<Integer, TextureRegion> sleeves = new HashMap<>(64);
|
||||
private static final Map<Integer, TextureRegion> cracks = new HashMap<>(16);
|
||||
private static final Map<Integer, TextureRegion> borders = new HashMap<>();
|
||||
private static final Map<Integer, TextureRegion> deckbox = new HashMap<>();
|
||||
private static final Map<Integer, TextureRegion> cursor = new HashMap<>();
|
||||
|
||||
private static Array<String> allSkins;
|
||||
private static FileHandle preferredDir;
|
||||
private static String preferredName;
|
||||
@@ -53,27 +44,19 @@ public class FSkin {
|
||||
prefs.setPref(FPref.UI_SKIN, skinName);
|
||||
prefs.save();
|
||||
|
||||
Forge.setTransitionScreen(new TransitionScreen(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FThreads.invokeInBackgroundThread(() -> FThreads.invokeInEdtLater(() -> {
|
||||
final LoadingOverlay loader = new LoadingOverlay(Forge.getLocalizer().getMessageorUseDefault("lblRestartInFewSeconds", "Forge will restart after a few seconds..."), true);
|
||||
loader.show();
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
FSkinFont.deleteCachedFiles(); //delete cached font files so font can be update for new skin
|
||||
FThreads.delayInEDT(2000, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Forge.clearTransitionScreen();
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
Forge.restart(true);
|
||||
});
|
||||
}
|
||||
});
|
||||
Forge.setTransitionScreen(new TransitionScreen(() -> FThreads.invokeInBackgroundThread(() -> FThreads.invokeInEdtLater(() -> {
|
||||
final LoadingOverlay loader = new LoadingOverlay(Forge.getLocalizer().getMessageorUseDefault("lblRestartInFewSeconds", "Forge will restart after a few seconds..."), true);
|
||||
loader.show();
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
FSkinFont.deleteCachedFiles(); //delete cached font files so font can be update for new skin
|
||||
FThreads.delayInEDT(2000, () -> {
|
||||
Forge.clearTransitionScreen();
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
Forge.restart(true);
|
||||
});
|
||||
}));
|
||||
}
|
||||
}, null, false, true));
|
||||
});
|
||||
});
|
||||
})), null, false, true));
|
||||
}
|
||||
public static void loadLight(String skinName, final SplashScreen splashScreen,FileHandle prefDir) {
|
||||
preferredDir = prefDir;
|
||||
@@ -88,7 +71,7 @@ public class FSkin {
|
||||
* the skin name
|
||||
*/
|
||||
public static void loadLight(String skinName, final SplashScreen splashScreen) {
|
||||
AssetManager manager = Forge.getAssets(true).manager;
|
||||
AssetManager manager = Forge.getAssets().manager();
|
||||
preferredName = skinName.toLowerCase().replace(' ', '_');
|
||||
|
||||
//reset hd buttons/icons
|
||||
@@ -165,17 +148,26 @@ public class FSkin {
|
||||
}
|
||||
|
||||
try {
|
||||
manager.load(f.path(), Texture.class);
|
||||
manager.finishLoadingAsset(f.path());
|
||||
final int w = manager.get(f.path(), Texture.class).getWidth();
|
||||
final int h = manager.get(f.path(), Texture.class).getHeight();
|
||||
|
||||
if (f2.exists()) {
|
||||
manager.load(f2.path(), Texture.class, new TextureLoader.TextureParameter(){{genMipMaps = true; minFilter = Texture.TextureFilter.MipMapLinearLinear; magFilter = Texture.TextureFilter.Linear;}});
|
||||
manager.finishLoadingAsset(f2.path());
|
||||
splashScreen.setBackground(new TextureRegion(manager.get(f2.path(), Texture.class)));
|
||||
int w, h;
|
||||
if (f.path().contains("fallback_skin")) {
|
||||
//the file is not accesible by the assetmanager using absolute fileresolver since it resides on internal path or classpath
|
||||
Texture txSplash = new Texture(f);
|
||||
w = txSplash.getWidth();
|
||||
h = txSplash.getHeight();
|
||||
splashScreen.setBackground(new TextureRegion(txSplash, 0, 0, w, h - 100));
|
||||
} else {
|
||||
splashScreen.setBackground(new TextureRegion(manager.get(f.path(), Texture.class), 0, 0, w, h - 100));
|
||||
manager.load(f.path(), Texture.class);
|
||||
manager.finishLoadingAsset(f.path());
|
||||
w = manager.get(f.path(), Texture.class).getWidth();
|
||||
h = manager.get(f.path(), Texture.class).getHeight();
|
||||
|
||||
if (f2.exists()) {
|
||||
manager.load(f2.path(), Texture.class, new TextureLoader.TextureParameter(){{genMipMaps = true; minFilter = Texture.TextureFilter.MipMapLinearLinear; magFilter = Texture.TextureFilter.Linear;}});
|
||||
manager.finishLoadingAsset(f2.path());
|
||||
splashScreen.setBackground(new TextureRegion(manager.get(f2.path(), Texture.class)));
|
||||
} else {
|
||||
splashScreen.setBackground(new TextureRegion(manager.get(f.path(), Texture.class), 0, 0, w, h - 100));
|
||||
}
|
||||
}
|
||||
|
||||
Pixmap pxSplash = new Pixmap(f);
|
||||
@@ -217,8 +209,8 @@ public class FSkin {
|
||||
if (FSkin.preferredName.isEmpty()) { FSkin.loadLight("default", splashScreen); }
|
||||
}
|
||||
|
||||
avatars.clear();
|
||||
sleeves.clear();
|
||||
Forge.getAssets().avatars().clear();
|
||||
Forge.getAssets().sleeves().clear();
|
||||
|
||||
TextureLoader.TextureParameter parameter = new TextureLoader.TextureParameter();
|
||||
if (Forge.isTextureFilteringEnabled()) {
|
||||
@@ -227,7 +219,7 @@ public class FSkin {
|
||||
parameter.magFilter = Texture.TextureFilter.Linear;
|
||||
}
|
||||
|
||||
AssetManager manager = Forge.getAssets(true).manager;
|
||||
AssetManager manager = Forge.getAssets().manager();
|
||||
|
||||
// Grab and test various sprite files.
|
||||
final FileHandle f1 = getDefaultSkinFile(SourceFile.ICONS.getFilename());
|
||||
@@ -246,6 +238,8 @@ public class FSkin {
|
||||
final FileHandle f17 = getDefaultSkinFile(ForgeConstants.SPRITE_CRACKS_FILE);
|
||||
final FileHandle f18 = getDefaultSkinFile(ForgeConstants.SPRITE_PHYREXIAN_FILE);
|
||||
final FileHandle f19 = getDefaultSkinFile(ForgeConstants.SPRITE_CURSOR_FILE);
|
||||
final FileHandle f20 = getSkinFile(ForgeConstants.SPRITE_SLEEVES_FILE);
|
||||
final FileHandle f21 = getSkinFile(ForgeConstants.SPRITE_SLEEVES2_FILE);
|
||||
|
||||
/*TODO Themeable
|
||||
final FileHandle f14 = getDefaultSkinFile(ForgeConstants.SPRITE_SETLOGO_FILE);
|
||||
@@ -321,7 +315,7 @@ public class FSkin {
|
||||
int counter = 0;
|
||||
int scount = 0;
|
||||
Color pxTest;
|
||||
Pixmap pxDefaultAvatars, pxPreferredAvatars, pxDefaultSleeves;
|
||||
Pixmap pxDefaultAvatars, pxPreferredAvatars, pxDefaultSleeves, pxPreferredSleeves;
|
||||
|
||||
pxDefaultAvatars = new Pixmap(f4);
|
||||
pxDefaultSleeves = new Pixmap(f8);
|
||||
@@ -345,7 +339,7 @@ public class FSkin {
|
||||
if (i == 0 && j == 0) { continue; }
|
||||
pxTest = new Color(pxPreferredAvatars.getPixel(i + 50, j + 50));
|
||||
if (pxTest.a == 0) { continue; }
|
||||
FSkin.avatars.put(counter++, new TextureRegion(manager.get(f5.path(), Texture.class), i, j, 100, 100));
|
||||
Forge.getAssets().avatars().put(counter++, new TextureRegion(manager.get(f5.path(), Texture.class), i, j, 100, 100));
|
||||
}
|
||||
}
|
||||
pxPreferredAvatars.dispose();
|
||||
@@ -360,37 +354,72 @@ public class FSkin {
|
||||
if (i == 0 && j == 0) { continue; }
|
||||
pxTest = new Color(pxDefaultAvatars.getPixel(i + 50, j + 50));
|
||||
if (pxTest.a == 0) { continue; }
|
||||
FSkin.avatars.put(counter++, new TextureRegion(manager.get(f4.path(), Texture.class), i, j, 100, 100));
|
||||
Forge.getAssets().avatars().put(counter++, new TextureRegion(manager.get(f4.path(), Texture.class), i, j, 100, 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (f20.exists()) {
|
||||
pxPreferredSleeves = new Pixmap(f20);
|
||||
manager.load(f20.path(), Texture.class, parameter);
|
||||
manager.finishLoadingAsset(f20.path());
|
||||
|
||||
final int sw = pxPreferredSleeves.getWidth();
|
||||
final int sh = pxPreferredSleeves.getHeight();
|
||||
|
||||
for (int j = 0; j < sh; j += 500) {
|
||||
for (int i = 0; i < sw; i += 360) {
|
||||
pxTest = new Color(pxPreferredSleeves.getPixel(i + 180, j + 250));
|
||||
if (pxTest.a == 0) { continue; }
|
||||
Forge.getAssets().sleeves().put(scount++, new TextureRegion(manager.get(f20.path(), Texture.class), i, j, 360, 500));
|
||||
}
|
||||
}
|
||||
pxPreferredSleeves.dispose();
|
||||
} else {
|
||||
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; }
|
||||
Forge.getAssets().sleeves().put(scount++, new TextureRegion(manager.get(f8.path(), Texture.class), i, j, 360, 500));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (f21.exists()) {
|
||||
pxPreferredSleeves = new Pixmap(f21);
|
||||
manager.load(f21.path(), Texture.class, parameter);
|
||||
manager.finishLoadingAsset(f21.path());
|
||||
|
||||
final int sw = pxPreferredSleeves.getWidth();
|
||||
final int sh = pxPreferredSleeves.getHeight();
|
||||
|
||||
for (int j = 0; j < sh; j += 500) {
|
||||
for (int i = 0; i < sw; i += 360) {
|
||||
pxTest = new Color(pxPreferredSleeves.getPixel(i + 180, j + 250));
|
||||
if (pxTest.a == 0) { continue; }
|
||||
Forge.getAssets().sleeves().put(scount++, new TextureRegion(manager.get(f21.path(), Texture.class), i, j, 360, 500));
|
||||
}
|
||||
}
|
||||
pxPreferredSleeves.dispose();
|
||||
} else {
|
||||
//re init second set of sleeves
|
||||
pxDefaultSleeves = new Pixmap(f9);
|
||||
manager.load(f9.path(), Texture.class, parameter);
|
||||
manager.finishLoadingAsset(f9.path());
|
||||
|
||||
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; }
|
||||
Forge.getAssets().sleeves().put(scount++, new TextureRegion(manager.get(f9.path(), Texture.class), i, j, 360, 500));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(manager.get(f8.path(), Texture.class), i, j, 360, 500));
|
||||
}
|
||||
}
|
||||
|
||||
//re init second set of sleeves
|
||||
pxDefaultSleeves = new Pixmap(f9);
|
||||
manager.load(f9.path(), Texture.class, parameter);
|
||||
manager.finishLoadingAsset(f9.path());
|
||||
|
||||
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(manager.get(f9.path(), Texture.class), i, j, 360, 500));
|
||||
}
|
||||
}
|
||||
//cracks
|
||||
manager.load(f17.path(), Texture.class, parameter);
|
||||
manager.finishLoadingAsset(f17.path());
|
||||
@@ -399,32 +428,32 @@ public class FSkin {
|
||||
int x = j * 200;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
int y = i * 279;
|
||||
FSkin.cracks.put(crackCount++, new TextureRegion(manager.get(f17.path(), Texture.class), x, y, 200, 279));
|
||||
Forge.getAssets().cracks().put(crackCount++, new TextureRegion(manager.get(f17.path(), Texture.class), x, y, 200, 279));
|
||||
}
|
||||
}
|
||||
|
||||
//borders
|
||||
manager.load(f10.path(), Texture.class);
|
||||
manager.finishLoadingAsset(f10.path());
|
||||
FSkin.borders.put(0, new TextureRegion(manager.get(f10.path(), Texture.class), 2, 2, 672, 936));
|
||||
FSkin.borders.put(1, new TextureRegion(manager.get(f10.path(), Texture.class), 676, 2, 672, 936));
|
||||
Forge.getAssets().borders().put(0, new TextureRegion(manager.get(f10.path(), Texture.class), 2, 2, 672, 936));
|
||||
Forge.getAssets().borders().put(1, new TextureRegion(manager.get(f10.path(), Texture.class), 676, 2, 672, 936));
|
||||
//deckboxes
|
||||
manager.load(f13.path(), Texture.class, parameter);
|
||||
manager.finishLoadingAsset(f13.path());
|
||||
//gold bg
|
||||
FSkin.deckbox.put(0, new TextureRegion(manager.get(f13.path(), Texture.class), 2, 2, 488, 680));
|
||||
Forge.getAssets().deckbox().put(0, new TextureRegion(manager.get(f13.path(), Texture.class), 2, 2, 488, 680));
|
||||
//deck box for card art
|
||||
FSkin.deckbox.put(1, new TextureRegion(manager.get(f13.path(), Texture.class), 492, 2, 488, 680));
|
||||
Forge.getAssets().deckbox().put(1, new TextureRegion(manager.get(f13.path(), Texture.class), 492, 2, 488, 680));
|
||||
//generic deck box
|
||||
FSkin.deckbox.put(2, new TextureRegion(manager.get(f13.path(), Texture.class), 982, 2, 488, 680));
|
||||
Forge.getAssets().deckbox().put(2, new TextureRegion(manager.get(f13.path(), Texture.class), 982, 2, 488, 680));
|
||||
//cursor
|
||||
manager.load(f19.path(), Texture.class);
|
||||
manager.finishLoadingAsset(f19.path());
|
||||
FSkin.cursor.put(0, new TextureRegion(manager.get(f19.path(), Texture.class), 0, 0, 32, 32)); //default
|
||||
FSkin.cursor.put(1, new TextureRegion(manager.get(f19.path(), Texture.class), 32, 0, 32, 32)); //magnify on
|
||||
FSkin.cursor.put(2, new TextureRegion(manager.get(f19.path(), Texture.class), 64, 0, 32, 32)); // magnify off
|
||||
Forge.getAssets().cursor().put(0, new TextureRegion(manager.get(f19.path(), Texture.class), 0, 0, 32, 32)); //default
|
||||
Forge.getAssets().cursor().put(1, new TextureRegion(manager.get(f19.path(), Texture.class), 32, 0, 32, 32)); //magnify on
|
||||
Forge.getAssets().cursor().put(2, new TextureRegion(manager.get(f19.path(), Texture.class), 64, 0, 32, 32)); // magnify off
|
||||
|
||||
Forge.setCursor(cursor.get(0), "0");
|
||||
Forge.setCursor(Forge.getAssets().cursor().get(0), "0");
|
||||
|
||||
preferredIcons.dispose();
|
||||
pxDefaultAvatars.dispose();
|
||||
@@ -514,31 +543,31 @@ public class FSkin {
|
||||
}
|
||||
|
||||
public static Map<FSkinProp, FSkinImage> getImages() {
|
||||
return images;
|
||||
return Forge.getAssets().images();
|
||||
}
|
||||
|
||||
public static Map<Integer, TextureRegion> getAvatars() {
|
||||
return avatars;
|
||||
return Forge.getAssets().avatars();
|
||||
}
|
||||
|
||||
public static Map<Integer, TextureRegion> getSleeves() {
|
||||
return sleeves;
|
||||
return Forge.getAssets().sleeves();
|
||||
}
|
||||
|
||||
public static Map<Integer, TextureRegion> getCracks() {
|
||||
return cracks;
|
||||
return Forge.getAssets().cracks();
|
||||
}
|
||||
|
||||
public static Map<Integer, TextureRegion> getBorders() {
|
||||
return borders;
|
||||
return Forge.getAssets().borders();
|
||||
}
|
||||
|
||||
public static Map<Integer, TextureRegion> getDeckbox() {
|
||||
return deckbox;
|
||||
return Forge.getAssets().deckbox();
|
||||
}
|
||||
|
||||
public static Map<Integer, TextureRegion> getCursor() {
|
||||
return cursor;
|
||||
return Forge.getAssets().cursor();
|
||||
}
|
||||
|
||||
public static boolean isLoaded() { return loaded; }
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.badlogic.gdx.graphics.glutils.PixmapTextureData;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import com.badlogic.gdx.utils.IntSet;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import forge.Forge;
|
||||
import forge.gui.FThreads;
|
||||
import forge.localinstance.properties.ForgeConstants;
|
||||
@@ -39,29 +38,19 @@ public class FSkinFont {
|
||||
private static final int MAX_FONT_SIZE_MANY_GLYPHS = 36;
|
||||
|
||||
private static final String TTF_FILE = "font1.ttf";
|
||||
private static final HashMap<Integer, FSkinFont> fonts = new HashMap<>();
|
||||
|
||||
private static final String commonCharacterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm"
|
||||
+ "nopqrstuvwxyz1234567890\"!?'.,;:()[]{}<>|/@\\^$-%+=#_&*\u2014"
|
||||
+ "\u2022ÁÉÍÓÚáéíóúÀÈÌÒÙàèìòùÑñÄËÏÖÜäëïöüẞß¿¡";
|
||||
private static ObjectMap<String, String> langUniqueCharacterSet = new ObjectMap<>();
|
||||
private static HashMap<String, String> langUniqueCharacterSet = new HashMap<>();
|
||||
|
||||
static {
|
||||
FileUtil.ensureDirectoryExists(ForgeConstants.FONTS_DIR);
|
||||
}
|
||||
public static void clear() {
|
||||
fonts.clear();
|
||||
//reset maxFontSize and Preload
|
||||
preloadAll("");
|
||||
}
|
||||
public static FSkinFont get(final int unscaledSize) {
|
||||
return _get((int)Utils.scale(unscaledSize));
|
||||
}
|
||||
public static FSkinFont _get(final int scaledSize) {
|
||||
FSkinFont skinFont = fonts.get(scaledSize);
|
||||
FSkinFont skinFont = Forge.getAssets().fonts().get(scaledSize);
|
||||
if (skinFont == null) {
|
||||
skinFont = new FSkinFont(scaledSize);
|
||||
fonts.put(scaledSize, skinFont);
|
||||
Forge.getAssets().fonts().put(scaledSize, skinFont);
|
||||
}
|
||||
return skinFont;
|
||||
}
|
||||
@@ -69,7 +58,8 @@ public class FSkinFont {
|
||||
public static FSkinFont forHeight(final float height) {
|
||||
int size = MIN_FONT_SIZE + 1;
|
||||
while (true) {
|
||||
if (_get(size).getLineHeight() > height) {
|
||||
FSkinFont f = _get(size);
|
||||
if (f != null && f.getLineHeight() > height) {
|
||||
return _get(size - 1);
|
||||
}
|
||||
size++;
|
||||
@@ -97,14 +87,14 @@ public class FSkinFont {
|
||||
}
|
||||
|
||||
public static void updateAll() {
|
||||
for (FSkinFont skinFont : fonts.values()) {
|
||||
for (FSkinFont skinFont : Forge.getAssets().fonts().values()) {
|
||||
skinFont.updateFont();
|
||||
}
|
||||
}
|
||||
|
||||
private final int fontSize;
|
||||
private final float scale;
|
||||
private BitmapFont font;
|
||||
BitmapFont font;
|
||||
|
||||
private FSkinFont(int fontSize0) {
|
||||
if (fontSize0 > MAX_FONT_SIZE) {
|
||||
@@ -127,6 +117,8 @@ public class FSkinFont {
|
||||
|
||||
}
|
||||
public int computeVisibleGlyphs (CharSequence str, int start, int end, float availableWidth) {
|
||||
if (font == null)
|
||||
return 0;
|
||||
BitmapFontData data = font.getData();
|
||||
int index = start;
|
||||
float width = 0;
|
||||
@@ -180,6 +172,9 @@ public class FSkinFont {
|
||||
return getBounds(str, 0, str.length());
|
||||
}
|
||||
public TextBounds getBounds(CharSequence str, int start, int end) {
|
||||
if (font == null) {
|
||||
return new TextBounds(0f, 0f);
|
||||
}
|
||||
BitmapFontData data = font.getData();
|
||||
//int start = 0;
|
||||
//int end = str.length();
|
||||
@@ -228,6 +223,9 @@ public class FSkinFont {
|
||||
}
|
||||
public TextBounds getMultiLineBounds(CharSequence str) {
|
||||
updateScale();
|
||||
if (font == null) {
|
||||
return new TextBounds(0f, 0f);
|
||||
}
|
||||
BitmapFontData data = font.getData();
|
||||
int start = 0;
|
||||
float maxWidth = 0;
|
||||
@@ -247,6 +245,9 @@ public class FSkinFont {
|
||||
}
|
||||
public TextBounds getWrappedBounds(CharSequence str, float wrapWidth) {
|
||||
updateScale();
|
||||
if (font == null) {
|
||||
return new TextBounds(0f, 0f);
|
||||
}
|
||||
BitmapFontData data = font.getData();
|
||||
if (wrapWidth <= 0) wrapWidth = Integer.MAX_VALUE;
|
||||
int start = 0;
|
||||
@@ -303,14 +304,20 @@ public class FSkinFont {
|
||||
return new TextBounds(maxWidth, data.capHeight + (numLines - 1) * data.lineHeight);
|
||||
}
|
||||
public float getAscent() {
|
||||
if (font == null)
|
||||
return 0f;
|
||||
updateScale();
|
||||
return font.getAscent();
|
||||
}
|
||||
public float getCapHeight() {
|
||||
if (font == null)
|
||||
return 0f;
|
||||
updateScale();
|
||||
return font.getCapHeight();
|
||||
}
|
||||
public float getLineHeight() {
|
||||
if (font == null)
|
||||
return 0f;
|
||||
updateScale();
|
||||
return font.getLineHeight();
|
||||
}
|
||||
@@ -323,8 +330,12 @@ public class FSkinFont {
|
||||
|
||||
//update scale of font if needed
|
||||
private void updateScale() {
|
||||
if (font.getScaleX() != scale) {
|
||||
font.getData().setScale(scale);
|
||||
try {
|
||||
if (font.getScaleX() != scale) {
|
||||
font.getData().setScale(scale);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,10 +359,10 @@ public class FSkinFont {
|
||||
if (langUniqueCharacterSet.containsKey(langCode)) {
|
||||
return langUniqueCharacterSet.get(langCode);
|
||||
}
|
||||
StringBuilder characters = new StringBuilder(commonCharacterSet);
|
||||
StringBuilder characters = new StringBuilder(FreeTypeFontGenerator.DEFAULT_CHARS);
|
||||
IntSet characterSet = new IntSet();
|
||||
for (int offset = 0; offset < commonCharacterSet.length();) {
|
||||
final int codePoint = commonCharacterSet.codePointAt(offset);
|
||||
for (int offset = 0; offset < FreeTypeFontGenerator.DEFAULT_CHARS.length();) {
|
||||
final int codePoint = FreeTypeFontGenerator.DEFAULT_CHARS.codePointAt(offset);
|
||||
characterSet.add(codePoint);
|
||||
offset += Character.charCount(codePoint);
|
||||
}
|
||||
@@ -400,16 +411,13 @@ public class FSkinFont {
|
||||
if (fontFile != null && fontFile.exists()) {
|
||||
final BitmapFontData data = new BitmapFontData(fontFile, false);
|
||||
String finalFontName = fontName;
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() { //font must be initialized on UI thread
|
||||
try {
|
||||
font = new BitmapFont(data, (TextureRegion) null, true);
|
||||
found[0] = true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
found[0] = false;
|
||||
}
|
||||
FThreads.invokeInEdtNowOrLater(() -> { //font must be initialized on UI thread
|
||||
try {
|
||||
font = new BitmapFont(data, (TextureRegion) null, true);
|
||||
found[0] = true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
found[0] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -128,9 +128,13 @@ public enum FSkinTexture implements FImage {
|
||||
FileHandle preferredFile = isPlane ? FSkin.getCachePlanechaseFile(filename) : FSkin.getSkinFile(filename);
|
||||
if (preferredFile.exists()) {
|
||||
try {
|
||||
Forge.getAssets(true).manager.load(preferredFile.path(), Texture.class);
|
||||
Forge.getAssets(true).manager.finishLoadingAsset(preferredFile.path());
|
||||
texture = Forge.getAssets(true).manager.get(preferredFile.path(), Texture.class);
|
||||
if (preferredFile.path().contains("fallback_skin")) {
|
||||
texture = new Texture(preferredFile);
|
||||
} else {
|
||||
Forge.getAssets().manager().load(preferredFile.path(), Texture.class);
|
||||
Forge.getAssets().manager().finishLoadingAsset(preferredFile.path());
|
||||
texture = Forge.getAssets().manager().get(preferredFile.path(), Texture.class);
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
System.err.println("Failed to load skin file: " + preferredFile);
|
||||
@@ -148,9 +152,13 @@ public enum FSkinTexture implements FImage {
|
||||
|
||||
if (defaultFile.exists()) {
|
||||
try {
|
||||
Forge.getAssets(true).manager.load(defaultFile.path(), Texture.class);
|
||||
Forge.getAssets(true).manager.finishLoadingAsset(defaultFile.path());
|
||||
texture = Forge.getAssets(true).manager.get(defaultFile.path(), Texture.class);
|
||||
if (defaultFile.path().contains("fallback_skin")) {
|
||||
texture = new Texture(defaultFile);
|
||||
} else {
|
||||
Forge.getAssets().manager().load(defaultFile.path(), Texture.class);
|
||||
Forge.getAssets().manager().finishLoadingAsset(defaultFile.path());
|
||||
texture = Forge.getAssets().manager().get(defaultFile.path(), Texture.class);
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
System.err.println("Failed to load skin file: " + defaultFile);
|
||||
|
||||
@@ -18,22 +18,22 @@
|
||||
package forge.assets;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.assets.loaders.TextureLoader.TextureParameter;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.TextureData;
|
||||
import com.badlogic.gdx.graphics.glutils.PixmapTextureData;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import com.badlogic.gdx.utils.ObjectSet;
|
||||
import com.google.common.collect.EvictingQueue;
|
||||
import com.google.common.collect.Queues;
|
||||
import com.google.common.collect.Sets;
|
||||
import forge.gui.FThreads;
|
||||
import forge.gui.GuiBase;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.TextUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -74,10 +74,12 @@ import forge.util.ImageUtil;
|
||||
* @version $Id: ImageCache.java 24769 2014-02-09 13:56:04Z Hellfish $
|
||||
*/
|
||||
public class ImageCache {
|
||||
private static final ObjectSet<String> missingIconKeys = new ObjectSet<>();
|
||||
private static final HashSet<String> missingIconKeys = new HashSet<>();
|
||||
private static List<String> borderlessCardlistKey = FileUtil.readFile(ForgeConstants.BORDERLESS_CARD_LIST_FILE);
|
||||
static int maxCardCapacity = 400; //default card capacity
|
||||
public static int counter = 0;
|
||||
static int maxCardCapacity = 300; //default card capacity
|
||||
static EvictingQueue<String> q;
|
||||
static Set<String> cardsLoaded;
|
||||
static Queue<String> syncQ;
|
||||
static TextureParameter defaultParameter = new TextureParameter();
|
||||
static TextureParameter filtered = new TextureParameter();
|
||||
@@ -92,12 +94,14 @@ public class ImageCache {
|
||||
q = EvictingQueue.create(capacity);
|
||||
//init syncQ for threadsafe use
|
||||
syncQ = Queues.synchronizedQueue(q);
|
||||
//cap
|
||||
int cl = GuiBase.isAndroid() ? maxCardCapacity+(capacity/3) : 400;
|
||||
cardsLoaded = new HashSet<>(cl);
|
||||
}
|
||||
public static final Texture defaultImage;
|
||||
public static FImage BlackBorder = FSkinImage.IMG_BORDER_BLACK;
|
||||
public static FImage WhiteBorder = FSkinImage.IMG_BORDER_WHITE;
|
||||
private static final ObjectMap<String, Pair<String, Boolean>> imageBorder = new ObjectMap<>(1024);
|
||||
private static final ObjectMap<String, Texture> generatedCards = new ObjectMap<>(512);
|
||||
private static final HashMap<String, Pair<String, Boolean>> imageBorder = new HashMap<>(1024);
|
||||
|
||||
private static boolean imageLoaded, delayLoadRequested;
|
||||
public static void allowSingleLoad() {
|
||||
@@ -112,7 +116,7 @@ public class ImageCache {
|
||||
} catch (Exception ex) {
|
||||
System.err.println("could not load default card image");
|
||||
} finally {
|
||||
defaultImage = (null == defImage) ? new Texture(10, 10, Format.RGBA8888) : defImage;
|
||||
defaultImage = (null == defImage) ? new Texture(10, 10, Format.RGBA4444) : defImage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,11 +125,18 @@ public class ImageCache {
|
||||
ImageKeys.clearMissingCards();
|
||||
}
|
||||
public static void clearGeneratedCards() {
|
||||
generatedCards.clear();
|
||||
Forge.getAssets().generatedCards().clear();
|
||||
}
|
||||
public static void disposeTextures(){
|
||||
CardRenderer.clearcardArtCache();
|
||||
Forge.getAssets(false).manager.clear();
|
||||
//unload all cardsLoaded
|
||||
for (String fileName : cardsLoaded) {
|
||||
if (Forge.getAssets().manager().contains(fileName)) {
|
||||
Forge.getAssets().manager().unload(fileName);
|
||||
}
|
||||
}
|
||||
cardsLoaded.clear();
|
||||
((Forge)Gdx.app.getApplicationListener()).needsUpdate = true;
|
||||
}
|
||||
|
||||
public static Texture getImage(InventoryItem ii) {
|
||||
@@ -201,7 +212,7 @@ public class ImageCache {
|
||||
public static Texture getImage(String imageKey, boolean useDefaultIfNotFound) {
|
||||
return getImage(imageKey, useDefaultIfNotFound, false);
|
||||
}
|
||||
public static Texture getImage(String imageKey, boolean useDefaultIfNotFound, boolean useOtherCache) {
|
||||
public static Texture getImage(String imageKey, boolean useDefaultIfNotFound, boolean others) {
|
||||
if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_CARD_IMAGES))
|
||||
return null;
|
||||
|
||||
@@ -226,7 +237,7 @@ public class ImageCache {
|
||||
File imageFile = ImageKeys.getImageFile(imageKey);
|
||||
if (useDefaultIfNotFound) {
|
||||
// Load from file and add to cache if not found in cache initially.
|
||||
image = getAsset(imageKey, imageFile, useOtherCache);
|
||||
image = getAsset(imageKey, imageFile, others);
|
||||
|
||||
if (image != null) { return image; }
|
||||
|
||||
@@ -242,7 +253,7 @@ public class ImageCache {
|
||||
}
|
||||
|
||||
try {
|
||||
image = loadAsset(imageKey, imageFile, useOtherCache);
|
||||
image = loadAsset(imageKey, imageFile, others);
|
||||
} catch (final Exception ex) {
|
||||
image = null;
|
||||
}
|
||||
@@ -261,55 +272,67 @@ public class ImageCache {
|
||||
}
|
||||
return image;
|
||||
}
|
||||
static Texture getAsset(String imageKey, File file, boolean otherCache) {
|
||||
static Texture getAsset(String imageKey, File file, boolean others) {
|
||||
if (file == null)
|
||||
return null;
|
||||
if (!otherCache && Forge.enableUIMask.equals("Full") && isBorderless(imageKey))
|
||||
return generatedCards.get(imageKey);
|
||||
return Forge.getAssets(otherCache).manager.get(file.getPath(), Texture.class, false);
|
||||
if (!others && Forge.enableUIMask.equals("Full") && isBorderless(imageKey))
|
||||
return Forge.getAssets().generatedCards().get(imageKey);
|
||||
return Forge.getAssets().manager().get(file.getPath(), Texture.class, false);
|
||||
}
|
||||
static Texture loadAsset(String imageKey, File file, boolean otherCache) {
|
||||
static Texture loadAsset(String imageKey, File file, boolean others) {
|
||||
if (file == null)
|
||||
return null;
|
||||
syncQ.add(file.getPath());
|
||||
if (!otherCache && Forge.getAssets(false).manager.getLoadedAssets() > maxCardCapacity) {
|
||||
unloadCardTextures(Forge.getAssets(false).manager);
|
||||
Texture check = getAsset(imageKey, file, others);
|
||||
if (check != null)
|
||||
return check;
|
||||
if (!others) {
|
||||
syncQ.add(file.getPath());
|
||||
cardsLoaded.add(file.getPath());
|
||||
}
|
||||
if (!others && cardsLoaded.size() > maxCardCapacity) {
|
||||
unloadCardTextures(Forge.getAssets().manager());
|
||||
return null;
|
||||
}
|
||||
String fileName = file.getPath();
|
||||
//load to assetmanager
|
||||
Forge.getAssets(otherCache).manager.load(fileName, Texture.class, Forge.isTextureFilteringEnabled() ? filtered : defaultParameter);
|
||||
Forge.getAssets(otherCache).manager.finishLoadingAsset(fileName);
|
||||
if (!Forge.getAssets().manager().contains(fileName, Texture.class)) {
|
||||
Forge.getAssets().manager().load(fileName, Texture.class, Forge.isTextureFilteringEnabled() ? filtered : defaultParameter);
|
||||
Forge.getAssets().manager().finishLoadingAsset(fileName);
|
||||
counter+=1;
|
||||
}
|
||||
|
||||
//return loaded assets
|
||||
if (otherCache) {
|
||||
return Forge.getAssets(true).manager.get(fileName, Texture.class, false);
|
||||
if (others) {
|
||||
return Forge.getAssets().manager().get(fileName, Texture.class, false);
|
||||
} else {
|
||||
Texture t = Forge.getAssets(false).manager.get(fileName, Texture.class, false);
|
||||
Texture cardTexture = Forge.getAssets().manager().get(fileName, Texture.class, false);
|
||||
//if full bordermasking is enabled, update the border color
|
||||
if (Forge.enableUIMask.equals("Full")) {
|
||||
boolean borderless = isBorderless(imageKey);
|
||||
updateBorders(t.toString(), borderless ? Pair.of(Color.valueOf("#171717").toString(), false): isCloserToWhite(getpixelColor(t)));
|
||||
updateBorders(cardTexture.toString(), borderless ? Pair.of(Color.valueOf("#171717").toString(), false): isCloserToWhite(getpixelColor(cardTexture)));
|
||||
//if borderless, generate new texture from the asset and store
|
||||
if (borderless) {
|
||||
generatedCards.put(imageKey, generateTexture(new FileHandle(file), t, Forge.isTextureFilteringEnabled()));
|
||||
Forge.getAssets().generatedCards().put(imageKey, generateTexture(new FileHandle(file), cardTexture, Forge.isTextureFilteringEnabled()));
|
||||
}
|
||||
}
|
||||
return t;
|
||||
return cardTexture;
|
||||
}
|
||||
}
|
||||
static void unloadCardTextures(AssetManager manager) {
|
||||
static void unloadCardTextures(Assets.MemoryTrackingAssetManager manager) {
|
||||
//get latest images from syncQ
|
||||
Set<String> newQ = Sets.newHashSet(syncQ);
|
||||
//get loaded images from assetmanager
|
||||
Set<String> old = Sets.newHashSet(manager.getAssetNames());
|
||||
//get all images not in newQ (old images to unload)
|
||||
Set<String> toUnload = Sets.difference(old, newQ);
|
||||
//get all images not in newQ (cardLists to unload)
|
||||
Set<String> toUnload = Sets.difference(cardsLoaded, newQ);
|
||||
//unload from assetmanager to save RAM
|
||||
for (String asset : toUnload) {
|
||||
manager.unload(asset);
|
||||
if(manager.contains(asset)) {
|
||||
manager.unload(asset);
|
||||
}
|
||||
cardsLoaded.remove(asset);
|
||||
}
|
||||
//clear cachedArt since this is dependant to the loaded texture
|
||||
CardRenderer.clearcardArtCache();
|
||||
((Forge)Gdx.app.getApplicationListener()).needsUpdate = true;
|
||||
}
|
||||
public static void preloadCache(Iterable<String> keys) {
|
||||
if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_CARD_IMAGES))
|
||||
@@ -409,10 +432,10 @@ public class ImageCache {
|
||||
|
||||
return borderColor(t);
|
||||
}
|
||||
public static Texture generateTexture(FileHandle fh, Texture t, boolean textureFilter) {
|
||||
if (t == null || fh == null)
|
||||
return t;
|
||||
final Texture[] n = new Texture[1];
|
||||
public static Texture generateTexture(FileHandle fh, Texture cardTexture, boolean textureFilter) {
|
||||
if (cardTexture == null || fh == null)
|
||||
return cardTexture;
|
||||
final Texture[] placeholder = new Texture[1];
|
||||
FThreads.invokeInEdtNowOrLater(() -> {
|
||||
Pixmap pImage = new Pixmap(fh);
|
||||
int w = pImage.getWidth();
|
||||
@@ -422,20 +445,20 @@ public class ImageCache {
|
||||
drawPixelstoMask(pImage, pMask);
|
||||
TextureData textureData = new PixmapTextureData(
|
||||
pMask, //pixmap to use
|
||||
Format.RGBA8888,
|
||||
Format.RGBA4444,
|
||||
textureFilter, //use mipmaps
|
||||
false, true);
|
||||
n[0] = new Texture(textureData);
|
||||
placeholder[0] = new Texture(textureData);
|
||||
if (textureFilter)
|
||||
n[0].setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear);
|
||||
placeholder[0].setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear);
|
||||
pImage.dispose();
|
||||
pMask.dispose();
|
||||
});
|
||||
return n[0];
|
||||
return placeholder[0];
|
||||
}
|
||||
public static Pixmap createRoundedRectangle(int width, int height, int cornerRadius, Color color) {
|
||||
Pixmap pixmap = new Pixmap(width, height, Pixmap.Format.RGBA8888);
|
||||
Pixmap ret = new Pixmap(width, height, Pixmap.Format.RGBA8888);
|
||||
Pixmap pixmap = new Pixmap(width, height, Format.RGBA4444);
|
||||
Pixmap ret = new Pixmap(width, height, Format.RGBA4444);
|
||||
pixmap.setColor(color);
|
||||
//round corners
|
||||
pixmap.fillCircle(cornerRadius, cornerRadius, cornerRadius);
|
||||
@@ -486,11 +509,7 @@ public class ImageCache {
|
||||
//generated texture/pixmap?
|
||||
if (t.toString().contains("com.badlogic.gdx.graphics.Texture@"))
|
||||
return true;
|
||||
for (String key : borderlessCardlistKey) {
|
||||
if (t.toString().contains(key))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return borderlessCardlistKey.stream().anyMatch(key -> t.toString().contains(key));
|
||||
}
|
||||
|
||||
public static String getpixelColor(Texture i) {
|
||||
|
||||
@@ -2,10 +2,8 @@ package forge.assets;
|
||||
|
||||
import java.text.BreakIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
@@ -20,64 +18,63 @@ import forge.util.TextBounds;
|
||||
|
||||
//Encodes text for drawing with symbols and reminder text
|
||||
public class TextRenderer {
|
||||
private static final Map<String, FSkinImage> symbolLookup = new HashMap<>(64);
|
||||
static {
|
||||
symbolLookup.put("C", FSkinImage.MANA_COLORLESS);
|
||||
symbolLookup.put("W", FSkinImage.MANA_W);
|
||||
symbolLookup.put("U", FSkinImage.MANA_U);
|
||||
symbolLookup.put("B", FSkinImage.MANA_B);
|
||||
symbolLookup.put("R", FSkinImage.MANA_R);
|
||||
symbolLookup.put("G", FSkinImage.MANA_G);
|
||||
symbolLookup.put("W/U", FSkinImage.MANA_HYBRID_WU);
|
||||
symbolLookup.put("U/B", FSkinImage.MANA_HYBRID_UB);
|
||||
symbolLookup.put("B/R", FSkinImage.MANA_HYBRID_BR);
|
||||
symbolLookup.put("R/G", FSkinImage.MANA_HYBRID_RG);
|
||||
symbolLookup.put("G/W", FSkinImage.MANA_HYBRID_GW);
|
||||
symbolLookup.put("W/B", FSkinImage.MANA_HYBRID_WB);
|
||||
symbolLookup.put("U/R", FSkinImage.MANA_HYBRID_UR);
|
||||
symbolLookup.put("B/G", FSkinImage.MANA_HYBRID_BG);
|
||||
symbolLookup.put("R/W", FSkinImage.MANA_HYBRID_RW);
|
||||
symbolLookup.put("G/U", FSkinImage.MANA_HYBRID_GU);
|
||||
symbolLookup.put("2/W", FSkinImage.MANA_2W);
|
||||
symbolLookup.put("2/U", FSkinImage.MANA_2U);
|
||||
symbolLookup.put("2/B", FSkinImage.MANA_2B);
|
||||
symbolLookup.put("2/R", FSkinImage.MANA_2R);
|
||||
symbolLookup.put("2/G", FSkinImage.MANA_2G);
|
||||
symbolLookup.put("P", FSkinImage.MANA_PHRYX);
|
||||
symbolLookup.put("P/W", FSkinImage.MANA_PHRYX_W);
|
||||
symbolLookup.put("P/U", FSkinImage.MANA_PHRYX_U);
|
||||
symbolLookup.put("P/B", FSkinImage.MANA_PHRYX_B);
|
||||
symbolLookup.put("P/R", FSkinImage.MANA_PHRYX_R);
|
||||
symbolLookup.put("P/G", FSkinImage.MANA_PHRYX_G);
|
||||
symbolLookup.put("W/P", FSkinImage.MANA_PHRYX_W);
|
||||
symbolLookup.put("U/P", FSkinImage.MANA_PHRYX_U);
|
||||
symbolLookup.put("B/P", FSkinImage.MANA_PHRYX_B);
|
||||
symbolLookup.put("R/P", FSkinImage.MANA_PHRYX_R);
|
||||
symbolLookup.put("G/P", FSkinImage.MANA_PHRYX_G);
|
||||
symbolLookup.put("P/B/G", FSkinImage.MANA_PHRYX_BG);
|
||||
symbolLookup.put("P/B/R", FSkinImage.MANA_PHRYX_BR);
|
||||
symbolLookup.put("P/G/U", FSkinImage.MANA_PHRYX_GU);
|
||||
symbolLookup.put("P/G/W", FSkinImage.MANA_PHRYX_GW);
|
||||
symbolLookup.put("P/R/G", FSkinImage.MANA_PHRYX_RG);
|
||||
symbolLookup.put("P/R/W", FSkinImage.MANA_PHRYX_RW);
|
||||
symbolLookup.put("P/U/B", FSkinImage.MANA_PHRYX_UB);
|
||||
symbolLookup.put("P/U/R", FSkinImage.MANA_PHRYX_UR);
|
||||
symbolLookup.put("P/W/B", FSkinImage.MANA_PHRYX_WB);
|
||||
symbolLookup.put("P/W/U", FSkinImage.MANA_PHRYX_WU);
|
||||
Forge.getAssets().symbolLookup().put("C", FSkinImage.MANA_COLORLESS);
|
||||
Forge.getAssets().symbolLookup().put("W", FSkinImage.MANA_W);
|
||||
Forge.getAssets().symbolLookup().put("U", FSkinImage.MANA_U);
|
||||
Forge.getAssets().symbolLookup().put("B", FSkinImage.MANA_B);
|
||||
Forge.getAssets().symbolLookup().put("R", FSkinImage.MANA_R);
|
||||
Forge.getAssets().symbolLookup().put("G", FSkinImage.MANA_G);
|
||||
Forge.getAssets().symbolLookup().put("W/U", FSkinImage.MANA_HYBRID_WU);
|
||||
Forge.getAssets().symbolLookup().put("U/B", FSkinImage.MANA_HYBRID_UB);
|
||||
Forge.getAssets().symbolLookup().put("B/R", FSkinImage.MANA_HYBRID_BR);
|
||||
Forge.getAssets().symbolLookup().put("R/G", FSkinImage.MANA_HYBRID_RG);
|
||||
Forge.getAssets().symbolLookup().put("G/W", FSkinImage.MANA_HYBRID_GW);
|
||||
Forge.getAssets().symbolLookup().put("W/B", FSkinImage.MANA_HYBRID_WB);
|
||||
Forge.getAssets().symbolLookup().put("U/R", FSkinImage.MANA_HYBRID_UR);
|
||||
Forge.getAssets().symbolLookup().put("B/G", FSkinImage.MANA_HYBRID_BG);
|
||||
Forge.getAssets().symbolLookup().put("R/W", FSkinImage.MANA_HYBRID_RW);
|
||||
Forge.getAssets().symbolLookup().put("G/U", FSkinImage.MANA_HYBRID_GU);
|
||||
Forge.getAssets().symbolLookup().put("2/W", FSkinImage.MANA_2W);
|
||||
Forge.getAssets().symbolLookup().put("2/U", FSkinImage.MANA_2U);
|
||||
Forge.getAssets().symbolLookup().put("2/B", FSkinImage.MANA_2B);
|
||||
Forge.getAssets().symbolLookup().put("2/R", FSkinImage.MANA_2R);
|
||||
Forge.getAssets().symbolLookup().put("2/G", FSkinImage.MANA_2G);
|
||||
Forge.getAssets().symbolLookup().put("P", FSkinImage.MANA_PHRYX);
|
||||
Forge.getAssets().symbolLookup().put("P/W", FSkinImage.MANA_PHRYX_W);
|
||||
Forge.getAssets().symbolLookup().put("P/U", FSkinImage.MANA_PHRYX_U);
|
||||
Forge.getAssets().symbolLookup().put("P/B", FSkinImage.MANA_PHRYX_B);
|
||||
Forge.getAssets().symbolLookup().put("P/R", FSkinImage.MANA_PHRYX_R);
|
||||
Forge.getAssets().symbolLookup().put("P/G", FSkinImage.MANA_PHRYX_G);
|
||||
Forge.getAssets().symbolLookup().put("W/P", FSkinImage.MANA_PHRYX_W);
|
||||
Forge.getAssets().symbolLookup().put("U/P", FSkinImage.MANA_PHRYX_U);
|
||||
Forge.getAssets().symbolLookup().put("B/P", FSkinImage.MANA_PHRYX_B);
|
||||
Forge.getAssets().symbolLookup().put("R/P", FSkinImage.MANA_PHRYX_R);
|
||||
Forge.getAssets().symbolLookup().put("G/P", FSkinImage.MANA_PHRYX_G);
|
||||
Forge.getAssets().symbolLookup().put("P/B/G", FSkinImage.MANA_PHRYX_BG);
|
||||
Forge.getAssets().symbolLookup().put("P/B/R", FSkinImage.MANA_PHRYX_BR);
|
||||
Forge.getAssets().symbolLookup().put("P/G/U", FSkinImage.MANA_PHRYX_GU);
|
||||
Forge.getAssets().symbolLookup().put("P/G/W", FSkinImage.MANA_PHRYX_GW);
|
||||
Forge.getAssets().symbolLookup().put("P/R/G", FSkinImage.MANA_PHRYX_RG);
|
||||
Forge.getAssets().symbolLookup().put("P/R/W", FSkinImage.MANA_PHRYX_RW);
|
||||
Forge.getAssets().symbolLookup().put("P/U/B", FSkinImage.MANA_PHRYX_UB);
|
||||
Forge.getAssets().symbolLookup().put("P/U/R", FSkinImage.MANA_PHRYX_UR);
|
||||
Forge.getAssets().symbolLookup().put("P/W/B", FSkinImage.MANA_PHRYX_WB);
|
||||
Forge.getAssets().symbolLookup().put("P/W/U", FSkinImage.MANA_PHRYX_WU);
|
||||
for (int i = 0; i <= 20; i++) {
|
||||
symbolLookup.put(String.valueOf(i), FSkinImage.valueOf("MANA_" + i));
|
||||
Forge.getAssets().symbolLookup().put(String.valueOf(i), FSkinImage.valueOf("MANA_" + i));
|
||||
}
|
||||
symbolLookup.put("X", FSkinImage.MANA_X);
|
||||
symbolLookup.put("Y", FSkinImage.MANA_Y);
|
||||
symbolLookup.put("Z", FSkinImage.MANA_Z);
|
||||
symbolLookup.put("CHAOS", FSkinImage.CHAOS);
|
||||
symbolLookup.put("Q", FSkinImage.UNTAP);
|
||||
symbolLookup.put("S", FSkinImage.MANA_SNOW);
|
||||
symbolLookup.put("T", FSkinImage.TAP);
|
||||
symbolLookup.put("E", FSkinImage.ENERGY);
|
||||
symbolLookup.put("AE", FSkinImage.AETHER_SHARD);
|
||||
symbolLookup.put("PW", FSkinImage.PW_BADGE_COMMON);
|
||||
symbolLookup.put("CR", FSkinImage.QUEST_COINSTACK);
|
||||
Forge.getAssets().symbolLookup().put("X", FSkinImage.MANA_X);
|
||||
Forge.getAssets().symbolLookup().put("Y", FSkinImage.MANA_Y);
|
||||
Forge.getAssets().symbolLookup().put("Z", FSkinImage.MANA_Z);
|
||||
Forge.getAssets().symbolLookup().put("CHAOS", FSkinImage.CHAOS);
|
||||
Forge.getAssets().symbolLookup().put("Q", FSkinImage.UNTAP);
|
||||
Forge.getAssets().symbolLookup().put("S", FSkinImage.MANA_SNOW);
|
||||
Forge.getAssets().symbolLookup().put("T", FSkinImage.TAP);
|
||||
Forge.getAssets().symbolLookup().put("E", FSkinImage.ENERGY);
|
||||
Forge.getAssets().symbolLookup().put("AE", FSkinImage.AETHER_SHARD);
|
||||
Forge.getAssets().symbolLookup().put("PW", FSkinImage.PW_BADGE_COMMON);
|
||||
Forge.getAssets().symbolLookup().put("CR", FSkinImage.QUEST_COINSTACK);
|
||||
}
|
||||
|
||||
public static String startColor(Color color) {
|
||||
@@ -192,7 +189,7 @@ public class TextRenderer {
|
||||
if (inSymbolCount > 0) {
|
||||
inSymbolCount--;
|
||||
if (text.length() > 0) {
|
||||
FSkinImage symbol = symbolLookup.get(text.toString());
|
||||
FSkinImage symbol = Forge.getAssets().symbolLookup().get(text.toString());
|
||||
if (symbol != null) {
|
||||
pieceWidth = lineHeight * CardFaceSymbols.FONT_SIZE_FACTOR;
|
||||
if (x + pieceWidth > width) {
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
*/
|
||||
package forge.card;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import forge.Forge;
|
||||
import forge.Graphics;
|
||||
import forge.assets.FSkinImage;
|
||||
import forge.card.mana.ManaCost;
|
||||
@@ -30,141 +29,140 @@ import forge.gui.error.BugReporter;
|
||||
|
||||
public class CardFaceSymbols {
|
||||
public static final float FONT_SIZE_FACTOR = 0.85f;
|
||||
private static final Map<String, FSkinImage> MANA_IMAGES = new HashMap<>(128);
|
||||
|
||||
public static void loadImages() {
|
||||
for (int i = 0; i <= 20; i++) {
|
||||
MANA_IMAGES.put(String.valueOf(i), FSkinImage.valueOf("MANA_" + i));
|
||||
Forge.getAssets().manaImages().put(String.valueOf(i), FSkinImage.valueOf("MANA_" + i));
|
||||
}
|
||||
MANA_IMAGES.put("X", FSkinImage.MANA_X);
|
||||
MANA_IMAGES.put("Y", FSkinImage.MANA_Y);
|
||||
MANA_IMAGES.put("Z", FSkinImage.MANA_Z);
|
||||
Forge.getAssets().manaImages().put("X", FSkinImage.MANA_X);
|
||||
Forge.getAssets().manaImages().put("Y", FSkinImage.MANA_Y);
|
||||
Forge.getAssets().manaImages().put("Z", FSkinImage.MANA_Z);
|
||||
|
||||
MANA_IMAGES.put("C", FSkinImage.MANA_COLORLESS);
|
||||
MANA_IMAGES.put("B", FSkinImage.MANA_B);
|
||||
MANA_IMAGES.put("BG", FSkinImage.MANA_HYBRID_BG);
|
||||
MANA_IMAGES.put("BR", FSkinImage.MANA_HYBRID_BR);
|
||||
MANA_IMAGES.put("G", FSkinImage.MANA_G);
|
||||
MANA_IMAGES.put("GU", FSkinImage.MANA_HYBRID_GU);
|
||||
MANA_IMAGES.put("GW", FSkinImage.MANA_HYBRID_GW);
|
||||
MANA_IMAGES.put("R", FSkinImage.MANA_R);
|
||||
MANA_IMAGES.put("RG", FSkinImage.MANA_HYBRID_RG);
|
||||
MANA_IMAGES.put("RW", FSkinImage.MANA_HYBRID_RW);
|
||||
MANA_IMAGES.put("U", FSkinImage.MANA_U);
|
||||
MANA_IMAGES.put("UB", FSkinImage.MANA_HYBRID_UB);
|
||||
MANA_IMAGES.put("UR", FSkinImage.MANA_HYBRID_UR);
|
||||
MANA_IMAGES.put("W", FSkinImage.MANA_W);
|
||||
MANA_IMAGES.put("WB", FSkinImage.MANA_HYBRID_WB);
|
||||
MANA_IMAGES.put("WU", FSkinImage.MANA_HYBRID_WU);
|
||||
MANA_IMAGES.put("P", FSkinImage.MANA_PHRYX);
|
||||
MANA_IMAGES.put("PW", FSkinImage.MANA_PHRYX_W);
|
||||
MANA_IMAGES.put("PR", FSkinImage.MANA_PHRYX_R);
|
||||
MANA_IMAGES.put("PU", FSkinImage.MANA_PHRYX_U);
|
||||
MANA_IMAGES.put("PB", FSkinImage.MANA_PHRYX_B);
|
||||
MANA_IMAGES.put("PG", FSkinImage.MANA_PHRYX_G);
|
||||
MANA_IMAGES.put("PBG", FSkinImage.MANA_PHRYX_BG);
|
||||
MANA_IMAGES.put("PBR", FSkinImage.MANA_PHRYX_BR);
|
||||
MANA_IMAGES.put("PGU", FSkinImage.MANA_PHRYX_GU);
|
||||
MANA_IMAGES.put("PGW", FSkinImage.MANA_PHRYX_GW);
|
||||
MANA_IMAGES.put("PRG", FSkinImage.MANA_PHRYX_RG);
|
||||
MANA_IMAGES.put("PRW", FSkinImage.MANA_PHRYX_RW);
|
||||
MANA_IMAGES.put("PUB", FSkinImage.MANA_PHRYX_UB);
|
||||
MANA_IMAGES.put("PUR", FSkinImage.MANA_PHRYX_UR);
|
||||
MANA_IMAGES.put("PWB", FSkinImage.MANA_PHRYX_WB);
|
||||
MANA_IMAGES.put("PWU", FSkinImage.MANA_PHRYX_WU);
|
||||
MANA_IMAGES.put("2W", FSkinImage.MANA_2W);
|
||||
MANA_IMAGES.put("2U", FSkinImage.MANA_2U);
|
||||
MANA_IMAGES.put("2R", FSkinImage.MANA_2R);
|
||||
MANA_IMAGES.put("2G", FSkinImage.MANA_2G);
|
||||
MANA_IMAGES.put("2B", FSkinImage.MANA_2B);
|
||||
Forge.getAssets().manaImages().put("C", FSkinImage.MANA_COLORLESS);
|
||||
Forge.getAssets().manaImages().put("B", FSkinImage.MANA_B);
|
||||
Forge.getAssets().manaImages().put("BG", FSkinImage.MANA_HYBRID_BG);
|
||||
Forge.getAssets().manaImages().put("BR", FSkinImage.MANA_HYBRID_BR);
|
||||
Forge.getAssets().manaImages().put("G", FSkinImage.MANA_G);
|
||||
Forge.getAssets().manaImages().put("GU", FSkinImage.MANA_HYBRID_GU);
|
||||
Forge.getAssets().manaImages().put("GW", FSkinImage.MANA_HYBRID_GW);
|
||||
Forge.getAssets().manaImages().put("R", FSkinImage.MANA_R);
|
||||
Forge.getAssets().manaImages().put("RG", FSkinImage.MANA_HYBRID_RG);
|
||||
Forge.getAssets().manaImages().put("RW", FSkinImage.MANA_HYBRID_RW);
|
||||
Forge.getAssets().manaImages().put("U", FSkinImage.MANA_U);
|
||||
Forge.getAssets().manaImages().put("UB", FSkinImage.MANA_HYBRID_UB);
|
||||
Forge.getAssets().manaImages().put("UR", FSkinImage.MANA_HYBRID_UR);
|
||||
Forge.getAssets().manaImages().put("W", FSkinImage.MANA_W);
|
||||
Forge.getAssets().manaImages().put("WB", FSkinImage.MANA_HYBRID_WB);
|
||||
Forge.getAssets().manaImages().put("WU", FSkinImage.MANA_HYBRID_WU);
|
||||
Forge.getAssets().manaImages().put("P", FSkinImage.MANA_PHRYX);
|
||||
Forge.getAssets().manaImages().put("PW", FSkinImage.MANA_PHRYX_W);
|
||||
Forge.getAssets().manaImages().put("PR", FSkinImage.MANA_PHRYX_R);
|
||||
Forge.getAssets().manaImages().put("PU", FSkinImage.MANA_PHRYX_U);
|
||||
Forge.getAssets().manaImages().put("PB", FSkinImage.MANA_PHRYX_B);
|
||||
Forge.getAssets().manaImages().put("PG", FSkinImage.MANA_PHRYX_G);
|
||||
Forge.getAssets().manaImages().put("PBG", FSkinImage.MANA_PHRYX_BG);
|
||||
Forge.getAssets().manaImages().put("PBR", FSkinImage.MANA_PHRYX_BR);
|
||||
Forge.getAssets().manaImages().put("PGU", FSkinImage.MANA_PHRYX_GU);
|
||||
Forge.getAssets().manaImages().put("PGW", FSkinImage.MANA_PHRYX_GW);
|
||||
Forge.getAssets().manaImages().put("PRG", FSkinImage.MANA_PHRYX_RG);
|
||||
Forge.getAssets().manaImages().put("PRW", FSkinImage.MANA_PHRYX_RW);
|
||||
Forge.getAssets().manaImages().put("PUB", FSkinImage.MANA_PHRYX_UB);
|
||||
Forge.getAssets().manaImages().put("PUR", FSkinImage.MANA_PHRYX_UR);
|
||||
Forge.getAssets().manaImages().put("PWB", FSkinImage.MANA_PHRYX_WB);
|
||||
Forge.getAssets().manaImages().put("PWU", FSkinImage.MANA_PHRYX_WU);
|
||||
Forge.getAssets().manaImages().put("2W", FSkinImage.MANA_2W);
|
||||
Forge.getAssets().manaImages().put("2U", FSkinImage.MANA_2U);
|
||||
Forge.getAssets().manaImages().put("2R", FSkinImage.MANA_2R);
|
||||
Forge.getAssets().manaImages().put("2G", FSkinImage.MANA_2G);
|
||||
Forge.getAssets().manaImages().put("2B", FSkinImage.MANA_2B);
|
||||
|
||||
MANA_IMAGES.put("S", FSkinImage.MANA_SNOW);
|
||||
MANA_IMAGES.put("T", FSkinImage.TAP);
|
||||
MANA_IMAGES.put("E", FSkinImage.ENERGY);
|
||||
MANA_IMAGES.put("slash", FSkinImage.SLASH);
|
||||
MANA_IMAGES.put("attack", FSkinImage.ATTACK);
|
||||
MANA_IMAGES.put("defend", FSkinImage.DEFEND);
|
||||
MANA_IMAGES.put("summonsick", FSkinImage.SUMMONSICK);
|
||||
MANA_IMAGES.put("phasing", FSkinImage.PHASING);
|
||||
MANA_IMAGES.put("sacrifice", FSkinImage.COSTRESERVED);
|
||||
MANA_IMAGES.put("counters1", FSkinImage.COUNTERS1);
|
||||
MANA_IMAGES.put("counters2", FSkinImage.COUNTERS2);
|
||||
MANA_IMAGES.put("counters3", FSkinImage.COUNTERS3);
|
||||
MANA_IMAGES.put("countersMulti", FSkinImage.COUNTERS_MULTI);
|
||||
Forge.getAssets().manaImages().put("S", FSkinImage.MANA_SNOW);
|
||||
Forge.getAssets().manaImages().put("T", FSkinImage.TAP);
|
||||
Forge.getAssets().manaImages().put("E", FSkinImage.ENERGY);
|
||||
Forge.getAssets().manaImages().put("slash", FSkinImage.SLASH);
|
||||
Forge.getAssets().manaImages().put("attack", FSkinImage.ATTACK);
|
||||
Forge.getAssets().manaImages().put("defend", FSkinImage.DEFEND);
|
||||
Forge.getAssets().manaImages().put("summonsick", FSkinImage.SUMMONSICK);
|
||||
Forge.getAssets().manaImages().put("phasing", FSkinImage.PHASING);
|
||||
Forge.getAssets().manaImages().put("sacrifice", FSkinImage.COSTRESERVED);
|
||||
Forge.getAssets().manaImages().put("counters1", FSkinImage.COUNTERS1);
|
||||
Forge.getAssets().manaImages().put("counters2", FSkinImage.COUNTERS2);
|
||||
Forge.getAssets().manaImages().put("counters3", FSkinImage.COUNTERS3);
|
||||
Forge.getAssets().manaImages().put("countersMulti", FSkinImage.COUNTERS_MULTI);
|
||||
|
||||
MANA_IMAGES.put("foil01", FSkinImage.FOIL_01);
|
||||
MANA_IMAGES.put("foil02", FSkinImage.FOIL_02);
|
||||
MANA_IMAGES.put("foil03", FSkinImage.FOIL_03);
|
||||
MANA_IMAGES.put("foil04", FSkinImage.FOIL_04);
|
||||
MANA_IMAGES.put("foil05", FSkinImage.FOIL_05);
|
||||
MANA_IMAGES.put("foil06", FSkinImage.FOIL_06);
|
||||
MANA_IMAGES.put("foil07", FSkinImage.FOIL_07);
|
||||
MANA_IMAGES.put("foil08", FSkinImage.FOIL_08);
|
||||
MANA_IMAGES.put("foil09", FSkinImage.FOIL_09);
|
||||
MANA_IMAGES.put("foil10", FSkinImage.FOIL_10);
|
||||
Forge.getAssets().manaImages().put("foil01", FSkinImage.FOIL_01);
|
||||
Forge.getAssets().manaImages().put("foil02", FSkinImage.FOIL_02);
|
||||
Forge.getAssets().manaImages().put("foil03", FSkinImage.FOIL_03);
|
||||
Forge.getAssets().manaImages().put("foil04", FSkinImage.FOIL_04);
|
||||
Forge.getAssets().manaImages().put("foil05", FSkinImage.FOIL_05);
|
||||
Forge.getAssets().manaImages().put("foil06", FSkinImage.FOIL_06);
|
||||
Forge.getAssets().manaImages().put("foil07", FSkinImage.FOIL_07);
|
||||
Forge.getAssets().manaImages().put("foil08", FSkinImage.FOIL_08);
|
||||
Forge.getAssets().manaImages().put("foil09", FSkinImage.FOIL_09);
|
||||
Forge.getAssets().manaImages().put("foil10", FSkinImage.FOIL_10);
|
||||
|
||||
MANA_IMAGES.put("foil11", FSkinImage.FOIL_11);
|
||||
MANA_IMAGES.put("foil12", FSkinImage.FOIL_12);
|
||||
MANA_IMAGES.put("foil13", FSkinImage.FOIL_13);
|
||||
MANA_IMAGES.put("foil14", FSkinImage.FOIL_14);
|
||||
MANA_IMAGES.put("foil15", FSkinImage.FOIL_15);
|
||||
MANA_IMAGES.put("foil16", FSkinImage.FOIL_16);
|
||||
MANA_IMAGES.put("foil17", FSkinImage.FOIL_17);
|
||||
MANA_IMAGES.put("foil18", FSkinImage.FOIL_18);
|
||||
MANA_IMAGES.put("foil19", FSkinImage.FOIL_19);
|
||||
MANA_IMAGES.put("foil20", FSkinImage.FOIL_20);
|
||||
Forge.getAssets().manaImages().put("foil11", FSkinImage.FOIL_11);
|
||||
Forge.getAssets().manaImages().put("foil12", FSkinImage.FOIL_12);
|
||||
Forge.getAssets().manaImages().put("foil13", FSkinImage.FOIL_13);
|
||||
Forge.getAssets().manaImages().put("foil14", FSkinImage.FOIL_14);
|
||||
Forge.getAssets().manaImages().put("foil15", FSkinImage.FOIL_15);
|
||||
Forge.getAssets().manaImages().put("foil16", FSkinImage.FOIL_16);
|
||||
Forge.getAssets().manaImages().put("foil17", FSkinImage.FOIL_17);
|
||||
Forge.getAssets().manaImages().put("foil18", FSkinImage.FOIL_18);
|
||||
Forge.getAssets().manaImages().put("foil19", FSkinImage.FOIL_19);
|
||||
Forge.getAssets().manaImages().put("foil20", FSkinImage.FOIL_20);
|
||||
|
||||
MANA_IMAGES.put("commander", FSkinImage.IMG_ABILITY_COMMANDER);
|
||||
Forge.getAssets().manaImages().put("commander", FSkinImage.IMG_ABILITY_COMMANDER);
|
||||
|
||||
MANA_IMAGES.put("deathtouch", FSkinImage.IMG_ABILITY_DEATHTOUCH);
|
||||
MANA_IMAGES.put("defender", FSkinImage.IMG_ABILITY_DEFENDER);
|
||||
MANA_IMAGES.put("doublestrike", FSkinImage.IMG_ABILITY_DOUBLE_STRIKE);
|
||||
MANA_IMAGES.put("firststrike", FSkinImage.IMG_ABILITY_FIRST_STRIKE);
|
||||
MANA_IMAGES.put("fear", FSkinImage.IMG_ABILITY_FEAR);
|
||||
MANA_IMAGES.put("flash", FSkinImage.IMG_ABILITY_FLASH);
|
||||
MANA_IMAGES.put("flying", FSkinImage.IMG_ABILITY_FLYING);
|
||||
MANA_IMAGES.put("haste", FSkinImage.IMG_ABILITY_HASTE);
|
||||
MANA_IMAGES.put("hexproof", FSkinImage.IMG_ABILITY_HEXPROOF);
|
||||
MANA_IMAGES.put("horsemanship", FSkinImage.IMG_ABILITY_HORSEMANSHIP);
|
||||
MANA_IMAGES.put("indestructible", FSkinImage.IMG_ABILITY_INDESTRUCTIBLE);
|
||||
MANA_IMAGES.put("intimidate", FSkinImage.IMG_ABILITY_INTIMIDATE);
|
||||
MANA_IMAGES.put("landwalk", FSkinImage.IMG_ABILITY_LANDWALK);
|
||||
MANA_IMAGES.put("lifelink", FSkinImage.IMG_ABILITY_LIFELINK);
|
||||
MANA_IMAGES.put("menace", FSkinImage.IMG_ABILITY_MENACE);
|
||||
MANA_IMAGES.put("reach", FSkinImage.IMG_ABILITY_REACH);
|
||||
MANA_IMAGES.put("shadow", FSkinImage.IMG_ABILITY_SHADOW);
|
||||
MANA_IMAGES.put("shroud", FSkinImage.IMG_ABILITY_SHROUD);
|
||||
MANA_IMAGES.put("trample", FSkinImage.IMG_ABILITY_TRAMPLE);
|
||||
MANA_IMAGES.put("vigilance", FSkinImage.IMG_ABILITY_VIGILANCE);
|
||||
Forge.getAssets().manaImages().put("deathtouch", FSkinImage.IMG_ABILITY_DEATHTOUCH);
|
||||
Forge.getAssets().manaImages().put("defender", FSkinImage.IMG_ABILITY_DEFENDER);
|
||||
Forge.getAssets().manaImages().put("doublestrike", FSkinImage.IMG_ABILITY_DOUBLE_STRIKE);
|
||||
Forge.getAssets().manaImages().put("firststrike", FSkinImage.IMG_ABILITY_FIRST_STRIKE);
|
||||
Forge.getAssets().manaImages().put("fear", FSkinImage.IMG_ABILITY_FEAR);
|
||||
Forge.getAssets().manaImages().put("flash", FSkinImage.IMG_ABILITY_FLASH);
|
||||
Forge.getAssets().manaImages().put("flying", FSkinImage.IMG_ABILITY_FLYING);
|
||||
Forge.getAssets().manaImages().put("haste", FSkinImage.IMG_ABILITY_HASTE);
|
||||
Forge.getAssets().manaImages().put("hexproof", FSkinImage.IMG_ABILITY_HEXPROOF);
|
||||
Forge.getAssets().manaImages().put("horsemanship", FSkinImage.IMG_ABILITY_HORSEMANSHIP);
|
||||
Forge.getAssets().manaImages().put("indestructible", FSkinImage.IMG_ABILITY_INDESTRUCTIBLE);
|
||||
Forge.getAssets().manaImages().put("intimidate", FSkinImage.IMG_ABILITY_INTIMIDATE);
|
||||
Forge.getAssets().manaImages().put("landwalk", FSkinImage.IMG_ABILITY_LANDWALK);
|
||||
Forge.getAssets().manaImages().put("lifelink", FSkinImage.IMG_ABILITY_LIFELINK);
|
||||
Forge.getAssets().manaImages().put("menace", FSkinImage.IMG_ABILITY_MENACE);
|
||||
Forge.getAssets().manaImages().put("reach", FSkinImage.IMG_ABILITY_REACH);
|
||||
Forge.getAssets().manaImages().put("shadow", FSkinImage.IMG_ABILITY_SHADOW);
|
||||
Forge.getAssets().manaImages().put("shroud", FSkinImage.IMG_ABILITY_SHROUD);
|
||||
Forge.getAssets().manaImages().put("trample", FSkinImage.IMG_ABILITY_TRAMPLE);
|
||||
Forge.getAssets().manaImages().put("vigilance", FSkinImage.IMG_ABILITY_VIGILANCE);
|
||||
//hexproof from
|
||||
MANA_IMAGES.put("hexproofR", FSkinImage.IMG_ABILITY_HEXPROOF_R);
|
||||
MANA_IMAGES.put("hexproofG", FSkinImage.IMG_ABILITY_HEXPROOF_G);
|
||||
MANA_IMAGES.put("hexproofB", FSkinImage.IMG_ABILITY_HEXPROOF_B);
|
||||
MANA_IMAGES.put("hexproofU", FSkinImage.IMG_ABILITY_HEXPROOF_U);
|
||||
MANA_IMAGES.put("hexproofW", FSkinImage.IMG_ABILITY_HEXPROOF_W);
|
||||
MANA_IMAGES.put("hexproofC", FSkinImage.IMG_ABILITY_HEXPROOF_C);
|
||||
MANA_IMAGES.put("hexproofUB", FSkinImage.IMG_ABILITY_HEXPROOF_UB);
|
||||
Forge.getAssets().manaImages().put("hexproofR", FSkinImage.IMG_ABILITY_HEXPROOF_R);
|
||||
Forge.getAssets().manaImages().put("hexproofG", FSkinImage.IMG_ABILITY_HEXPROOF_G);
|
||||
Forge.getAssets().manaImages().put("hexproofB", FSkinImage.IMG_ABILITY_HEXPROOF_B);
|
||||
Forge.getAssets().manaImages().put("hexproofU", FSkinImage.IMG_ABILITY_HEXPROOF_U);
|
||||
Forge.getAssets().manaImages().put("hexproofW", FSkinImage.IMG_ABILITY_HEXPROOF_W);
|
||||
Forge.getAssets().manaImages().put("hexproofC", FSkinImage.IMG_ABILITY_HEXPROOF_C);
|
||||
Forge.getAssets().manaImages().put("hexproofUB", FSkinImage.IMG_ABILITY_HEXPROOF_UB);
|
||||
//token icon
|
||||
MANA_IMAGES.put("token", FSkinImage.IMG_ABILITY_TOKEN);
|
||||
Forge.getAssets().manaImages().put("token", FSkinImage.IMG_ABILITY_TOKEN);
|
||||
//protection from
|
||||
MANA_IMAGES.put("protectAll", FSkinImage.IMG_ABILITY_PROTECT_ALL);
|
||||
MANA_IMAGES.put("protectB", FSkinImage.IMG_ABILITY_PROTECT_B);
|
||||
MANA_IMAGES.put("protectBU", FSkinImage.IMG_ABILITY_PROTECT_BU);
|
||||
MANA_IMAGES.put("protectBW", FSkinImage.IMG_ABILITY_PROTECT_BW);
|
||||
MANA_IMAGES.put("protectColoredSpells", FSkinImage.IMG_ABILITY_PROTECT_COLOREDSPELLS);
|
||||
MANA_IMAGES.put("protectG", FSkinImage.IMG_ABILITY_PROTECT_G);
|
||||
MANA_IMAGES.put("protectGB", FSkinImage.IMG_ABILITY_PROTECT_GB);
|
||||
MANA_IMAGES.put("protectGU", FSkinImage.IMG_ABILITY_PROTECT_GU);
|
||||
MANA_IMAGES.put("protectGW", FSkinImage.IMG_ABILITY_PROTECT_GW);
|
||||
MANA_IMAGES.put("protectGeneric", FSkinImage.IMG_ABILITY_PROTECT_GENERIC);
|
||||
MANA_IMAGES.put("protectR", FSkinImage.IMG_ABILITY_PROTECT_R);
|
||||
MANA_IMAGES.put("protectRB", FSkinImage.IMG_ABILITY_PROTECT_RB);
|
||||
MANA_IMAGES.put("protectRG", FSkinImage.IMG_ABILITY_PROTECT_RG);
|
||||
MANA_IMAGES.put("protectRU", FSkinImage.IMG_ABILITY_PROTECT_RU);
|
||||
MANA_IMAGES.put("protectRW", FSkinImage.IMG_ABILITY_PROTECT_RW);
|
||||
MANA_IMAGES.put("protectU", FSkinImage.IMG_ABILITY_PROTECT_U);
|
||||
MANA_IMAGES.put("protectUW", FSkinImage.IMG_ABILITY_PROTECT_UW);
|
||||
MANA_IMAGES.put("protectW", FSkinImage.IMG_ABILITY_PROTECT_W);
|
||||
Forge.getAssets().manaImages().put("protectAll", FSkinImage.IMG_ABILITY_PROTECT_ALL);
|
||||
Forge.getAssets().manaImages().put("protectB", FSkinImage.IMG_ABILITY_PROTECT_B);
|
||||
Forge.getAssets().manaImages().put("protectBU", FSkinImage.IMG_ABILITY_PROTECT_BU);
|
||||
Forge.getAssets().manaImages().put("protectBW", FSkinImage.IMG_ABILITY_PROTECT_BW);
|
||||
Forge.getAssets().manaImages().put("protectColoredSpells", FSkinImage.IMG_ABILITY_PROTECT_COLOREDSPELLS);
|
||||
Forge.getAssets().manaImages().put("protectG", FSkinImage.IMG_ABILITY_PROTECT_G);
|
||||
Forge.getAssets().manaImages().put("protectGB", FSkinImage.IMG_ABILITY_PROTECT_GB);
|
||||
Forge.getAssets().manaImages().put("protectGU", FSkinImage.IMG_ABILITY_PROTECT_GU);
|
||||
Forge.getAssets().manaImages().put("protectGW", FSkinImage.IMG_ABILITY_PROTECT_GW);
|
||||
Forge.getAssets().manaImages().put("protectGeneric", FSkinImage.IMG_ABILITY_PROTECT_GENERIC);
|
||||
Forge.getAssets().manaImages().put("protectR", FSkinImage.IMG_ABILITY_PROTECT_R);
|
||||
Forge.getAssets().manaImages().put("protectRB", FSkinImage.IMG_ABILITY_PROTECT_RB);
|
||||
Forge.getAssets().manaImages().put("protectRG", FSkinImage.IMG_ABILITY_PROTECT_RG);
|
||||
Forge.getAssets().manaImages().put("protectRU", FSkinImage.IMG_ABILITY_PROTECT_RU);
|
||||
Forge.getAssets().manaImages().put("protectRW", FSkinImage.IMG_ABILITY_PROTECT_RW);
|
||||
Forge.getAssets().manaImages().put("protectU", FSkinImage.IMG_ABILITY_PROTECT_U);
|
||||
Forge.getAssets().manaImages().put("protectUW", FSkinImage.IMG_ABILITY_PROTECT_UW);
|
||||
Forge.getAssets().manaImages().put("protectW", FSkinImage.IMG_ABILITY_PROTECT_W);
|
||||
}
|
||||
|
||||
public static void drawManaCost(Graphics g, ManaCost manaCost, float x, float y, final float imageSize) {
|
||||
@@ -228,7 +226,7 @@ public class CardFaceSymbols {
|
||||
StringTokenizer tok = new StringTokenizer(s, " ");
|
||||
while (tok.hasMoreTokens()) {
|
||||
String symbol = tok.nextToken();
|
||||
FSkinImage image = MANA_IMAGES.get(symbol);
|
||||
FSkinImage image = Forge.getAssets().manaImages().get(symbol);
|
||||
if (image == null) {
|
||||
BugReporter.reportBug("Symbol not recognized \"" + symbol + "\" in string: " + s);
|
||||
continue;
|
||||
@@ -245,7 +243,7 @@ public class CardFaceSymbols {
|
||||
}
|
||||
|
||||
public static void drawSymbol(final String imageName, final Graphics g, final float x, final float y, final float w, final float h) {
|
||||
g.drawImage(MANA_IMAGES.get(imageName), x, y, w, h);
|
||||
g.drawImage(Forge.getAssets().manaImages().get(imageName), x, y, w, h);
|
||||
}
|
||||
|
||||
public static float getWidth(final ManaCost manaCost, float imageSize) {
|
||||
|
||||
@@ -52,6 +52,7 @@ public class CardImageRenderer {
|
||||
prevImageWidth = 0;
|
||||
prevImageHeight = 0;
|
||||
forgeArt.clear();
|
||||
stretchedArt.clear();
|
||||
}
|
||||
|
||||
private static void updateStaticFields(float w, float h) {
|
||||
@@ -267,6 +268,7 @@ public class CardImageRenderer {
|
||||
}
|
||||
|
||||
public static final FBufferedImage forgeArt;
|
||||
private static final FBufferedImage stretchedArt;
|
||||
static {
|
||||
final float logoWidth = FSkinImage.LOGO.getWidth();
|
||||
final float logoHeight = FSkinImage.LOGO.getHeight();
|
||||
@@ -280,9 +282,25 @@ public class CardImageRenderer {
|
||||
g.drawImage(FSkinImage.LOGO, (w - logoWidth) / 2, (h - logoHeight) / 2, logoWidth, logoHeight);
|
||||
}
|
||||
};
|
||||
stretchedArt = new FBufferedImage(w, h) {
|
||||
@Override
|
||||
protected void draw(Graphics g, float w, float h) {
|
||||
g.drawImage(FSkinTexture.BG_TEXTURE, 0, 0, w, h);
|
||||
g.fillRect(FScreen.TEXTURE_OVERLAY_COLOR, 0, 0, w, h);
|
||||
g.drawImage(FSkinImage.LOGO, (w - logoWidth) / 2, ((h - logoHeight) / 2)+h/3.5f, logoWidth, logoHeight/3);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void drawArt(CardView cv, Graphics g, float x, float y, float w, float h, boolean altState, boolean isFaceDown) {
|
||||
boolean isSaga = cv.getCurrentState().getType().hasSubtype("Saga");
|
||||
boolean isClass = cv.getCurrentState().getType().hasSubtype("Class");
|
||||
boolean isDungeon = cv.getCurrentState().getType().isDungeon();
|
||||
if (altState && cv.hasAlternateState()) {
|
||||
isSaga = cv.getAlternateState().getType().hasSubtype("Saga");
|
||||
isClass = cv.getAlternateState().getType().hasSubtype("Class");
|
||||
isDungeon = cv.getAlternateState().getType().isDungeon();
|
||||
}
|
||||
if (cv == null) {
|
||||
if (isFaceDown) {
|
||||
Texture cardBack = ImageCache.getImage(ImageKeys.getTokenKey(ImageKeys.HIDDEN_CARD), false);
|
||||
@@ -292,7 +310,11 @@ public class CardImageRenderer {
|
||||
}
|
||||
}
|
||||
//fallback
|
||||
g.drawImage(forgeArt, x, y, w, h);
|
||||
if (isSaga || isClass || isDungeon) {
|
||||
g.drawImage(stretchedArt, x, y, w, h);
|
||||
} else {
|
||||
g.drawImage(forgeArt, x, y, w, h);
|
||||
}
|
||||
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
|
||||
return;
|
||||
}
|
||||
@@ -303,7 +325,11 @@ public class CardImageRenderer {
|
||||
|| cv.getCurrentState().getImageKey().equals(ImageKeys.getTokenKey(ImageKeys.FORETELL_IMAGE)));
|
||||
if (cardArt != null) {
|
||||
if (isHidden && !altState) {
|
||||
if (isSaga || isClass || isDungeon) {
|
||||
g.drawImage(stretchedArt, x, y, w, h);
|
||||
} else {
|
||||
g.drawImage(forgeArt, x, y, w, h);
|
||||
}
|
||||
} else if (cv.getCurrentState().getImageKey().equals(ImageKeys.getTokenKey(ImageKeys.MANIFEST_IMAGE)) && !altState) {
|
||||
altArt = CardRenderer.getAlternateCardArt(ImageKeys.getTokenKey(ImageKeys.MANIFEST_IMAGE), false);
|
||||
g.drawImage(altArt, x, y, w, h);
|
||||
@@ -330,10 +356,18 @@ public class CardImageRenderer {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g.drawImage(forgeArt, x, y, w, h);
|
||||
if (isSaga || isClass || isDungeon) {
|
||||
g.drawImage(stretchedArt, x, y, w, h);
|
||||
} else {
|
||||
g.drawImage(forgeArt, x, y, w, h);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g.drawImage(forgeArt, x, y, w, h);
|
||||
if (isSaga || isClass || isDungeon) {
|
||||
g.drawImage(stretchedArt, x, y, w, h);
|
||||
} else {
|
||||
g.drawImage(forgeArt, x, y, w, h);
|
||||
}
|
||||
}
|
||||
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
|
||||
}
|
||||
|
||||
@@ -67,28 +67,28 @@ public class CardRenderer {
|
||||
|
||||
// class that simplifies the callback logic of CachedCardImage
|
||||
static class RendererCachedCardImage extends CachedCardImage {
|
||||
boolean clearCardArtCache = false;
|
||||
boolean clearcardArtCache = false;
|
||||
|
||||
public RendererCachedCardImage(CardView card, boolean clearArtCache) {
|
||||
super(card);
|
||||
this.clearCardArtCache = clearArtCache;
|
||||
this.clearcardArtCache = clearArtCache;
|
||||
}
|
||||
|
||||
public RendererCachedCardImage(InventoryItem ii, boolean clearArtCache) {
|
||||
super(ii);
|
||||
this.clearCardArtCache = clearArtCache;
|
||||
this.clearcardArtCache = clearArtCache;
|
||||
}
|
||||
|
||||
public RendererCachedCardImage(String key, boolean clearArtCache) {
|
||||
super(key);
|
||||
this.clearCardArtCache = clearArtCache;
|
||||
this.clearcardArtCache = clearArtCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onImageFetched() {
|
||||
ImageCache.clear();
|
||||
if (clearCardArtCache) {
|
||||
cardArtCache.remove(key);
|
||||
if (clearcardArtCache) {
|
||||
Forge.getAssets().cardArtCache().remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,8 +104,6 @@ public class CardRenderer {
|
||||
private static final float BORDER_THICKNESS = Utils.scale(1);
|
||||
public static final float PADDING_MULTIPLIER = 0.021f;
|
||||
public static final float CROP_MULTIPLIER = 0.96f;
|
||||
|
||||
private static Map<Integer, BitmapFont> counterFonts = new HashMap<>();
|
||||
private static final Color counterBackgroundColor = new Color(0f, 0f, 0f, 0.9f);
|
||||
private static final Map<CounterType, Color> counterColorCache = new HashMap<>();
|
||||
private static final GlyphLayout layout = new GlyphLayout();
|
||||
@@ -191,13 +189,12 @@ public class CardRenderer {
|
||||
return Math.round(MANA_SYMBOL_SIZE + FSkinFont.get(12).getLineHeight() + 3 * FList.PADDING + 1);
|
||||
}
|
||||
|
||||
private static final Map<String, FImageComplex> cardArtCache = new HashMap<>(1024);
|
||||
public static final float CARD_ART_RATIO = 1.302f;
|
||||
public static final float CARD_ART_HEIGHT_PERCENTAGE = 0.43f;
|
||||
private static List<String> classicModuleCardtoCrop = FileUtil.readFile(ForgeConstants.CLASSIC_MODULE_CARD_TO_CROP_FILE);
|
||||
|
||||
public static void clearcardArtCache(){
|
||||
cardArtCache.clear();
|
||||
Forge.getAssets().cardArtCache().clear();
|
||||
}
|
||||
|
||||
//extract card art from the given card
|
||||
@@ -221,7 +218,7 @@ public class CardRenderer {
|
||||
}
|
||||
|
||||
public static FImageComplex getCardArt(String imageKey, boolean isSplitCard, boolean isHorizontalCard, boolean isAftermathCard, boolean isSaga, boolean isClass, boolean isDungeon, boolean isFlipCard, boolean isPlanesWalker, boolean isModernFrame) {
|
||||
FImageComplex cardArt = cardArtCache.get(imageKey);
|
||||
FImageComplex cardArt = Forge.getAssets().cardArtCache().get(imageKey);
|
||||
boolean isClassicModule = imageKey != null && imageKey.length() > 2 && classicModuleCardtoCrop.contains(imageKey.substring(ImageKeys.CARD_PREFIX.length()).replace(".jpg", "").replace(".png", ""));
|
||||
if (cardArt == null) {
|
||||
Texture image = new RendererCachedCardImage(imageKey, true).getImage();
|
||||
@@ -282,7 +279,7 @@ public class CardRenderer {
|
||||
w *= artH / srcH;
|
||||
h *= artW / srcW;
|
||||
cardArt = new FRotatedImage(image, Math.round(x), Math.round(y), Math.round(w), Math.round(h), true);
|
||||
cardArtCache.put(imageKey, cardArt);
|
||||
Forge.getAssets().cardArtCache().put(imageKey, cardArt);
|
||||
return cardArt;
|
||||
}
|
||||
} else {
|
||||
@@ -305,7 +302,7 @@ public class CardRenderer {
|
||||
cardArt = new FTextureRegionImage(new TextureRegion(image, Math.round(x), Math.round(y), Math.round(w), Math.round(h)));
|
||||
}
|
||||
if (!CardImageRenderer.forgeArt.equals(cardArt))
|
||||
cardArtCache.put(imageKey, cardArt);
|
||||
Forge.getAssets().cardArtCache().put(imageKey, cardArt);
|
||||
}
|
||||
}
|
||||
//fix display for effect
|
||||
@@ -315,13 +312,13 @@ public class CardRenderer {
|
||||
}
|
||||
|
||||
public static FImageComplex getAftermathSecondCardArt(final String imageKey) {
|
||||
FImageComplex cardArt = cardArtCache.get("Aftermath_second_"+imageKey);
|
||||
FImageComplex cardArt = Forge.getAssets().cardArtCache().get("Aftermath_second_"+imageKey);
|
||||
if (cardArt == null) {
|
||||
Texture image = new CachedCardImage(imageKey) {
|
||||
@Override
|
||||
public void onImageFetched() {
|
||||
ImageCache.clear();
|
||||
cardArtCache.remove("Aftermath_second_" + imageKey);
|
||||
Forge.getAssets().cardArtCache().remove("Aftermath_second_" + imageKey);
|
||||
}
|
||||
}.getImage();
|
||||
if (image != null) {
|
||||
@@ -341,20 +338,20 @@ public class CardRenderer {
|
||||
|
||||
}
|
||||
if (!CardImageRenderer.forgeArt.equals(cardArt))
|
||||
cardArtCache.put("Aftermath_second_"+imageKey, cardArt);
|
||||
Forge.getAssets().cardArtCache().put("Aftermath_second_"+imageKey, cardArt);
|
||||
}
|
||||
}
|
||||
return cardArt;
|
||||
}
|
||||
|
||||
public static FImageComplex getAlternateCardArt(final String imageKey, boolean isPlanesWalker) {
|
||||
FImageComplex cardArt = cardArtCache.get("Alternate_"+imageKey);
|
||||
FImageComplex cardArt = Forge.getAssets().cardArtCache().get("Alternate_"+imageKey);
|
||||
if (cardArt == null) {
|
||||
Texture image = new CachedCardImage(imageKey) {
|
||||
@Override
|
||||
public void onImageFetched() {
|
||||
ImageCache.clear();
|
||||
cardArtCache.remove("Alternate_" + imageKey);
|
||||
Forge.getAssets().cardArtCache().remove("Alternate_" + imageKey);
|
||||
}
|
||||
}.getImage();
|
||||
if (image != null) {
|
||||
@@ -388,7 +385,7 @@ public class CardRenderer {
|
||||
cardArt = new FTextureRegionImage(new TextureRegion(image, Math.round(x), Math.round(y), Math.round(w), Math.round(h)));
|
||||
}
|
||||
if (!CardImageRenderer.forgeArt.equals(cardArt))
|
||||
cardArtCache.put("Alternate_"+imageKey, cardArt);
|
||||
Forge.getAssets().cardArtCache().put("Alternate_"+imageKey, cardArt);
|
||||
}
|
||||
}
|
||||
return cardArt;
|
||||
@@ -397,9 +394,9 @@ public class CardRenderer {
|
||||
public static FImageComplex getMeldCardParts(final String imageKey, boolean bottom) {
|
||||
FImageComplex cardArt;
|
||||
if (!bottom) {
|
||||
cardArt = cardArtCache.get("Meld_primary_"+imageKey);
|
||||
cardArt = Forge.getAssets().cardArtCache().get("Meld_primary_"+imageKey);
|
||||
} else {
|
||||
cardArt = cardArtCache.get("Meld_secondary_"+imageKey);
|
||||
cardArt = Forge.getAssets().cardArtCache().get("Meld_secondary_"+imageKey);
|
||||
}
|
||||
|
||||
if (cardArt == null) {
|
||||
@@ -407,8 +404,8 @@ public class CardRenderer {
|
||||
@Override
|
||||
public void onImageFetched() {
|
||||
ImageCache.clear();
|
||||
cardArtCache.remove("Meld_primary_" + imageKey);
|
||||
cardArtCache.remove("Meld_secondary_" + imageKey);
|
||||
Forge.getAssets().cardArtCache().remove("Meld_primary_" + imageKey);
|
||||
Forge.getAssets().cardArtCache().remove("Meld_secondary_" + imageKey);
|
||||
}
|
||||
}.getImage();
|
||||
if (image != null) {
|
||||
@@ -423,9 +420,9 @@ public class CardRenderer {
|
||||
|
||||
}
|
||||
if (!bottom && !CardImageRenderer.forgeArt.equals(cardArt))
|
||||
cardArtCache.put("Meld_primary_"+imageKey, cardArt);
|
||||
Forge.getAssets().cardArtCache().put("Meld_primary_"+imageKey, cardArt);
|
||||
else if (!CardImageRenderer.forgeArt.equals(cardArt))
|
||||
cardArtCache.put("Meld_secondary_"+imageKey, cardArt);
|
||||
Forge.getAssets().cardArtCache().put("Meld_secondary_"+imageKey, cardArt);
|
||||
}
|
||||
}
|
||||
return cardArt;
|
||||
@@ -1101,7 +1098,7 @@ public class CardRenderer {
|
||||
private static void drawCounterTabs(final CardView card, final Graphics g, final float x, final float y, final float w, final float h) {
|
||||
|
||||
int fontSize = Math.max(11, Math.min(22, (int) (h * 0.08)));
|
||||
BitmapFont font = counterFonts.get(fontSize);
|
||||
BitmapFont font = Forge.getAssets().counterFonts().get(fontSize);
|
||||
|
||||
final float additionalXOffset = 3f * ((fontSize - 11) / 11f);
|
||||
final float variableWidth = ((fontSize - 11) / 11f) * 44f;
|
||||
@@ -1218,7 +1215,7 @@ public class CardRenderer {
|
||||
private static void drawMarkersTabs(final List<String> markers, final Graphics g, final float x, final float y, final float w, final float h, boolean larger) {
|
||||
|
||||
int fontSize = larger ? Math.max(9, Math.min(22, (int) (h * 0.08))) : Math.max(8, Math.min(22, (int) (h * 0.05)));
|
||||
BitmapFont font = counterFonts.get(fontSize);
|
||||
BitmapFont font = Forge.getAssets().counterFonts().get(fontSize);
|
||||
|
||||
final float additionalXOffset = 3f * ((fontSize - 8) / 8f);
|
||||
|
||||
@@ -1410,7 +1407,7 @@ public class CardRenderer {
|
||||
textureRegions.add(new TextureRegion(texture));
|
||||
}
|
||||
|
||||
counterFonts.put(fontSize, new BitmapFont(fontData, textureRegions, true));
|
||||
Forge.getAssets().counterFonts().put(fontSize, new BitmapFont(fontData, textureRegions, true));
|
||||
|
||||
generator.dispose();
|
||||
packer.dispose();
|
||||
|
||||
@@ -131,75 +131,59 @@ public class FDeckChooser extends FScreen {
|
||||
lstDecks = new DeckManager(gameType0);
|
||||
isAi = isAi0;
|
||||
|
||||
lstDecks.setItemActivateHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
if (lstDecks.getGameType() == GameType.DeckManager) {
|
||||
//for Deck Editor, edit deck instead of accepting
|
||||
editSelectedDeck();
|
||||
return;
|
||||
}
|
||||
accept();
|
||||
}
|
||||
});
|
||||
btnNewDeck.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
createNewDeck();
|
||||
}
|
||||
});
|
||||
btnEditDeck.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
lstDecks.setItemActivateHandler(event -> {
|
||||
if (lstDecks.getGameType() == GameType.DeckManager) {
|
||||
//for Deck Editor, edit deck instead of accepting
|
||||
editSelectedDeck();
|
||||
return;
|
||||
}
|
||||
accept();
|
||||
});
|
||||
btnNewDeck.setCommand(event -> createNewDeck());
|
||||
btnEditDeck.setCommand(event -> editSelectedDeck());
|
||||
btnViewDeck.setCommand(event -> {
|
||||
if (selectedDeckType != DeckType.STANDARD_COLOR_DECK && selectedDeckType != DeckType.STANDARD_CARDGEN_DECK
|
||||
&& selectedDeckType != DeckType.PIONEER_CARDGEN_DECK && selectedDeckType != DeckType.HISTORIC_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
|
||||
&& selectedDeckType != DeckType.RANDOM_COMMANDER_DECK && selectedDeckType != DeckType.RANDOM_CARDGEN_COMMANDER_DECK) {
|
||||
FDeckViewer.show(getDeck(), false, DeckType.DRAFT_DECK.equals(selectedDeckType));
|
||||
}
|
||||
});
|
||||
btnViewDeck.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
if (selectedDeckType != DeckType.STANDARD_COLOR_DECK && selectedDeckType != DeckType.STANDARD_CARDGEN_DECK
|
||||
&& selectedDeckType != DeckType.PIONEER_CARDGEN_DECK && selectedDeckType != DeckType.HISTORIC_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
|
||||
&& selectedDeckType != DeckType.RANDOM_COMMANDER_DECK && selectedDeckType != DeckType.RANDOM_CARDGEN_COMMANDER_DECK) {
|
||||
FDeckViewer.show(getDeck(), false, DeckType.DRAFT_DECK.equals(selectedDeckType));
|
||||
}
|
||||
btnRandom.setCommand(event -> {
|
||||
if (lstDecks.getGameType() == GameType.DeckManager) {
|
||||
//for Deck Editor, test deck instead of randomly selecting deck
|
||||
testSelectedDeck();
|
||||
return;
|
||||
}
|
||||
});
|
||||
btnRandom.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
if (lstDecks.getGameType() == GameType.DeckManager) {
|
||||
//for Deck Editor, test deck instead of randomly selecting deck
|
||||
testSelectedDeck();
|
||||
return;
|
||||
}
|
||||
if (selectedDeckType == DeckType.COLOR_DECK || selectedDeckType == DeckType.STANDARD_COLOR_DECK
|
||||
|| selectedDeckType == DeckType.MODERN_COLOR_DECK) {
|
||||
DeckgenUtil.randomSelectColors(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.STANDARD_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.PIONEER_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.HISTORIC_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.MODERN_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.LEGACY_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.VINTAGE_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else {
|
||||
int size = 0;
|
||||
if (selectedDeckType == DeckType.COLOR_DECK || selectedDeckType == DeckType.STANDARD_COLOR_DECK
|
||||
|| selectedDeckType == DeckType.MODERN_COLOR_DECK) {
|
||||
DeckgenUtil.randomSelectColors(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.STANDARD_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.PIONEER_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.HISTORIC_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.MODERN_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.LEGACY_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else if (selectedDeckType == DeckType.VINTAGE_CARDGEN_DECK){
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
else {
|
||||
int size = 0;
|
||||
try {
|
||||
if (isAi && !isGeneratedDeck(selectedDeckType) && Forge.autoAIDeckSelection) {
|
||||
btnRandom.setEnabled(false);
|
||||
AIDecks = lstDecks.getPool().toFlatList().parallelStream().filter(deckProxy -> deckProxy.getAI().inMainDeck == 0).collect(Collectors.toList());
|
||||
size = AIDecks.size();
|
||||
}
|
||||
@@ -207,9 +191,12 @@ public class FDeckChooser extends FScreen {
|
||||
lstDecks.setSelectedItem(AIDecks.get(MyRandom.getRandom().nextInt(size)));
|
||||
else
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
} catch (Exception ee) {
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
accept();
|
||||
}
|
||||
btnRandom.setEnabled(true);
|
||||
accept();
|
||||
});
|
||||
switch (lstDecks.getGameType()) {
|
||||
case Constructed:
|
||||
@@ -371,32 +358,29 @@ public class FDeckChooser extends FScreen {
|
||||
} else {
|
||||
editor = new FDeckEditor(getEditorType(), "", false);
|
||||
}
|
||||
editor.setSaveHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
//ensure user returns to proper deck type and that list is refreshed if new deck is saved
|
||||
if (!needRefreshOnActivate) {
|
||||
needRefreshOnActivate = true;
|
||||
if (lstDecks.getGameType() == GameType.DeckManager) {
|
||||
switch (selectedDeckType) {
|
||||
case COMMANDER_DECK:
|
||||
case OATHBREAKER_DECK:
|
||||
case TINY_LEADERS_DECK:
|
||||
case BRAWL_DECK:
|
||||
case SCHEME_DECK:
|
||||
case PLANAR_DECK:
|
||||
case DRAFT_DECK:
|
||||
case SEALED_DECK:
|
||||
break;
|
||||
default:
|
||||
setSelectedDeckType(DeckType.CONSTRUCTED_DECK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
setSelectedDeckType(DeckType.CUSTOM_DECK);
|
||||
editor.setSaveHandler(event -> {
|
||||
//ensure user returns to proper deck type and that list is refreshed if new deck is saved
|
||||
if (!needRefreshOnActivate) {
|
||||
needRefreshOnActivate = true;
|
||||
if (lstDecks.getGameType() == GameType.DeckManager) {
|
||||
switch (selectedDeckType) {
|
||||
case COMMANDER_DECK:
|
||||
case OATHBREAKER_DECK:
|
||||
case TINY_LEADERS_DECK:
|
||||
case BRAWL_DECK:
|
||||
case SCHEME_DECK:
|
||||
case PLANAR_DECK:
|
||||
case DRAFT_DECK:
|
||||
case SEALED_DECK:
|
||||
break;
|
||||
default:
|
||||
setSelectedDeckType(DeckType.CONSTRUCTED_DECK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
setSelectedDeckType(DeckType.CUSTOM_DECK);
|
||||
}
|
||||
}
|
||||
});
|
||||
Forge.openScreen(editor);
|
||||
@@ -624,249 +608,205 @@ public class FDeckChooser extends FScreen {
|
||||
cmbDeckTypes.setAlignment(Align.center);
|
||||
restoreSavedState();
|
||||
|
||||
cmbDeckTypes.setChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
cmbDeckTypes.setChangedHandler(event -> {
|
||||
final DeckType deckType = cmbDeckTypes.getSelectedItem();
|
||||
|
||||
public void handleEvent(final FEvent e) {
|
||||
final DeckType deckType = cmbDeckTypes.getSelectedItem();
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_DECK || deckType == DeckType.NET_COMMANDER_DECK)) {
|
||||
//needed for loading net decks
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = deckType == DeckType.NET_COMMANDER_DECK ? GameType.Commander : GameType.Constructed;
|
||||
}
|
||||
final NetDeckCategory category = NetDeckCategory.selectAndLoad(gameType);
|
||||
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_DECK || deckType == DeckType.NET_COMMANDER_DECK)) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||
@Override
|
||||
public void run() {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = deckType == DeckType.NET_COMMANDER_DECK ? GameType.Commander : GameType.Constructed;
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && netDeckCategory != null) {
|
||||
cmbDeckTypes.setText(netDeckCategory.getDeckType());
|
||||
}
|
||||
final NetDeckCategory category = NetDeckCategory.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && netDeckCategory != null) {
|
||||
cmbDeckTypes.setText(netDeckCategory.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
netDeckCategory = category;
|
||||
refreshDecksList(deckType, true, e);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
netDeckCategory = category;
|
||||
refreshDecksList(deckType, true, event);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_STANDARD_DECK)) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||
@Override
|
||||
public void run() {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchiveStandard category = NetDeckArchiveStandard.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchiveStandard != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchiveStandard.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchiveStandard = category;
|
||||
refreshDecksList(deckType, true, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_PIONEER_DECK)) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||
@Override
|
||||
public void run() {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchivePioneer category = NetDeckArchivePioneer.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchivePioneer != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchivePioneer.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchivePioneer = category;
|
||||
refreshDecksList(deckType, true, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_MODERN_DECK)) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||
@Override
|
||||
public void run() {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchiveModern category = NetDeckArchiveModern.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchiveModern != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchiveModern.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchiveModern = category;
|
||||
refreshDecksList(deckType, true, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_PAUPER_DECK)) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||
@Override
|
||||
public void run() {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchivePauper category = NetDeckArchivePauper.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchivePauper != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchivePauper.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchivePauper = category;
|
||||
refreshDecksList(deckType, true, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_LEGACY_DECK)) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||
@Override
|
||||
public void run() {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchiveLegacy category = NetDeckArchiveLegacy.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchiveLegacy != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchiveLegacy.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchiveLegacy = category;
|
||||
refreshDecksList(deckType, true, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_VINTAGE_DECK)) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||
@Override
|
||||
public void run() {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchiveVintage category = NetDeckArchiveVintage.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchiveVintage != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchiveVintage.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchiveVintage = category;
|
||||
refreshDecksList(deckType, true, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_BLOCK_DECK)) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||
@Override
|
||||
public void run() {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchiveBlock category = NetDeckArchiveBlock.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchiveBlock != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchiveBlock.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchiveBlock = category;
|
||||
refreshDecksList(deckType, true, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
refreshDecksList(deckType, false, e);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_STANDARD_DECK)) {
|
||||
//needed for loading net decks
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchiveStandard category = NetDeckArchiveStandard.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchiveStandard != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchiveStandard.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchiveStandard = category;
|
||||
refreshDecksList(deckType, true, event);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_PIONEER_DECK)) {
|
||||
//needed for loading net decks
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchivePioneer category = NetDeckArchivePioneer.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchivePioneer != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchivePioneer.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchivePioneer = category;
|
||||
refreshDecksList(deckType, true, event);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_MODERN_DECK)) {
|
||||
//needed for loading net decks
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchiveModern category = NetDeckArchiveModern.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchiveModern != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchiveModern.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchiveModern = category;
|
||||
refreshDecksList(deckType, true, event);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_PAUPER_DECK)) {
|
||||
//needed for loading net decks
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchivePauper category = NetDeckArchivePauper.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchivePauper != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchivePauper.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchivePauper = category;
|
||||
refreshDecksList(deckType, true, event);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_LEGACY_DECK)) {
|
||||
//needed for loading net decks
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchiveLegacy category = NetDeckArchiveLegacy.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchiveLegacy != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchiveLegacy.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchiveLegacy = category;
|
||||
refreshDecksList(deckType, true, event);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_VINTAGE_DECK)) {
|
||||
//needed for loading net decks
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchiveVintage category = NetDeckArchiveVintage.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchiveVintage != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchiveVintage.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchiveVintage = category;
|
||||
refreshDecksList(deckType, true, event);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!refreshingDeckType&&(deckType == DeckType.NET_ARCHIVE_BLOCK_DECK)) {
|
||||
//needed for loading net decks
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
GameType gameType = lstDecks.getGameType();
|
||||
if (gameType == GameType.DeckManager) {
|
||||
gameType = GameType.Constructed;
|
||||
}
|
||||
final NetDeckArchiveBlock category = NetDeckArchiveBlock.selectAndLoad(gameType);
|
||||
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == deckType && NetDeckArchiveBlock != null) {
|
||||
cmbDeckTypes.setText(NetDeckArchiveBlock.getDeckType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NetDeckArchiveBlock = category;
|
||||
refreshDecksList(deckType, true, event);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
refreshDecksList(deckType, false, event);
|
||||
});
|
||||
add(cmbDeckTypes);
|
||||
add(lstDecks);
|
||||
@@ -888,11 +828,11 @@ public class FDeckChooser extends FScreen {
|
||||
saveState();
|
||||
}
|
||||
|
||||
private void refreshDecksList(DeckType deckType, boolean forceRefresh, FEvent e) {
|
||||
private void refreshDecksList(DeckType deckType, boolean forceRefresh, FEvent event) {
|
||||
if (selectedDeckType == deckType && !forceRefresh) { return; }
|
||||
selectedDeckType = deckType;
|
||||
|
||||
if (e == null) {
|
||||
if (event == null) {
|
||||
refreshingDeckType = true;
|
||||
cmbDeckTypes.setSelectedItem(deckType);
|
||||
refreshingDeckType = false;
|
||||
@@ -1186,7 +1126,7 @@ public class FDeckChooser extends FScreen {
|
||||
|
||||
btnRandom.setLeft(getWidth() - PADDING - btnRandom.getWidth());
|
||||
|
||||
if (e != null) { //set default list selection if from combo box change event
|
||||
if (event != null) { //set default list selection if from combo box change event
|
||||
if (deckType == DeckType.COLOR_DECK) {
|
||||
// default selection = basic two color deck
|
||||
lstDecks.setSelectedIndices(new Integer[]{0, 1});
|
||||
@@ -1510,36 +1450,26 @@ public class FDeckChooser extends FScreen {
|
||||
return;
|
||||
}
|
||||
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||
@Override
|
||||
public void run() {
|
||||
final NetDeckCategory netCat;
|
||||
if (allowedDeckTypes.contains(DeckType.NET_DECK)) {
|
||||
netCat = NetDeckCategory.selectAndLoad(GameType.Constructed);
|
||||
} else {
|
||||
netCat = null;
|
||||
}
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GauntletData gauntlet = GauntletUtil.createQuickGauntlet(userDeck, numOpponents, allowedDeckTypes, netCat);
|
||||
FModel.setGauntletData(gauntlet);
|
||||
|
||||
List<RegisteredPlayer> players = new ArrayList<>();
|
||||
RegisteredPlayer humanPlayer = new RegisteredPlayer(userDeck).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
players.add(humanPlayer);
|
||||
players.add(new RegisteredPlayer(gauntlet.getDecks().get(gauntlet.getCompleted())).setPlayer(GamePlayerUtil.createAiPlayer()));
|
||||
|
||||
gauntlet.startRound(players, humanPlayer);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
//needed for loading net decks
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
final NetDeckCategory netCat;
|
||||
if (allowedDeckTypes.contains(DeckType.NET_DECK)) {
|
||||
netCat = NetDeckCategory.selectAndLoad(GameType.Constructed);
|
||||
} else {
|
||||
netCat = null;
|
||||
}
|
||||
|
||||
FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), true, () -> {
|
||||
GauntletData gauntlet = GauntletUtil.createQuickGauntlet(userDeck, numOpponents, allowedDeckTypes, netCat);
|
||||
FModel.setGauntletData(gauntlet);
|
||||
|
||||
List<RegisteredPlayer> players = new ArrayList<>();
|
||||
RegisteredPlayer humanPlayer = new RegisteredPlayer(userDeck).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
players.add(humanPlayer);
|
||||
players.add(new RegisteredPlayer(gauntlet.getDecks().get(gauntlet.getCompleted())).setPlayer(GamePlayerUtil.createAiPlayer()));
|
||||
|
||||
gauntlet.startRound(players, humanPlayer);
|
||||
}));
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1554,26 +1484,23 @@ public class FDeckChooser extends FScreen {
|
||||
public void run(final Deck aiDeck) {
|
||||
if (aiDeck == null) { return; }
|
||||
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Set<GameType> appliedVariants = new HashSet<>();
|
||||
appliedVariants.add(variant);
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), true, () -> {
|
||||
Set<GameType> appliedVariants = new HashSet<>();
|
||||
appliedVariants.add(variant);
|
||||
|
||||
List<RegisteredPlayer> players = new ArrayList<>();
|
||||
RegisteredPlayer humanPlayer = RegisteredPlayer.forVariants(2, appliedVariants, userDeck, null, false, null, null);
|
||||
humanPlayer.setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
RegisteredPlayer aiPlayer = RegisteredPlayer.forVariants(2, appliedVariants, aiDeck, null, false, null, null);
|
||||
aiPlayer.setPlayer(GamePlayerUtil.createAiPlayer());
|
||||
players.add(humanPlayer);
|
||||
players.add(aiPlayer);
|
||||
List<RegisteredPlayer> players = new ArrayList<>();
|
||||
RegisteredPlayer humanPlayer = RegisteredPlayer.forVariants(2, appliedVariants, userDeck, null, false, null, null);
|
||||
humanPlayer.setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
RegisteredPlayer aiPlayer = RegisteredPlayer.forVariants(2, appliedVariants, aiDeck, null, false, null, null);
|
||||
aiPlayer.setPlayer(GamePlayerUtil.createAiPlayer());
|
||||
players.add(humanPlayer);
|
||||
players.add(aiPlayer);
|
||||
|
||||
final Map<RegisteredPlayer, IGuiGame> guiMap = new HashMap<>();
|
||||
guiMap.put(humanPlayer, MatchController.instance);
|
||||
final Map<RegisteredPlayer, IGuiGame> guiMap = new HashMap<>();
|
||||
guiMap.put(humanPlayer, MatchController.instance);
|
||||
|
||||
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.startMatch(GameType.Constructed, appliedVariants, players, guiMap);
|
||||
}
|
||||
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.startMatch(GameType.Constructed, appliedVariants, players, guiMap);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -22,39 +22,25 @@ public class LoadingOverlay extends FOverlay {
|
||||
private static final FSkinFont FONT = FSkinFont.get(22);
|
||||
private static final FSkinColor BACK_COLOR = FSkinColor.get(Colors.CLR_ACTIVE).alphaColor(0.75f);
|
||||
private static final FSkinColor FORE_COLOR = FSkinColor.get(Colors.CLR_TEXT);
|
||||
|
||||
public static void show(String caption0, final Runnable runnable) {
|
||||
final LoadingOverlay loader = new LoadingOverlay(caption0);
|
||||
show(caption0, false, runnable);
|
||||
}
|
||||
public static void show(String caption0, boolean textMode, final Runnable runnable) {
|
||||
final LoadingOverlay loader = new LoadingOverlay(caption0, textMode);
|
||||
loader.show(); //show loading overlay then delay running remaining logic so UI can respond
|
||||
ThreadUtil.invokeInGameThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runnable.run();
|
||||
loader.hide();
|
||||
loader.finishedloading(); //setLoadingaMatch to false
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
ThreadUtil.invokeInGameThread(() -> FThreads.invokeInEdtLater(() -> {
|
||||
runnable.run();
|
||||
loader.hide();
|
||||
loader.finishedloading(); //setLoadingaMatch to false
|
||||
}));
|
||||
}
|
||||
|
||||
public static void runBackgroundTask(String caption0, final Runnable task) {
|
||||
final LoadingOverlay loader = new LoadingOverlay(caption0);
|
||||
final LoadingOverlay loader = new LoadingOverlay(caption0, true);
|
||||
loader.show();
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
task.run();
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
loader.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
task.run();
|
||||
FThreads.invokeInEdtLater(() -> loader.hide());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -63,6 +49,7 @@ public class LoadingOverlay extends FOverlay {
|
||||
|
||||
public LoadingOverlay(String caption0) {
|
||||
caption = caption0;
|
||||
textMode = false;
|
||||
}
|
||||
|
||||
public LoadingOverlay(String caption0, boolean textOnly) {
|
||||
|
||||
@@ -169,7 +169,7 @@ public class SplashScreen extends FContainer {
|
||||
}
|
||||
|
||||
void drawTransition(Graphics g, boolean openAdventure, float percentage) {
|
||||
TextureRegion tr = new TextureRegion(Forge.getTitleBG());
|
||||
TextureRegion tr = new TextureRegion(Forge.getAssets().fallback_skins().get(0));
|
||||
if (!Forge.isLandscapeMode() && tr != null) {
|
||||
float ar = 1.78f;
|
||||
int w = (int) (tr.getRegionHeight() / ar);
|
||||
@@ -307,7 +307,7 @@ public class SplashScreen extends FContainer {
|
||||
+ "Forge is open source software, released under the GNU General Public License.";
|
||||
if (Forge.forcedEnglishonCJKMissing && !clear) {
|
||||
clear = true;
|
||||
FSkinFont.clear();
|
||||
FSkinFont.preloadAll("");
|
||||
disclaimerFont = FSkinFont.get(9);
|
||||
}
|
||||
g.drawText(disclaimer, disclaimerFont, FProgressBar.SEL_FORE_COLOR,
|
||||
|
||||
@@ -44,8 +44,6 @@ import forge.screens.LoadingOverlay;
|
||||
import forge.screens.settings.SettingsScreen;
|
||||
import forge.toolbox.FCheckBox;
|
||||
import forge.toolbox.FComboBox;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FList;
|
||||
import forge.toolbox.FOptionPane;
|
||||
@@ -111,23 +109,20 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
cbPlayerCount.addItem(i);
|
||||
}
|
||||
cbPlayerCount.setSelectedItem(2);
|
||||
cbPlayerCount.setChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
int numPlayers = getNumPlayers();
|
||||
while(lobby.getNumberOfSlots() < getNumPlayers()){
|
||||
lobby.addSlot();
|
||||
}
|
||||
while(lobby.getNumberOfSlots() > getNumPlayers()){
|
||||
lobby.removeSlot(lobby.getNumberOfSlots()-1);
|
||||
}
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if(i<playerPanels.size()) {
|
||||
playerPanels.get(i).setVisible(i < numPlayers);
|
||||
}
|
||||
}
|
||||
playersScroll.revalidate();
|
||||
cbPlayerCount.setChangedHandler(event -> {
|
||||
int numPlayers = getNumPlayers();
|
||||
while(lobby.getNumberOfSlots() < getNumPlayers()){
|
||||
lobby.addSlot();
|
||||
}
|
||||
while(lobby.getNumberOfSlots() > getNumPlayers()){
|
||||
lobby.removeSlot(lobby.getNumberOfSlots()-1);
|
||||
}
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if(i<playerPanels.size()) {
|
||||
playerPanels.get(i).setVisible(i < numPlayers);
|
||||
}
|
||||
}
|
||||
playersScroll.revalidate();
|
||||
});
|
||||
|
||||
initLobby(lobby0);
|
||||
@@ -139,12 +134,7 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
cbGamesInMatch.addItem("3");
|
||||
cbGamesInMatch.addItem("5");
|
||||
cbGamesInMatch.setSelectedItem(FModel.getPreferences().getPref((FPref.UI_MATCHES_PER_GAME)));
|
||||
cbGamesInMatch.setChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
FModel.getPreferences().setPref(FPref.UI_MATCHES_PER_GAME, cbGamesInMatch.getSelectedItem());
|
||||
}
|
||||
});
|
||||
cbGamesInMatch.setChangedHandler(event -> FModel.getPreferences().setPref(FPref.UI_MATCHES_PER_GAME, cbGamesInMatch.getSelectedItem()));
|
||||
|
||||
add(lblVariants);
|
||||
add(cbVariants);
|
||||
@@ -161,31 +151,28 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
cbVariants.addItem(GameType.Archenemy);
|
||||
cbVariants.addItem(GameType.ArchenemyRumble);
|
||||
cbVariants.addItem(Forge.getLocalizer().getMessage("lblMore"));
|
||||
cbVariants.setChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
if (cbVariants.getSelectedIndex() <= 0) {
|
||||
lobby.clearVariants();
|
||||
updateLayoutForVariants();
|
||||
Set<GameType> gameTypes = new HashSet<>();
|
||||
FModel.getPreferences().setGameType(FPref.UI_APPLIED_VARIANTS, gameTypes);
|
||||
FModel.getPreferences().save();
|
||||
}
|
||||
else if (cbVariants.getSelectedIndex() == cbVariants.getItemCount() - 1) {
|
||||
Forge.openScreen(new MultiVariantSelect());
|
||||
updateVariantSelection();
|
||||
}
|
||||
else {
|
||||
lobby.clearVariants();
|
||||
lobby.applyVariant((GameType)cbVariants.getSelectedItem());
|
||||
updateLayoutForVariants();
|
||||
Set<GameType> gameTypes = new HashSet<>();
|
||||
for (GameType variant: lobby.getAppliedVariants()) {
|
||||
gameTypes.add(variant);
|
||||
}
|
||||
FModel.getPreferences().setGameType(FPref.UI_APPLIED_VARIANTS, gameTypes);
|
||||
FModel.getPreferences().save();
|
||||
cbVariants.setChangedHandler(event -> {
|
||||
if (cbVariants.getSelectedIndex() <= 0) {
|
||||
lobby.clearVariants();
|
||||
updateLayoutForVariants();
|
||||
Set<GameType> gameTypes = new HashSet<>();
|
||||
FModel.getPreferences().setGameType(FPref.UI_APPLIED_VARIANTS, gameTypes);
|
||||
FModel.getPreferences().save();
|
||||
}
|
||||
else if (cbVariants.getSelectedIndex() == cbVariants.getItemCount() - 1) {
|
||||
Forge.openScreen(new MultiVariantSelect());
|
||||
updateVariantSelection();
|
||||
}
|
||||
else {
|
||||
lobby.clearVariants();
|
||||
lobby.applyVariant((GameType)cbVariants.getSelectedItem());
|
||||
updateLayoutForVariants();
|
||||
Set<GameType> gameTypes = new HashSet<>();
|
||||
for (GameType variant: lobby.getAppliedVariants()) {
|
||||
gameTypes.add(variant);
|
||||
}
|
||||
FModel.getPreferences().setGameType(FPref.UI_APPLIED_VARIANTS, gameTypes);
|
||||
FModel.getPreferences().save();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -195,40 +182,34 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
|
||||
updatePlayersFromPrefs();
|
||||
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
playerPanels.get(0).initialize(FPref.CONSTRUCTED_P1_DECK_STATE, FPref.COMMANDER_P1_DECK_STATE, FPref.OATHBREAKER_P1_DECK_STATE, FPref.TINY_LEADER_P1_DECK_STATE, FPref.BRAWL_P1_DECK_STATE, DeckType.PRECONSTRUCTED_DECK);
|
||||
playerPanels.get(1).initialize(FPref.CONSTRUCTED_P2_DECK_STATE, FPref.COMMANDER_P2_DECK_STATE, FPref.OATHBREAKER_P2_DECK_STATE, FPref.TINY_LEADER_P2_DECK_STATE, FPref.BRAWL_P2_DECK_STATE, DeckType.COLOR_DECK);
|
||||
try {
|
||||
if (getNumPlayers() > 2) {
|
||||
playerPanels.get(2).initialize(FPref.CONSTRUCTED_P3_DECK_STATE, FPref.COMMANDER_P3_DECK_STATE, FPref.OATHBREAKER_P3_DECK_STATE, FPref.TINY_LEADER_P3_DECK_STATE, FPref.BRAWL_P3_DECK_STATE, DeckType.COLOR_DECK);
|
||||
}
|
||||
if (getNumPlayers() > 3) {
|
||||
playerPanels.get(3).initialize(FPref.CONSTRUCTED_P4_DECK_STATE, FPref.COMMANDER_P4_DECK_STATE, FPref.OATHBREAKER_P3_DECK_STATE, FPref.TINY_LEADER_P4_DECK_STATE, FPref.BRAWL_P4_DECK_STATE, DeckType.COLOR_DECK);
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
/*playerPanels.get(4).initialize(FPref.CONSTRUCTED_P5_DECK_STATE, DeckType.COLOR_DECK);
|
||||
playerPanels.get(5).initialize(FPref.CONSTRUCTED_P6_DECK_STATE, DeckType.COLOR_DECK);
|
||||
playerPanels.get(6).initialize(FPref.CONSTRUCTED_P7_DECK_STATE, DeckType.COLOR_DECK);
|
||||
playerPanels.get(7).initialize(FPref.CONSTRUCTED_P8_DECK_STATE, DeckType.COLOR_DECK);*/ //TODO: Improve performance of loading this screen by using background thread
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
playerPanels.get(0).initialize(FPref.CONSTRUCTED_P1_DECK_STATE, FPref.COMMANDER_P1_DECK_STATE, FPref.OATHBREAKER_P1_DECK_STATE, FPref.TINY_LEADER_P1_DECK_STATE, FPref.BRAWL_P1_DECK_STATE, DeckType.PRECONSTRUCTED_DECK);
|
||||
playerPanels.get(1).initialize(FPref.CONSTRUCTED_P2_DECK_STATE, FPref.COMMANDER_P2_DECK_STATE, FPref.OATHBREAKER_P2_DECK_STATE, FPref.TINY_LEADER_P2_DECK_STATE, FPref.BRAWL_P2_DECK_STATE, DeckType.COLOR_DECK);
|
||||
try {
|
||||
if (getNumPlayers() > 2) {
|
||||
playerPanels.get(2).initialize(FPref.CONSTRUCTED_P3_DECK_STATE, FPref.COMMANDER_P3_DECK_STATE, FPref.OATHBREAKER_P3_DECK_STATE, FPref.TINY_LEADER_P3_DECK_STATE, FPref.BRAWL_P3_DECK_STATE, DeckType.COLOR_DECK);
|
||||
}
|
||||
if (getNumPlayers() > 3) {
|
||||
playerPanels.get(3).initialize(FPref.CONSTRUCTED_P4_DECK_STATE, FPref.COMMANDER_P4_DECK_STATE, FPref.OATHBREAKER_P3_DECK_STATE, FPref.TINY_LEADER_P4_DECK_STATE, FPref.BRAWL_P4_DECK_STATE, DeckType.COLOR_DECK);
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
/*playerPanels.get(4).initialize(FPref.CONSTRUCTED_P5_DECK_STATE, DeckType.COLOR_DECK);
|
||||
playerPanels.get(5).initialize(FPref.CONSTRUCTED_P6_DECK_STATE, DeckType.COLOR_DECK);
|
||||
playerPanels.get(6).initialize(FPref.CONSTRUCTED_P7_DECK_STATE, DeckType.COLOR_DECK);
|
||||
playerPanels.get(7).initialize(FPref.CONSTRUCTED_P8_DECK_STATE, DeckType.COLOR_DECK);*/ //TODO: Improve performance of loading this screen by using background thread
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
btnStart.setEnabled(lobby.hasControl());
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
btnStart.setEnabled(lobby.hasControl());
|
||||
|
||||
Set<GameType> gameTypes = FModel.getPreferences().getGameType(FPref.UI_APPLIED_VARIANTS);
|
||||
if (!gameTypes.isEmpty()) {
|
||||
for (GameType gameType : gameTypes) {
|
||||
lobby.applyVariant(gameType);
|
||||
}
|
||||
updateVariantSelection();
|
||||
updateLayoutForVariants();
|
||||
}
|
||||
Set<GameType> gameTypes = FModel.getPreferences().getGameType(FPref.UI_APPLIED_VARIANTS);
|
||||
if (!gameTypes.isEmpty()) {
|
||||
for (GameType gameType : gameTypes) {
|
||||
lobby.applyVariant(gameType);
|
||||
}
|
||||
});
|
||||
}
|
||||
updateVariantSelection();
|
||||
updateLayoutForVariants();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
lblPlayers.setEnabled(true);
|
||||
@@ -351,20 +332,13 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
updateName(0, GamePlayerUtil.getGuiPlayer().getName());
|
||||
}
|
||||
}
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //must call startGame in background thread in case there are alerts
|
||||
@Override
|
||||
public void run() {
|
||||
final Runnable startGame = lobby.startGame();
|
||||
if (startGame != null) {
|
||||
//set this so we cant get any multi/rapid tap on start button
|
||||
Forge.setLoadingaMatch(true);
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), startGame);
|
||||
}
|
||||
});
|
||||
}
|
||||
//must call startGame in background thread in case there are alerts
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
final Runnable startGame = lobby.startGame();
|
||||
if (startGame != null) {
|
||||
//set this so we cant get any multi/rapid tap on start button
|
||||
Forge.setLoadingaMatch(true);
|
||||
FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), true, startGame));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import java.io.File;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
@@ -31,8 +30,6 @@ import forge.screens.home.LoadGameMenu;
|
||||
import forge.screens.home.NewGameMenu.NewGameScreen;
|
||||
import forge.screens.settings.SettingsScreen;
|
||||
import forge.toolbox.FButton;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FList;
|
||||
import forge.toolbox.FOptionPane;
|
||||
import forge.util.Callback;
|
||||
@@ -53,26 +50,11 @@ public class LoadGauntletScreen extends LaunchScreen {
|
||||
super(null, LoadGameMenu.getMenu());
|
||||
|
||||
btnNewGauntlet.setFont(FSkinFont.get(16));
|
||||
btnNewGauntlet.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
NewGameScreen.Gauntlet.open();
|
||||
}
|
||||
});
|
||||
btnNewGauntlet.setCommand(event -> NewGameScreen.Gauntlet.open());
|
||||
btnRenameGauntlet.setFont(btnNewGauntlet.getFont());
|
||||
btnRenameGauntlet.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
renameGauntlet(lstGauntlets.getSelectedGauntlet());
|
||||
}
|
||||
});
|
||||
btnRenameGauntlet.setCommand(event -> renameGauntlet(lstGauntlets.getSelectedGauntlet()));
|
||||
btnDeleteGauntlet.setFont(btnNewGauntlet.getFont());
|
||||
btnDeleteGauntlet.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
deleteGauntlet(lstGauntlets.getSelectedGauntlet());
|
||||
}
|
||||
});
|
||||
btnDeleteGauntlet.setCommand(event -> deleteGauntlet(lstGauntlets.getSelectedGauntlet()));
|
||||
}
|
||||
|
||||
public void onActivate() {
|
||||
@@ -136,81 +118,69 @@ public class LoadGauntletScreen extends LaunchScreen {
|
||||
return;
|
||||
}
|
||||
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final GauntletData gauntlet = FModel.getGauntletData();
|
||||
List<RegisteredPlayer> players = new ArrayList<>();
|
||||
RegisteredPlayer humanPlayer = new RegisteredPlayer(gauntlet.getUserDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
players.add(humanPlayer);
|
||||
players.add(new RegisteredPlayer(gauntlet.getDecks().get(gauntlet.getCompleted())).setPlayer(GamePlayerUtil.createAiPlayer()));
|
||||
gauntlet.startRound(players, humanPlayer);
|
||||
}
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), true, () -> {
|
||||
final GauntletData gauntlet1 = FModel.getGauntletData();
|
||||
List<RegisteredPlayer> players = new ArrayList<>();
|
||||
RegisteredPlayer humanPlayer = new RegisteredPlayer(gauntlet1.getUserDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
players.add(humanPlayer);
|
||||
players.add(new RegisteredPlayer(gauntlet1.getDecks().get(gauntlet1.getCompleted())).setPlayer(GamePlayerUtil.createAiPlayer()));
|
||||
gauntlet1.startRound(players, humanPlayer);
|
||||
});
|
||||
}
|
||||
|
||||
private void renameGauntlet(final GauntletData gauntlet) {
|
||||
if (gauntlet == null) { return; }
|
||||
|
||||
ThreadUtil.invokeInGameThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String gauntletName;
|
||||
String oldGauntletName = gauntlet.getName();
|
||||
while (true) {
|
||||
gauntletName = SOptionPane.showInputDialog(Forge.getLocalizer().getMessage("lblEnterNewGauntletGameName"), Forge.getLocalizer().getMessage("lblRenameGauntlet"), null, oldGauntletName);
|
||||
if (gauntletName == null) { return; }
|
||||
ThreadUtil.invokeInGameThread(() -> {
|
||||
String gauntletName;
|
||||
String oldGauntletName = gauntlet.getName();
|
||||
while (true) {
|
||||
gauntletName = SOptionPane.showInputDialog(Forge.getLocalizer().getMessage("lblEnterNewGauntletGameName"), Forge.getLocalizer().getMessage("lblRenameGauntlet"), null, oldGauntletName);
|
||||
if (gauntletName == null) { return; }
|
||||
|
||||
gauntletName = QuestUtil.cleanString(gauntletName);
|
||||
if (gauntletName.equals(oldGauntletName)) { return; } //quit if chose same name
|
||||
gauntletName = QuestUtil.cleanString(gauntletName);
|
||||
if (gauntletName.equals(oldGauntletName)) { return; } //quit if chose same name
|
||||
|
||||
if (gauntletName.isEmpty()) {
|
||||
SOptionPane.showMessageDialog(Forge.getLocalizer().getMessage("lblPleaseSpecifyGauntletName"));
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean exists = false;
|
||||
for (GauntletData gauntletData : lstGauntlets) {
|
||||
if (gauntletData.getName().equalsIgnoreCase(gauntletName)) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (exists) {
|
||||
SOptionPane.showMessageDialog(Forge.getLocalizer().getMessage("lblGauntletNameExistsPleasePickAnotherName"));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
if (gauntletName.isEmpty()) {
|
||||
SOptionPane.showMessageDialog(Forge.getLocalizer().getMessage("lblPleaseSpecifyGauntletName"));
|
||||
continue;
|
||||
}
|
||||
final String newGauntletName = gauntletName;
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
gauntlet.rename(newGauntletName);
|
||||
lstGauntlets.refresh();
|
||||
lstGauntlets.setSelectedGauntlet(gauntlet);
|
||||
|
||||
boolean exists = false;
|
||||
for (GauntletData gauntletData : lstGauntlets) {
|
||||
if (gauntletData.getName().equalsIgnoreCase(gauntletName)) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (exists) {
|
||||
SOptionPane.showMessageDialog(Forge.getLocalizer().getMessage("lblGauntletNameExistsPleasePickAnotherName"));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
final String newGauntletName = gauntletName;
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
gauntlet.rename(newGauntletName);
|
||||
lstGauntlets.refresh();
|
||||
lstGauntlets.setSelectedGauntlet(gauntlet);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void deleteGauntlet(final GauntletData gauntlet) {
|
||||
if (gauntlet == null) { return; }
|
||||
|
||||
ThreadUtil.invokeInGameThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!SOptionPane.showConfirmDialog(
|
||||
Forge.getLocalizer().getMessage("lblAreYouSuerDeleteGauntlet", gauntlet.getName()),
|
||||
Forge.getLocalizer().getMessage("lblDeleteGauntlet"), Forge.getLocalizer().getMessage("lblDelete"), Forge.getLocalizer().getMessage("lblCancel"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
GauntletIO.getGauntletFile(gauntlet).delete();
|
||||
|
||||
lstGauntlets.removeGauntlet(gauntlet);
|
||||
ThreadUtil.invokeInGameThread(() -> {
|
||||
if (!SOptionPane.showConfirmDialog(
|
||||
Forge.getLocalizer().getMessage("lblAreYouSuerDeleteGauntlet", gauntlet.getName()),
|
||||
Forge.getLocalizer().getMessage("lblDeleteGauntlet"), Forge.getLocalizer().getMessage("lblDelete"), Forge.getLocalizer().getMessage("lblCancel"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
GauntletIO.getGauntletFile(gauntlet).delete();
|
||||
|
||||
lstGauntlets.removeGauntlet(gauntlet);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -299,12 +269,7 @@ public class LoadGauntletScreen extends LaunchScreen {
|
||||
public void refresh() {
|
||||
List<GauntletData> sorted = new ArrayList<>();
|
||||
sorted.addAll(gauntlets);
|
||||
Collections.sort(sorted, new Comparator<GauntletData>() {
|
||||
@Override
|
||||
public int compare(final GauntletData x, final GauntletData y) {
|
||||
return x.getName().toLowerCase().compareTo(y.getName().toLowerCase());
|
||||
}
|
||||
});
|
||||
Collections.sort(sorted, (x, y) -> x.getName().toLowerCase().compareTo(y.getName().toLowerCase()));
|
||||
setListData(sorted);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,39 +60,26 @@ public class PuzzleScreen extends LaunchScreen {
|
||||
@Override
|
||||
public void run(final Puzzle chosen) {
|
||||
if (chosen != null) {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingThePuzzle"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Load selected puzzle
|
||||
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.setStartGameHook(new Runnable() {
|
||||
@Override
|
||||
public final void run() {
|
||||
chosen.applyToGame(hostedMatch.getGame());
|
||||
}
|
||||
});
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingThePuzzle"), true, () -> {
|
||||
// Load selected puzzle
|
||||
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.setStartGameHook(() -> chosen.applyToGame(hostedMatch.getGame()));
|
||||
|
||||
hostedMatch.setEndGameHook((new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
chosen.savePuzzleSolve(hostedMatch.getGame().getOutcome().isWinner(GamePlayerUtil.getGuiPlayer()));
|
||||
}
|
||||
}));
|
||||
hostedMatch.setEndGameHook((() -> chosen.savePuzzleSolve(hostedMatch.getGame().getOutcome().isWinner(GamePlayerUtil.getGuiPlayer()))));
|
||||
|
||||
final List<RegisteredPlayer> players = new ArrayList<>();
|
||||
final RegisteredPlayer human = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
human.setStartingHand(0);
|
||||
players.add(human);
|
||||
final List<RegisteredPlayer> players = new ArrayList<>();
|
||||
final RegisteredPlayer human = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
human.setStartingHand(0);
|
||||
players.add(human);
|
||||
|
||||
final RegisteredPlayer ai = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.createAiPlayer());
|
||||
ai.setStartingHand(0);
|
||||
players.add(ai);
|
||||
final RegisteredPlayer ai = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.createAiPlayer());
|
||||
ai.setStartingHand(0);
|
||||
players.add(ai);
|
||||
|
||||
GameRules rules = new GameRules(GameType.Puzzle);
|
||||
rules.setGamesPerMatch(1);
|
||||
hostedMatch.startMatch(rules, null, players, human, GuiBase.getInterface().getNewGuiGame());
|
||||
FOptionPane.showMessageDialog(chosen.getGoalDescription(), chosen.getName());
|
||||
}
|
||||
GameRules rules = new GameRules(GameType.Puzzle);
|
||||
rules.setGamesPerMatch(1);
|
||||
hostedMatch.startMatch(rules, null, players, human, GuiBase.getInterface().getNewGuiGame());
|
||||
FOptionPane.showMessageDialog(chosen.getGoalDescription(), chosen.getName());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ import forge.screens.LaunchScreen;
|
||||
import forge.screens.LoadingOverlay;
|
||||
import forge.screens.home.LoadGameMenu;
|
||||
import forge.toolbox.FComboBox;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FOptionPane;
|
||||
|
||||
@@ -54,12 +52,7 @@ public class LoadDraftScreen extends LaunchScreen {
|
||||
cbMode.addItem(Forge.getLocalizer().getMessage("lblSingleMatch"));
|
||||
|
||||
lstDecks.setup(ItemManagerConfig.DRAFT_DECKS);
|
||||
lstDecks.setItemActivateHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
editSelectedDeck();
|
||||
}
|
||||
});
|
||||
lstDecks.setItemActivateHandler(event -> editSelectedDeck());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,80 +89,63 @@ public class LoadDraftScreen extends LaunchScreen {
|
||||
|
||||
@Override
|
||||
protected void startMatch() {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final DeckProxy humanDeck = lstDecks.getSelectedItem();
|
||||
if (humanDeck == null) {
|
||||
FOptionPane.showErrorDialog(Forge.getLocalizer().getMessage("lblYouMustSelectExistingDeck"), Forge.getLocalizer().getMessage("lblNoDeck"));
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
final DeckProxy humanDeck = lstDecks.getSelectedItem();
|
||||
if (humanDeck == null) {
|
||||
FOptionPane.showErrorDialog(Forge.getLocalizer().getMessage("lblYouMustSelectExistingDeck"), Forge.getLocalizer().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(Forge.getLocalizer().getMessage("lblGauntlet"));
|
||||
|
||||
if (gauntlet) {
|
||||
final Integer rounds = SGuiChoose.getInteger(Forge.getLocalizer().getMessage("lblHowManyOpponents"),
|
||||
1, FModel.getDecks().getDraft().get(humanDeck.getName()).getAiDecks().size());
|
||||
if (rounds == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: if booster draft tournaments are supported in the future, add the possibility to choose them here
|
||||
final boolean gauntlet = cbMode.getSelectedItem().equals(Forge.getLocalizer().getMessage("lblGauntlet"));
|
||||
|
||||
if (gauntlet) {
|
||||
final Integer rounds = SGuiChoose.getInteger(Forge.getLocalizer().getMessage("lblHowManyOpponents"),
|
||||
1, FModel.getDecks().getDraft().get(humanDeck.getName()).getAiDecks().size());
|
||||
if (rounds == null) {
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (!checkDeckLegality(humanDeck)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!checkDeckLegality(humanDeck)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FModel.getGauntletMini().resetGauntletDraft();
|
||||
FModel.getGauntletMini().launch(rounds, humanDeck.getDeck(), GameType.Draft);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final Integer aiIndex = SGuiChoose.getInteger(Forge.getLocalizer().getMessage("lblWhichOpponentWouldYouLikeToFace"),
|
||||
1, FModel.getDecks().getDraft().get(humanDeck.getName()).getAiDecks().size());
|
||||
if (aiIndex == null) {
|
||||
return; // Cancel was pressed
|
||||
}
|
||||
|
||||
final DeckGroup opponentDecks = FModel.getDecks().getDraft().get(humanDeck.getName());
|
||||
final Deck aiDeck = opponentDecks.getAiDecks().get(aiIndex - 1);
|
||||
if (aiDeck == null) {
|
||||
throw new IllegalStateException("Draft: Computer deck is null!");
|
||||
}
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!checkDeckLegality(humanDeck)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<RegisteredPlayer> starter = new ArrayList<>();
|
||||
final RegisteredPlayer human = new RegisteredPlayer(humanDeck.getDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
starter.add(human);
|
||||
starter.add(new RegisteredPlayer(aiDeck).setPlayer(GamePlayerUtil.createAiPlayer()));
|
||||
for (final RegisteredPlayer pl : starter) {
|
||||
pl.assignConspiracies();
|
||||
}
|
||||
|
||||
FModel.getGauntletMini().resetGauntletDraft();
|
||||
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.startMatch(GameType.Draft, null, starter, human, GuiBase.getInterface().getNewGuiGame());
|
||||
}
|
||||
});
|
||||
}
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), true, () -> {
|
||||
FModel.getGauntletMini().resetGauntletDraft();
|
||||
FModel.getGauntletMini().launch(rounds, humanDeck.getDeck(), GameType.Draft);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
final Integer aiIndex = SGuiChoose.getInteger(Forge.getLocalizer().getMessage("lblWhichOpponentWouldYouLikeToFace"),
|
||||
1, FModel.getDecks().getDraft().get(humanDeck.getName()).getAiDecks().size());
|
||||
if (aiIndex == null) {
|
||||
return; // Cancel was pressed
|
||||
}
|
||||
|
||||
final DeckGroup opponentDecks = FModel.getDecks().getDraft().get(humanDeck.getName());
|
||||
final Deck aiDeck = opponentDecks.getAiDecks().get(aiIndex - 1);
|
||||
if (aiDeck == null) {
|
||||
throw new IllegalStateException("Draft: Computer deck is null!");
|
||||
}
|
||||
|
||||
FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), true, () -> {
|
||||
if (!checkDeckLegality(humanDeck)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<RegisteredPlayer> starter = new ArrayList<>();
|
||||
final RegisteredPlayer human = new RegisteredPlayer(humanDeck.getDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
starter.add(human);
|
||||
starter.add(new RegisteredPlayer(aiDeck).setPlayer(GamePlayerUtil.createAiPlayer()));
|
||||
for (final RegisteredPlayer pl : starter) {
|
||||
pl.assignConspiracies();
|
||||
}
|
||||
|
||||
FModel.getGauntletMini().resetGauntletDraft();
|
||||
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.startMatch(GameType.Draft, null, starter, human, GuiBase.getInterface().getNewGuiGame());
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ import forge.screens.LaunchScreen;
|
||||
import forge.screens.LoadingOverlay;
|
||||
import forge.screens.home.LoadGameMenu;
|
||||
import forge.toolbox.FComboBox;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FOptionPane;
|
||||
|
||||
@@ -54,12 +52,7 @@ public class LoadSealedScreen extends LaunchScreen {
|
||||
cbMode.addItem(Forge.getLocalizer().getMessage("lblSingleMatch"));
|
||||
|
||||
lstDecks.setup(ItemManagerConfig.SEALED_DECKS);
|
||||
lstDecks.setItemActivateHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
editSelectedDeck();
|
||||
}
|
||||
});
|
||||
lstDecks.setItemActivateHandler(event -> editSelectedDeck());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,74 +88,59 @@ public class LoadSealedScreen extends LaunchScreen {
|
||||
|
||||
@Override
|
||||
protected void startMatch() {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final DeckProxy humanDeck = lstDecks.getSelectedItem();
|
||||
if (humanDeck == null) {
|
||||
FOptionPane.showErrorDialog(Forge.getLocalizer().getMessage("lblYouMustSelectExistingSealedPool"), Forge.getLocalizer().getMessage("lblNoDeck"));
|
||||
return;
|
||||
}
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
final DeckProxy humanDeck = lstDecks.getSelectedItem();
|
||||
if (humanDeck == null) {
|
||||
FOptionPane.showErrorDialog(Forge.getLocalizer().getMessage("lblYouMustSelectExistingSealedPool"), Forge.getLocalizer().getMessage("lblNoDeck"));
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean gauntlet = cbMode.getSelectedItem().equals(Forge.getLocalizer().getMessage("lblGauntlet"));
|
||||
final boolean gauntlet = cbMode.getSelectedItem().equals(Forge.getLocalizer().getMessage("lblGauntlet"));
|
||||
|
||||
if (gauntlet) {
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!checkDeckLegality(humanDeck)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final int matches = FModel.getDecks().getSealed().get(humanDeck.getName()).getAiDecks().size();
|
||||
FModel.getGauntletMini().launch(matches, humanDeck.getDeck(), GameType.Sealed);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
final Integer aiIndex = SGuiChoose.getInteger(Forge.getLocalizer().getMessage("lblWhichOpponentWouldYouLikeToFace"),
|
||||
1, FModel.getDecks().getSealed().get(humanDeck.getName()).getAiDecks().size());
|
||||
if (aiIndex == null) {
|
||||
return; // Cancel was pressed
|
||||
if (gauntlet) {
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (!checkDeckLegality(humanDeck)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final DeckGroup opponentDecks = FModel.getDecks().getSealed().get(humanDeck.getName());
|
||||
final Deck aiDeck = opponentDecks.getAiDecks().get(aiIndex - 1);
|
||||
if (aiDeck == null) {
|
||||
throw new IllegalStateException("Draft: Computer deck is null!");
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), true, () -> {
|
||||
final int matches = FModel.getDecks().getSealed().get(humanDeck.getName()).getAiDecks().size();
|
||||
FModel.getGauntletMini().launch(matches, humanDeck.getDeck(), GameType.Sealed);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
|
||||
final Integer aiIndex = SGuiChoose.getInteger(Forge.getLocalizer().getMessage("lblWhichOpponentWouldYouLikeToFace"),
|
||||
1, FModel.getDecks().getSealed().get(humanDeck.getName()).getAiDecks().size());
|
||||
if (aiIndex == null) {
|
||||
return; // Cancel was pressed
|
||||
}
|
||||
|
||||
final DeckGroup opponentDecks = FModel.getDecks().getSealed().get(humanDeck.getName());
|
||||
final Deck aiDeck = opponentDecks.getAiDecks().get(aiIndex - 1);
|
||||
if (aiDeck == null) {
|
||||
throw new IllegalStateException("Draft: Computer deck is null!");
|
||||
}
|
||||
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (!checkDeckLegality(humanDeck)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!checkDeckLegality(humanDeck)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final List<RegisteredPlayer> starter = new ArrayList<>();
|
||||
final RegisteredPlayer human = new RegisteredPlayer(humanDeck.getDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
starter.add(human);
|
||||
starter.add(new RegisteredPlayer(aiDeck).setPlayer(GamePlayerUtil.createAiPlayer()));
|
||||
for (final RegisteredPlayer pl : starter) {
|
||||
pl.assignConspiracies();
|
||||
}
|
||||
|
||||
FModel.getGauntletMini().resetGauntletDraft();
|
||||
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.startMatch(GameType.Sealed, null, starter, human, GuiBase.getInterface().getNewGuiGame());
|
||||
}
|
||||
});
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), true, () -> {
|
||||
final List<RegisteredPlayer> starter = new ArrayList<>();
|
||||
final RegisteredPlayer human = new RegisteredPlayer(humanDeck.getDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
starter.add(human);
|
||||
starter.add(new RegisteredPlayer(aiDeck).setPlayer(GamePlayerUtil.createAiPlayer()));
|
||||
for (final RegisteredPlayer pl : starter) {
|
||||
pl.assignConspiracies();
|
||||
}
|
||||
|
||||
FModel.getGauntletMini().resetGauntletDraft();
|
||||
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.startMatch(GameType.Sealed, null, starter, human, GuiBase.getInterface().getNewGuiGame());
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -41,27 +41,15 @@ public class NewDraftScreen extends LaunchScreen {
|
||||
|
||||
@Override
|
||||
protected void startMatch() {
|
||||
ThreadUtil.invokeInGameThread(new Runnable() { //must run in game thread to prevent blocking UI thread
|
||||
@Override
|
||||
public void run() {
|
||||
final LimitedPoolType poolType = SGuiChoose.oneOrNone(Forge.getLocalizer().getMessage("lblChooseDraftFormat"), LimitedPoolType.values());
|
||||
if (poolType == null) { return; }
|
||||
//must run in game thread to prevent blocking UI thread
|
||||
ThreadUtil.invokeInGameThread(() -> {
|
||||
final LimitedPoolType poolType = SGuiChoose.oneOrNone(Forge.getLocalizer().getMessage("lblChooseDraftFormat"), LimitedPoolType.values());
|
||||
if (poolType == null) { return; }
|
||||
|
||||
final BoosterDraft draft = BoosterDraft.createDraft(poolType);
|
||||
if (draft == null) { return; }
|
||||
final BoosterDraft draft = BoosterDraft.createDraft(poolType);
|
||||
if (draft == null) { return; }
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewDraft"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Forge.openScreen(new DraftingProcessScreen(draft, EditorType.Draft, null));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewDraft"), true, () -> Forge.openScreen(new DraftingProcessScreen(draft, EditorType.Draft, null))));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package forge.screens.match;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -74,8 +73,6 @@ public class MatchController extends AbstractGuiGame {
|
||||
private MatchController() { }
|
||||
public static final MatchController instance = new MatchController();
|
||||
|
||||
private static final Map<String, FImage> avatarImages = new HashMap<>();
|
||||
|
||||
private static HostedMatch hostedMatch;
|
||||
private static MatchScreen view;
|
||||
private static GameState phaseGameState;
|
||||
@@ -114,7 +111,7 @@ public class MatchController extends AbstractGuiGame {
|
||||
|
||||
public static FImage getPlayerAvatar(final PlayerView p) {
|
||||
final String lp = p.getLobbyPlayerName();
|
||||
FImage avatar = avatarImages.get(lp);
|
||||
FImage avatar = Forge.getAssets().avatarImages().get(lp);
|
||||
if (avatar == null) {
|
||||
if (StringUtils.isEmpty(p.getAvatarCardImageKey())) {
|
||||
avatar = new FTextureRegionImage(FSkin.getAvatars().get(p.getAvatarIndex()));
|
||||
@@ -488,15 +485,13 @@ public class MatchController extends AbstractGuiGame {
|
||||
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));
|
||||
}
|
||||
FThreads.invokeInEdtNowOrLater(() -> {
|
||||
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));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -506,15 +501,13 @@ public class MatchController extends AbstractGuiGame {
|
||||
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));
|
||||
}
|
||||
FThreads.invokeInEdtNowOrLater(() -> {
|
||||
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));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -703,7 +696,7 @@ public class MatchController extends AbstractGuiGame {
|
||||
|
||||
@Override
|
||||
public void setPlayerAvatar(final LobbyPlayer player, final IHasIcon ihi) {
|
||||
avatarImages.put(player.getName(), ImageCache.getIcon(ihi));
|
||||
Forge.getAssets().avatarImages().put(player.getName(), ImageCache.getIcon(ihi));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -56,18 +56,15 @@ public class OnlineLobbyScreen extends LobbyScreen implements IOnlineLobby {
|
||||
clearGameLobby();
|
||||
Forge.back();
|
||||
if (msg.length() > 0) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean callBackAlwaysTrue = SOptionPane.showOptionDialog(msg, Forge.getLocalizer().getMessage("lblError"), FSkinProp.ICO_WARNING, ImmutableList.of(Forge.getLocalizer().getMessage("lblOk")), 1) == 0;
|
||||
if (callBackAlwaysTrue) { //to activate online menu popup when player press play online
|
||||
GuiBase.setInterrupted(false);
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
final boolean callBackAlwaysTrue = SOptionPane.showOptionDialog(msg, Forge.getLocalizer().getMessage("lblError"), FSkinProp.ICO_WARNING, ImmutableList.of(Forge.getLocalizer().getMessage("lblOk")), 1) == 0;
|
||||
if (callBackAlwaysTrue) { //to activate online menu popup when player press play online
|
||||
GuiBase.setInterrupted(false);
|
||||
|
||||
if(FServerManager.getInstance() != null)
|
||||
FServerManager.getInstance().stopServer();
|
||||
if(getfGameClient() != null)
|
||||
closeClient();
|
||||
}
|
||||
if(FServerManager.getInstance() != null)
|
||||
FServerManager.getInstance().stopServer();
|
||||
if(getfGameClient() != null)
|
||||
closeClient();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -93,51 +90,37 @@ public class OnlineLobbyScreen extends LobbyScreen implements IOnlineLobby {
|
||||
if (getGameLobby() == null) {
|
||||
setGameLobby(getLobby());
|
||||
//prompt to connect to server when offline lobby activated
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final String url = NetConnectUtil.getServerUrl();
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (url == null) {
|
||||
closeConn(""); //go back to previous screen if user cancels connection
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
final String url = NetConnectUtil.getServerUrl();
|
||||
FThreads.invokeInEdtLater(() -> {
|
||||
if (url == null) {
|
||||
closeConn(""); //go back to previous screen if user cancels connection
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean joinServer = url.length() > 0;
|
||||
final String caption = joinServer ? Forge.getLocalizer().getMessage("lblConnectingToServer") : Forge.getLocalizer().getMessage("lblStartingServer");
|
||||
LoadingOverlay.show(caption, true, () -> {
|
||||
final ChatMessage result;
|
||||
final IOnlineChatInterface chatInterface = (IOnlineChatInterface)OnlineScreen.Chat.getScreen();
|
||||
if (joinServer) {
|
||||
result = NetConnectUtil.join(url, OnlineLobbyScreen.this, chatInterface);
|
||||
if (result.getMessage() == ForgeConstants.CLOSE_CONN_COMMAND) { //this message is returned via netconnectutil on exception
|
||||
closeConn(Forge.getLocalizer().getMessage("lblDetectedInvalidHostAddress", url));
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean joinServer = url.length() > 0;
|
||||
final String caption = joinServer ? Forge.getLocalizer().getMessage("lblConnectingToServer") : Forge.getLocalizer().getMessage("lblStartingServer");
|
||||
LoadingOverlay.show(caption, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ChatMessage result;
|
||||
final IOnlineChatInterface chatInterface = (IOnlineChatInterface)OnlineScreen.Chat.getScreen();
|
||||
if (joinServer) {
|
||||
result = NetConnectUtil.join(url, OnlineLobbyScreen.this, chatInterface);
|
||||
if (result.getMessage() == ForgeConstants.CLOSE_CONN_COMMAND) { //this message is returned via netconnectutil on exception
|
||||
closeConn(Forge.getLocalizer().getMessage("lblDetectedInvalidHostAddress", url));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = NetConnectUtil.host(OnlineLobbyScreen.this, chatInterface);
|
||||
}
|
||||
chatInterface.addMessage(result);
|
||||
if (!joinServer) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NetConnectUtil.copyHostedServerUrl();
|
||||
}
|
||||
});
|
||||
}
|
||||
//update menu buttons
|
||||
OnlineScreen.Lobby.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
result = NetConnectUtil.host(OnlineLobbyScreen.this, chatInterface);
|
||||
}
|
||||
chatInterface.addMessage(result);
|
||||
if (!joinServer) {
|
||||
FThreads.invokeInBackgroundThread(() -> NetConnectUtil.copyHostedServerUrl());
|
||||
}
|
||||
//update menu buttons
|
||||
OnlineScreen.Lobby.update();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ import forge.screens.FScreen;
|
||||
import forge.screens.LoadingOverlay;
|
||||
import forge.screens.home.HomeScreen;
|
||||
import forge.screens.home.LoadGameMenu.LoadGameScreen;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
|
||||
public class ConquestMenu extends FPopupMenu {
|
||||
private static final ConquestMenu conquestMenu = new ConquestMenu();
|
||||
@@ -26,54 +24,14 @@ public class ConquestMenu extends FPopupMenu {
|
||||
private static final ConquestStatsScreen statsScreen = new ConquestStatsScreen();
|
||||
private static final ConquestPrefsScreen prefsScreen = new ConquestPrefsScreen();
|
||||
|
||||
private static final FMenuItem multiverseItem = new FMenuItem(Forge.getLocalizer().getMessage("lblTheMultiverse"), FSkinImage.MULTIVERSE, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(multiverseScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem aetherItem = new FMenuItem(Forge.getLocalizer().getMessage("lblTheAether"), FSkinImage.AETHER_SHARD, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(aetherScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem commandersItem = new FMenuItem(Forge.getLocalizer().getMessage("lblCommanders"), FSkinImage.COMMANDER, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(commandersScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem planeswalkersItem = new FMenuItem(Forge.getLocalizer().getMessage("lblPlaneswalkers"), FSkinImage.PLANESWALKER, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(planeswalkersScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem collectionItem = new FMenuItem(Forge.getLocalizer().getMessage("lblCollection"), FSkinImage.SPELLBOOK, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(collectionScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem statsItem = new FMenuItem(Forge.getLocalizer().getMessage("lblStatistics"), FSkinImage.MENU_STATS, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(statsScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem planeswalkItem = new FMenuItem(Forge.getLocalizer().getMessage("lblPlaneswalk"), FSkinImage.PW_BADGE_COMMON, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(planeswalkScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem prefsItem = new FMenuItem(Forge.getLocalizer().getMessage("Preferences"), Forge.hdbuttons ? FSkinImage.HDPREFERENCE : FSkinImage.SETTINGS, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(prefsScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem multiverseItem = new FMenuItem(Forge.getLocalizer().getMessage("lblTheMultiverse"), FSkinImage.MULTIVERSE, event -> setCurrentScreen(multiverseScreen));
|
||||
private static final FMenuItem aetherItem = new FMenuItem(Forge.getLocalizer().getMessage("lblTheAether"), FSkinImage.AETHER_SHARD, event -> setCurrentScreen(aetherScreen));
|
||||
private static final FMenuItem commandersItem = new FMenuItem(Forge.getLocalizer().getMessage("lblCommanders"), FSkinImage.COMMANDER, event -> setCurrentScreen(commandersScreen));
|
||||
private static final FMenuItem planeswalkersItem = new FMenuItem(Forge.getLocalizer().getMessage("lblPlaneswalkers"), FSkinImage.PLANESWALKER, event -> setCurrentScreen(planeswalkersScreen));
|
||||
private static final FMenuItem collectionItem = new FMenuItem(Forge.getLocalizer().getMessage("lblCollection"), FSkinImage.SPELLBOOK, event -> setCurrentScreen(collectionScreen));
|
||||
private static final FMenuItem statsItem = new FMenuItem(Forge.getLocalizer().getMessage("lblStatistics"), FSkinImage.MENU_STATS, event -> setCurrentScreen(statsScreen));
|
||||
private static final FMenuItem planeswalkItem = new FMenuItem(Forge.getLocalizer().getMessage("lblPlaneswalk"), FSkinImage.PW_BADGE_COMMON, event -> setCurrentScreen(planeswalkScreen));
|
||||
private static final FMenuItem prefsItem = new FMenuItem(Forge.getLocalizer().getMessage("Preferences"), Forge.hdbuttons ? FSkinImage.HDPREFERENCE : FSkinImage.SETTINGS, event -> setCurrentScreen(prefsScreen));
|
||||
|
||||
private static void setCurrentScreen(FScreen screen0) {
|
||||
//make it so pressing Back from any screen besides Multiverse screen always goes to Multiverse screen
|
||||
@@ -84,12 +42,7 @@ public class ConquestMenu extends FPopupMenu {
|
||||
static {
|
||||
//the first time planarconquest mode is launched, add button for it if in Landscape mode
|
||||
if (Forge.isLandscapeMode()) {
|
||||
HomeScreen.instance.addButtonForMode("-"+Forge.getLocalizer().getMessage("lblPlanarConquest"), new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
launchPlanarConquest(LaunchReason.StartPlanarConquest);
|
||||
}
|
||||
});
|
||||
HomeScreen.instance.addButtonForMode("-"+Forge.getLocalizer().getMessage("lblPlanarConquest"), event -> launchPlanarConquest(LaunchReason.StartPlanarConquest));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,20 +61,16 @@ public class ConquestMenu extends FPopupMenu {
|
||||
|
||||
public static void launchPlanarConquest(final LaunchReason reason) {
|
||||
Forge.lastButtonIndex = 7;
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingCurrentConquest"), new Runnable() {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void run() {
|
||||
((DeckController<Deck>)EditorType.PlanarConquest.getController()).setRootFolder(FModel.getConquest().getDecks());
|
||||
if (reason == LaunchReason.StartPlanarConquest) {
|
||||
Forge.openScreen(multiverseScreen);
|
||||
}
|
||||
else {
|
||||
multiverseScreen.update();
|
||||
Forge.openScreen(multiverseScreen);
|
||||
if (reason == LaunchReason.NewConquest) {
|
||||
LoadGameScreen.PlanarConquest.setAsBackScreen(true);
|
||||
}
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingCurrentConquest"), true, () -> {
|
||||
((DeckController<Deck>)EditorType.PlanarConquest.getController()).setRootFolder(FModel.getConquest().getDecks());
|
||||
if (reason == LaunchReason.StartPlanarConquest) {
|
||||
Forge.openScreen(multiverseScreen);
|
||||
}
|
||||
else {
|
||||
multiverseScreen.update();
|
||||
Forge.openScreen(multiverseScreen);
|
||||
if (reason == LaunchReason.NewConquest) {
|
||||
LoadGameScreen.PlanarConquest.setAsBackScreen(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -47,8 +47,6 @@ import forge.screens.LoadingOverlay;
|
||||
import forge.toolbox.FButton;
|
||||
import forge.toolbox.FContainer;
|
||||
import forge.toolbox.FDisplayObject;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FList;
|
||||
import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.FScrollPane;
|
||||
@@ -260,29 +258,18 @@ public class ConquestMultiverseScreen extends FScreen {
|
||||
}
|
||||
|
||||
private void launchEvent() {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblStartingBattle"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ConquestLocation loc = model.getCurrentLocation();
|
||||
activeBattle = loc.getEvent().createBattle(loc, 0);
|
||||
FModel.getConquest().startBattle(activeBattle);
|
||||
}
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblStartingBattle"), true, () -> {
|
||||
ConquestLocation loc = model.getCurrentLocation();
|
||||
activeBattle = loc.getEvent().createBattle(loc, 0);
|
||||
FModel.getConquest().startBattle(activeBattle);
|
||||
});
|
||||
}
|
||||
|
||||
private void launchChaosBattle() {
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblChaosApproaching"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
activeBattle = new ConquestChaosBattle();
|
||||
FModel.getConquest().startBattle(activeBattle);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
FThreads.invokeInEdtNowOrLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblChaosApproaching"), true, () -> {
|
||||
activeBattle = new ConquestChaosBattle();
|
||||
FModel.getConquest().startBattle(activeBattle);
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -678,12 +665,7 @@ public class ConquestMultiverseScreen extends FScreen {
|
||||
private BattleBar() {
|
||||
playerAvatar = add(new AvatarDisplay(false));
|
||||
opponentAvatar = add(new AvatarDisplay(true));
|
||||
btnBattle = add(new FButton(Forge.getLocalizer().getMessage("lblBattle"), new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
launchEvent();
|
||||
}
|
||||
}));
|
||||
btnBattle = add(new FButton(Forge.getLocalizer().getMessage("lblBattle"), event -> launchEvent()));
|
||||
btnBattle.setFont(FSkinFont.get(20));
|
||||
}
|
||||
|
||||
|
||||
@@ -37,12 +37,7 @@ public class NewConquestScreen extends MultiStepWizardScreen<NewConquestScreenMo
|
||||
@Override
|
||||
protected void finish() {
|
||||
//create new quest in game thread so option panes can wait for input
|
||||
ThreadUtil.invokeInGameThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
newConquest();
|
||||
}
|
||||
});
|
||||
ThreadUtil.invokeInGameThread(() -> newConquest());
|
||||
}
|
||||
|
||||
private void newConquest() {
|
||||
@@ -52,26 +47,18 @@ public class NewConquestScreen extends MultiStepWizardScreen<NewConquestScreenMo
|
||||
}
|
||||
|
||||
private void startNewConquest(final String conquestName) {
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblStartingNewConquest"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ConquestController qc = FModel.getConquest();
|
||||
qc.setModel(new ConquestData(conquestName, model.startingPlane, model.startingPlaneswalker, model.startingCommander));
|
||||
qc.getDecks().add(Iterables.getFirst(qc.getModel().getCommanders(), null).getDeck()); //ensure starting deck is saved
|
||||
qc.getModel().saveData();
|
||||
FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblStartingNewConquest"), true, () -> {
|
||||
ConquestController qc = FModel.getConquest();
|
||||
qc.setModel(new ConquestData(conquestName, model.startingPlane, model.startingPlaneswalker, model.startingCommander));
|
||||
qc.getDecks().add(Iterables.getFirst(qc.getModel().getCommanders(), null).getDeck()); //ensure starting deck is saved
|
||||
qc.getModel().saveData();
|
||||
|
||||
// Save in preferences.
|
||||
FModel.getConquestPreferences().setPref(CQPref.CURRENT_CONQUEST, conquestName);
|
||||
FModel.getConquestPreferences().save();
|
||||
// Save in preferences.
|
||||
FModel.getConquestPreferences().setPref(CQPref.CURRENT_CONQUEST, conquestName);
|
||||
FModel.getConquestPreferences().save();
|
||||
|
||||
ConquestMenu.launchPlanarConquest(LaunchReason.NewConquest);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
ConquestMenu.launchPlanarConquest(LaunchReason.NewConquest);
|
||||
}));
|
||||
}
|
||||
|
||||
private static class SelectStartingPlaneStep extends WizardStep<NewConquestScreenModel> {
|
||||
|
||||
@@ -42,8 +42,6 @@ import forge.screens.quest.QuestMenu.LaunchReason;
|
||||
import forge.toolbox.FCheckBox;
|
||||
import forge.toolbox.FComboBox;
|
||||
import forge.toolbox.FDisplayObject;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FNumericTextField;
|
||||
import forge.toolbox.FOptionPane;
|
||||
@@ -186,17 +184,9 @@ public class NewQuestScreen extends FScreen {
|
||||
private final FCheckBox cbCommander = scroller.add(new FCheckBox(Forge.getLocalizer().getMessage("rbCommanderSubformat")));
|
||||
|
||||
private final FLabel btnEmbark = add(new FLabel.ButtonBuilder()
|
||||
.font(FSkinFont.get(22)).text(Forge.getLocalizer().getMessage("lblEmbark")).icon(FSkinImage.QUEST_ZEP).command(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
//create new quest in game thread so option panes can wait for input
|
||||
ThreadUtil.invokeInGameThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
newQuest();
|
||||
}
|
||||
});
|
||||
}
|
||||
.font(FSkinFont.get(22)).text(Forge.getLocalizer().getMessage("lblEmbark")).icon(FSkinImage.QUEST_ZEP).command(event -> {
|
||||
//create new quest in game thread so option panes can wait for input
|
||||
ThreadUtil.invokeInGameThread(() -> newQuest());
|
||||
}).build());
|
||||
|
||||
public NewQuestScreen() {
|
||||
@@ -209,24 +199,18 @@ public class NewQuestScreen extends FScreen {
|
||||
cbxStartingPool.addItem(StartingPoolType.DraftDeck);
|
||||
cbxStartingPool.addItem(StartingPoolType.SealedDeck);
|
||||
cbxStartingPool.addItem(StartingPoolType.Cube);
|
||||
cbxStartingPool.setChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
updateStartingPoolOptions();
|
||||
scroller.revalidate();
|
||||
}
|
||||
cbxStartingPool.setChangedHandler(event -> {
|
||||
updateStartingPoolOptions();
|
||||
scroller.revalidate();
|
||||
});
|
||||
|
||||
cbxPrizedCards.addItem(Forge.getLocalizer().getMessage("lblSameAsStartingPool"));
|
||||
cbxPrizedCards.addItem(StartingPoolType.Complete);
|
||||
cbxPrizedCards.addItem(StartingPoolType.Sanctioned);
|
||||
cbxPrizedCards.addItem(StartingPoolType.Casual);
|
||||
cbxPrizedCards.setChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
updatePrizeOptions();
|
||||
scroller.revalidate();
|
||||
}
|
||||
cbxPrizedCards.setChangedHandler(event -> {
|
||||
updatePrizeOptions();
|
||||
scroller.revalidate();
|
||||
});
|
||||
|
||||
for (GameFormat gf : FModel.getFormats().getSanctionedList()) {
|
||||
@@ -243,18 +227,15 @@ public class NewQuestScreen extends FScreen {
|
||||
numberOfBoostersField.setEnabled(false);
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
UiCommand colorBoxEnabler = new UiCommand() {
|
||||
@Override
|
||||
public void run() {
|
||||
cbBlack.setEnabled(radBalanced.isSelected());
|
||||
cbBlue.setEnabled(radBalanced.isSelected());
|
||||
cbGreen.setEnabled(radBalanced.isSelected());
|
||||
cbRed.setEnabled(radBalanced.isSelected());
|
||||
cbWhite.setEnabled(radBalanced.isSelected());
|
||||
cbColorless.setEnabled(radBalanced.isSelected());
|
||||
cbIncludeArtifacts.setEnabled(!radSurpriseMe.isSelected());
|
||||
numberOfBoostersField.setEnabled(radBoosters.isSelected());
|
||||
}
|
||||
UiCommand colorBoxEnabler = () -> {
|
||||
cbBlack.setEnabled(radBalanced.isSelected());
|
||||
cbBlue.setEnabled(radBalanced.isSelected());
|
||||
cbGreen.setEnabled(radBalanced.isSelected());
|
||||
cbRed.setEnabled(radBalanced.isSelected());
|
||||
cbWhite.setEnabled(radBalanced.isSelected());
|
||||
cbColorless.setEnabled(radBalanced.isSelected());
|
||||
cbIncludeArtifacts.setEnabled(!radSurpriseMe.isSelected());
|
||||
numberOfBoostersField.setEnabled(radBoosters.isSelected());
|
||||
};
|
||||
|
||||
radBalanced.setCommand(colorBoxEnabler);
|
||||
@@ -268,12 +249,7 @@ public class NewQuestScreen extends FScreen {
|
||||
// Default to 'Main world'
|
||||
cbxStartingWorld.setSelectedItem(FModel.getWorlds().get("Main world"));
|
||||
|
||||
cbxStartingWorld.setChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
updateEnabledFormats();
|
||||
}
|
||||
});
|
||||
cbxStartingWorld.setChangedHandler(event -> updateEnabledFormats());
|
||||
|
||||
updateStartingPoolOptions();
|
||||
updatePrizeOptions();
|
||||
@@ -298,59 +274,44 @@ public class NewQuestScreen extends FScreen {
|
||||
unselectableSets.add("ARC");
|
||||
unselectableSets.add("PC2");
|
||||
|
||||
btnSelectFormat.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
ArchivedFormatSelect archivedFormatSelect = new ArchivedFormatSelect();
|
||||
archivedFormatSelect.setOnCloseCallBack(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
customFormatCodes.clear();
|
||||
btnSelectFormat.setText(archivedFormatSelect.getSelectedFormat().getName());
|
||||
List<String> setsToAdd = archivedFormatSelect.getSelectedFormat().getAllowedSetCodes();
|
||||
for (String setName:setsToAdd){
|
||||
if(!unselectableSets.contains(setName)){
|
||||
customFormatCodes.add(setName);
|
||||
}
|
||||
}
|
||||
btnSelectFormat.setCommand(event -> {
|
||||
ArchivedFormatSelect archivedFormatSelect = new ArchivedFormatSelect();
|
||||
archivedFormatSelect.setOnCloseCallBack(() -> {
|
||||
customFormatCodes.clear();
|
||||
btnSelectFormat.setText(archivedFormatSelect.getSelectedFormat().getName());
|
||||
List<String> setsToAdd = archivedFormatSelect.getSelectedFormat().getAllowedSetCodes();
|
||||
for (String setName:setsToAdd){
|
||||
if(!unselectableSets.contains(setName)){
|
||||
customFormatCodes.add(setName);
|
||||
}
|
||||
});
|
||||
Forge.openScreen(archivedFormatSelect);
|
||||
}
|
||||
}
|
||||
});
|
||||
Forge.openScreen(archivedFormatSelect);
|
||||
});
|
||||
|
||||
btnPrizeSelectFormat.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
ArchivedFormatSelect archivedFormatSelect = new ArchivedFormatSelect();
|
||||
archivedFormatSelect.setOnCloseCallBack(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
customPrizeFormatCodes.clear();
|
||||
btnPrizeSelectFormat.setText(archivedFormatSelect.getSelectedFormat().getName());
|
||||
List<String> setsToAdd = archivedFormatSelect.getSelectedFormat().getAllowedSetCodes();
|
||||
for (String setName:setsToAdd){
|
||||
if(!unselectableSets.contains(setName)){
|
||||
customPrizeFormatCodes.add(setName);
|
||||
}
|
||||
}
|
||||
btnPrizeSelectFormat.setCommand(event -> {
|
||||
ArchivedFormatSelect archivedFormatSelect = new ArchivedFormatSelect();
|
||||
archivedFormatSelect.setOnCloseCallBack(() -> {
|
||||
customPrizeFormatCodes.clear();
|
||||
btnPrizeSelectFormat.setText(archivedFormatSelect.getSelectedFormat().getName());
|
||||
List<String> setsToAdd = archivedFormatSelect.getSelectedFormat().getAllowedSetCodes();
|
||||
for (String setName:setsToAdd){
|
||||
if(!unselectableSets.contains(setName)){
|
||||
customPrizeFormatCodes.add(setName);
|
||||
}
|
||||
});
|
||||
Forge.openScreen(archivedFormatSelect);
|
||||
}
|
||||
}
|
||||
});
|
||||
Forge.openScreen(archivedFormatSelect);
|
||||
});
|
||||
|
||||
// Fantasy box enabled by Default
|
||||
cbFantasy.setSelected(true);
|
||||
cbFantasy.setEnabled(true);
|
||||
cbCommander.setSelected(false);
|
||||
cbCommander.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
if (!isCommander())
|
||||
return;
|
||||
cbxStartingWorld.setSelectedItem(FModel.getWorlds().get("Random Commander"));
|
||||
}
|
||||
cbCommander.setCommand(event -> {
|
||||
if (!isCommander())
|
||||
return;
|
||||
cbxStartingWorld.setSelectedItem(FModel.getWorlds().get("Random Commander"));
|
||||
});
|
||||
|
||||
}
|
||||
@@ -644,30 +605,22 @@ public class NewQuestScreen extends FScreen {
|
||||
}
|
||||
|
||||
private void startNewQuest(final String questName, final GameFormat fmtPrizes, final Deck dckStartPool, final GameFormat fmtStartPool) {
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblCreatingNewQuest"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final QuestMode mode = isFantasy() ? QuestMode.Fantasy : QuestMode.Classic;
|
||||
final StartingPoolPreferences userPrefs =
|
||||
new StartingPoolPreferences(getPoolType(), getPreferredColors(), cbIncludeArtifacts.isSelected(), startWithCompleteSet(), allowDuplicateCards(), numberOfBoostersField.getValue());
|
||||
QuestController qc = FModel.getQuest();
|
||||
FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblCreatingNewQuest"), true, () -> {
|
||||
final QuestMode mode = isFantasy() ? QuestMode.Fantasy : QuestMode.Classic;
|
||||
final StartingPoolPreferences userPrefs =
|
||||
new StartingPoolPreferences(getPoolType(), getPreferredColors(), cbIncludeArtifacts.isSelected(), startWithCompleteSet(), allowDuplicateCards(), numberOfBoostersField.getValue());
|
||||
QuestController qc = FModel.getQuest();
|
||||
|
||||
DeckConstructionRules dcr = isCommander() ? DeckConstructionRules.Commander: DeckConstructionRules.Default;
|
||||
DeckConstructionRules dcr = isCommander() ? DeckConstructionRules.Commander: DeckConstructionRules.Default;
|
||||
|
||||
qc.newGame(questName, getSelectedDifficulty(), mode, fmtPrizes, isUnlockSetsAllowed(), dckStartPool, fmtStartPool, getStartingWorldName(), userPrefs, dcr);
|
||||
qc.save();
|
||||
qc.newGame(questName, getSelectedDifficulty(), mode, fmtPrizes, isUnlockSetsAllowed(), dckStartPool, fmtStartPool, getStartingWorldName(), userPrefs, dcr);
|
||||
qc.save();
|
||||
|
||||
// Save in preferences.
|
||||
FModel.getQuestPreferences().setPref(QPref.CURRENT_QUEST, questName + ".dat");
|
||||
FModel.getQuestPreferences().save();
|
||||
// Save in preferences.
|
||||
FModel.getQuestPreferences().setPref(QPref.CURRENT_QUEST, questName + ".dat");
|
||||
FModel.getQuestPreferences().save();
|
||||
|
||||
QuestMenu.launchQuestMode(LaunchReason.NewQuest, isCommander()); //launch quest mode for new quest
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
QuestMenu.launchQuestMode(LaunchReason.NewQuest, isCommander()); //launch quest mode for new quest
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ import forge.gui.FThreads;
|
||||
import forge.gui.interfaces.IButton;
|
||||
import forge.model.FModel;
|
||||
import forge.screens.LoadingOverlay;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FLabel;
|
||||
|
||||
public class QuestDuelsScreen extends QuestLaunchScreen {
|
||||
@@ -33,12 +31,7 @@ public class QuestDuelsScreen extends QuestLaunchScreen {
|
||||
|
||||
public QuestDuelsScreen() {
|
||||
super();
|
||||
pnlDuels.setActivateHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
startMatch();
|
||||
}
|
||||
});
|
||||
pnlDuels.setActivateHandler(event -> startMatch());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,23 +67,15 @@ public class QuestDuelsScreen extends QuestLaunchScreen {
|
||||
}
|
||||
|
||||
private void generateDuels() {
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingCurrentQuest"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
pnlDuels.clear();
|
||||
List<QuestEventDuel> duels = FModel.getQuest().getDuelsManager().generateDuels();
|
||||
if (duels != null) {
|
||||
for (QuestEventDuel duel : duels) {
|
||||
pnlDuels.add(new QuestEventPanel(duel, pnlDuels));
|
||||
}
|
||||
}
|
||||
pnlDuels.revalidate();
|
||||
}
|
||||
});
|
||||
FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingCurrentQuest"), true, () -> {
|
||||
pnlDuels.clear();
|
||||
List<QuestEventDuel> duels = FModel.getQuest().getDuelsManager().generateDuels();
|
||||
if (duels != null) {
|
||||
for (QuestEventDuel duel : duels) {
|
||||
pnlDuels.add(new QuestEventPanel(duel, pnlDuels));
|
||||
}
|
||||
}
|
||||
});
|
||||
pnlDuels.revalidate();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,23 +22,10 @@ public abstract class QuestLaunchScreen extends LaunchScreen {
|
||||
|
||||
@Override
|
||||
protected void startMatch() {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (QuestUtil.canStartGame()) {
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
QuestUtil.finishStartingGame();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
if (QuestUtil.canStartGame()) {
|
||||
FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingNewGame"), true, () -> QuestUtil.finishStartingGame()));
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -26,8 +26,6 @@ import forge.screens.LoadingOverlay;
|
||||
import forge.screens.home.HomeScreen;
|
||||
import forge.screens.home.LoadGameMenu.LoadGameScreen;
|
||||
import forge.screens.home.NewGameMenu.NewGameScreen;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.util.ThreadUtil;
|
||||
|
||||
public class QuestMenu extends FPopupMenu implements IVQuestStats {
|
||||
@@ -42,88 +40,28 @@ public class QuestMenu extends FPopupMenu implements IVQuestStats {
|
||||
private static final QuestStatsScreen statsScreen = new QuestStatsScreen();
|
||||
private static final QuestTournamentsScreen tournamentsScreen = new QuestTournamentsScreen();
|
||||
|
||||
private static final FMenuItem duelsItem = new FMenuItem(Forge.getLocalizer().getMessage("lblDuels"), FSkinImage.QUEST_BIG_SWORD, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(duelsScreen);
|
||||
}
|
||||
private static final FMenuItem duelsItem = new FMenuItem(Forge.getLocalizer().getMessage("lblDuels"), FSkinImage.QUEST_BIG_SWORD, event -> setCurrentScreen(duelsScreen));
|
||||
private static final FMenuItem challengesItem = new FMenuItem(Forge.getLocalizer().getMessage("lblChallenges"), FSkinImage.QUEST_HEART, event -> setCurrentScreen(challengesScreen));
|
||||
private static final FMenuItem tournamentsItem = new FMenuItem(Forge.getLocalizer().getMessage("lblTournaments"), FSkinImage.QUEST_BIG_SHIELD, event -> setCurrentScreen(tournamentsScreen));
|
||||
private static final FMenuItem decksItem = new FMenuItem(Forge.getLocalizer().getMessage("lblQuestDecks"), FSkinImage.QUEST_BIG_BAG, event -> setCurrentScreen(decksScreen));
|
||||
private static final FMenuItem spellShopItem = new FMenuItem(Forge.getLocalizer().getMessage("lblSpellShop"), FSkinImage.QUEST_BOOK, event -> setCurrentScreen(spellShopScreen));
|
||||
private static final FMenuItem bazaarItem = new FMenuItem(Forge.getLocalizer().getMessage("lblBazaar"), FSkinImage.QUEST_BOTTLES, event -> setCurrentScreen(bazaarScreen));
|
||||
private static final FMenuItem statsItem = new FMenuItem(Forge.getLocalizer().getMessage("lblStatistics"), FSkinImage.MENU_STATS, event -> setCurrentScreen(statsScreen));
|
||||
private static final FMenuItem unlockSetsItem = new FMenuItem(Forge.getLocalizer().getMessage("btnUnlockSets"), FSkinImage.QUEST_MAP, event -> {
|
||||
//invoke in background thread so prompts can work
|
||||
ThreadUtil.invokeInGameThread(() -> {
|
||||
QuestUtil.chooseAndUnlockEdition();
|
||||
FThreads.invokeInEdtLater(() -> updateCurrentQuestScreen());
|
||||
});
|
||||
});
|
||||
private static final FMenuItem challengesItem = new FMenuItem(Forge.getLocalizer().getMessage("lblChallenges"), FSkinImage.QUEST_HEART, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(challengesScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem tournamentsItem = new FMenuItem(Forge.getLocalizer().getMessage("lblTournaments"), FSkinImage.QUEST_BIG_SHIELD, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(tournamentsScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem decksItem = new FMenuItem(Forge.getLocalizer().getMessage("lblQuestDecks"), FSkinImage.QUEST_BIG_BAG, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(decksScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem spellShopItem = new FMenuItem(Forge.getLocalizer().getMessage("lblSpellShop"), FSkinImage.QUEST_BOOK, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(spellShopScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem bazaarItem = new FMenuItem(Forge.getLocalizer().getMessage("lblBazaar"), FSkinImage.QUEST_BOTTLES, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(bazaarScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem statsItem = new FMenuItem(Forge.getLocalizer().getMessage("lblStatistics"), FSkinImage.MENU_STATS, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(statsScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem unlockSetsItem = new FMenuItem(Forge.getLocalizer().getMessage("btnUnlockSets"), FSkinImage.QUEST_MAP, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
ThreadUtil.invokeInGameThread(new Runnable() { //invoke in background thread so prompts can work
|
||||
@Override
|
||||
public void run() {
|
||||
QuestUtil.chooseAndUnlockEdition();
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateCurrentQuestScreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
private static final FMenuItem travelItem = new FMenuItem(Forge.getLocalizer().getMessage("btnTravel"), FSkinImage.QUEST_MAP, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
ThreadUtil.invokeInGameThread(new Runnable() { //invoke in background thread so prompts can work
|
||||
@Override
|
||||
public void run() {
|
||||
QuestUtil.travelWorld();
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateCurrentQuestScreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
private static final FMenuItem prefsItem = new FMenuItem(Forge.getLocalizer().getMessage("Preferences"), Forge.hdbuttons ? FSkinImage.HDPREFERENCE : FSkinImage.SETTINGS, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(prefsScreen);
|
||||
}
|
||||
private static final FMenuItem travelItem = new FMenuItem(Forge.getLocalizer().getMessage("btnTravel"), FSkinImage.QUEST_MAP, event -> {
|
||||
//invoke in background thread so prompts can work
|
||||
ThreadUtil.invokeInGameThread(() -> {
|
||||
QuestUtil.travelWorld();
|
||||
FThreads.invokeInEdtLater(() -> updateCurrentQuestScreen());
|
||||
});
|
||||
});
|
||||
private static final FMenuItem prefsItem = new FMenuItem(Forge.getLocalizer().getMessage("Preferences"), Forge.hdbuttons ? FSkinImage.HDPREFERENCE : FSkinImage.SETTINGS, event -> setCurrentScreen(prefsScreen));
|
||||
|
||||
static {
|
||||
statsScreen.addTournamentResultsLabels(tournamentsScreen);
|
||||
@@ -159,12 +97,7 @@ public class QuestMenu extends FPopupMenu implements IVQuestStats {
|
||||
static {
|
||||
//the first time quest mode is launched, add button for it if in Landscape mode
|
||||
if (Forge.isLandscapeMode()) {
|
||||
HomeScreen.instance.addButtonForMode("-"+Forge.getLocalizer().getMessage("lblQuestMode"), new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
launchQuestMode(LaunchReason.StartQuestMode, HomeScreen.instance.getQuestCommanderMode());
|
||||
}
|
||||
});
|
||||
HomeScreen.instance.addButtonForMode("-"+Forge.getLocalizer().getMessage("lblQuestMode"), event -> launchQuestMode(LaunchReason.StartQuestMode, HomeScreen.instance.getQuestCommanderMode()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,40 +123,36 @@ public class QuestMenu extends FPopupMenu implements IVQuestStats {
|
||||
final String questname = FModel.getQuestPreferences().getPref(QPref.CURRENT_QUEST);
|
||||
final File data = new File(dirQuests.getPath(), questname);
|
||||
if (data.exists()) {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingCurrentQuest"), new Runnable() {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void run() {
|
||||
try {
|
||||
FModel.getQuest().load(QuestDataIO.loadData(data));
|
||||
} catch (IOException e) {
|
||||
System.err.println(String.format("Failed to load quest '%s'", questname));
|
||||
// Failed to load last quest, don't continue with quest loading stuff
|
||||
return;
|
||||
}
|
||||
LoadingOverlay.show(Forge.getLocalizer().getMessage("lblLoadingCurrentQuest"), true, () -> {
|
||||
try {
|
||||
FModel.getQuest().load(QuestDataIO.loadData(data));
|
||||
} catch (IOException e) {
|
||||
System.err.println(String.format("Failed to load quest '%s'", questname));
|
||||
// Failed to load last quest, don't continue with quest loading stuff
|
||||
return;
|
||||
}
|
||||
|
||||
((DeckController<Deck>)EditorType.Quest.getController()).setRootFolder(FModel.getQuest().getMyDecks());
|
||||
((DeckController<DeckGroup>)EditorType.QuestDraft.getController()).setRootFolder(FModel.getQuest().getDraftDecks());
|
||||
if (reason == LaunchReason.StartQuestMode) {
|
||||
if (QuestUtil.getCurrentDeck() == null) {
|
||||
Forge.openScreen(decksScreen); //if quest doesn't have a deck specified, open decks screen by default
|
||||
}
|
||||
else {
|
||||
Forge.openScreen(duelsScreen); //TODO: Consider opening most recent quest view
|
||||
}
|
||||
((DeckController<Deck>)EditorType.Quest.getController()).setRootFolder(FModel.getQuest().getMyDecks());
|
||||
((DeckController<DeckGroup>)EditorType.QuestDraft.getController()).setRootFolder(FModel.getQuest().getDraftDecks());
|
||||
if (reason == LaunchReason.StartQuestMode) {
|
||||
if (QuestUtil.getCurrentDeck() == null) {
|
||||
Forge.openScreen(decksScreen); //if quest doesn't have a deck specified, open decks screen by default
|
||||
}
|
||||
else {
|
||||
duelsScreen.update();
|
||||
challengesScreen.update();
|
||||
tournamentsScreen.update();
|
||||
decksScreen.refreshDecks();
|
||||
Forge.openScreen(duelsScreen);
|
||||
if (reason == LaunchReason.NewQuest) {
|
||||
LoadGameScreen.QuestMode.setAsBackScreen(true);
|
||||
}
|
||||
Forge.openScreen(duelsScreen); //TODO: Consider opening most recent quest view
|
||||
}
|
||||
HomeScreen.instance.updateQuestWorld(FModel.getQuest().getWorld() == null ? "" : FModel.getQuest().getWorld().toString());
|
||||
}
|
||||
else {
|
||||
duelsScreen.update();
|
||||
challengesScreen.update();
|
||||
tournamentsScreen.update();
|
||||
decksScreen.refreshDecks();
|
||||
Forge.openScreen(duelsScreen);
|
||||
if (reason == LaunchReason.NewQuest) {
|
||||
LoadGameScreen.QuestMode.setAsBackScreen(true);
|
||||
}
|
||||
}
|
||||
HomeScreen.instance.updateQuestWorld(FModel.getQuest().getWorld() == null ? "" : FModel.getQuest().getWorld().toString());
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -29,8 +29,6 @@ import forge.model.FModel;
|
||||
import forge.screens.LoadingOverlay;
|
||||
import forge.screens.TabPageScreen;
|
||||
import forge.toolbox.FDisplayObject;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FTextArea;
|
||||
import forge.toolbox.GuiChoose;
|
||||
@@ -49,36 +47,25 @@ public class QuestSpellShopScreen extends TabPageScreen<QuestSpellShopScreen> {
|
||||
inventoryPage = ((InventoryPage)tabPages[1]);
|
||||
|
||||
btnBuySellMultiple.setVisible(false); //hide unless in multi-select mode
|
||||
btnBuySellMultiple.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
final SpellShopManager itemManager = ((SpellShopBasePage)getSelectedPage()).itemManager;
|
||||
final ItemPool<InventoryItem> items = itemManager.getSelectedItemPool();
|
||||
btnBuySellMultiple.setCommand(event -> {
|
||||
final SpellShopManager itemManager = ((SpellShopBasePage)getSelectedPage()).itemManager;
|
||||
final ItemPool<InventoryItem> items = itemManager.getSelectedItemPool();
|
||||
|
||||
if (items.isEmpty()) {
|
||||
//toggle off multi-select mode if no items selected
|
||||
itemManager.toggleMultiSelectMode(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (getSelectedPage() == spellShopPage) {
|
||||
spellShopPage.activateItems(items);
|
||||
}
|
||||
else {
|
||||
inventoryPage.activateItems(items);
|
||||
}
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateCreditsLabel();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (items.isEmpty()) {
|
||||
//toggle off multi-select mode if no items selected
|
||||
itemManager.toggleMultiSelectMode(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
if (getSelectedPage() == spellShopPage) {
|
||||
spellShopPage.activateItems(items);
|
||||
}
|
||||
else {
|
||||
inventoryPage.activateItems(items);
|
||||
}
|
||||
FThreads.invokeInEdtLater(() -> updateCreditsLabel());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -190,28 +177,17 @@ public class QuestSpellShopScreen extends TabPageScreen<QuestSpellShopScreen> {
|
||||
parentScreen.tabHeader.setVisible(!multiSelectMode);
|
||||
}
|
||||
});
|
||||
itemManager.setItemActivateHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
}
|
||||
itemManager.setItemActivateHandler(event -> {
|
||||
});
|
||||
itemManager.setContextMenuBuilder(new ContextMenuBuilder<InventoryItem>() {
|
||||
@Override
|
||||
public void buildMenu(final FDropDownMenu menu, final InventoryItem item) {
|
||||
menu.addItem(new FMenuItem(getVerb(), getVerbIcon(), new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
activateSelectedItem();
|
||||
}
|
||||
}));
|
||||
menu.addItem(new FMenuItem(getVerb(), getVerbIcon(), event -> activateSelectedItem()));
|
||||
}
|
||||
});
|
||||
itemManager.setSelectionChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
if (itemManager.getMultiSelectMode()) {
|
||||
parentScreen.updateBuySellButtonCaption();
|
||||
}
|
||||
itemManager.setSelectionChangedHandler(event -> {
|
||||
if (itemManager.getMultiSelectMode()) {
|
||||
parentScreen.updateBuySellButtonCaption();
|
||||
}
|
||||
});
|
||||
add(lblCredits);
|
||||
@@ -235,19 +211,11 @@ public class QuestSpellShopScreen extends TabPageScreen<QuestSpellShopScreen> {
|
||||
if (result == null || result <= 0) { return; }
|
||||
|
||||
//invoke in background thread so other dialogs can be shown properly
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ItemPool<InventoryItem> items = new ItemPool<>(InventoryItem.class);
|
||||
items.add(item, result);
|
||||
activateItems(items);
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
parentScreen.updateCreditsLabel();
|
||||
}
|
||||
});
|
||||
}
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
ItemPool<InventoryItem> items = new ItemPool<>(InventoryItem.class);
|
||||
items.add(item, result);
|
||||
activateItems(items);
|
||||
FThreads.invokeInEdtLater(() -> parentScreen.updateCreditsLabel());
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -290,22 +258,14 @@ public class QuestSpellShopScreen extends TabPageScreen<QuestSpellShopScreen> {
|
||||
|
||||
@Override
|
||||
protected void refresh() {
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show(Forge.getLocalizer().getInstance().getMessage("lblLoading"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Map<ColumnDef, ItemColumn> colOverrides = new HashMap<>();
|
||||
ItemColumn.addColOverride(ItemManagerConfig.SPELL_SHOP, colOverrides, ColumnDef.PRICE, QuestSpellShop.fnPriceCompare, QuestSpellShop.fnPriceGet);
|
||||
ItemColumn.addColOverride(ItemManagerConfig.SPELL_SHOP, colOverrides, ColumnDef.OWNED, FModel.getQuest().getCards().getFnOwnedCompare(), FModel.getQuest().getCards().getFnOwnedGet());
|
||||
itemManager.setup(ItemManagerConfig.SPELL_SHOP, colOverrides);
|
||||
FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getInstance().getMessage("lblLoading"), true, () -> {
|
||||
Map<ColumnDef, ItemColumn> colOverrides = new HashMap<>();
|
||||
ItemColumn.addColOverride(ItemManagerConfig.SPELL_SHOP, colOverrides, ColumnDef.PRICE, QuestSpellShop.fnPriceCompare, QuestSpellShop.fnPriceGet);
|
||||
ItemColumn.addColOverride(ItemManagerConfig.SPELL_SHOP, colOverrides, ColumnDef.OWNED, FModel.getQuest().getCards().getFnOwnedCompare(), FModel.getQuest().getCards().getFnOwnedGet());
|
||||
itemManager.setup(ItemManagerConfig.SPELL_SHOP, colOverrides);
|
||||
|
||||
itemManager.setPool(FModel.getQuest().getCards().getShopList());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
itemManager.setPool(FModel.getQuest().getCards().getShopList());
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -337,47 +297,25 @@ public class QuestSpellShopScreen extends TabPageScreen<QuestSpellShopScreen> {
|
||||
private static class InventoryPage extends SpellShopBasePage {
|
||||
protected FLabel lblSellExtras = add(new FLabel.Builder().text(Forge.getLocalizer().getMessage("lblSellAllExtras"))
|
||||
.icon(Forge.hdbuttons ? FSkinImage.HDMINUS : FSkinImage.MINUS).iconScaleFactor(1f).align(Align.right).font(FSkinFont.get(16))
|
||||
.command(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
//invoke in background thread so other dialogs can be shown properly
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
.command(event -> {
|
||||
//invoke in background thread so other dialogs can be shown properly
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
QuestSpellShop.sellExtras(parentScreen.spellShopPage.itemManager, itemManager);
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
parentScreen.updateCreditsLabel();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}).build());
|
||||
FThreads.invokeInEdtLater(() -> parentScreen.updateCreditsLabel());
|
||||
});
|
||||
}).build());
|
||||
|
||||
protected FLabel lblSelectAll = add(new FLabel.Builder().text(Forge.getLocalizer().getMessage("lblSelectAllCards"))
|
||||
.icon(Forge.hdbuttons ? FSkinImage.HDSTAR_FILLED : FSkinImage.STAR_FILLED).iconScaleFactor(1f).align(Align.right).font(FSkinFont.get(16))
|
||||
.command(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
//invoke in background thread so other dialogs can be shown properly
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!itemManager.getMultiSelectMode()) {
|
||||
itemManager.toggleMultiSelectMode(0);
|
||||
}
|
||||
itemManager.selectAll();
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
parentScreen.updateCreditsLabel();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
.command(event -> {
|
||||
//invoke in background thread so other dialogs can be shown properly
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
if (!itemManager.getMultiSelectMode()) {
|
||||
itemManager.toggleMultiSelectMode(0);
|
||||
}
|
||||
itemManager.selectAll();
|
||||
FThreads.invokeInEdtLater(() -> parentScreen.updateCreditsLabel());
|
||||
});
|
||||
}).build());
|
||||
|
||||
private InventoryPage() {
|
||||
|
||||
@@ -34,8 +34,6 @@ import forge.screens.LoadingOverlay;
|
||||
import forge.screens.limited.DraftingProcessScreen;
|
||||
import forge.toolbox.FButton;
|
||||
import forge.toolbox.FContainer;
|
||||
import forge.toolbox.FEvent;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FTextField;
|
||||
import forge.util.Utils;
|
||||
@@ -84,52 +82,21 @@ public class QuestTournamentsScreen extends QuestLaunchScreen implements IQuestT
|
||||
public QuestTournamentsScreen() {
|
||||
super();
|
||||
controller = new QuestTournamentController(this);
|
||||
btnSpendToken.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //must run in background thread to handle alerts
|
||||
@Override
|
||||
public void run() {
|
||||
controller.spendToken();
|
||||
}
|
||||
});
|
||||
}
|
||||
btnSpendToken.setCommand(event -> {
|
||||
//must run in background thread to handle alerts
|
||||
FThreads.invokeInBackgroundThread(() -> controller.spendToken());
|
||||
});
|
||||
btnEditDeck.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
editDeck(true);
|
||||
}
|
||||
});
|
||||
btnLeaveTournament.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //must run in background thread to handle alerts
|
||||
@Override
|
||||
public void run() {
|
||||
controller.endTournamentAndAwardPrizes();
|
||||
}
|
||||
});
|
||||
}
|
||||
btnEditDeck.setCommand(event -> editDeck(true));
|
||||
btnLeaveTournament.setCommand(event -> {
|
||||
//must run in background thread to handle alerts
|
||||
FThreads.invokeInBackgroundThread(() -> controller.endTournamentAndAwardPrizes());
|
||||
});
|
||||
|
||||
// TODO: is it possible to somehow reuse the original btnEditDeck/btnLeaveTournament
|
||||
btnEditDeckInTourn.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
editDeck(true);
|
||||
}
|
||||
});
|
||||
btnLeaveTournamentInTourn.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //must run in background thread to handle alerts
|
||||
@Override
|
||||
public void run() {
|
||||
controller.endTournamentAndAwardPrizes();
|
||||
}
|
||||
});
|
||||
}
|
||||
btnEditDeckInTourn.setCommand(event -> editDeck(true));
|
||||
btnLeaveTournamentInTourn.setCommand(event -> {
|
||||
//must run in background thread to handle alerts
|
||||
FThreads.invokeInBackgroundThread(() -> controller.endTournamentAndAwardPrizes());
|
||||
});
|
||||
|
||||
pnlPrepareDeck.add(btnEditDeck);
|
||||
@@ -173,7 +140,8 @@ public class QuestTournamentsScreen extends QuestLaunchScreen implements IQuestT
|
||||
@Override
|
||||
protected void updateHeaderCaption() {
|
||||
if (mode == Mode.PREPARE_DECK) {
|
||||
setHeaderCaption(FModel.getQuest().getName() + " - " + getGameType() + "\n" + Forge.getLocalizer().getMessage("lblDraft") + " - " + FModel.getQuest().getAchievements().getCurrentDraft().getTitle());
|
||||
String title = FModel.getQuest().getAchievements().getCurrentDraft() == null ? "" : FModel.getQuest().getAchievements().getCurrentDraft().getTitle();
|
||||
setHeaderCaption(FModel.getQuest().getName() + " - " + getGameType() + "\n" + Forge.getLocalizer().getMessage("lblDraft") + " - " + title);
|
||||
}
|
||||
else {
|
||||
super.updateHeaderCaption();
|
||||
@@ -230,17 +198,7 @@ public class QuestTournamentsScreen extends QuestLaunchScreen implements IQuestT
|
||||
|
||||
@Override
|
||||
public void startDraft(BoosterDraft draft) {
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoadingOverlay.show("Loading Quest Tournament", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Forge.openScreen(new DraftingProcessScreen(draft, EditorType.QuestDraft, controller));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
FThreads.invokeInEdtLater(() -> LoadingOverlay.show("Loading Quest Tournament", true, () -> Forge.openScreen(new DraftingProcessScreen(draft, EditorType.QuestDraft, controller))));
|
||||
}
|
||||
|
||||
private Deck getDeck() {
|
||||
@@ -275,22 +233,20 @@ public class QuestTournamentsScreen extends QuestLaunchScreen implements IQuestT
|
||||
return;
|
||||
}
|
||||
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //must run in background thread to handle alerts
|
||||
@Override
|
||||
public void run() {
|
||||
switch (mode) {
|
||||
case SELECT_TOURNAMENT:
|
||||
controller.startDraft();
|
||||
break;
|
||||
case PREPARE_DECK:
|
||||
controller.startTournament();
|
||||
break;
|
||||
case TOURNAMENT_ACTIVE:
|
||||
controller.startNextMatch();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//must run in background thread to handle alerts
|
||||
FThreads.invokeInBackgroundThread(() -> {
|
||||
switch (mode) {
|
||||
case SELECT_TOURNAMENT:
|
||||
controller.startDraft();
|
||||
break;
|
||||
case PREPARE_DECK:
|
||||
controller.startTournament();
|
||||
break;
|
||||
case TOURNAMENT_ACTIVE:
|
||||
controller.startNextMatch();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,7 +5,11 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import forge.StaticData;
|
||||
import forge.gui.FThreads;
|
||||
import forge.gui.GuiBase;
|
||||
import forge.screens.LoadingOverlay;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
@@ -34,6 +38,7 @@ import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.GuiChoose;
|
||||
import forge.util.Callback;
|
||||
import forge.util.FileUtil;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
public class FilesPage extends TabPage<SettingsScreen> {
|
||||
private final FGroupList<FilesItem> lstItems = add(new FGroupList<>());
|
||||
@@ -43,10 +48,45 @@ public class FilesPage extends TabPage<SettingsScreen> {
|
||||
|
||||
lstItems.setListItemRenderer(new FilesItemRenderer());
|
||||
|
||||
lstItems.addGroup(Forge.getLocalizer().getMessage("lblCardAudit"));
|
||||
lstItems.addGroup(Forge.getLocalizer().getMessage("ContentDownloaders"));
|
||||
lstItems.addGroup(Forge.getLocalizer().getMessage("lblStorageLocations"));
|
||||
//lstItems.addGroup("Data Import");
|
||||
|
||||
//Auditer
|
||||
lstItems.addItem(new Extra(Forge.getLocalizer().getMessage("btnListImageData"), Forge.getLocalizer().getMessage("lblListImageData")) {
|
||||
@Override
|
||||
public void select() {
|
||||
FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblProcessingCards"), true, () -> {
|
||||
StringBuffer nifSB = new StringBuffer(); // NO IMAGE FOUND BUFFER
|
||||
StringBuffer cniSB = new StringBuffer(); // CARD NOT IMPLEMENTED BUFFER
|
||||
|
||||
nifSB.append("\n\n-------------------\n");
|
||||
nifSB.append("NO IMAGE FOUND LIST\n");
|
||||
nifSB.append("-------------------\n\n");
|
||||
|
||||
cniSB.append("\n\n-------------------\n");
|
||||
cniSB.append("UNIMPLEMENTED CARD LIST\n");
|
||||
cniSB.append("-------------------\n\n");
|
||||
|
||||
Pair<Integer, Integer> totalAudit = StaticData.instance().audit(nifSB, cniSB);
|
||||
String msg = nifSB.toString();
|
||||
String title = "Missing images: " + totalAudit.getLeft() + "\nUnimplemented cards: " + totalAudit.getRight();
|
||||
FOptionPane.showOptionDialog(msg, title, FOptionPane.INFORMATION_ICON, ImmutableList.of(Forge.getLocalizer().getMessage("lblCopy"), Forge.getLocalizer().getMessage("lblClose")), -1, new Callback<Integer>() {
|
||||
@Override
|
||||
public void run(Integer result) {
|
||||
switch (result) {
|
||||
case 0:
|
||||
Forge.getClipboard().setContents(msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
}, 0);
|
||||
//content downloaders
|
||||
lstItems.addItem(new ContentDownloader(Forge.getLocalizer().getMessage("btnDownloadPics"),
|
||||
Forge.getLocalizer().getMessage("lblDownloadPics")) {
|
||||
@@ -54,35 +94,35 @@ public class FilesPage extends TabPage<SettingsScreen> {
|
||||
protected GuiDownloadService createService() {
|
||||
return new GuiDownloadPicturesLQ();
|
||||
}
|
||||
}, 0);
|
||||
}, 1);
|
||||
lstItems.addItem(new ContentDownloader(Forge.getLocalizer().getMessage("btnDownloadSetPics"),
|
||||
Forge.getLocalizer().getMessage("lblDownloadSetPics")) {
|
||||
@Override
|
||||
protected GuiDownloadService createService() {
|
||||
return new GuiDownloadSetPicturesLQ();
|
||||
}
|
||||
}, 0);
|
||||
}, 1);
|
||||
lstItems.addItem(new ContentDownloader(Forge.getLocalizer().getMessage("btnDownloadQuestImages"),
|
||||
Forge.getLocalizer().getMessage("lblDownloadQuestImages")) {
|
||||
@Override
|
||||
protected GuiDownloadService createService() {
|
||||
return new GuiDownloadQuestImages();
|
||||
}
|
||||
}, 0);
|
||||
}, 1);
|
||||
lstItems.addItem(new ContentDownloader(Forge.getLocalizer().getMessage("btnDownloadAchievementImages"),
|
||||
Forge.getLocalizer().getMessage("lblDownloadAchievementImages")) {
|
||||
@Override
|
||||
protected GuiDownloadService createService() {
|
||||
return new GuiDownloadAchievementImages();
|
||||
}
|
||||
}, 0);
|
||||
}, 1);
|
||||
lstItems.addItem(new ContentDownloader(Forge.getLocalizer().getMessage("btnDownloadPrices"),
|
||||
Forge.getLocalizer().getMessage("lblDownloadPrices")) {
|
||||
@Override
|
||||
protected GuiDownloadService createService() {
|
||||
return new GuiDownloadPrices();
|
||||
}
|
||||
}, 0);
|
||||
}, 1);
|
||||
lstItems.addItem(new ContentDownloader(Forge.getLocalizer().getMessage("btnDownloadSkins"),
|
||||
Forge.getLocalizer().getMessage("lblDownloadSkins")) {
|
||||
@Override
|
||||
@@ -93,7 +133,7 @@ public class FilesPage extends TabPage<SettingsScreen> {
|
||||
protected void finishCallback() {
|
||||
SettingsScreen.getSettingsScreen().getSettingsPage().refreshSkinsList();
|
||||
}
|
||||
}, 0);
|
||||
}, 1);
|
||||
lstItems.addItem(new OptionContentDownloader(Forge.getLocalizer().getMessage("btnDownloadCJKFonts"),
|
||||
Forge.getLocalizer().getMessage("lblDownloadCJKFonts"),
|
||||
Forge.getLocalizer().getMessage("lblDownloadCJKFontPrompt")) {
|
||||
@@ -118,7 +158,7 @@ public class FilesPage extends TabPage<SettingsScreen> {
|
||||
protected void finishCallback() {
|
||||
SettingsScreen.getSettingsScreen().getSettingsPage().refreshCJKFontsList();
|
||||
}
|
||||
}, 0);
|
||||
}, 1);
|
||||
//storage locations
|
||||
final StorageOption cardPicsOption = new StorageOption(Forge.getLocalizer().getMessage("lblCardPicsLocation"), ForgeProfileProperties.getCardPicsDir()) {
|
||||
@Override
|
||||
@@ -141,7 +181,7 @@ public class FilesPage extends TabPage<SettingsScreen> {
|
||||
//ensure decks option is updated if needed
|
||||
decksOption.updateDir(ForgeProfileProperties.getDecksDir());
|
||||
}
|
||||
}, 1);
|
||||
}, 2);
|
||||
lstItems.addItem(new StorageOption(Forge.getLocalizer().getMessage("lblImageCacheLocation"), ForgeProfileProperties.getCacheDir()) {
|
||||
@Override
|
||||
protected void onDirectoryChanged(String newDir) {
|
||||
@@ -150,9 +190,9 @@ public class FilesPage extends TabPage<SettingsScreen> {
|
||||
//ensure card pics option is updated if needed
|
||||
cardPicsOption.updateDir(ForgeProfileProperties.getCardPicsDir());
|
||||
}
|
||||
}, 1);
|
||||
lstItems.addItem(cardPicsOption, 1);
|
||||
lstItems.addItem(decksOption, 1);
|
||||
}, 2);
|
||||
lstItems.addItem(cardPicsOption, 2);
|
||||
lstItems.addItem(decksOption, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +241,19 @@ public class FilesPage extends TabPage<SettingsScreen> {
|
||||
g.drawText(value.description, SettingsScreen.DESC_FONT, SettingsScreen.DESC_COLOR, x, y + h, w, totalHeight - h + SettingsScreen.getInsets(w), true, Align.left, false);
|
||||
}
|
||||
}
|
||||
private abstract class Extra extends FilesItem {
|
||||
Extra(String label0, String description0) {
|
||||
super(label0, description0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void select() {
|
||||
|
||||
}
|
||||
|
||||
protected void finishCallback() {
|
||||
}
|
||||
}
|
||||
private abstract class ContentDownloader extends FilesItem {
|
||||
ContentDownloader(String label0, String description0) {
|
||||
super(label0, description0);
|
||||
@@ -239,7 +291,7 @@ public class FilesPage extends TabPage<SettingsScreen> {
|
||||
@Override
|
||||
public void run(String result) {
|
||||
final String url = categories.get(result);
|
||||
final String name = url.substring(url.lastIndexOf("/") + 1);
|
||||
final String name = url.substring(url.lastIndexOf("/") + 2);
|
||||
new GuiDownloader(new GuiDownloadZipService(name, name, url, ForgeConstants.FONTS_DIR, null, null), new Callback<Boolean>() {
|
||||
@Override
|
||||
public void run(Boolean finished) {
|
||||
|
||||
@@ -61,5 +61,6 @@ twosat
|
||||
Xyx
|
||||
Zimtente
|
||||
Zuchinni
|
||||
XavierMD
|
||||
|
||||
(If you think your name should be on this list, add it with your next contribution)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Name:Aerial Predation
|
||||
ManaCost:2 G
|
||||
Types:Instant
|
||||
A:SP$ Destroy | Cost$ 2 G | ValidTgts$ Creature.withFlying | TgtPrompt$ Select target creature with flying | SubAbility$ NaturalLife | SpellDescription$ Destroy target creature with flying. You gain 2 life
|
||||
SVar:NaturalLife:DB$ GainLife | Defined$ You | LifeAmount$ 2
|
||||
A:SP$ Destroy | ValidTgts$ Creature.withFlying | TgtPrompt$ Select target creature with flying | SubAbility$ DBGainLife | SpellDescription$ Destroy target creature with flying. You gain 2 life.
|
||||
SVar:DBGainLife:DB$ GainLife | LifeAmount$ 2
|
||||
DeckHas:Ability$LifeGain
|
||||
Oracle:Destroy target creature with flying. You gain 2 life.
|
||||
|
||||
@@ -5,7 +5,7 @@ K:Casualty:2
|
||||
A:SP$ ChangeZone | ValidTgts$ Permanent.nonEnchantment | TgtPrompt$ Select target nonenchantment permanent | Origin$ Battlefield | Destination$ Library | Shuffle$ True | SubAbility$ DBExile | SpellDescription$ The owner of target nonenchantment permanent shuffles it into their library,
|
||||
SVar:DBExile:DB$ Dig | DigNum$ 1 | ChangeNum$ All | DestinationZone$ Exile | Defined$ TargetedOwner | RememberChanged$ True | SubAbility$ DBPutLand | SpellDescription$ then exiles the top card of their library.
|
||||
SVar:DBPutLand:DB$ ChangeZone | ConditionDefined$ Remembered | ConditionPresent$ Land | Defined$ Remembered | DefinedDesc$ it | Origin$ Exile | Destination$ Battlefield | ForgetChanged$ True | SubAbility$ DBCast | SpellDescription$ If it's a land card, they put it onto the battlefield.
|
||||
SVar:DBCast:DB$ Play | Defined$ Remembered | DefinedDesc$ it | ValidSA$ Spell | WithoutManaCost$ True | Optional$ True | SubAbility$ DBCleanup | SpellDescription$ Otherwise, they may cast it without paying its mana cost.
|
||||
SVar:DBCast:DB$ Play | Defined$ Remembered | DefinedDesc$ it | ValidSA$ Spell | Controller$ RememberedOwner | WithoutManaCost$ True | Optional$ True | SubAbility$ DBCleanup | SpellDescription$ Otherwise, they may cast it without paying its mana cost.
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
DeckHas:Ability$Sacrifice
|
||||
Oracle:Casualty 2 (As you cast this spell, you may sacrifice a creature with power 2 or greater. When you do, copy this spell and you may choose a new target for the copy.)\nThe owner of target nonenchantment permanent shuffles it into their library, then exiles the top card of their library. If it's a land card, they put it onto the battlefield. Otherwise, they may cast it without paying its mana cost.
|
||||
|
||||
@@ -3,7 +3,7 @@ ManaCost:2 G
|
||||
Types:Snow Creature Elf Warrior
|
||||
PT:3/2
|
||||
T:Mode$ SpellCast | ValidCard$ Creature | ValidActivatingPlayer$ You | Execute$ TrigEffect | TriggerZones$ Battlefield | SnowSpentForCardsColor$ True | TriggerDescription$ Whenever you cast a creature spell, if {S} of any of that spell's colors was spent to cast it, that creature enters the battlefield with an additional +1/+1 counter on it. ({S} is mana from a snow source.)
|
||||
SVar:TrigEffect:DB$ Effect | RememberObjects$ TriggeredCard | ReplacementEffects$ ETBCreat
|
||||
SVar:TrigEffect:DB$ Effect | RememberObjects$ TriggeredCard | ReplacementEffects$ ETBCreat | ExileOnMoved$ Stack
|
||||
SVar:ETBCreat:Event$ Moved | ValidCard$ Card.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | ReplacementResult$ Updated | Description$ That creature enters the battlefield with an additional +1/+1 counter on it.
|
||||
SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ 1 | SubAbility$ DBExile
|
||||
SVar:DBExile:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user