diff --git a/forge-ai/src/main/java/forge/ai/ability/ControlExchangeAi.java b/forge-ai/src/main/java/forge/ai/ability/ControlExchangeAi.java index 78bdef0ceee..e8fff9b3ba5 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ControlExchangeAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ControlExchangeAi.java @@ -30,7 +30,7 @@ public class ControlExchangeAi extends SpellAbilityAi { sa.resetTargets(); CardCollection list = - CardLists.getValidCards(AiAttackController.choosePreferredDefenderPlayer(ai).getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, sa.getHostCard(), sa); + CardLists.getValidCards(ai.getOpponents().getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, sa.getHostCard(), sa); // AI won't try to grab cards that are filtered out of AI decks on purpose list = CardLists.filter(list, new Predicate() { @Override @@ -65,7 +65,7 @@ public class ControlExchangeAi extends SpellAbilityAi { } } else { if (mandatory) { - return chkAIDrawback(sa, aiPlayer); + return chkAIDrawback(sa, aiPlayer) || sa.isTargetNumberValid(); } else { return canPlayAI(aiPlayer, sa); } @@ -97,8 +97,12 @@ public class ControlExchangeAi extends SpellAbilityAi { Card best = ComputerUtilCard.getBestAI(list); + // add best Target: + // do it here already even if we don't want to play this as it might be for targeting a trigger + sa.getTargets().add(best); + // if Param has Defined, check if the best Target is better than the Defined - if (sa.hasParam("Defined")) { + if (sa.hasParam("Defined") && (!sa.isTrigger() || sa.getRootAbility().isOptionalTrigger())) { final Card object = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa).get(0); // TODO add evaluate Land if able final Card realBest = ComputerUtilCard.getBestAI(Lists.newArrayList(best, object)); @@ -109,9 +113,6 @@ public class ControlExchangeAi extends SpellAbilityAi { } } - // add best Target - sa.getTargets().add(best); - // second target needed (the AI's own worst) if ("TrigTwoTargets".equals(sa.getParam("AILogic"))) { return doTrigTwoTargetsLogic(aiPlayer, sa, best); diff --git a/forge-ai/src/main/java/forge/ai/ability/CountersPutAllAi.java b/forge-ai/src/main/java/forge/ai/ability/CountersPutAllAi.java index bec9bf76058..29e9565c142 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CountersPutAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CountersPutAllAi.java @@ -37,7 +37,7 @@ public class CountersPutAllAi extends SpellAbilityAi { final boolean curse = sa.isCurse(); final TargetRestrictions tgt = sa.getTargetRestrictions(); - if ("OwnCreatsAndOtherPWs".equals(sa.getParam("AILogic"))) { + if ("OwnCreatsAndOtherPWs".equals(logic)) { hList = CardLists.getValidCards(ai.getWeakestOpponent().getCardsIn(ZoneType.Battlefield), "Creature.YouCtrl,Planeswalker.YouCtrl+Other", source.getController(), source, sa); cList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), "Creature.YouCtrl,Planeswalker.YouCtrl+Other", source.getController(), source, sa); } else { diff --git a/forge-ai/src/main/java/forge/ai/ability/DamageAllAi.java b/forge-ai/src/main/java/forge/ai/ability/DamageAllAi.java index a465df0c34a..d21327c08c6 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DamageAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DamageAllAi.java @@ -94,7 +94,7 @@ public class DamageAllAi extends SpellAbilityAi { private Player determineOppToKill(Player ai, SpellAbility sa, Card source, int x) { // Attempt to determine which opponent can be finished off such that the most players // are killed at the same time, given X damage tops - final String validP = sa.hasParam("ValidPlayers") ? sa.getParam("ValidPlayers") : ""; + final String validP = sa.getParamOrDefault("ValidPlayers", ""); int aiLife = ai.getLife(); Player bestOpp = null; // default opponent, if all else fails @@ -125,7 +125,7 @@ public class DamageAllAi extends SpellAbilityAi { computerList.clear(); } - final String validP = sa.hasParam("ValidPlayers") ? sa.getParam("ValidPlayers") : ""; + final String validP = sa.getParamOrDefault("ValidPlayers", ""); // TODO: if damage is dependant on mana paid, maybe have X be human's max life // Don't kill yourself if (validP.equals("Player") && (ai.getLife() <= ComputerUtilCombat.predictDamageTo(ai, dmg, source, false))) { @@ -191,7 +191,7 @@ public class DamageAllAi extends SpellAbilityAi { @Override public boolean chkAIDrawback(SpellAbility sa, Player ai) { final Card source = sa.getHostCard(); - String validP = ""; + final String validP = sa.getParamOrDefault("ValidPlayers", ""); final String damage = sa.getParam("NumDmg"); int dmg; @@ -203,10 +203,6 @@ public class DamageAllAi extends SpellAbilityAi { dmg = AbilityUtils.calculateAmount(source, damage, sa); } - if (sa.hasParam("ValidPlayers")) { - validP = sa.getParam("ValidPlayers"); - } - // Evaluate creatures getting killed Player enemy = ai.getWeakestOpponent(); final CardCollection humanList = getKillableCreatures(sa, enemy, dmg); @@ -251,7 +247,7 @@ public class DamageAllAi extends SpellAbilityAi { */ private CardCollection getKillableCreatures(final SpellAbility sa, final Player player, final int dmg) { final Card source = sa.getHostCard(); - String validC = sa.hasParam("ValidCards") ? sa.getParam("ValidCards") : ""; + String validC = sa.getParamOrDefault("ValidCards", ""); // TODO: X may be something different than X paid CardCollection list = @@ -273,7 +269,7 @@ public class DamageAllAi extends SpellAbilityAi { @Override protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { final Card source = sa.getHostCard(); - String validP = ""; + final String validP = sa.getParamOrDefault("ValidPlayers", ""); final String damage = sa.getParam("NumDmg"); int dmg; @@ -286,10 +282,6 @@ public class DamageAllAi extends SpellAbilityAi { dmg = AbilityUtils.calculateAmount(source, damage, sa); } - if (sa.hasParam("ValidPlayers")) { - validP = sa.getParam("ValidPlayers"); - } - // Evaluate creatures getting killed Player enemy = ai.getWeakestOpponent(); final CardCollection humanList = getKillableCreatures(sa, enemy, dmg); diff --git a/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java b/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java index 79f88577204..990db0b9757 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java @@ -81,10 +81,7 @@ public class DestroyAllAi extends SpellAbilityAi { return true; // e.g. Tetzimoc, Primal Death, where we want to cast the permanent even if the removal trigger does nothing } - String valid = ""; - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + String valid = sa.getParamOrDefault("ValidCards", ""); if (valid.contains("X") && sa.getSVar("X").equals("Count$xPaid")) { // Set PayX here to maximum value. diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java b/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java index 82620607240..e882a63bbe3 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java @@ -33,7 +33,6 @@ public class PumpAllAi extends PumpAiBase { */ @Override protected boolean canPlayAI(final Player ai, final SpellAbility sa) { - String valid = ""; final Card source = sa.getHostCard(); final Game game = ai.getGame(); final Combat combat = game.getCombat(); @@ -78,9 +77,7 @@ public class PumpAllAi extends PumpAiBase { final List keywords = sa.hasParam("KW") ? Arrays.asList(sa.getParam("KW").split(" & ")) : new ArrayList<>(); final PhaseType phase = game.getPhaseHandler().getPhase(); - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); CardCollection comp = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source, sa); CardCollection human = CardLists.getValidCards(opp.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source, sa); diff --git a/forge-ai/src/main/java/forge/ai/ability/RegenerateAllAi.java b/forge-ai/src/main/java/forge/ai/ability/RegenerateAllAi.java index 0f8e35a4854..f4add7b107e 100644 --- a/forge-ai/src/main/java/forge/ai/ability/RegenerateAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/RegenerateAllAi.java @@ -26,11 +26,7 @@ public class RegenerateAllAi extends SpellAbilityAi { final Game game = ai.getGame(); // filter AIs battlefield by what I can target - String valid = ""; - - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); CardCollectionView list = game.getCardsIn(ZoneType.Battlefield); list = CardLists.getValidCards(list, valid.split(","), hostCard.getController(), hostCard, sa); diff --git a/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java b/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java index 9f7264b55d2..dd89e45ab75 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java @@ -34,10 +34,7 @@ public class TapAllAi extends SpellAbilityAi { return false; } - String valid = ""; - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); CardCollectionView validTappables = game.getCardsIn(ZoneType.Battlefield); @@ -99,10 +96,7 @@ public class TapAllAi extends SpellAbilityAi { protected boolean doTriggerAINoCost(final Player ai, SpellAbility sa, boolean mandatory) { final Card source = sa.getHostCard(); - String valid = ""; - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); CardCollectionView validTappables = getTapAllTargets(valid, source, sa); diff --git a/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java b/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java index b0416572962..9fafd25f28d 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java @@ -24,10 +24,7 @@ public class TwoPilesAi extends SpellAbilityAi { zone = ZoneType.smartValueOf(sa.getParam("Zone")); } - String valid = ""; - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); final Player opp = AiAttackController.choosePreferredDefenderPlayer(ai); diff --git a/forge-ai/src/main/java/forge/ai/ability/UntapAllAi.java b/forge-ai/src/main/java/forge/ai/ability/UntapAllAi.java index 7c53560db5c..97d70b3fafa 100644 --- a/forge-ai/src/main/java/forge/ai/ability/UntapAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/UntapAllAi.java @@ -24,11 +24,8 @@ public class UntapAllAi extends SpellAbilityAi { && source.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_END)) { return false; } - String valid = ""; CardCollectionView list = CardLists.filter(aiPlayer.getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.TAPPED); - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); list = CardLists.getValidCards(list, valid.split(","), source.getController(), source, sa); // don't untap if only opponent benefits PlayerCollection goodControllers = aiPlayer.getAllies(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java index 7c37e2a7fb9..44d0e0f8145 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java @@ -121,11 +121,7 @@ public class AnimateAllEffect extends AnimateEffectBase { sVars.addAll(Arrays.asList(sa.getParam("sVars").split(","))); } - String valid = ""; - - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); CardCollectionView list; diff --git a/forge-game/src/main/java/forge/game/ability/effects/CountersPutAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CountersPutAllEffect.java index d80af630170..4cc5e1cda08 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CountersPutAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CountersPutAllEffect.java @@ -20,7 +20,7 @@ public class CountersPutAllEffect extends SpellAbilityEffect { final CounterType cType = CounterType.getType(sa.getParam("CounterType")); final int amount = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("CounterNum"), sa); - final String zone = sa.hasParam("ValidZone") ? sa.getParam("ValidZone") : "Battlefield"; + final String zone = sa.getParamOrDefault("ValidZone", "Battlefield"); sb.append("Put ").append(amount).append(" ").append(cType.getName()).append(" counter"); if (amount != 1) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java index e5145588050..fb80153cbd8 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java @@ -22,7 +22,7 @@ public class CountersRemoveAllEffect extends SpellAbilityEffect { final CounterType cType = CounterType.getType(sa.getParam("CounterType")); final int amount = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("CounterNum"), sa); - final String zone = sa.hasParam("ValidZone") ? sa.getParam("ValidZone") : "Battlefield"; + final String zone = sa.getParamOrDefault("ValidZone", "Battlefield"); String amountString = Integer.toString(amount); if (sa.hasParam("AllCounters")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/DamageAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DamageAllEffect.java index b1ff536f4a9..6786183cd3c 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DamageAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DamageAllEffect.java @@ -22,10 +22,7 @@ public class DamageAllEffect extends DamageBaseEffect { protected String getStackDescription(SpellAbility sa) { final StringBuilder sb = new StringBuilder(); - String desc = ""; - if (sa.hasParam("ValidDescription")) { - desc = sa.getParam("ValidDescription"); - } + final String desc = sa.getParamOrDefault("ValidDescription", ""); final String damage = sa.getParam("NumDmg"); final int dmg = AbilityUtils.calculateAmount(sa.getHostCard(), damage, sa); @@ -63,11 +60,7 @@ public class DamageAllEffect extends DamageBaseEffect { //Remember params from this effect have been moved to dealDamage in GameAction Player targetPlayer = sa.getTargets().getFirstTargetedPlayer(); - String players = ""; - - if (sa.hasParam("ValidPlayers")) { - players = sa.getParam("ValidPlayers"); - } + final String players = sa.getParamOrDefault("ValidPlayers", ""); CardCollectionView list; if (sa.hasParam("ValidCards")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/DamagePreventAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DamagePreventAllEffect.java index 91e904ac804..4142ca1f3d3 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DamagePreventAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DamagePreventAllEffect.java @@ -15,11 +15,7 @@ public class DamagePreventAllEffect extends DamagePreventEffectBase { final Game game = sa.getActivatingPlayer().getGame(); final int numDam = AbilityUtils.calculateAmount(source, sa.getParam("Amount"), sa); - String players = ""; - - if (sa.hasParam("ValidPlayers")) { - players = sa.getParam("ValidPlayers"); - } + final String players = sa.getParamOrDefault("ValidPlayers", ""); if (sa.hasParam("ValidCards")) { CardCollectionView list = game.getCardsIn(ZoneType.Battlefield); diff --git a/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java index 4f0acaa45be..8f82c5e08bb 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java @@ -24,7 +24,6 @@ public class DestroyAllEffect extends SpellAbilityEffect { @Override protected String getStackDescription(SpellAbility sa) { - if (sa.hasParam("SpellDescription")) { return sa.getParam("SpellDescription"); } @@ -51,11 +50,7 @@ public class DestroyAllEffect extends SpellAbilityEffect { Player targetPlayer = sa.getTargets().getFirstTargetedPlayer(); - String valid = ""; - - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + String valid = sa.getParamOrDefault("ValidCards", ""); // Ugh. If calculateAmount needs to be called with DestroyAll it _needs_ // to use the X variable diff --git a/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java index 27d26eca314..4b1d514d412 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java @@ -72,7 +72,7 @@ public class DigEffect extends SpellAbilityEffect { int libraryPosition = sa.hasParam("LibraryPosition") ? Integer.parseInt(sa.getParam("LibraryPosition")) : -1; int destZone1ChangeNum = 1; final boolean mitosis = sa.hasParam("Mitosis"); - String changeValid = sa.hasParam("ChangeValid") ? sa.getParam("ChangeValid") : ""; + String changeValid = sa.getParamOrDefault("ChangeValid", ""); final boolean anyNumber = sa.hasParam("AnyNumber"); final int libraryPosition2 = sa.hasParam("LibraryPosition2") ? Integer.parseInt(sa.getParam("LibraryPosition2")) : -1; @@ -86,7 +86,7 @@ public class DigEffect extends SpellAbilityEffect { // These parameters are used to indicate that a dialog box must be show to the player asking if the player wants to proceed // with an optional ability, otherwise the optional ability is skipped. final boolean mayBeSkipped = sa.hasParam("PromptToSkipOptionalAbility"); - final String optionalAbilityPrompt = sa.hasParam("OptionalAbilityPrompt") ? sa.getParam("OptionalAbilityPrompt") : ""; + final String optionalAbilityPrompt = sa.getParamOrDefault("OptionalAbilityPrompt", ""); boolean remZone1 = false; boolean remZone2 = false; diff --git a/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java index cdf886b6541..9cdfaca6eb8 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java @@ -35,7 +35,7 @@ public class DigMultipleEffect extends SpellAbilityEffect { int libraryPosition = sa.hasParam("LibraryPosition") ? Integer.parseInt(sa.getParam("LibraryPosition")) : -1; final int libraryPosition2 = sa.hasParam("LibraryPosition2") ? Integer.parseInt(sa.getParam("LibraryPosition2")) : -1; - String changeValid = sa.hasParam("ChangeValid") ? sa.getParam("ChangeValid") : ""; + String changeValid = sa.getParamOrDefault("ChangeValid", ""); boolean chooseOptional = sa.hasParam("Optional"); CardZoneTable table = new CardZoneTable(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java b/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java index 58194ece00b..19b06893824 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java @@ -60,7 +60,7 @@ public class FlipCoinEffect extends SpellAbilityEffect { } final boolean noCall = sa.hasParam("NoCall"); - String varName = sa.hasParam("SaveNumFlipsToSVar") ? sa.getParam("SaveNumFlipsToSVar") : "X"; + String varName = sa.getParamOrDefault("SaveNumFlipsToSVar", "X"); boolean victory = false; int amount = 1; if (sa.hasParam("Amount")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/ManifestEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ManifestEffect.java index adb4ef97dc2..5c84eb8d5d7 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ManifestEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ManifestEffect.java @@ -27,7 +27,7 @@ public class ManifestEffect extends SpellAbilityEffect { final int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(source, sa.getParam("Amount"), sa) : 1; // Most commonly "defined" is Top of Library - final String defined = sa.hasParam("Defined") ? sa.getParam("Defined") : "TopOfLibrary"; + final String defined = sa.getParamOrDefault("Defined", "TopOfLibrary"); CardCollectionView lastStateBattlefield = game.copyLastStateBattlefield(); CardCollectionView lastStateGraveyard = game.copyLastStateGraveyard(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/MultiplePilesEffect.java b/forge-game/src/main/java/forge/game/ability/effects/MultiplePilesEffect.java index c9c10e36a73..30821255082 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/MultiplePilesEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/MultiplePilesEffect.java @@ -31,12 +31,8 @@ public class MultiplePilesEffect extends SpellAbilityEffect { final StringBuilder sb = new StringBuilder(); final List tgtPlayers = getTargetPlayers(sa); - - String valid = ""; String piles = sa.getParam("Piles"); - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); sb.append("Separate all ").append(valid).append(" cards "); @@ -58,10 +54,7 @@ public class MultiplePilesEffect extends SpellAbilityEffect { final int piles = Integer.parseInt(sa.getParam("Piles")); final Map> record = Maps.newHashMap(); - String valid = ""; - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); final TargetRestrictions tgt = sa.getTargetRestrictions(); final List tgtPlayers = getTargetPlayers(sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/PeekAndRevealEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PeekAndRevealEffect.java index 8e249fc3a66..ff9f2bd49c9 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PeekAndRevealEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PeekAndRevealEffect.java @@ -37,8 +37,8 @@ public class PeekAndRevealEffect extends SpellAbilityEffect { Card source = sa.getHostCard(); final boolean rememberRevealed = sa.hasParam("RememberRevealed"); final boolean imprintRevealed = sa.hasParam("ImprintRevealed"); - String revealValid = sa.hasParam("RevealValid") ? sa.getParam("RevealValid") : "Card"; - String peekAmount = sa.hasParam("PeekAmount") ? sa.getParam("PeekAmount") : "1"; + String revealValid = sa.getParamOrDefault("RevealValid", "Card"); + String peekAmount = sa.getParamOrDefault("PeekAmount", "1"); int numPeek = AbilityUtils.calculateAmount(sa.getHostCard(), peekAmount, sa); // Right now, this is only used on your own library. diff --git a/forge-game/src/main/java/forge/game/ability/effects/ProtectAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ProtectAllEffect.java index 75e48fe6c60..f7e111cb6ef 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ProtectAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ProtectAllEffect.java @@ -82,10 +82,7 @@ public class ProtectAllEffect extends SpellAbilityEffect { } // Deal with permanents - String valid = ""; - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); if (!valid.equals("")) { CardCollectionView list = game.getCardsIn(ZoneType.Battlefield); list = CardLists.getValidCards(list, valid, sa.getActivatingPlayer(), host, sa); @@ -113,10 +110,7 @@ public class ProtectAllEffect extends SpellAbilityEffect { } // Deal with Players - String players = ""; - if (sa.hasParam("ValidPlayers")) { - players = sa.getParam("ValidPlayers"); - } + final String players = sa.getParamOrDefault("ValidPlayers", ""); if (!players.equals("")) { final List playerList = AbilityUtils.getDefinedPlayers(host, players, sa); for (final Player player : playerList) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java index e6c9a5f40af..44d33726de5 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java @@ -137,10 +137,7 @@ public class PumpAllEffect extends SpellAbilityEffect { list = tgtPlayers.getCardsIn(affectedZones); } - String valid = ""; - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); list = AbilityUtils.filterListByType(list, valid, sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/RegenerateAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RegenerateAllEffect.java index 055c3ea4cac..f936eb2e662 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RegenerateAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RegenerateAllEffect.java @@ -26,11 +26,7 @@ public class RegenerateAllEffect extends RegenerateBaseEffect { public void resolve(SpellAbility sa) { final Card hostCard = sa.getHostCard(); final Game game = hostCard.getGame(); - String valid = ""; - - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); CardCollectionView list = game.getCardsIn(ZoneType.Battlefield); list = CardLists.getValidCards(list, valid.split(","), hostCard.getController(), hostCard, sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java index 421cc34859e..43cb3018645 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java @@ -76,11 +76,7 @@ public class RepeatEffect extends SpellAbilityEffect { if (sa.hasParam("RepeatPresent")) { final String repeatPresent = sa.getParam("RepeatPresent"); - - String repeatCompare = "GE1"; - if (sa.hasParam("RepeatCompare")) { - repeatCompare = sa.getParam("RepeatCompare"); - } + String repeatCompare = sa.getParamOrDefault("RepeatCompare", "GE1"); CardCollectionView list; if (sa.hasParam("RepeatDefined")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java index dbc2fdf43df..da413a82838 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java @@ -243,7 +243,6 @@ public class SacrificeEffect extends SpellAbilityEffect { removeCandidates(validTargets, validTargetsList, union, index + 1, included, amount); - CardCollection candidate = validTargetsList.get(index); if (candidate.isEmpty()) { return; diff --git a/forge-game/src/main/java/forge/game/ability/effects/TapOrUntapAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/TapOrUntapAllEffect.java index 4eeb2082f4e..a041728e6d1 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/TapOrUntapAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/TapOrUntapAllEffect.java @@ -28,8 +28,7 @@ public class TapOrUntapAllEffect extends SpellAbilityEffect { if (sa.hasParam("ValidMessage")) { sb.append(sa.getParam("ValidMessage")); - } - else { + } else { final List tgtCards = getTargetCards(sa); sb.append(StringUtils.join(tgtCards, ", ")); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/TwoPilesEffect.java b/forge-game/src/main/java/forge/game/ability/effects/TwoPilesEffect.java index d13f4e576f3..746d6190d3e 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/TwoPilesEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/TwoPilesEffect.java @@ -26,10 +26,7 @@ public class TwoPilesEffect extends SpellAbilityEffect { final List tgtPlayers = getTargetPlayers(sa); - String valid = ""; - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); sb.append("Separate all ").append(valid).append(" cards "); @@ -54,10 +51,7 @@ public class TwoPilesEffect extends SpellAbilityEffect { zone = ZoneType.smartValueOf(sa.getParam("Zone")); } - String valid = "Card"; - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); final TargetRestrictions tgt = sa.getTargetRestrictions(); final List tgtPlayers = getTargetPlayers(sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/UntapAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/UntapAllEffect.java index b5399762c6a..89e5ec12511 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/UntapAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/UntapAllEffect.java @@ -24,15 +24,9 @@ public class UntapAllEffect extends SpellAbilityEffect { @Override public void resolve(SpellAbility sa) { final Card card = sa.getHostCard(); - - String valid = ""; CardCollectionView list; - List tgtPlayers = getTargetPlayers(sa); - - if (sa.hasParam("ValidCards")) { - valid = sa.getParam("ValidCards"); - } + final String valid = sa.getParamOrDefault("ValidCards", ""); if (!sa.usesTargeting() && !sa.hasParam("Defined")) { list = sa.getActivatingPlayer().getGame().getCardsIn(ZoneType.Battlefield); diff --git a/forge-gui-desktop/src/main/java/forge/menus/LayoutMenu.java b/forge-gui-desktop/src/main/java/forge/menus/LayoutMenu.java index 731d804bc40..026b8d07eb2 100644 --- a/forge-gui-desktop/src/main/java/forge/menus/LayoutMenu.java +++ b/forge-gui-desktop/src/main/java/forge/menus/LayoutMenu.java @@ -213,7 +213,7 @@ public final class LayoutMenu { private static ActionListener getSetWindowSizeAction() { return new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { - final String[] options = {"800x600", "1024x768", "1280x720"}; + final String[] options = {"800x600", "1024x768", "1280x720", "1600x900", "1920x1080", "2560x1440", "3840x2160"}; final Localizer localizer = Localizer.getInstance(); final String choice = GuiChoose.oneOrNone(localizer.getMessage("lblChooseNewWindowSize"), options); if (choice != null) { diff --git a/forge-gui/res/cardsfolder/upcoming/hawkins_national_laboratory_the_upside_down.txt b/forge-gui/res/cardsfolder/upcoming/hawkins_national_laboratory_the_upside_down.txt new file mode 100644 index 00000000000..12e12a0cdc0 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/hawkins_national_laboratory_the_upside_down.txt @@ -0,0 +1,26 @@ +Name:Hawkins National Laboratory +ManaCost:no cost +Types:Legendary Land +A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. +A:AB$ Investigate | Cost$ 4 T | SpellDescription$ Investigate. +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | CheckSVar$ ClueResearch | SVarCompare$ GE3 | Execute$ TrigTransform | TriggerDescription$ At the beginning of your end step, if you sacrificed three or more clues this turn, transform CARDNAME. +SVar:TrigTransform:DB$ SetState | Defined$ Self | Mode$ Transform +SVar:ClueResearch:Count$SacrificedThisTurn Clue +AlternateMode:DoubleFaced +DeckHints:Ability$Investigate +DeckHas:Ability$Investigate & Ability$Token & Ability$Sacrifice +Oracle:{T}: Add {C}.\n{4}, {T}: Investigate.\nAt the beginning of your end step, if you sacrificed three or more clues this turn, transform Hawkins National Laboratory. + +ALTERNATE + +Name:The Upside Down +ManaCost:no cost +Types:Legendary Land +T:Mode$ Transformed | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When this land transforms into CARDNAME, return target creature card from your graveyard to the battlefield. +SVar:TrigReturn:DB$ ChangeZone | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select target creature card from your graveyard | Origin$ Graveyard | Destination$ Battlefield | RememberTargets$ True +T:Mode$ ChangesZone | ValidCard$ Card.IsRemembered | Origin$ Battlefield | Destination$ Any | Execute$ TrigTransform2 | TriggerZones$ Battlefield | TriggerDescription$ When the creature card put onto the battlefield with CARDNAME leaves the battlefield, transform CARDNAME. +SVar:TrigTransform2:DB$ SetState | Defined$ Self | Mode$ Transform | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +A:AB$ Mana | Cost$ T PayLife<1> | Produced$ B | SpellDescription$ Add {B}. +DeckHas:Ability$Graveyard +Oracle:When this land transforms into The Upside Down, return target creature card from your graveyard to the battlefield.\nWhen the creature card put onto the battlefield with The Upside Down leaves the battlefield, transform The Upside Down.\n{T}, Pay 1 life: Add {B}. diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index f492477b6c9..fa5276fcd3d 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -168,7 +168,7 @@ nlRemoveSmall=Verhindert 1/1- und 0/X-Kreaturen in erzeugten Decks nlSingletons=Verhindert Duplikate von Nicht-Landkarten in erzeugten Decks nlRemoveArtifacts=Verhindert Artefakte in erzeugten Decks nlCardBased=Erzeugt stimmigere zufällig erzeugte Decks (Erfordert Neustart) -DeckEditorOptions=Deck Editor Optionen +DeckEditorOptions=Deck-Editor-Optionen nlFilterLandsByColorId=Macht es einfacher die richtigen Länder zu finden, wenn Farbfilter genutzt werden. AdvancedSettings=Erweiterte Optionen nlDevMode=Ativiert ein Menü mit Funktionen, welche das Testen vereinfachen. @@ -466,7 +466,7 @@ lblBrawlDesc=Jeder Spieler hat eine legendäre \"General\"-Karte, welche (fast) lblPlaneswalker=Planeswalker lblPlaneswalkerDesc=Jeder Spieler hat eine Planeswalker-Karte, welche (fast) jederzeit gespielt werden kann. lblPlanechase=Weltenjagd -lblPlanechaseDesc=Weltenkarten haben globale Effekte. Wenn ein Spieler auf dem Weltenwürfel \"Planeswalk\"wirft, wechselt die Weltenkarte. +lblPlanechaseDesc=Weltenkarten haben globale Effekte. Wenn ein Spieler auf dem Weltenwürfel \"Planeswalk\" wirft, wechselt die Weltenkarte. lblArchenemyDesc=Ein Spieler ist der Erzfeind und kämpft gegen die anderen Spieler. Er hat Komplottkarten.\nEiner gegen alle. lblArchenemyRumble=Erzfeind Rumble lblArchenemyRumbleDesc=Alle Spieler sind Erzfeinde und haben Komplottkarten.\nJeder gegen jeden. @@ -1355,7 +1355,7 @@ lblRemoveCardBelongingWitchPlayer=Entferne Karte(n) von welchem Spielers? lblRemoveCardFromWhichZone=Entferne Karte(n) aus welcher Zone? lblChooseCardsRemoveFromGame=Welche Karten aus dem Spiel entfernen? lblRemoved=Entfernt -lblEnterASequence=Gib Abfolge ein (Karten-ID und/oder "opponen"/"me"(z.B. 7, opponent, 18)). +lblEnterASequence=Gib Abfolge ein (Karten-ID und/oder "opponent"/"me"(z.B. 7, opponent, 18)). lblActionSequenceCleared=Aktion gelöscht lblRestartingActionSequence=Starte Aktion neu. lblErrorPleaseCheckID=Fehler: Prüfe IDs und ob sie durch Leerzeichen und/oder Kommas getrennt sind. @@ -2636,95 +2636,90 @@ lblTargetingArcsAlwaysOn=Zielpfleile: Immer an #ListCardArea.java lblDone=Fertig #DeckImport.java -lblDeckImporterPanelTitle=Deck Importer - {0} -ttUseOnlySetsReleasedBefore=Use in combination with Card Art Preference -nlUseOnlySetsReleasedBefore=Filter card editions by release date -lblUseFormatFilter=Choose a Format for the Decklist -lblIgnoreBnR=Also import Banned and Restricted Cards -ttIgnoreBnR=If activated, any Banned or Restricted Card will be also imported in the Deck. -nlIgnoreBnR=Warning: The Deck may not be playable if Deck Conformance is enabled. -lblExtraOptions=Show Options -lblHideOptions=Hide Options -lblCardPreview=Card Preview -lblCardListTitle=Card List -lblDecklistTitle=Decklist -lblSummaryStats=Summary Statistics -lblDeckSection=Section -lblNewDeckCheckbox=Create a New Deck -lblImportCardsCmd=Import Cards -lblCreateNewCmd=New Deck -lblErrNotAllowedCard=Set not allowed in {0} +lblDeckImporterPanelTitle=Deck-Importer - {0} +ttUseOnlySetsReleasedBefore=In Kombination mit bevorzugtem Kartenbild nutzen +nlUseOnlySetsReleasedBefore=Filtere Karten-Editionen nach Erscheinungsdatum +lblUseFormatFilter=Wähle ein Format für die Deckliste +lblIgnoreBnR=Importiere auch gebannte und eingeschränkte Karten +ttIgnoreBnR=Wenn aktiviert, erden auch gebannte oder eingeschränkte Karten ins Deck importiert. +nlIgnoreBnR=Warnung: Das Deck kann bei eingeschalteter Deckkonkonformität nicht spielbar sein. +lblExtraOptions=Zeige Optionen +lblHideOptions=Verstecke Optionen +lblCardPreview=Karten-Vorschau +lblCardListTitle=Karten-Liste +lblDecklistTitle=Deckliste +lblSummaryStats=Gesamt-Statistik +lblDeckSection=Bereich +lblNewDeckCheckbox=Erzeuge ein neues Deck +lblImportCardsCmd=Importiere Karten +lblCreateNewCmd=Neues Deck +lblErrNotAllowedCard=Set ist nicht erlaubt in {0} lblWarnLimitedCard={0} in {1} -lblErrCardEditionDate=Set not compliant with Release Date option -lblErrUnsupportedCard=Not allowed in {0} -lblWarnUnknownCardMsg=Unknown Card or Unsupported in Forge -lblWarnTooManyCommanders=Current {0} Section contains {1} potential Commander Cards: {2} -lblWarnCommandersInSideExtra=Please check and move one to the Commander Section, in case. -lblWarnDeckSectionNotAllowedInEditor={0} Section is not allowed in {1} -lblWarnCardInInvalidSection={0} moved from {1} to {2}. -lblWarningMsgPrefix=WARNING -lblNewDeckName=New Deck -lblCurrentDecklist=Current Decklist -lblDeckName=Deck Name -nlGuideTitle=Quick Instructions -nlGuideQuickInstructions=To start using the Deck Importer just type or paste the names of the \ - cards you want in the Card List (one per line). The Card list can contain either a few spare cards, \ - or a full deck in one of the most popular M:TG formats (Please see below the list of supported Deck formats). \n \ - Each line in the Card list is processed immediately, and any recognized entry will appear in the Decklist in one \ - of the following colors: {0} -lblGuideImportCard=Card successfully recognized and ready to be imported. -lblGuideWarnMessage=Unknown or Limited Card (i.e. Banned or Restricted), or general warning message. -lblGuideNoImportCard=Invalid or Unsupported Card that cannot be imported. -nlGuideTipsTitle=Importer Options and Customizations -nlGuideTipsText=Please read this section if you want to know the many ways the Deck Importer allows to refine and organize \ - your Decklist. \n {0} -lblGuideTipsTitleCount=Card Amount -lblGuideTipsCount={0}: Prepend to each card line the number of copies to import (default: 1). \n\ - For example, both {1} and {2} are accepted entries. -lblGuideTipsTitleSet=Card Art -lblGuideTipsSet={0}: Specify the code of an M:TG set (right before or right after card name) to choose a \ - specific card art. Also add card collector number or the art index at the end of the line, if the chosen \ - set has multiple arts for the same card (See more examples below). -lblGuideTipsTitleFoil=Foil Cards -lblGuideTipsFoil={0}: Any card name ending with the "+" sign will be imported foiled, e.g. {1}. Alternatively, \ - appending the {2} symbol at the end of card line (as it is customary in some M:TG deck formats) will \ - do the same (Please see the Examples Section below). -lblGuideTipsTitlePlaceholder=Card Groups -lblGuideTipsPlaceholder={0}: Special placeholder keywords can be used to organize the Card list. They can be either \ - Core Card Types (e.g. {1}), Card Rarity (i.e. {2}), Mana Cost (e.g. {3}), or Mana Colors (e.g. {4}). -lblGuideTipsTitleDeckSections=Deck Sections -lblGuideTipsDeckSection={0}: Similar to Card Groups, the Card list can also be organized in Deck Sections \ - (e.g. {1}), that will also used by the Importer to assign cards in the deck (default: {2}). \ - For this reason, the Importer also integrates an automated validation of cards in sections to \ - reduce the risk of errors. -lblGuideTipsTitleDeckName=Deck Name -lblGuideTipsDeckName={0}: Assign a name to your Deck. Just type "Deck:" or "Name:", followed by the name \ - to assign to the deck. -lblGuideTipsTitleDeckFormat=Deck Formats -lblGuideTipsDeckFormats={0}: Several M:TG deck formats are supported: MTG Arena; \ - MTGO, XMage, MTG Goldfish (all export); TappedOut (all export, but CSV); DeckStats.net; ".dec" files. -nlGuideExamplesTitle=Examples +lblErrCardEditionDate=Set verträgt sich nicht mit der Erscheinungsdatum-Option +lblErrUnsupportedCard=Ist nicht erlaubt in {0} +lblWarnUnknownCardMsg=Unbekannte oder in Forge nicht unterstützte Karte +lblWarnTooManyCommanders=Aktueller {0}-Bereich enthält {1} mögliche Commander-Karten: {2} +lblWarnCommandersInSideExtra=Bitte prüfen und, falls nötig, min. eine Karte in den Commander-Bereich verschieben. +lblWarnDeckSectionNotAllowedInEditor=In {1} ist der {0}-Bereich nicht erlaubt. +lblWarnCardInInvalidSection={0} wurde verschoben von {1} nach {2}. +lblWarningMsgPrefix=WARNUNG +lblNewDeckName=Neues Deck +lblCurrentDecklist=Aktuelle Deckliste +lblDeckName=Deck-Name +nlGuideTitle=Kurz-Anleitung +nlGuideQuickInstructions=Um den Deck-Importer zu nutzen tippe oder kopiere den (englischen) Namen einer Karte (eine pro Zeile) in die \ + Kartenliste ein. Die Kartenliste kann entweder einige beliebige Karten, oder ein ganzes Deck in einem der beliebten M:TG-Formate enthalten \ + (Eine Liste der unterstützten Formate findet sich unten). \n \ + Jede Zeile wird umgehend verarbeitet, und jeder erkannte Eintrag erscheint in der Deckliste in einer der folgenden Farben: {0} +lblGuideImportCard=Karte wurde erfolgreich erkannt und ist fertig zum Übernehmen. +lblGuideWarnMessage=Unbekannte oder eingeschränkte Karte (steht auf der Bann- o. Beschränkungsliste), oder generälle Warnung. +lblGuideNoImportCard=Ungültige oder nicht unterstützte Karte, welche nicht übernommen werden kann. +nlGuideTipsTitle=Importer-Optionen und Anpassungen +nlGuideTipsText=Bitte lese diesen Abschnitt, wenn du mehr über die Möglicjkeiten wissen willst, wie der Importer deine Deckliste bearbeiten \ + und organisieren kann. \n {0} +lblGuideTipsTitleCount=Karten-Anzahl +lblGuideTipsCount={0}: Stelle jeder Karte die zu importierende Anzahl voran (Vorgabe: 1). \n\ + Zum Beispiel sind {1} und {2} beides akzeptierte Einträge. +lblGuideTipsTitleSet=Kartenbild +lblGuideTipsSet={0}: Gebe den Code eines M:TG-Sets (direkt vor oder nach dem Kartennamen) an, um ein spezielles Kartenbild zu wählen. \ + Außerdem gib die Sammlernummer oder eine Bild-Versionsnummer an, falls mehrere Bildversionen einer Karte im Set existieren \ + (weitere Beispiele unten). +lblGuideTipsTitleFoil=Foil-Karten +lblGuideTipsFoil={0}: Jede Karte endend mit "+" wird als Foil importiert, z.B. {1}. Anhängen des {2}-Symbols am Ende der Kartenzeile \ + (üblich in einigen beliebten Deck-Formaten) bewirkt das Gleiche (siehe Beispiele unten). +lblGuideTipsTitlePlaceholder=Karten-Gruppierung +lblGuideTipsPlaceholder={0}: Spezielle Schlüsselwörter können zur Organisation der Deckliste genutzt werden. Sie können \ + Kartentypen (z.B. {1}), Seltenheit (z.B. {2}), Manakosten (z.B. {3}), or Manafarben (z.B. {4}) sein. +lblGuideTipsTitleDeckSections=Deck-Bereiche +lblGuideTipsDeckSection={0}: Genauso wie Grupierungen kann die Kartenliste in Bereiche eingeteilt werden \ + (z.B. {1}), welche der Importer nutzt, um die Karten im Deck zuzuweisen (Vorgabe: {2}). \ + Aus diesem Grund nutzt der Importer eine automatische Gegenprüfung der Karten in den Bereichen um das Risiko von Fehler zu verringern. +lblGuideTipsTitleDeckName=Deck-Name +lblGuideTipsDeckName={0}: Um dem Deck einen Namen zuzuweisen, gib "Deck:" oder "Name:" ein, gefolgt vom gewünschten Namen des Decks. +lblGuideTipsTitleDeckFormat=Deck-Formate +lblGuideTipsDeckFormats={0}: Diverse M:TG-Deckformate werden unterstützt: MTG Arena, \ + MTGO, XMage, MTG Goldfish (alle Exporte); TappedOut (alle Exporte, außer CSV); DeckStats.net; ".dec"-Dateien. +nlGuideExamplesTitle=Beispiele lblExample1=10x Islands+ MIR 2 -nlExample1=10 FOIL "Island" from Set "Mirage", Art Index 2\. +nlExample1=10 FOIL "Insel" vom Set "Trugbilder", Bildversion 2\. lblExample2=4 Darksteel Citadel (M15) 242 -nlExample2=4 "Darksteel Citadel" from "M15", Collector Nr. "242".\n\n \ - This is an exemplar entry in MTGArena format as exported by TappedOut. +nlExample2=4 "Nachtstahl-Zitadelle" von "M15", Sammlernummer "242".\n\n \ + Dies ist ein Beispieleintrag im MTGArena-Format exportiert von TappedOut. lblExample3=18 Forest <254> [THB] (F) -nlExample3=18 FOIL "Forest" from "THB", Collector Nr. "254".\n\n \ - This is an exemplar entry in MTGArena deck format as exported by MTGGoldfish. \ - The "(F)" in the end denotes a foil card, and the Collector Number in angular brackets is \ - is used to select a specific Card Art). +nlExample3=18 FOIL "Wald" von "THB", Sammlernummer "254".\n\n \ + Dies ist ein Beispielentrag im MTGArena-Deckformat exportiert von MTGGoldfish. \ + Das "(F)" am Ende bezeichnet eine Foil-Karte, und die Sammlernummer in gewinkelten Klammern wird genutzt eine \ + bestimmte Kartenbildversion zu wählen. lblExample4=4x TMP|Counterspell -nlExample4=4 copies of "Counterspell" from "Tempest".\n\n \ - In this entry, the Set code is specified before the card name using the (optional) pipe separator.\ - Alternative valid separators for set codes are braces, brackets, and parenthesis. +nlExample4=4 Kopien von "Gegenzauber" von "Sturmwind".\n\n \ + In diesem Eintrag wird der Set-Code vor dem Kartennamen unter Nutzung des (optionalen) Trenners Pipe.\ + Andere gültige Trenner für Set-Codes sind geschweifte, eckige und runde Klammern. lblExample5=SB: 2 [M19:28] Mighty Leap -nlExample5=2 copies of "Mighty Leap" from "M19", Collector Nr. "28" to be added in "Sideboard".\n\n \ - This is an exemplar entry in XMage deck format. In this format, the Set code and the Collector Number are \ - column-separated, and specified in brackets right before card name. \ - Moreover, an optional Prefix (i.e. SB:) is used to denote the Deck Section where the card should be added to. \ - The Deck Importer in Forge further extends this idea by also adding support to two extra prefixes, i.e. "MB:" and \ - "CM:" as for "Main" and "Commander" Section, respectively. +nlExample5=2 Kopien von "Mächtiger Sprung" von "M19", Sammlernummer "28" werden dem "Sideboard" zugeordnet.\n\n \ + Dies ist ein Beispieleintrag im XMage-Deckformat. In diesem Format sind der Set-Code und die Sammlernummer durch einen Doppelpunkt \ + getrennt, werden direkt vor dem Kartennamen in eckigen Klammern angegeben. \ + Zusätzlich wird ein optionaler Prefix (z.B. SB:) genutzt um den gewünschten Bereich für die Karte anzugeben. \ + Der Deck-Importer in Forge unterstützt zwei weitere Prefixe, z.B. "MB:" und "CM:" für den "Haupt-" und den "Commander-"Bereich. #CEditorTokenViewer.java lblAllTokens=Alle Spielsteine #StartRenderer.java @@ -2748,14 +2743,14 @@ htmlPhaseCleanupTooltip=Phase: Aufräumen
Klicke zum Umschalten. lblSideboardForPlayer=Sideboard für {0} lblOtherInteger=Andere... #DeckImportController.java -lblConfirmCardImport=You are about to merge the Decklist in the {0} deck.{1}\n\nWould you like to proceed?\n\n Note: \ - Please remember to click on the "Save" button in the Deck Editor to finalize the changes to current deck! -lblCardImportWarning=\nWarning: The deck {0} will be renamed as {1}. -lblConfirmCreateNewDeck=You are about to create a new deck {0}. {1}\n\nWould you like to proceed?\n\n Note: \ - Please remember to click on the "Save" button in the Deck Editor to add the new deck to the Catalog! -lblNewDeckWarning=\nWarning: Any unsaved changes to the current deck {0} will be lost. -lblImportCardsDialogTitle=Import cards in the Current Deck -lblNewDeckDialogTitle=Create a New Deck +lblConfirmCardImport=Du bist dabei die Deckliste ins {0}-Deck einzufügen.{1}\n\nWillst du fortfahren?\n\n Hinweis: \ + Bitte denk daran den "Save"-Knopf im Deck-Editor zu klicken, um die Änderungen am aktuellen Deck zu bestätigen! +lblCardImportWarning=\nWarnung: Das Deck {0} wird umbenannt in {1}. +lblConfirmCreateNewDeck=Du bist dabei das neue Deck {0} zu erzeugen. {1}\n\nWillst du fortfahren?\n\n Hinweis: \ + Bitte denk daran den "Save"-Knopf im Deck-Editor zu klicken, um das neue Deck dem Deck-Katalog hinzuzufügen! +lblNewDeckWarning=\nWarnung: Alle ungesicherten Änderungen am aktuellen Deck {0} werden verlorengehen. +lblImportCardsDialogTitle=Importiere Karten in aktuelles Deck +lblNewDeckDialogTitle=Erzeuge neues Deck #FNetOverlay.java lblChat=Chat lblSend=Senden diff --git a/forge-gui/src/main/java/forge/gamemodes/quest/QuestTournamentController.java b/forge-gui/src/main/java/forge/gamemodes/quest/QuestTournamentController.java index 619123a89a3..e9fbe388553 100644 --- a/forge-gui/src/main/java/forge/gamemodes/quest/QuestTournamentController.java +++ b/forge-gui/src/main/java/forge/gamemodes/quest/QuestTournamentController.java @@ -16,6 +16,7 @@ import forge.gamemodes.quest.data.QuestPreferences; import forge.gamemodes.tournament.system.TournamentBracket; import forge.gamemodes.tournament.system.TournamentPairing; import forge.gamemodes.tournament.system.TournamentPlayer; +import forge.gui.FThreads; import forge.gui.GuiBase; import forge.gui.interfaces.IGuiGame; import forge.gui.util.SGuiChoose; @@ -406,7 +407,12 @@ public class QuestTournamentController { drafting = true; final BoosterDraft draft = draftEvent.enter(); - view.startDraft(draft); + FThreads.invokeInEdtLater(new Runnable() { + @Override + public void run() { + view.startDraft(draft); + } + }); } }); } diff --git a/forge-gui/src/main/java/forge/localinstance/achievements/AchievementCollection.java b/forge-gui/src/main/java/forge/localinstance/achievements/AchievementCollection.java index 2b6c7c4acfc..ec4cbeb7d2a 100644 --- a/forge-gui/src/main/java/forge/localinstance/achievements/AchievementCollection.java +++ b/forge-gui/src/main/java/forge/localinstance/achievements/AchievementCollection.java @@ -102,8 +102,7 @@ public abstract class AchievementCollection implements Iterable { add(new TotalMatchWins(100, 250, 500, 1000)); if (isLimitedFormat) { //make need for speed goal more realistic for limited formats add(new NeedForSpeed(8, 6, 4, 2)); - } - else { + } else { add(new NeedForSpeed(5, 3, 1, 0)); } add(new Overkill(-25, -50, -100, -200)); @@ -114,8 +113,7 @@ public abstract class AchievementCollection implements Iterable { add(new ManaScrewed()); if (isLimitedFormat) { //lower gold and mythic thresholds based on smaller decks add(new ManaFlooded(8, 11, 14, 17)); - } - else { + } else { add(new ManaFlooded(8, 12, 18, 24)); } add(new RagsToRiches());