mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
Merge remote-tracking branch 'upstream/master' into deck-importer-decks-file-format
This commit is contained in:
@@ -208,7 +208,7 @@ public class AiAttackController {
|
|||||||
*/
|
*/
|
||||||
public final boolean isEffectiveAttacker(final Player ai, final Card attacker, final Combat combat, final GameEntity defender) {
|
public final boolean isEffectiveAttacker(final Player ai, final Card attacker, final Combat combat, final GameEntity defender) {
|
||||||
// if the attacker will die when attacking don't attack
|
// if the attacker will die when attacking don't attack
|
||||||
if ((attacker.getNetToughness() + ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, null, combat, true)) <= 0) {
|
if (attacker.getNetToughness() + ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, null, combat, true) <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,19 +17,11 @@
|
|||||||
*/
|
*/
|
||||||
package forge.ai;
|
package forge.ai;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import com.esotericsoftware.minlog.Log;
|
import com.esotericsoftware.minlog.Log;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.ai.ability.ChangeZoneAi;
|
import forge.ai.ability.ChangeZoneAi;
|
||||||
import forge.ai.ability.ExploreAi;
|
import forge.ai.ability.ExploreAi;
|
||||||
import forge.ai.ability.LearnAi;
|
import forge.ai.ability.LearnAi;
|
||||||
@@ -40,39 +32,17 @@ import forge.card.mana.ManaCost;
|
|||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.deck.DeckSection;
|
import forge.deck.DeckSection;
|
||||||
import forge.game.CardTraitBase;
|
import forge.game.*;
|
||||||
import forge.game.CardTraitPredicates;
|
|
||||||
import forge.game.Direction;
|
|
||||||
import forge.game.Game;
|
|
||||||
import forge.game.GameActionUtil;
|
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.GlobalRuleChange;
|
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.ability.SpellApiBased;
|
import forge.game.ability.SpellApiBased;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardFactoryUtil;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPlayOption;
|
|
||||||
import forge.game.card.CardPredicates;
|
|
||||||
import forge.game.card.CardPredicates.Accessors;
|
import forge.game.card.CardPredicates.Accessors;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
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.Combat;
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.*;
|
||||||
import forge.game.cost.CostAdjustment;
|
|
||||||
import forge.game.cost.CostDiscard;
|
|
||||||
import forge.game.cost.CostPart;
|
|
||||||
import forge.game.cost.CostPayEnergy;
|
|
||||||
import forge.game.cost.CostPayLife;
|
|
||||||
import forge.game.cost.CostPutCounter;
|
|
||||||
import forge.game.cost.CostRemoveCounter;
|
|
||||||
import forge.game.cost.CostSacrifice;
|
|
||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
import forge.game.mana.ManaCostBeingPaid;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
@@ -82,15 +52,7 @@ import forge.game.replacement.ReplaceMoved;
|
|||||||
import forge.game.replacement.ReplacementEffect;
|
import forge.game.replacement.ReplacementEffect;
|
||||||
import forge.game.replacement.ReplacementLayer;
|
import forge.game.replacement.ReplacementLayer;
|
||||||
import forge.game.replacement.ReplacementType;
|
import forge.game.replacement.ReplacementType;
|
||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.*;
|
||||||
import forge.game.spellability.LandAbility;
|
|
||||||
import forge.game.spellability.OptionalCost;
|
|
||||||
import forge.game.spellability.OptionalCostValue;
|
|
||||||
import forge.game.spellability.Spell;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.game.spellability.SpellAbilityCondition;
|
|
||||||
import forge.game.spellability.SpellAbilityPredicates;
|
|
||||||
import forge.game.spellability.SpellPermanent;
|
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.staticability.StaticAbilityMustTarget;
|
import forge.game.staticability.StaticAbilityMustTarget;
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
@@ -106,6 +68,9 @@ import forge.util.collect.FCollectionView;
|
|||||||
import io.sentry.Sentry;
|
import io.sentry.Sentry;
|
||||||
import io.sentry.event.BreadcrumbBuilder;
|
import io.sentry.event.BreadcrumbBuilder;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* AiController class.
|
* AiController class.
|
||||||
@@ -1968,6 +1933,38 @@ public class AiController {
|
|||||||
// Whims of the Fates {all, 0, 0}
|
// Whims of the Fates {all, 0, 0}
|
||||||
result.addAll(pool);
|
result.addAll(pool);
|
||||||
break;
|
break;
|
||||||
|
case FlipOntoBattlefield:
|
||||||
|
if ("DamageCreatures".equals(sa.getParam("AILogic"))) {
|
||||||
|
int maxToughness = Integer.valueOf(sa.getSubAbility().getParam("NumDmg"));
|
||||||
|
CardCollectionView rightToughness = CardLists.filter(pool, new Predicate<Card>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(Card card) {
|
||||||
|
return card.getController().isOpponentOf(sa.getActivatingPlayer())
|
||||||
|
&& card.getNetToughness() <= maxToughness
|
||||||
|
&& card.canBeDestroyed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Card bestCreature = ComputerUtilCard.getBestCreatureAI(rightToughness.isEmpty() ? pool : rightToughness);
|
||||||
|
if (bestCreature != null) {
|
||||||
|
result.add(bestCreature);
|
||||||
|
} else {
|
||||||
|
result.add(Aggregates.random(pool)); // should ideally never get here
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CardCollectionView viableOptions = CardLists.filter(pool, Predicates.and(CardPredicates.isControlledByAnyOf(sa.getActivatingPlayer().getOpponents())),
|
||||||
|
new Predicate<Card>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(Card card) {
|
||||||
|
return card.canBeDestroyed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Card best = ComputerUtilCard.getBestAI(viableOptions);
|
||||||
|
if (best == null) {
|
||||||
|
best = Aggregates.random(pool); // should ideally never get here either
|
||||||
|
}
|
||||||
|
result.add(best);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
CardCollection editablePool = new CardCollection(pool);
|
CardCollection editablePool = new CardCollection(pool);
|
||||||
for (int i = 0; i < max; i++) {
|
for (int i = 0; i < max; i++) {
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ import forge.game.card.CardFactory;
|
|||||||
import forge.game.card.CardFactoryUtil;
|
import forge.game.card.CardFactoryUtil;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.card.CounterEnumType;
|
import forge.game.card.CounterEnumType;
|
||||||
import forge.game.card.CounterType;
|
import forge.game.card.CounterType;
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
@@ -905,7 +904,7 @@ public class ComputerUtilCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final Card crd : list) {
|
for (final Card crd : list) {
|
||||||
ColorSet color = CardUtil.getColors(crd);
|
ColorSet color = crd.determineColor();
|
||||||
if (color.hasWhite()) map.get(0).setValue(Integer.valueOf(map.get(0).getValue()+1));
|
if (color.hasWhite()) map.get(0).setValue(Integer.valueOf(map.get(0).getValue()+1));
|
||||||
if (color.hasBlue()) map.get(1).setValue(Integer.valueOf(map.get(1).getValue()+1));
|
if (color.hasBlue()) map.get(1).setValue(Integer.valueOf(map.get(1).getValue()+1));
|
||||||
if (color.hasBlack()) map.get(2).setValue(Integer.valueOf(map.get(2).getValue()+1));
|
if (color.hasBlack()) map.get(2).setValue(Integer.valueOf(map.get(2).getValue()+1));
|
||||||
|
|||||||
@@ -1478,7 +1478,7 @@ public class ComputerUtilCombat {
|
|||||||
|
|
||||||
// DealDamage triggers
|
// DealDamage triggers
|
||||||
if (ApiType.DealDamage.equals(sa.getApi())) {
|
if (ApiType.DealDamage.equals(sa.getApi())) {
|
||||||
if ("TriggeredAttacker".equals(sa.getParam("Defined"))) {
|
if (!sa.hasParam("Defined") || !sa.getParam("Defined").startsWith("TriggeredAttacker")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int damage = AbilityUtils.calculateAmount(source, sa.getParam("NumDmg"), sa);
|
int damage = AbilityUtils.calculateAmount(source, sa.getParam("NumDmg"), sa);
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ public enum SpellApiToAi {
|
|||||||
.put(ApiType.Explore, ExploreAi.class)
|
.put(ApiType.Explore, ExploreAi.class)
|
||||||
.put(ApiType.Fight, FightAi.class)
|
.put(ApiType.Fight, FightAi.class)
|
||||||
.put(ApiType.FlipACoin, FlipACoinAi.class)
|
.put(ApiType.FlipACoin, FlipACoinAi.class)
|
||||||
|
.put(ApiType.FlipOntoBattlefield, FlipOntoBattlefieldAi.class)
|
||||||
.put(ApiType.Fog, FogAi.class)
|
.put(ApiType.Fog, FogAi.class)
|
||||||
.put(ApiType.GainControl, ControlGainAi.class)
|
.put(ApiType.GainControl, ControlGainAi.class)
|
||||||
.put(ApiType.GainControlVariant, ControlGainVariantAi.class)
|
.put(ApiType.GainControlVariant, ControlGainVariantAi.class)
|
||||||
@@ -140,6 +141,7 @@ public enum SpellApiToAi {
|
|||||||
.put(ApiType.RemoveCounterAll, CannotPlayAi.class)
|
.put(ApiType.RemoveCounterAll, CannotPlayAi.class)
|
||||||
.put(ApiType.RemoveFromCombat, RemoveFromCombatAi.class)
|
.put(ApiType.RemoveFromCombat, RemoveFromCombatAi.class)
|
||||||
.put(ApiType.RemoveFromGame, AlwaysPlayAi.class)
|
.put(ApiType.RemoveFromGame, AlwaysPlayAi.class)
|
||||||
|
.put(ApiType.RemoveFromMatch, AlwaysPlayAi.class)
|
||||||
.put(ApiType.ReorderZone, AlwaysPlayAi.class)
|
.put(ApiType.ReorderZone, AlwaysPlayAi.class)
|
||||||
.put(ApiType.Repeat, RepeatAi.class)
|
.put(ApiType.Repeat, RepeatAi.class)
|
||||||
.put(ApiType.RepeatEach, RepeatEachAi.class)
|
.put(ApiType.RepeatEach, RepeatEachAi.class)
|
||||||
|
|||||||
@@ -260,8 +260,9 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
// minimum card advantage unless the hand will be fully reloaded
|
// minimum card advantage unless the hand will be fully reloaded
|
||||||
int minAdv = logic.contains(".minAdv") ? Integer.parseInt(logic.substring(logic.indexOf(".minAdv") + 7)) : 0;
|
int minAdv = logic.contains(".minAdv") ? Integer.parseInt(logic.substring(logic.indexOf(".minAdv") + 7)) : 0;
|
||||||
|
boolean noDiscard = logic.contains(".noDiscard");
|
||||||
|
|
||||||
if (numExiledWithSrc > curHandSize) {
|
if (numExiledWithSrc > curHandSize || (noDiscard && numExiledWithSrc > 0)) {
|
||||||
if (ComputerUtil.predictThreatenedObjects(ai, sa, true).contains(source)) {
|
if (ComputerUtil.predictThreatenedObjects(ai, sa, true).contains(source)) {
|
||||||
// Try to gain some card advantage if the card will die anyway
|
// Try to gain some card advantage if the card will die anyway
|
||||||
// TODO: ideally, should evaluate the hand value and not discard good hands to it
|
// TODO: ideally, should evaluate the hand value and not discard good hands to it
|
||||||
@@ -269,7 +270,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (curHandSize + minAdv - 1 < numExiledWithSrc) || (numExiledWithSrc >= ai.getMaxHandSize());
|
return (curHandSize + minAdv - 1 < numExiledWithSrc) || (!noDiscard && numExiledWithSrc >= ai.getMaxHandSize());
|
||||||
}
|
}
|
||||||
} else if (origin.equals(ZoneType.Stack)) {
|
} else if (origin.equals(ZoneType.Stack)) {
|
||||||
// time stop can do something like this:
|
// time stop can do something like this:
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
//if Iona does prevent from casting, allow it to draw
|
//if Iona does prevent from casting, allow it to draw
|
||||||
for (final Card io : player.getCardsIn(ZoneType.Battlefield, "Iona, Shield of Emeria")) {
|
for (final Card io : player.getCardsIn(ZoneType.Battlefield, "Iona, Shield of Emeria")) {
|
||||||
if (CardUtil.getColors(imprinted).hasAnyColor(MagicColor.fromName(io.getChosenColor()))) {
|
if (imprinted.determineColor().hasAnyColor(MagicColor.fromName(io.getChosenColor()))) {
|
||||||
return allow;
|
return allow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -303,6 +303,8 @@ public class DestroyAi extends SpellAbilityAi {
|
|||||||
|| ai.getLife() <= 5)) {
|
|| ai.getLife() <= 5)) {
|
||||||
// Basic ai logic for Lethal Vapors
|
// Basic ai logic for Lethal Vapors
|
||||||
return false;
|
return false;
|
||||||
|
} else if ("Always".equals(logic)) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.isEmpty()
|
if (list.isEmpty()
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ public class DigUntilAi extends SpellAbilityAi {
|
|||||||
// until opponent's end of turn phase!
|
// until opponent's end of turn phase!
|
||||||
// But we still want more (and want to fill grave) if nothing better to do then
|
// But we still want more (and want to fill grave) if nothing better to do then
|
||||||
// This is important for Replenish/Living Death type decks
|
// This is important for Replenish/Living Death type decks
|
||||||
if (!((ai.getGame().getPhaseHandler().is(PhaseType.END_OF_TURN))
|
if (!ai.getGame().getPhaseHandler().is(PhaseType.END_OF_TURN)
|
||||||
&& (!ai.getGame().getPhaseHandler().isPlayerTurn(ai)))) {
|
&& !ai.getGame().getPhaseHandler().isPlayerTurn(ai)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ public class DigUntilAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String num = sa.getParam("Amount");
|
final String num = sa.getParam("Amount");
|
||||||
if ((num != null) && num.equals("X") && sa.getSVar(num).equals("Count$xPaid")) {
|
if (num != null && num.equals("X") && sa.getSVar(num).equals("Count$xPaid")) {
|
||||||
// Set PayX here to maximum value.
|
// Set PayX here to maximum value.
|
||||||
SpellAbility root = sa.getRootAbility();
|
SpellAbility root = sa.getRootAbility();
|
||||||
if (root.getXManaCostPaid() == null) {
|
if (root.getXManaCostPaid() == null) {
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package forge.ai.ability;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import forge.ai.SpellAbilityAi;
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardCollectionView;
|
||||||
|
import forge.game.card.CardLists;
|
||||||
|
import forge.game.phase.PhaseHandler;
|
||||||
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.player.PlayerActionConfirmMode;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
|
public class FlipOntoBattlefieldAi extends SpellAbilityAi {
|
||||||
|
@Override
|
||||||
|
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
|
||||||
|
PhaseHandler ph = sa.getHostCard().getGame().getPhaseHandler();
|
||||||
|
String logic = sa.getParamOrDefault("AILogic", "");
|
||||||
|
|
||||||
|
if (!SpellAbilityAi.isSorcerySpeed(sa) && sa.getPayCosts().hasManaCost()) {
|
||||||
|
return ph.is(PhaseType.END_OF_TURN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("DamageCreatures".equals(logic)) {
|
||||||
|
int maxToughness = Integer.valueOf(sa.getSubAbility().getParam("NumDmg"));
|
||||||
|
CardCollectionView rightToughness = CardLists.filter(aiPlayer.getOpponents().getCreaturesInPlay(), new Predicate<Card>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(Card card) {
|
||||||
|
return card.getNetToughness() <= maxToughness && card.canBeDestroyed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return !rightToughness.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
return !aiPlayer.getOpponents().getCardsIn(ZoneType.Battlefield).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
|
||||||
|
return canPlayAI(aiPlayer, sa) || mandatory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -165,11 +165,10 @@ public class StaticData {
|
|||||||
return this.editions;
|
return this.editions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final CardEdition.Collection getCustomEditions(){
|
public final CardEdition.Collection getCustomEditions() {
|
||||||
return this.customEditions;
|
return this.customEditions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<CardEdition> sortedEditions;
|
private List<CardEdition> sortedEditions;
|
||||||
public final List<CardEdition> getSortedEditions() {
|
public final List<CardEdition> getSortedEditions() {
|
||||||
if (sortedEditions == null) {
|
if (sortedEditions == null) {
|
||||||
@@ -189,13 +188,13 @@ public class StaticData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TreeMap<CardEdition.Type, List<CardEdition>> editionsTypeMap;
|
private TreeMap<CardEdition.Type, List<CardEdition>> editionsTypeMap;
|
||||||
public final Map<CardEdition.Type, List<CardEdition>> getEditionsTypeMap(){
|
public final Map<CardEdition.Type, List<CardEdition>> getEditionsTypeMap() {
|
||||||
if (editionsTypeMap == null){
|
if (editionsTypeMap == null) {
|
||||||
editionsTypeMap = new TreeMap<>();
|
editionsTypeMap = new TreeMap<>();
|
||||||
for (CardEdition.Type editionType : CardEdition.Type.values()){
|
for (CardEdition.Type editionType : CardEdition.Type.values()) {
|
||||||
editionsTypeMap.put(editionType, new ArrayList<>());
|
editionsTypeMap.put(editionType, new ArrayList<>());
|
||||||
}
|
}
|
||||||
for (CardEdition edition : this.getSortedEditions()){
|
for (CardEdition edition : this.getSortedEditions()) {
|
||||||
CardEdition.Type key = edition.getType();
|
CardEdition.Type key = edition.getType();
|
||||||
List<CardEdition> editionsOfType = editionsTypeMap.get(key);
|
List<CardEdition> editionsOfType = editionsTypeMap.get(key);
|
||||||
editionsOfType.add(edition);
|
editionsOfType.add(edition);
|
||||||
@@ -204,9 +203,9 @@ public class StaticData {
|
|||||||
return editionsTypeMap;
|
return editionsTypeMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardEdition getCardEdition(String setCode){
|
public CardEdition getCardEdition(String setCode) {
|
||||||
CardEdition edition = this.editions.get(setCode);
|
CardEdition edition = this.editions.get(setCode);
|
||||||
if (edition == null) // try custom editions
|
if (edition == null) // try custom editions
|
||||||
edition = this.customEditions.get(setCode);
|
edition = this.customEditions.get(setCode);
|
||||||
return edition;
|
return edition;
|
||||||
}
|
}
|
||||||
@@ -231,8 +230,7 @@ public class StaticData {
|
|||||||
public void attemptToLoadCard(String cardName){
|
public void attemptToLoadCard(String cardName){
|
||||||
this.attemptToLoadCard(cardName, null);
|
this.attemptToLoadCard(cardName, null);
|
||||||
}
|
}
|
||||||
|
public void attemptToLoadCard(String cardName, String setCode) {
|
||||||
public void attemptToLoadCard(String cardName, String setCode){
|
|
||||||
CardRules rules = cardReader.attemptToLoadCard(cardName);
|
CardRules rules = cardReader.attemptToLoadCard(cardName);
|
||||||
CardRules customRules = null;
|
CardRules customRules = null;
|
||||||
if (customCardReader != null) {
|
if (customCardReader != null) {
|
||||||
@@ -257,7 +255,7 @@ public class StaticData {
|
|||||||
* @param collectorNumber Card's collector Number
|
* @param collectorNumber Card's collector Number
|
||||||
* @return PaperCard instance found in one of the available CardDb databases, or <code>null</code> if not found.
|
* @return PaperCard instance found in one of the available CardDb databases, or <code>null</code> if not found.
|
||||||
*/
|
*/
|
||||||
public PaperCard fetchCard(final String cardName, final String setCode, final String collectorNumber){
|
public PaperCard fetchCard(final String cardName, final String setCode, final String collectorNumber) {
|
||||||
PaperCard card = null;
|
PaperCard card = null;
|
||||||
for (CardDb db : this.getAvailableDatabases().values()) {
|
for (CardDb db : this.getAvailableDatabases().values()) {
|
||||||
card = db.getCard(cardName, setCode, collectorNumber);
|
card = db.getCard(cardName, setCode, collectorNumber);
|
||||||
@@ -345,7 +343,7 @@ public class StaticData {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CardDb matchTargetCardDb(final String cardName){
|
private CardDb matchTargetCardDb(final String cardName) {
|
||||||
// NOTE: any foil request in cardName is NOT taken into account here.
|
// NOTE: any foil request in cardName is NOT taken into account here.
|
||||||
// It's a private method, so it's a fair assumption.
|
// It's a private method, so it's a fair assumption.
|
||||||
for (CardDb targetDb : this.getAvailableDatabases().values()){
|
for (CardDb targetDb : this.getAvailableDatabases().values()){
|
||||||
@@ -360,7 +358,7 @@ public class StaticData {
|
|||||||
* @param cardName Name of the Card to verify (CASE SENSITIVE)
|
* @param cardName Name of the Card to verify (CASE SENSITIVE)
|
||||||
* @return True if a card with the given input string can be found. False otherwise.
|
* @return True if a card with the given input string can be found. False otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isMTGCard(final String cardName){
|
public boolean isMTGCard(final String cardName) {
|
||||||
if (cardName == null || cardName.trim().length() == 0)
|
if (cardName == null || cardName.trim().length() == 0)
|
||||||
return false;
|
return false;
|
||||||
CardDb.CardRequest cr = CardDb.CardRequest.fromString(cardName); // accounts for any foil request ending with +
|
CardDb.CardRequest cr = CardDb.CardRequest.fromString(cardName); // accounts for any foil request ending with +
|
||||||
@@ -450,10 +448,6 @@ public class StaticData {
|
|||||||
|
|
||||||
public Predicate<PaperCard> getBrawlPredicate() { return brawlPredicate; }
|
public Predicate<PaperCard> getBrawlPredicate() { return brawlPredicate; }
|
||||||
|
|
||||||
public void setFilteredHandsEnabled(boolean filteredHandsEnabled){
|
|
||||||
this.filteredHandsEnabled = filteredHandsEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an alternative card print for the given card wrt. the input setReleaseDate.
|
* Get an alternative card print for the given card wrt. the input setReleaseDate.
|
||||||
* The reference release date will be used to retrieve the alternative art, according
|
* The reference release date will be used to retrieve the alternative art, according
|
||||||
@@ -501,7 +495,7 @@ public class StaticData {
|
|||||||
*/
|
*/
|
||||||
public PaperCard getAlternativeCardPrint(PaperCard card, Date setReleaseDate,
|
public PaperCard getAlternativeCardPrint(PaperCard card, Date setReleaseDate,
|
||||||
boolean isCardArtPreferenceLatestArt,
|
boolean isCardArtPreferenceLatestArt,
|
||||||
boolean cardArtPreferenceHasFilter){
|
boolean cardArtPreferenceHasFilter) {
|
||||||
Date searchReferenceDate = getReferenceDate(setReleaseDate, isCardArtPreferenceLatestArt);
|
Date searchReferenceDate = getReferenceDate(setReleaseDate, isCardArtPreferenceLatestArt);
|
||||||
CardDb.CardArtPreference searchCardArtStrategy = getSearchStrategyForAlternativeCardArt(isCardArtPreferenceLatestArt,
|
CardDb.CardArtPreference searchCardArtStrategy = getSearchStrategyForAlternativeCardArt(isCardArtPreferenceLatestArt,
|
||||||
cardArtPreferenceHasFilter);
|
cardArtPreferenceHasFilter);
|
||||||
@@ -537,7 +531,6 @@ public class StaticData {
|
|||||||
public PaperCard getAlternativeCardPrint(PaperCard card, Date setReleaseDate, boolean isCardArtPreferenceLatestArt,
|
public PaperCard getAlternativeCardPrint(PaperCard card, Date setReleaseDate, boolean isCardArtPreferenceLatestArt,
|
||||||
boolean cardArtPreferenceHasFilter,
|
boolean cardArtPreferenceHasFilter,
|
||||||
boolean preferCandidatesFromExpansionSets, boolean preferModernFrame) {
|
boolean preferCandidatesFromExpansionSets, boolean preferModernFrame) {
|
||||||
|
|
||||||
PaperCard altCard = this.getAlternativeCardPrint(card, setReleaseDate, isCardArtPreferenceLatestArt,
|
PaperCard altCard = this.getAlternativeCardPrint(card, setReleaseDate, isCardArtPreferenceLatestArt,
|
||||||
cardArtPreferenceHasFilter);
|
cardArtPreferenceHasFilter);
|
||||||
if (altCard == null)
|
if (altCard == null)
|
||||||
@@ -618,7 +611,7 @@ public class StaticData {
|
|||||||
|
|
||||||
private PaperCard tryToGetCardPrintFromExpansionSet(PaperCard altCard,
|
private PaperCard tryToGetCardPrintFromExpansionSet(PaperCard altCard,
|
||||||
boolean isCardArtPreferenceLatestArt,
|
boolean isCardArtPreferenceLatestArt,
|
||||||
boolean preferModernFrame){
|
boolean preferModernFrame) {
|
||||||
CardEdition altCardEdition = editions.get(altCard.getEdition());
|
CardEdition altCardEdition = editions.get(altCard.getEdition());
|
||||||
if (altCardEdition.getType() == CardEdition.Type.EXPANSION)
|
if (altCardEdition.getType() == CardEdition.Type.EXPANSION)
|
||||||
return null; // Nothing to do here!
|
return null; // Nothing to do here!
|
||||||
@@ -628,7 +621,7 @@ public class StaticData {
|
|||||||
CardDb.CardArtPreference searchStrategy = getSearchStrategyForAlternativeCardArt(searchStrategyFlag,
|
CardDb.CardArtPreference searchStrategy = getSearchStrategyForAlternativeCardArt(searchStrategyFlag,
|
||||||
true);
|
true);
|
||||||
PaperCard altCandidate = altCard;
|
PaperCard altCandidate = altCard;
|
||||||
while (altCandidate != null){
|
while (altCandidate != null) {
|
||||||
Date referenceDate = editions.get(altCandidate.getEdition()).getDate();
|
Date referenceDate = editions.get(altCandidate.getEdition()).getDate();
|
||||||
altCandidate = this.searchAlternativeCardCandidate(altCandidate, preferModernFrame,
|
altCandidate = this.searchAlternativeCardCandidate(altCandidate, preferModernFrame,
|
||||||
referenceDate, searchStrategy);
|
referenceDate, searchStrategy);
|
||||||
@@ -645,7 +638,7 @@ public class StaticData {
|
|||||||
private PaperCard tryToGetCardPrintWithMatchingFrame(PaperCard altCard,
|
private PaperCard tryToGetCardPrintWithMatchingFrame(PaperCard altCard,
|
||||||
boolean isCardArtPreferenceLatestArt,
|
boolean isCardArtPreferenceLatestArt,
|
||||||
boolean cardArtHasFilter,
|
boolean cardArtHasFilter,
|
||||||
boolean preferModernFrame){
|
boolean preferModernFrame) {
|
||||||
CardEdition altCardEdition = editions.get(altCard.getEdition());
|
CardEdition altCardEdition = editions.get(altCard.getEdition());
|
||||||
boolean frameIsCompliantAlready = (altCardEdition.isModern() == preferModernFrame);
|
boolean frameIsCompliantAlready = (altCardEdition.isModern() == preferModernFrame);
|
||||||
if (frameIsCompliantAlready)
|
if (frameIsCompliantAlready)
|
||||||
@@ -654,7 +647,7 @@ public class StaticData {
|
|||||||
CardDb.CardArtPreference searchStrategy = getSearchStrategyForAlternativeCardArt(searchStrategyFlag,
|
CardDb.CardArtPreference searchStrategy = getSearchStrategyForAlternativeCardArt(searchStrategyFlag,
|
||||||
cardArtHasFilter);
|
cardArtHasFilter);
|
||||||
PaperCard altCandidate = altCard;
|
PaperCard altCandidate = altCard;
|
||||||
while (altCandidate != null){
|
while (altCandidate != null) {
|
||||||
Date referenceDate = editions.get(altCandidate.getEdition()).getDate();
|
Date referenceDate = editions.get(altCandidate.getEdition()).getDate();
|
||||||
altCandidate = this.searchAlternativeCardCandidate(altCandidate, preferModernFrame,
|
altCandidate = this.searchAlternativeCardCandidate(altCandidate, preferModernFrame,
|
||||||
referenceDate, searchStrategy);
|
referenceDate, searchStrategy);
|
||||||
@@ -677,7 +670,7 @@ public class StaticData {
|
|||||||
* @param card Instance of target <code>PaperCard</code>
|
* @param card Instance of target <code>PaperCard</code>
|
||||||
* @return The number of available arts for the given card in the corresponding set, or 0 if not found.
|
* @return The number of available arts for the given card in the corresponding set, or 0 if not found.
|
||||||
*/
|
*/
|
||||||
public int getCardArtCount(PaperCard card){
|
public int getCardArtCount(PaperCard card) {
|
||||||
Collection<CardDb> databases = this.getAvailableDatabases().values();
|
Collection<CardDb> databases = this.getAvailableDatabases().values();
|
||||||
for (CardDb db: databases){
|
for (CardDb db: databases){
|
||||||
int artCount = db.getArtCount(card.getName(), card.getEdition());
|
int artCount = db.getArtCount(card.getName(), card.getEdition());
|
||||||
@@ -687,9 +680,12 @@ public class StaticData {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getFilteredHandsEnabled(){
|
public boolean getFilteredHandsEnabled() {
|
||||||
return filteredHandsEnabled;
|
return filteredHandsEnabled;
|
||||||
}
|
}
|
||||||
|
public void setFilteredHandsEnabled(boolean filteredHandsEnabled) {
|
||||||
|
this.filteredHandsEnabled = filteredHandsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
public void setMulliganRule(MulliganDefs.MulliganRule rule) {
|
public void setMulliganRule(MulliganDefs.MulliganRule rule) {
|
||||||
mulliganRule = rule;
|
mulliganRule = rule;
|
||||||
@@ -699,21 +695,21 @@ public class StaticData {
|
|||||||
return mulliganRule;
|
return mulliganRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCardArtPreference(boolean latestArt, boolean coreExpansionOnly){
|
public void setCardArtPreference(boolean latestArt, boolean coreExpansionOnly) {
|
||||||
this.commonCards.setCardArtPreference(latestArt, coreExpansionOnly);
|
this.commonCards.setCardArtPreference(latestArt, coreExpansionOnly);
|
||||||
this.variantCards.setCardArtPreference(latestArt, coreExpansionOnly);
|
this.variantCards.setCardArtPreference(latestArt, coreExpansionOnly);
|
||||||
this.customCards.setCardArtPreference(latestArt, coreExpansionOnly);
|
this.customCards.setCardArtPreference(latestArt, coreExpansionOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCardArtPreferenceName(){
|
public String getCardArtPreferenceName() {
|
||||||
return this.commonCards.getCardArtPreference().toString();
|
return this.commonCards.getCardArtPreference().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardDb.CardArtPreference getCardArtPreference(){
|
public CardDb.CardArtPreference getCardArtPreference() {
|
||||||
return this.commonCards.getCardArtPreference();
|
return this.commonCards.getCardArtPreference();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardDb.CardArtPreference getCardArtPreference(boolean latestArt, boolean coreExpansionOnly){
|
public CardDb.CardArtPreference getCardArtPreference(boolean latestArt, boolean coreExpansionOnly) {
|
||||||
if (latestArt){
|
if (latestArt){
|
||||||
return coreExpansionOnly ? CardDb.CardArtPreference.LATEST_ART_CORE_EXPANSIONS_REPRINT_ONLY : CardDb.CardArtPreference.LATEST_ART_ALL_EDITIONS;
|
return coreExpansionOnly ? CardDb.CardArtPreference.LATEST_ART_CORE_EXPANSIONS_REPRINT_ONLY : CardDb.CardArtPreference.LATEST_ART_ALL_EDITIONS;
|
||||||
}
|
}
|
||||||
@@ -721,15 +717,15 @@ public class StaticData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isCoreExpansionOnlyFilterSet(){ return this.commonCards.getCardArtPreference().filterSets; }
|
public boolean isCoreExpansionOnlyFilterSet() { return this.commonCards.getCardArtPreference().filterSets; }
|
||||||
|
|
||||||
public boolean cardArtPreferenceIsLatest(){
|
public boolean cardArtPreferenceIsLatest() {
|
||||||
return this.commonCards.getCardArtPreference().latestFirst;
|
return this.commonCards.getCardArtPreference().latestFirst;
|
||||||
}
|
}
|
||||||
|
|
||||||
// === MOBILE APP Alternative Methods (using String Labels, not yet localised!!) ===
|
// === MOBILE APP Alternative Methods (using String Labels, not yet localised!!) ===
|
||||||
// Note: only used in mobile
|
// Note: only used in mobile
|
||||||
public String[] getCardArtAvailablePreferences(){
|
public String[] getCardArtAvailablePreferences() {
|
||||||
CardDb.CardArtPreference[] preferences = CardDb.CardArtPreference.values();
|
CardDb.CardArtPreference[] preferences = CardDb.CardArtPreference.values();
|
||||||
String[] preferences_avails = new String[preferences.length];
|
String[] preferences_avails = new String[preferences.length];
|
||||||
for (int i = 0; i < preferences.length; i++)
|
for (int i = 0; i < preferences.length; i++)
|
||||||
@@ -745,17 +741,16 @@ public class StaticData {
|
|||||||
return label.toString().trim();
|
return label.toString().trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCardArtPreference(String artPreference){
|
public void setCardArtPreference(String artPreference) {
|
||||||
this.commonCards.setCardArtPreference(artPreference);
|
this.commonCards.setCardArtPreference(artPreference);
|
||||||
this.variantCards.setCardArtPreference(artPreference);
|
this.variantCards.setCardArtPreference(artPreference);
|
||||||
this.customCards.setCardArtPreference(artPreference);
|
this.customCards.setCardArtPreference(artPreference);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
public boolean isEnabledCardArtSmartSelection() {
|
||||||
public boolean isEnabledCardArtSmartSelection(){
|
|
||||||
return this.enableSmartCardArtSelection;
|
return this.enableSmartCardArtSelection;
|
||||||
}
|
}
|
||||||
public void setEnableSmartCardArtSelection(boolean isEnabled){
|
public void setEnableSmartCardArtSelection(boolean isEnabled) {
|
||||||
this.enableSmartCardArtSelection = isEnabled;
|
this.enableSmartCardArtSelection = isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
|
|
||||||
public void add(final String cardRequest, final int amount) {
|
public void add(final String cardRequest, final int amount) {
|
||||||
CardDb.CardRequest request = CardDb.CardRequest.fromString(cardRequest);
|
CardDb.CardRequest request = CardDb.CardRequest.fromString(cardRequest);
|
||||||
this.add(request.cardName, request.edition, request.artIndex, amount);
|
this.add(CardDb.CardRequest.compose(request.cardName, request.isFoil), request.edition, request.artIndex, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(final String cardName, final String setCode) {
|
public void add(final String cardName, final String setCode) {
|
||||||
@@ -100,7 +100,7 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
paperCard = StaticData.instance().getCommonCards().getCard(cardName);
|
paperCard = StaticData.instance().getCommonCards().getCard(cardName);
|
||||||
selectedDbName = "Common";
|
selectedDbName = "Common";
|
||||||
}
|
}
|
||||||
if (paperCard == null){
|
if (paperCard == null) {
|
||||||
// after all still null
|
// after all still null
|
||||||
System.err.println("An unsupported card was requested: \"" + cardName + "\" from \"" + setCode + "\". \n");
|
System.err.println("An unsupported card was requested: \"" + cardName + "\" from \"" + setCode + "\". \n");
|
||||||
paperCard = StaticData.instance().getCommonCards().createUnsupportedCard(cardName);
|
paperCard = StaticData.instance().getCommonCards().createUnsupportedCard(cardName);
|
||||||
@@ -130,7 +130,6 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add all from a List of CardPrinted.
|
* Add all from a List of CardPrinted.
|
||||||
*
|
*
|
||||||
@@ -222,10 +221,10 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
*
|
*
|
||||||
* @see CardPool#getCardEditionStatistics(boolean)
|
* @see CardPool#getCardEditionStatistics(boolean)
|
||||||
*/
|
*/
|
||||||
public Map<CardEdition.Type, Integer> getCardEditionTypeStatistics(boolean includeBasicLands){
|
public Map<CardEdition.Type, Integer> getCardEditionTypeStatistics(boolean includeBasicLands) {
|
||||||
Map<CardEdition.Type, Integer> editionTypeStats = new HashMap<>();
|
Map<CardEdition.Type, Integer> editionTypeStats = new HashMap<>();
|
||||||
Map<CardEdition, Integer> editionStatistics = this.getCardEditionStatistics(includeBasicLands);
|
Map<CardEdition, Integer> editionStatistics = this.getCardEditionStatistics(includeBasicLands);
|
||||||
for(Entry<CardEdition, Integer> entry : editionStatistics.entrySet()) {
|
for (Entry<CardEdition, Integer> entry : editionStatistics.entrySet()) {
|
||||||
CardEdition edition = entry.getKey();
|
CardEdition edition = entry.getKey();
|
||||||
int count = entry.getValue();
|
int count = entry.getValue();
|
||||||
CardEdition.Type key = edition.getType();
|
CardEdition.Type key = edition.getType();
|
||||||
@@ -242,11 +241,11 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
*
|
*
|
||||||
* @return The most frequent CardEdition.Type in the pool, or null if the Pool is empty
|
* @return The most frequent CardEdition.Type in the pool, or null if the Pool is empty
|
||||||
*/
|
*/
|
||||||
public CardEdition.Type getTheMostFrequentEditionType(){
|
public CardEdition.Type getTheMostFrequentEditionType() {
|
||||||
Map<CardEdition.Type, Integer> editionTypeStats = this.getCardEditionTypeStatistics(false);
|
Map<CardEdition.Type, Integer> editionTypeStats = this.getCardEditionTypeStatistics(false);
|
||||||
Integer mostFrequentType = 0;
|
Integer mostFrequentType = 0;
|
||||||
List<CardEdition.Type> mostFrequentEditionTypes = new ArrayList<>();
|
List<CardEdition.Type> mostFrequentEditionTypes = new ArrayList<>();
|
||||||
for (Map.Entry<CardEdition.Type, Integer> entry : editionTypeStats.entrySet()){
|
for (Map.Entry<CardEdition.Type, Integer> entry : editionTypeStats.entrySet()) {
|
||||||
if (entry.getValue() > mostFrequentType) {
|
if (entry.getValue() > mostFrequentType) {
|
||||||
mostFrequentType = entry.getValue();
|
mostFrequentType = entry.getValue();
|
||||||
mostFrequentEditionTypes.add(entry.getKey());
|
mostFrequentEditionTypes.add(entry.getKey());
|
||||||
@@ -271,11 +270,11 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
* If the count of Modern and PreModern cards is tied, the return value is determined
|
* If the count of Modern and PreModern cards is tied, the return value is determined
|
||||||
* by the preferred Card Art Preference settings, namely True if Latest Art, False otherwise.
|
* by the preferred Card Art Preference settings, namely True if Latest Art, False otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isModern(){
|
public boolean isModern() {
|
||||||
int modernEditionsCount = 0;
|
int modernEditionsCount = 0;
|
||||||
int preModernEditionsCount = 0;
|
int preModernEditionsCount = 0;
|
||||||
Map<CardEdition, Integer> editionStats = this.getCardEditionStatistics(false);
|
Map<CardEdition, Integer> editionStats = this.getCardEditionStatistics(false);
|
||||||
for (Map.Entry<CardEdition, Integer> entry: editionStats.entrySet()){
|
for (Map.Entry<CardEdition, Integer> entry: editionStats.entrySet()) {
|
||||||
CardEdition edition = entry.getKey();
|
CardEdition edition = entry.getKey();
|
||||||
if (edition.isModern())
|
if (edition.isModern())
|
||||||
modernEditionsCount += entry.getValue();
|
modernEditionsCount += entry.getValue();
|
||||||
@@ -364,7 +363,7 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
private static int getMedianFrequency(List<Integer> frequencyValues, float meanFrequency) {
|
private static int getMedianFrequency(List<Integer> frequencyValues, float meanFrequency) {
|
||||||
int medianFrequency = frequencyValues.get(0);
|
int medianFrequency = frequencyValues.get(0);
|
||||||
float refDelta = Math.abs(meanFrequency - medianFrequency);
|
float refDelta = Math.abs(meanFrequency - medianFrequency);
|
||||||
for (int i = 1; i < frequencyValues.size(); i++){
|
for (int i = 1; i < frequencyValues.size(); i++) {
|
||||||
int currentFrequency = frequencyValues.get(i);
|
int currentFrequency = frequencyValues.get(i);
|
||||||
float delta = Math.abs(meanFrequency - currentFrequency);
|
float delta = Math.abs(meanFrequency - currentFrequency);
|
||||||
if (delta < refDelta) {
|
if (delta < refDelta) {
|
||||||
@@ -411,7 +410,7 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Pair<String, Integer>> processCardList(final Iterable<String> lines){
|
public static List<Pair<String, Integer>> processCardList(final Iterable<String> lines) {
|
||||||
List<Pair<String, Integer>> cardRequests = new ArrayList<>();
|
List<Pair<String, Integer>> cardRequests = new ArrayList<>();
|
||||||
if (lines == null)
|
if (lines == null)
|
||||||
return cardRequests; // empty list
|
return cardRequests; // empty list
|
||||||
@@ -466,7 +465,7 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
public CardPool getFilteredPool(Predicate<PaperCard> predicate) {
|
public CardPool getFilteredPool(Predicate<PaperCard> predicate) {
|
||||||
CardPool filteredPool = new CardPool();
|
CardPool filteredPool = new CardPool();
|
||||||
Iterator<PaperCard> cardsInPool = this.items.keySet().iterator();
|
Iterator<PaperCard> cardsInPool = this.items.keySet().iterator();
|
||||||
while (cardsInPool.hasNext()){
|
while (cardsInPool.hasNext()) {
|
||||||
PaperCard c = cardsInPool.next();
|
PaperCard c = cardsInPool.next();
|
||||||
if (predicate.apply(c))
|
if (predicate.apply(c))
|
||||||
filteredPool.add(c, this.items.get(c));
|
filteredPool.add(c, this.items.get(c));
|
||||||
@@ -479,12 +478,12 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
* @param predicate the Predicate to apply to this CardPool
|
* @param predicate the Predicate to apply to this CardPool
|
||||||
* @return a new CardPool made from this CardPool with only the cards that agree with the provided Predicate
|
* @return a new CardPool made from this CardPool with only the cards that agree with the provided Predicate
|
||||||
*/
|
*/
|
||||||
public CardPool getFilteredPoolWithCardsCount(Predicate<PaperCard> predicate){
|
public CardPool getFilteredPoolWithCardsCount(Predicate<PaperCard> predicate) {
|
||||||
CardPool filteredPool = new CardPool();
|
CardPool filteredPool = new CardPool();
|
||||||
for(Entry<PaperCard, Integer> entry : this.items.entrySet()){
|
for (Entry<PaperCard, Integer> entry : this.items.entrySet()) {
|
||||||
PaperCard pc = entry.getKey();
|
PaperCard pc = entry.getKey();
|
||||||
int count = entry.getValue();
|
int count = entry.getValue();
|
||||||
if(predicate.apply(pc))
|
if (predicate.apply(pc))
|
||||||
filteredPool.add(pc, count);
|
filteredPool.add(pc, count);
|
||||||
}
|
}
|
||||||
return filteredPool;
|
return filteredPool;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import forge.card.CardDb;
|
|||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.item.IPaperCard;
|
import forge.item.IPaperCard;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -216,7 +217,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadDeferredSections() {
|
private void loadDeferredSections() {
|
||||||
if ((deferredSections == null) && (loadedSections == null))
|
if (deferredSections == null && loadedSections == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (loadedSections != null && !includeCardsFromUnspecifiedSet)
|
if (loadedSections != null && !includeCardsFromUnspecifiedSet)
|
||||||
@@ -236,8 +237,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
if (deferredSections != null) {
|
if (deferredSections != null) {
|
||||||
this.validateDeferredSections();
|
this.validateDeferredSections();
|
||||||
referenceDeckLoadingMap = new HashMap<>(this.deferredSections);
|
referenceDeckLoadingMap = new HashMap<>(this.deferredSections);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
referenceDeckLoadingMap = new HashMap<>(loadedSections);
|
referenceDeckLoadingMap = new HashMap<>(loadedSections);
|
||||||
|
|
||||||
loadedSections = new HashMap<>();
|
loadedSections = new HashMap<>();
|
||||||
@@ -255,7 +255,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
continue;
|
continue;
|
||||||
final List<String> cardsInSection = s.getValue();
|
final List<String> cardsInSection = s.getValue();
|
||||||
ArrayList<String> cardNamesWithNoEdition = getAllCardNamesWithNoSpecifiedEdition(cardsInSection);
|
ArrayList<String> cardNamesWithNoEdition = getAllCardNamesWithNoSpecifiedEdition(cardsInSection);
|
||||||
if (cardNamesWithNoEdition.size() > 0){
|
if (cardNamesWithNoEdition.size() > 0) {
|
||||||
includeCardsFromUnspecifiedSet = true;
|
includeCardsFromUnspecifiedSet = true;
|
||||||
if (smartCardArtSelection)
|
if (smartCardArtSelection)
|
||||||
cardsWithNoEdition.put(sec, cardNamesWithNoEdition);
|
cardsWithNoEdition.put(sec, cardNamesWithNoEdition);
|
||||||
@@ -267,10 +267,9 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
deferredSections = null; // set to null, just in case!
|
deferredSections = null; // set to null, just in case!
|
||||||
if (includeCardsFromUnspecifiedSet && smartCardArtSelection)
|
if (includeCardsFromUnspecifiedSet && smartCardArtSelection)
|
||||||
optimiseCardArtSelectionInDeckSections(cardsWithNoEdition);
|
optimiseCardArtSelectionInDeckSections(cardsWithNoEdition);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateDeferredSections(){
|
private void validateDeferredSections() {
|
||||||
/*
|
/*
|
||||||
Construct a temporary (DeckSection, CardPool) Maps, to be sanitised and finalised
|
Construct a temporary (DeckSection, CardPool) Maps, to be sanitised and finalised
|
||||||
before copying into `this.parts`. This sanitisation is applied because of the
|
before copying into `this.parts`. This sanitisation is applied because of the
|
||||||
@@ -285,6 +284,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
}
|
}
|
||||||
|
|
||||||
final List<String> cardsInSection = s.getValue();
|
final List<String> cardsInSection = s.getValue();
|
||||||
|
List<Pair<String, Integer>> originalCardRequests = CardPool.processCardList(cardsInSection);
|
||||||
CardPool pool = CardPool.fromCardList(cardsInSection);
|
CardPool pool = CardPool.fromCardList(cardsInSection);
|
||||||
if (pool.countDistinct() == 0)
|
if (pool.countDistinct() == 0)
|
||||||
continue; // pool empty, no card has been found!
|
continue; // pool empty, no card has been found!
|
||||||
@@ -301,13 +301,12 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
if (whiteList == null)
|
if (whiteList == null)
|
||||||
whiteList = new ArrayList<>();
|
whiteList = new ArrayList<>();
|
||||||
for (Entry<PaperCard, Integer> entry : filteredPool) {
|
for (Entry<PaperCard, Integer> entry : filteredPool) {
|
||||||
String poolRequest = getPoolRequest(entry);
|
String poolRequest = getPoolRequest(entry, originalCardRequests);
|
||||||
whiteList.add(poolRequest);
|
whiteList.add(poolRequest);
|
||||||
}
|
}
|
||||||
validatedSections.put(s.getKey(), whiteList);
|
validatedSections.put(s.getKey(), whiteList);
|
||||||
|
|
||||||
if (filteredPool.countDistinct() != pool.countDistinct()){
|
if (filteredPool.countDistinct() != pool.countDistinct()) {
|
||||||
|
|
||||||
CardPool blackList = pool.getFilteredPoolWithCardsCount(new Predicate<PaperCard>() {
|
CardPool blackList = pool.getFilteredPoolWithCardsCount(new Predicate<PaperCard>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(PaperCard input) {
|
public boolean apply(PaperCard input) {
|
||||||
@@ -317,7 +316,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
|
|
||||||
for (Entry<PaperCard, Integer> entry : blackList) {
|
for (Entry<PaperCard, Integer> entry : blackList) {
|
||||||
DeckSection cardSection = DeckSection.matchingSection(entry.getKey());
|
DeckSection cardSection = DeckSection.matchingSection(entry.getKey());
|
||||||
String poolRequest = getPoolRequest(entry);
|
String poolRequest = getPoolRequest(entry, originalCardRequests);
|
||||||
List<String> sectionCardList = validatedSections.getOrDefault(cardSection.name(), null);
|
List<String> sectionCardList = validatedSections.getOrDefault(cardSection.name(), null);
|
||||||
if (sectionCardList == null)
|
if (sectionCardList == null)
|
||||||
sectionCardList = new ArrayList<>();
|
sectionCardList = new ArrayList<>();
|
||||||
@@ -331,11 +330,26 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
this.deferredSections = validatedSections;
|
this.deferredSections = validatedSections;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPoolRequest(Entry<PaperCard, Integer> entry) {
|
private String getPoolRequest(Entry<PaperCard, Integer> entry, List<Pair<String, Integer>> originalCardRequests) {
|
||||||
PaperCard card = entry.getKey();
|
PaperCard card = entry.getKey();
|
||||||
int amount = entry.getValue();
|
int amount = entry.getValue();
|
||||||
String cardRequest = CardDb.CardRequest.compose(card.getName(), card.getEdition(), card.getArtIndex());
|
String poolCardRequest = CardDb.CardRequest.compose(
|
||||||
return String.format("%d %s", amount, cardRequest);
|
card.isFoil() ? CardDb.CardRequest.compose(card.getName(), true) : card.getName(),
|
||||||
|
card.getEdition(), card.getArtIndex());
|
||||||
|
String originalRequestCandidate = null;
|
||||||
|
for (Pair<String, Integer> originalRequest : originalCardRequests){
|
||||||
|
String cardRequest = originalRequest.getLeft();
|
||||||
|
if (!StringUtils.startsWithIgnoreCase(poolCardRequest, cardRequest))
|
||||||
|
continue;
|
||||||
|
originalRequestCandidate = cardRequest;
|
||||||
|
int cardAmount = originalRequest.getRight();
|
||||||
|
if (amount == cardAmount)
|
||||||
|
return String.format("%d %s", cardAmount, cardRequest);
|
||||||
|
}
|
||||||
|
// This is just in case, it should never happen as we're
|
||||||
|
if (originalRequestCandidate != null)
|
||||||
|
return String.format("%d %s", amount, originalRequestCandidate);
|
||||||
|
return String.format("%d %s", amount, poolCardRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<String> getAllCardNamesWithNoSpecifiedEdition(List<String> cardsInSection) {
|
private ArrayList<String> getAllCardNamesWithNoSpecifiedEdition(List<String> cardsInSection) {
|
||||||
@@ -356,9 +370,9 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
boolean isCardArtPreferenceLatestArt = data.cardArtPreferenceIsLatest();
|
boolean isCardArtPreferenceLatestArt = data.cardArtPreferenceIsLatest();
|
||||||
boolean cardArtPreferenceHasFilter = data.isCoreExpansionOnlyFilterSet();
|
boolean cardArtPreferenceHasFilter = data.isCoreExpansionOnlyFilterSet();
|
||||||
|
|
||||||
for(Entry<DeckSection, CardPool> part : parts.entrySet()) {
|
for (Entry<DeckSection, CardPool> part : parts.entrySet()) {
|
||||||
DeckSection deckSection = part.getKey();
|
DeckSection deckSection = part.getKey();
|
||||||
if(deckSection == DeckSection.Planes || deckSection == DeckSection.Schemes || deckSection == DeckSection.Avatar)
|
if (deckSection != DeckSection.Main && deckSection != DeckSection.Sideboard && deckSection != DeckSection.Commander)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// == 0. First Off, check if there is anything at all to do for the current section
|
// == 0. First Off, check if there is anything at all to do for the current section
|
||||||
@@ -432,7 +446,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
cardsPerArtIndex = Math.max(1, cardsPerArtIndex); // make sure is never zero
|
cardsPerArtIndex = Math.max(1, cardsPerArtIndex); // make sure is never zero
|
||||||
int cardsAdded = 0;
|
int cardsAdded = 0;
|
||||||
PaperCard alternativeCardArt = null;
|
PaperCard alternativeCardArt = null;
|
||||||
for (int artIndex = 1; artIndex <= nrOfAvailableArts; artIndex++){
|
for (int artIndex = 1; artIndex <= nrOfAvailableArts; artIndex++) {
|
||||||
alternativeCardArt = data.getOrLoadCommonCard(cardName, setCode, artIndex, isFoil);
|
alternativeCardArt = data.getOrLoadCommonCard(cardName, setCode, artIndex, isFoil);
|
||||||
cardsAdded += cardsPerArtIndex;
|
cardsAdded += cardsPerArtIndex;
|
||||||
pool.add(alternativeCardArt, cardsPerArtIndex);
|
pool.add(alternativeCardArt, cardsPerArtIndex);
|
||||||
@@ -461,7 +475,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
|
|
||||||
if (card.getRules().isVariant())
|
if (card.getRules().isVariant())
|
||||||
return false; // skip variant cards
|
return false; // skip variant cards
|
||||||
if (StaticData.instance().getCommonCards().hasPreferredArt(card.getName())){
|
if (StaticData.instance().getCommonCards().hasPreferredArt(card.getName())) {
|
||||||
// if there is any preferred art, never update it!
|
// if there is any preferred art, never update it!
|
||||||
CardDb.CardRequest request = CardDb.CardRequest.fromString(card.getName());
|
CardDb.CardRequest request = CardDb.CardRequest.fromString(card.getName());
|
||||||
if (request.edition.equals(card.getEdition()) && request.artIndex == card.getArtIndex())
|
if (request.edition.equals(card.getEdition()) && request.artIndex == card.getArtIndex())
|
||||||
@@ -478,8 +492,6 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
return releaseDate.compareTo(referenceReleaseDate) < 0;
|
return releaseDate.compareTo(referenceReleaseDate) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static final Function<Deck, String> FN_NAME_SELECTOR = new Function<Deck, String>() {
|
public static final Function<Deck, String> FN_NAME_SELECTOR = new Function<Deck, String>() {
|
||||||
@Override
|
@Override
|
||||||
public String apply(Deck arg1) {
|
public String apply(Deck arg1) {
|
||||||
|
|||||||
@@ -123,6 +123,14 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
|||||||
}
|
}
|
||||||
return this.foiledVersion;
|
return this.foiledVersion;
|
||||||
}
|
}
|
||||||
|
public PaperCard getUnFoiled() {
|
||||||
|
if (!this.foil)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
PaperCard unFoiledVersion = new PaperCard(this.rules, this.edition, this.rarity,
|
||||||
|
this.artIndex, false, String.valueOf(collectorNumber), this.artist);
|
||||||
|
return unFoiledVersion;
|
||||||
|
}
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
// public String getImageKey() {
|
// public String getImageKey() {
|
||||||
@@ -260,7 +268,6 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
|||||||
return sortableCNKey;
|
return sortableCNKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(final IPaperCard o) {
|
public int compareTo(final IPaperCard o) {
|
||||||
final int nameCmp = name.compareToIgnoreCase(o.getName());
|
final int nameCmp = name.compareToIgnoreCase(o.getName());
|
||||||
|
|||||||
@@ -830,7 +830,7 @@ public class Game {
|
|||||||
c.removeTempController(p);
|
c.removeTempController(p);
|
||||||
// return stolen spells
|
// return stolen spells
|
||||||
if (c.isInZone(ZoneType.Stack)) {
|
if (c.isInZone(ZoneType.Stack)) {
|
||||||
SpellAbilityStackInstance si = getStack().getInstanceFromSpellAbility(c.getCastSA());
|
SpellAbilityStackInstance si = getStack().getInstanceMatchingSpellAbilityID(c.getCastSA());
|
||||||
si.setActivatingPlayer(c.getController());
|
si.setActivatingPlayer(c.getController());
|
||||||
}
|
}
|
||||||
if (c.getController().equals(p)) {
|
if (c.getController().equals(p)) {
|
||||||
@@ -854,7 +854,7 @@ public class Game {
|
|||||||
|
|
||||||
if (p != null && p.isMonarch()) {
|
if (p != null && p.isMonarch()) {
|
||||||
// if the player who lost was the Monarch, someone else will be the monarch
|
// if the player who lost was the Monarch, someone else will be the monarch
|
||||||
if(p.equals(getPhaseHandler().getPlayerTurn())) {
|
if (p.equals(getPhaseHandler().getPlayerTurn())) {
|
||||||
getAction().becomeMonarch(getNextPlayerAfter(p), null);
|
getAction().becomeMonarch(getNextPlayerAfter(p), null);
|
||||||
} else {
|
} else {
|
||||||
getAction().becomeMonarch(getPhaseHandler().getPlayerTurn(), null);
|
getAction().becomeMonarch(getPhaseHandler().getPlayerTurn(), null);
|
||||||
|
|||||||
@@ -997,6 +997,9 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void ceaseToExist(Card c, boolean skipTrig) {
|
public void ceaseToExist(Card c, boolean skipTrig) {
|
||||||
|
if (c.isInZone(ZoneType.Stack)) {
|
||||||
|
c.getGame().getStack().remove(c);
|
||||||
|
}
|
||||||
c.getZone().remove(c);
|
c.getZone().remove(c);
|
||||||
|
|
||||||
// CR 603.6c other players LTB triggers should work
|
// CR 603.6c other players LTB triggers should work
|
||||||
|
|||||||
@@ -1,24 +1,7 @@
|
|||||||
package forge.game;
|
package forge.game;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import com.google.common.collect.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
|
||||||
import com.google.common.collect.HashMultimap;
|
|
||||||
import com.google.common.collect.HashMultiset;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
import com.google.common.collect.Multiset;
|
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
|
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
@@ -40,7 +23,11 @@ import forge.util.Localizer;
|
|||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
import forge.util.collect.FCollectionView;
|
import forge.util.collect.FCollectionView;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
public class Match {
|
public class Match {
|
||||||
|
private static List<PaperCard> removedCards = Lists.newArrayList();
|
||||||
private final List<RegisteredPlayer> players;
|
private final List<RegisteredPlayer> players;
|
||||||
private final GameRules rules;
|
private final GameRules rules;
|
||||||
private final String title;
|
private final String title;
|
||||||
@@ -198,6 +185,12 @@ public class Match {
|
|||||||
return myRemovedAnteCards;
|
return myRemovedAnteCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<PaperCard> getRemovedCards() { return removedCards; }
|
||||||
|
|
||||||
|
public void removeCard(PaperCard c) {
|
||||||
|
removedCards.add(c);
|
||||||
|
}
|
||||||
|
|
||||||
private static void preparePlayerZone(Player player, final ZoneType zoneType, CardPool section, boolean canRandomFoil) {
|
private static void preparePlayerZone(Player player, final ZoneType zoneType, CardPool section, boolean canRandomFoil) {
|
||||||
PlayerZone library = player.getZone(zoneType);
|
PlayerZone library = player.getZone(zoneType);
|
||||||
List<Card> newLibrary = new ArrayList<>();
|
List<Card> newLibrary = new ArrayList<>();
|
||||||
@@ -257,6 +250,23 @@ public class Match {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Deck toChange = psc.getDeck();
|
Deck toChange = psc.getDeck();
|
||||||
|
if (!getRemovedCards().isEmpty()) {
|
||||||
|
CardPool main = new CardPool();
|
||||||
|
main.addAll(toChange.get(DeckSection.Main));
|
||||||
|
CardPool sideboard = new CardPool();
|
||||||
|
sideboard.addAll(toChange.getOrCreate(DeckSection.Sideboard));
|
||||||
|
for (PaperCard c : removedCards) {
|
||||||
|
if (main.contains(c)) {
|
||||||
|
main.remove(c, 1);
|
||||||
|
} else if (sideboard.contains(c)) {
|
||||||
|
sideboard.remove(c, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toChange.getMain().clear();
|
||||||
|
toChange.getMain().addAll(main);
|
||||||
|
toChange.get(DeckSection.Sideboard).clear();
|
||||||
|
toChange.get(DeckSection.Sideboard).addAll(sideboard);
|
||||||
|
}
|
||||||
List<PaperCard> newMain = person.sideboard(toChange, rules.getGameType(), player.getName());
|
List<PaperCard> newMain = person.sideboard(toChange, rules.getGameType(), player.getName());
|
||||||
if (null != newMain) {
|
if (null != newMain) {
|
||||||
CardPool allCards = new CardPool();
|
CardPool allCards = new CardPool();
|
||||||
|
|||||||
@@ -1789,7 +1789,7 @@ public class AbilityUtils {
|
|||||||
if (sq[0].contains("HasNumChosenColors")) {
|
if (sq[0].contains("HasNumChosenColors")) {
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
for (Card card : getDefinedCards(c, sq[1], sa)) {
|
for (Card card : getDefinedCards(c, sq[1], sa)) {
|
||||||
sum += CardUtil.getColors(card).getSharedColors(ColorSet.fromNames(c.getChosenColors())).countColors();
|
sum += card.determineColor().getSharedColors(ColorSet.fromNames(c.getChosenColors())).countColors();
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
@@ -1990,7 +1990,7 @@ public class AbilityUtils {
|
|||||||
|
|
||||||
// Count$CardMulticolor.<numMC>.<numNotMC>
|
// Count$CardMulticolor.<numMC>.<numNotMC>
|
||||||
if (sq[0].contains("CardMulticolor")) {
|
if (sq[0].contains("CardMulticolor")) {
|
||||||
final boolean isMulti = CardUtil.getColors(c).isMulticolor();
|
final boolean isMulti = c.determineColor().isMulticolor();
|
||||||
return doXMath(Integer.parseInt(sq[isMulti ? 1 : 2]), expr, c, ctb);
|
return doXMath(Integer.parseInt(sq[isMulti ? 1 : 2]), expr, c, ctb);
|
||||||
}
|
}
|
||||||
// Count$Madness.<True>.<False>
|
// Count$Madness.<True>.<False>
|
||||||
@@ -2046,7 +2046,7 @@ public class AbilityUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("CardNumColors")) {
|
if (sq[0].contains("CardNumColors")) {
|
||||||
return doXMath(CardUtil.getColors(c).countColors(), expr, c, ctb);
|
return doXMath(c.determineColor().countColors(), expr, c, ctb);
|
||||||
}
|
}
|
||||||
if (sq[0].contains("CardNumAttacksThisTurn")) {
|
if (sq[0].contains("CardNumAttacksThisTurn")) {
|
||||||
return doXMath(c.getDamageHistory().getCreatureAttacksThisTurn(), expr, c, ctb);
|
return doXMath(c.getDamageHistory().getCreatureAttacksThisTurn(), expr, c, ctb);
|
||||||
@@ -3766,7 +3766,7 @@ public class AbilityUtils {
|
|||||||
someCards = CardLists.filter(someCards, new Predicate<Card>() {
|
someCards = CardLists.filter(someCards, new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
return CardUtil.getColors(c).isMulticolor();
|
return c.determineColor().isMulticolor();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -3775,7 +3775,7 @@ public class AbilityUtils {
|
|||||||
someCards = CardLists.filter(someCards, new Predicate<Card>() {
|
someCards = CardLists.filter(someCards, new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
return CardUtil.getColors(c).isMonoColor();
|
return c.determineColor().isMonoColor();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ public enum ApiType {
|
|||||||
Explore (ExploreEffect.class),
|
Explore (ExploreEffect.class),
|
||||||
Fight (FightEffect.class),
|
Fight (FightEffect.class),
|
||||||
FlipACoin (FlipCoinEffect.class),
|
FlipACoin (FlipCoinEffect.class),
|
||||||
|
FlipOntoBattlefield (FlipOntoBattlefieldEffect.class),
|
||||||
Fog (FogEffect.class),
|
Fog (FogEffect.class),
|
||||||
GainControl (ControlGainEffect.class),
|
GainControl (ControlGainEffect.class),
|
||||||
GainControlVariant (ControlGainVariantEffect.class),
|
GainControlVariant (ControlGainVariantEffect.class),
|
||||||
@@ -139,6 +140,7 @@ public enum ApiType {
|
|||||||
RemoveCounterAll (CountersRemoveAllEffect.class),
|
RemoveCounterAll (CountersRemoveAllEffect.class),
|
||||||
RemoveFromCombat (RemoveFromCombatEffect.class),
|
RemoveFromCombat (RemoveFromCombatEffect.class),
|
||||||
RemoveFromGame (RemoveFromGameEffect.class),
|
RemoveFromGame (RemoveFromGameEffect.class),
|
||||||
|
RemoveFromMatch (RemoveFromMatchEffect.class),
|
||||||
ReorderZone (ReorderZoneEffect.class),
|
ReorderZone (ReorderZoneEffect.class),
|
||||||
Repeat (RepeatEffect.class),
|
Repeat (RepeatEffect.class),
|
||||||
RepeatEach (RepeatEachEffect.class),
|
RepeatEach (RepeatEachEffect.class),
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.google.common.collect.Lists;
|
|||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardUtil;
|
||||||
import forge.game.event.GameEventCardModeChosen;
|
import forge.game.event.GameEventCardModeChosen;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -81,6 +82,19 @@ public class ChooseGenericEffect extends SpellAbilityEffect {
|
|||||||
chosenSAs = p.getController().chooseSpellAbilitiesForEffect(abilities, sa, prompt, amount, ImmutableMap.of());
|
chosenSAs = p.getController().chooseSpellAbilitiesForEffect(abilities, sa, prompt, amount, ImmutableMap.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (SpellAbility chosenSA : chosenSAs) {
|
||||||
|
if (sa.hasParam("AtRandom") && sa.getParam("AtRandom").equals("Urza") && chosenSA.usesTargeting()) {
|
||||||
|
List<Card> validTargets = CardUtil.getValidCardsToTarget(chosenSA.getTargetRestrictions(), sa);
|
||||||
|
if (validTargets.isEmpty()) {
|
||||||
|
List <SpellAbility> newChosenSAs = Lists.newArrayList();
|
||||||
|
Aggregates.random(abilities, amount, newChosenSAs);
|
||||||
|
chosenSAs = newChosenSAs;
|
||||||
|
} else {
|
||||||
|
p.getController().chooseTargetsFor(chosenSA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!chosenSAs.isEmpty()) {
|
if (!chosenSAs.isEmpty()) {
|
||||||
for (SpellAbility chosenSA : chosenSAs) {
|
for (SpellAbility chosenSA : chosenSAs) {
|
||||||
String chosenValue = chosenSA.getDescription();
|
String chosenValue = chosenSA.getDescription();
|
||||||
|
|||||||
@@ -42,8 +42,9 @@ public class DigEffect extends SpellAbilityEffect {
|
|||||||
final int numToDig = AbilityUtils.calculateAmount(host, sa.getParam("DigNum"), sa);
|
final int numToDig = AbilityUtils.calculateAmount(host, sa.getParam("DigNum"), sa);
|
||||||
final List<Player> tgtPlayers = getTargetPlayers(sa);
|
final List<Player> tgtPlayers = getTargetPlayers(sa);
|
||||||
|
|
||||||
sb.append(host.getController()).append(" looks at the top ");
|
sb.append(host.getController()).append(sa.hasParam("Reveal") && sa.getParam("Reveal").equals("True")
|
||||||
sb.append(Lang.nounWithAmount(numToDig, "card")).append(" of ");
|
? " reveals " : " looks at ").append("the top ");
|
||||||
|
sb.append(numToDig == 1 ? "card" : (Lang.getNumeral(numToDig) + " cards")).append(" of ");
|
||||||
|
|
||||||
if (tgtPlayers.contains(host.getController())) {
|
if (tgtPlayers.contains(host.getController())) {
|
||||||
sb.append("their ");
|
sb.append("their ");
|
||||||
|
|||||||
@@ -179,12 +179,12 @@ public class DigUntilEffect extends SpellAbilityEffect {
|
|||||||
Localizer.getInstance().getMessage("lblDoYouWantPutCardToZone", foundDest.getTranslatedName()))) {
|
Localizer.getInstance().getMessage("lblDoYouWantPutCardToZone", foundDest.getTranslatedName()))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
|
||||||
|
moveParams.put(AbilityKey.LastStateBattlefield, lastStateBattlefield);
|
||||||
|
moveParams.put(AbilityKey.LastStateGraveyard, lastStateGraveyard);
|
||||||
Card m = null;
|
Card m = null;
|
||||||
if (sa.hasParam("GainControl") && foundDest.equals(ZoneType.Battlefield)) {
|
if (sa.hasParam("GainControl") && foundDest.equals(ZoneType.Battlefield)) {
|
||||||
c.setController(sa.getActivatingPlayer(), game.getNextTimestamp());
|
c.setController(sa.getActivatingPlayer(), game.getNextTimestamp());
|
||||||
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
|
|
||||||
moveParams.put(AbilityKey.LastStateBattlefield, lastStateBattlefield);
|
|
||||||
moveParams.put(AbilityKey.LastStateGraveyard, lastStateGraveyard);
|
|
||||||
m = game.getAction().moveTo(c.getController().getZone(foundDest), c, sa, moveParams);
|
m = game.getAction().moveTo(c.getController().getZone(foundDest), c, sa, moveParams);
|
||||||
if (sa.hasParam("Tapped")) {
|
if (sa.hasParam("Tapped")) {
|
||||||
c.setTapped(true);
|
c.setTapped(true);
|
||||||
@@ -195,7 +195,7 @@ public class DigUntilEffect extends SpellAbilityEffect {
|
|||||||
} else if (sa.hasParam("NoMoveFound") && foundDest.equals(ZoneType.Library)) {
|
} else if (sa.hasParam("NoMoveFound") && foundDest.equals(ZoneType.Library)) {
|
||||||
//Don't do anything
|
//Don't do anything
|
||||||
} else {
|
} else {
|
||||||
m = game.getAction().moveTo(foundDest, c, foundLibPos, sa);
|
m = game.getAction().moveTo(foundDest, c, foundLibPos, sa, moveParams);
|
||||||
}
|
}
|
||||||
revealed.remove(c);
|
revealed.remove(c);
|
||||||
if (m != null && !origin.equals(m.getZone().getZoneType())) {
|
if (m != null && !origin.equals(m.getZone().getZoneType())) {
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import forge.game.Game;
|
||||||
|
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.player.Player;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.util.Aggregates;
|
||||||
|
import forge.util.Localizer;
|
||||||
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class FlipOntoBattlefieldEffect extends SpellAbilityEffect {
|
||||||
|
@Override
|
||||||
|
public void resolve(SpellAbility sa) {
|
||||||
|
// Basic parameters defining the chances
|
||||||
|
final float chanceToFlip = 0.85f;
|
||||||
|
final int maxFlipTimes = 2;
|
||||||
|
final float chanceToHit = 0.70f;
|
||||||
|
final float chanceToHitTwoCards = 0.20f;
|
||||||
|
|
||||||
|
final Card host = sa.getHostCard();
|
||||||
|
final Player p = sa.getActivatingPlayer();
|
||||||
|
final Game game = host.getGame();
|
||||||
|
boolean flippedOnce = false;
|
||||||
|
|
||||||
|
// TODO: allow to make a bounding box of sorts somehow, ideally - upgrade to a full system allowing to actually target by location
|
||||||
|
CardCollectionView tgtBox = p.getController().chooseCardsForEffect(game.getCardsIn(ZoneType.Battlefield), sa, Localizer.getInstance().getMessage("lblChooseDesiredLocation"), 1, 1, sa.hasParam("AllowRandom"), null);
|
||||||
|
|
||||||
|
Card tgtLoc = tgtBox.getFirst();
|
||||||
|
|
||||||
|
Card lhsNeighbor = getNeighboringCard(tgtLoc, -1);
|
||||||
|
Card rhsNeighbor = getNeighboringCard(tgtLoc, 1);
|
||||||
|
|
||||||
|
CardCollection randChoices = new CardCollection();
|
||||||
|
randChoices.add(tgtLoc);
|
||||||
|
if (lhsNeighbor != null) {
|
||||||
|
randChoices.add(lhsNeighbor);
|
||||||
|
} else if (rhsNeighbor != null) {
|
||||||
|
randChoices.add(rhsNeighbor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: would be fun to add a small chance (e.g. 3-5%) to land unpredictably on some random target?
|
||||||
|
|
||||||
|
flippedOnce = MyRandom.getRandom().nextFloat() <= chanceToFlip; // 20% chance that the card won't flip even once
|
||||||
|
if (!flippedOnce) {
|
||||||
|
sa.setSVar("TimesFlipped", "0");
|
||||||
|
game.getAction().notifyOfValue(sa, host, Localizer.getInstance().getMessage("lblDidNotFlipOver"), null);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
int flippedTimes = MyRandom.getRandom().nextInt(maxFlipTimes) + 1;
|
||||||
|
sa.setSVar("TimesFlipped", String.valueOf(flippedTimes)); // Currently the exact # of times is unused
|
||||||
|
game.getAction().notifyOfValue(sa, host, Localizer.getInstance().getMessage("lblFlippedOver", flippedTimes), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose what was hit
|
||||||
|
CardCollection hit = new CardCollection();
|
||||||
|
float outcome = MyRandom.getRandom().nextFloat();
|
||||||
|
if (outcome <= chanceToHitTwoCards) {
|
||||||
|
hit.addAll(Aggregates.random(randChoices, randChoices.size() > 1 ? 2 : 1));
|
||||||
|
if (hit.size() == 2) {
|
||||||
|
game.getAction().notifyOfValue(sa, host, Localizer.getInstance().getMessage("lblLandedOnTwoCards", hit.getFirst(), hit.getLast()), null);
|
||||||
|
} else {
|
||||||
|
game.getAction().notifyOfValue(sa, host, Localizer.getInstance().getMessage("lblLandedOnOneCard", hit.getFirst()), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (outcome <= chanceToHit) {
|
||||||
|
hit.add(Aggregates.random(randChoices));
|
||||||
|
game.getAction().notifyOfValue(sa, host, Localizer.getInstance().getMessage("lblLandedOnOneCard", hit.getFirst()), null);
|
||||||
|
} else {
|
||||||
|
game.getAction().notifyOfValue(sa, host, Localizer.getInstance().getMessage("lblDidNotLandOnCards"), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember whatever was hit
|
||||||
|
for (Card c : hit) {
|
||||||
|
host.addRemembered(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getStackDescription(SpellAbility sa) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
final Card host = sa.getHostCard();
|
||||||
|
final Player p = sa.getActivatingPlayer();
|
||||||
|
|
||||||
|
sb.append("Flip ");
|
||||||
|
sb.append(host.toString());
|
||||||
|
sb.append(" onto the battlefield from a height of at least one foot.");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Card getNeighboringCard(Card c, int direction) {
|
||||||
|
// Currently gets the nearest (in zone order) card to the left or to the right of the designated one by type
|
||||||
|
Player controller = c.getController();
|
||||||
|
ArrayList<Card> cardsOTB = Lists.newArrayList(CardLists.filter(
|
||||||
|
controller.getCardsIn(ZoneType.Battlefield), new Predicate<Card>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(Card card) {
|
||||||
|
if (c.isCreature()) {
|
||||||
|
return card.isCreature();
|
||||||
|
} else if (c.isPlaneswalker() || c.isArtifact() || (c.isEnchantment() && !c.isAura())) {
|
||||||
|
return card.isPlaneswalker() || card.isArtifact() || (c.isEnchantment() && !c.isAura());
|
||||||
|
} else if (c.isLand()) {
|
||||||
|
return card.isLand();
|
||||||
|
} else if (c.isAttachedToEntity()) {
|
||||||
|
return card.isAttachedToEntity(c.getEntityAttachedTo()) || c.equals(card.getAttachedTo());
|
||||||
|
}
|
||||||
|
return card.sharesCardTypeWith(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
int loc = cardsOTB.indexOf(c);
|
||||||
|
if (direction < 0 && loc > 0) {
|
||||||
|
return cardsOTB.get(loc - 1);
|
||||||
|
} else if (loc < cardsOTB.size() - 1) {
|
||||||
|
return cardsOTB.get(loc + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -99,12 +99,8 @@ public class MillEffect extends SpellAbilityEffect {
|
|||||||
} else if (dest.equals(ZoneType.Ante)) {
|
} else if (dest.equals(ZoneType.Ante)) {
|
||||||
sb.append("antes ");
|
sb.append("antes ");
|
||||||
}
|
}
|
||||||
sb.append(numCards);
|
|
||||||
sb.append(" card");
|
sb.append(numCards == 1 ? "a card" : (Lang.getNumeral(numCards) + " cards")).append(".");
|
||||||
if (numCards != 1) {
|
|
||||||
sb.append("s");
|
|
||||||
}
|
|
||||||
sb.append(".");
|
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import forge.game.Game;
|
|||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardFactory;
|
import forge.game.card.CardFactory;
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
@@ -35,7 +34,7 @@ public class PlayLandVariantEffect extends SpellAbilityEffect {
|
|||||||
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
||||||
}
|
}
|
||||||
// current color of source card
|
// current color of source card
|
||||||
final ColorSet color = CardUtil.getColors(source);
|
final ColorSet color = source.determineColor();
|
||||||
if (color.isColorless()) {
|
if (color.isColorless()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import forge.game.ability.SpellAbilityEffect;
|
|||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -65,7 +64,7 @@ public class ProtectAllEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
} else if (sa.getParam("Gains").equals("TargetedCardColor")) {
|
} else if (sa.getParam("Gains").equals("TargetedCardColor")) {
|
||||||
for (final Card c : sa.getSATargetingCard().getTargets().getTargetCards()) {
|
for (final Card c : sa.getSATargetingCard().getTargets().getTargetCards()) {
|
||||||
ColorSet cs = CardUtil.getColors(c);
|
ColorSet cs = c.determineColor();
|
||||||
for (byte col : MagicColor.WUBRG) {
|
for (byte col : MagicColor.WUBRG) {
|
||||||
if (cs.hasAnyColor(col))
|
if (cs.hasAnyColor(col))
|
||||||
gains.add(MagicColor.toLongString(col).toLowerCase());
|
gains.add(MagicColor.toLongString(col).toLowerCase());
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
|
import forge.game.ability.AbilityUtils;
|
||||||
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardCollection;
|
||||||
|
import forge.game.event.GameEventRandomLog;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
|
||||||
|
public class RemoveFromMatchEffect extends SpellAbilityEffect {
|
||||||
|
@Override
|
||||||
|
public void resolve(SpellAbility sa) {
|
||||||
|
final Card host = sa.getHostCard();
|
||||||
|
CardCollection toRemove;
|
||||||
|
|
||||||
|
if (sa.hasParam("RemoveType")) {
|
||||||
|
CardCollection cards = (CardCollection) host.getOwner().getGame().getCardsInGame();
|
||||||
|
if (sa.hasParam("IncludeSideboard")) {
|
||||||
|
CardCollection sideboard = (CardCollection) host.getGame().getCardsIn(ZoneType.Sideboard);
|
||||||
|
cards.addAll(sideboard);
|
||||||
|
}
|
||||||
|
toRemove = (CardCollection) AbilityUtils.filterListByType(cards, sa.getParam("RemoveType"), sa);
|
||||||
|
} else {
|
||||||
|
toRemove = getTargetCards(sa);
|
||||||
|
}
|
||||||
|
String logMessage = sa.getParamOrDefault("LogMessage", "Removed from match");
|
||||||
|
String remove = toRemove.toString().replace("[","").replace("]","");
|
||||||
|
host.getController().getGame().fireEvent(new GameEventRandomLog(logMessage + ": " + remove));
|
||||||
|
for (final Card tgtC : toRemove) {
|
||||||
|
tgtC.getGame().getAction().ceaseToExist(tgtC, true);
|
||||||
|
PaperCard rem = (PaperCard) tgtC.getPaperCard();
|
||||||
|
host.getGame().getMatch().removeCard(rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,7 +51,7 @@ public class TwoPilesEffect extends SpellAbilityEffect {
|
|||||||
zone = ZoneType.smartValueOf(sa.getParam("Zone"));
|
zone = ZoneType.smartValueOf(sa.getParam("Zone"));
|
||||||
}
|
}
|
||||||
|
|
||||||
final String valid = sa.getParamOrDefault("ValidCards", "");
|
final String valid = sa.getParamOrDefault("ValidCards", "Card");
|
||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
final List<Player> tgtPlayers = getTargetPlayers(sa);
|
final List<Player> tgtPlayers = getTargetPlayers(sa);
|
||||||
|
|||||||
@@ -4937,17 +4937,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
view.updateEmblem(this);
|
view.updateEmblem(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
public final boolean isOfColor(final String col) { return determineColor().hasAnyColor(MagicColor.fromName(col)); }
|
||||||
* there are easy checkers for Color. The CardUtil functions should be made
|
public final boolean isBlack() { return determineColor().hasBlack(); }
|
||||||
* part of the Card class, so calling out is not necessary
|
public final boolean isBlue() { return determineColor().hasBlue(); }
|
||||||
*/
|
public final boolean isRed() { return determineColor().hasRed(); }
|
||||||
public final boolean isOfColor(final String col) { return CardUtil.getColors(this).hasAnyColor(MagicColor.fromName(col)); }
|
public final boolean isGreen() { return determineColor().hasGreen(); }
|
||||||
public final boolean isBlack() { return CardUtil.getColors(this).hasBlack(); }
|
public final boolean isWhite() { return determineColor().hasWhite(); }
|
||||||
public final boolean isBlue() { return CardUtil.getColors(this).hasBlue(); }
|
public final boolean isColorless() { return determineColor().isColorless(); }
|
||||||
public final boolean isRed() { return CardUtil.getColors(this).hasRed(); }
|
|
||||||
public final boolean isGreen() { return CardUtil.getColors(this).hasGreen(); }
|
|
||||||
public final boolean isWhite() { return CardUtil.getColors(this).hasWhite(); }
|
|
||||||
public final boolean isColorless() { return CardUtil.getColors(this).isColorless(); }
|
|
||||||
|
|
||||||
public final boolean sharesNameWith(final Card c1) {
|
public final boolean sharesNameWith(final Card c1) {
|
||||||
// in a corner case where c1 is null, there is no name to share with.
|
// in a corner case where c1 is null, there is no name to share with.
|
||||||
@@ -5891,6 +5887,10 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean canBeTargetedBy(final SpellAbility sa) {
|
public final boolean canBeTargetedBy(final SpellAbility sa) {
|
||||||
|
if (getOwner().hasLost()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (sa == null) {
|
if (sa == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,11 @@ public class CardFactory {
|
|||||||
out.setCommander(in.isRealCommander());
|
out.setCommander(in.isRealCommander());
|
||||||
//out.setFaceDown(in.isFaceDown());
|
//out.setFaceDown(in.isFaceDown());
|
||||||
|
|
||||||
|
int foil = in.getCurrentState().getFoil();
|
||||||
|
if (foil > 0) {
|
||||||
|
out.setFoil(foil);
|
||||||
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final Card crd : list) {
|
for (final Card crd : list) {
|
||||||
ColorSet color = CardUtil.getColors(crd);
|
ColorSet color = crd.determineColor();
|
||||||
for (int i = 0; i < cntColors; i++) {
|
for (int i = 0; i < cntColors; i++) {
|
||||||
if (color.hasAnyColor(MagicColor.WUBRG[i]))
|
if (color.hasAnyColor(MagicColor.WUBRG[i]))
|
||||||
map[i]++;
|
map[i]++;
|
||||||
@@ -376,7 +376,7 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final Card crd : list) {
|
for (final Card crd : list) {
|
||||||
ColorSet color = CardUtil.getColors(crd);
|
ColorSet color = crd.determineColor();
|
||||||
for (int i = 0; i < cntColors; i++) {
|
for (int i = 0; i < cntColors; i++) {
|
||||||
if (color.hasAnyColor(MagicColor.WUBRG[i]))
|
if (color.hasAnyColor(MagicColor.WUBRG[i]))
|
||||||
map[i]++;
|
map[i]++;
|
||||||
@@ -407,7 +407,7 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final Card crd : list) {
|
for (final Card crd : list) {
|
||||||
ColorSet color = CardUtil.getColors(crd);
|
ColorSet color = crd.determineColor();
|
||||||
for (int i = 0; i < cntColors; i++) {
|
for (int i = 0; i < cntColors; i++) {
|
||||||
if (color.hasAnyColor(colorRestrictions.get(i))) {
|
if (color.hasAnyColor(colorRestrictions.get(i))) {
|
||||||
map[i]++;
|
map[i]++;
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ public final class CardPredicates {
|
|||||||
return new Predicate<Card>() {
|
return new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
return CardUtil.getColors(c).hasAnyColor(color);
|
return c.determineColor().hasAnyColor(color);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // getColor()
|
} // getColor()
|
||||||
@@ -273,7 +273,7 @@ public final class CardPredicates {
|
|||||||
return new Predicate<Card>() {
|
return new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
return CardUtil.getColors(c).hasExactlyColor(color);
|
return c.determineColor().hasExactlyColor(color);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -282,7 +282,7 @@ public final class CardPredicates {
|
|||||||
return new Predicate<Card>() {
|
return new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
return CardUtil.getColors(c).isColorless();
|
return c.determineColor().isColorless();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -689,7 +689,7 @@ public class CardProperty {
|
|||||||
break;
|
break;
|
||||||
case "MostProminentColor":
|
case "MostProminentColor":
|
||||||
byte mask = CardFactoryUtil.getMostProminentColors(game.getCardsIn(ZoneType.Battlefield));
|
byte mask = CardFactoryUtil.getMostProminentColors(game.getCardsIn(ZoneType.Battlefield));
|
||||||
if (!CardUtil.getColors(card).hasAnyColor(mask))
|
if (!card.determineColor().hasAnyColor(mask))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case "LastCastThisTurn":
|
case "LastCastThisTurn":
|
||||||
@@ -703,7 +703,7 @@ public class CardProperty {
|
|||||||
if (castSA == null) {
|
if (castSA == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!CardUtil.getColors(card).hasAnyColor(castSA.getPayingColors().getColor())) {
|
if (!card.determineColor().hasAnyColor(castSA.getPayingColors().getColor())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -85,10 +85,6 @@ public final class CardUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ColorSet getColors(final Card c) {
|
|
||||||
return c.determineColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isStackingKeyword(final String keyword) {
|
public static boolean isStackingKeyword(final String keyword) {
|
||||||
String kw = keyword;
|
String kw = keyword;
|
||||||
if (kw.startsWith("HIDDEN")) {
|
if (kw.startsWith("HIDDEN")) {
|
||||||
@@ -158,7 +154,6 @@ public final class CardUtil {
|
|||||||
|
|
||||||
public static List<Card> getLastTurnCast(final String valid, final Card src, final CardTraitBase ctb) {
|
public static List<Card> getLastTurnCast(final String valid, final Card src, final CardTraitBase ctb) {
|
||||||
return CardLists.getValidCardsAsList(src.getGame().getStack().getSpellsCastLastTurn(), valid, src.getController(), src, ctb);
|
return CardLists.getValidCardsAsList(src.getGame().getStack().getSpellsCastLastTurn(), valid, src.getController(), src, ctb);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Card> getLKICopyList(final Iterable<Card> in, Map<Integer, Card> cachedMap) {
|
public static List<Card> getLKICopyList(final Iterable<Card> in, Map<Integer, Card> cachedMap) {
|
||||||
@@ -343,7 +338,7 @@ public final class CardUtil {
|
|||||||
|
|
||||||
byte combinedColor = 0;
|
byte combinedColor = 0;
|
||||||
for (Card tgt : tgts) {
|
for (Card tgt : tgts) {
|
||||||
ColorSet cs = CardUtil.getColors(tgt);
|
ColorSet cs = tgt.determineColor();
|
||||||
for (byte color : MagicColor.WUBRG) {
|
for (byte color : MagicColor.WUBRG) {
|
||||||
if(!cs.hasAnyColor(color))
|
if(!cs.hasAnyColor(color))
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ public class TokenInfo {
|
|||||||
if (!colorMap.isEmpty()) {
|
if (!colorMap.isEmpty()) {
|
||||||
if (!result.isColorless()) {
|
if (!result.isColorless()) {
|
||||||
// change Token Colors
|
// change Token Colors
|
||||||
byte color = CardUtil.getColors(result).getColor();
|
byte color = result.determineColor().getColor();
|
||||||
|
|
||||||
for (final Map.Entry<String, String> e : colorMap.entrySet()) {
|
for (final Map.Entry<String, String> e : colorMap.entrySet()) {
|
||||||
byte v = MagicColor.fromName(e.getValue());
|
byte v = MagicColor.fromName(e.getValue());
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import forge.game.GameObjectPredicates;
|
|||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -300,9 +299,9 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
|||||||
if (first == null) {
|
if (first == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
byte firstColor = CardUtil.getColors(first).getColor();
|
byte firstColor = first.determineColor().getColor();
|
||||||
for (Card c : tgts) {
|
for (Card c : tgts) {
|
||||||
if (CardUtil.getColors(c).getColor() != firstColor) {
|
if (c.determineColor().getColor() != firstColor) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,52 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
|
|
||||||
|
# returns the JDK version.
|
||||||
|
# 8 for 1.8.0_nn, 9 for 9-ea etc, and "no_java" for undetected
|
||||||
|
# Based on the code from this source: https://eed3si9n.com/detecting-java-version-bash
|
||||||
|
jdk_version() {
|
||||||
|
local result
|
||||||
|
local java_cmd
|
||||||
|
if [[ -n $(type -p java) ]]
|
||||||
|
then
|
||||||
|
java_cmd=java
|
||||||
|
elif [[ (-n "$JAVA_HOME") && (-x "$JAVA_HOME/bin/java") ]]
|
||||||
|
then
|
||||||
|
java_cmd="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
local IFS=$'\n'
|
||||||
|
# remove \r for Cygwin
|
||||||
|
local lines=$("$java_cmd" -Xms32M -Xmx32M -version 2>&1 | tr '\r' '\n')
|
||||||
|
if [[ -z $java_cmd ]]
|
||||||
|
then
|
||||||
|
result=no_java
|
||||||
|
else
|
||||||
|
for line in $lines; do
|
||||||
|
if [[ (-z $result) && ($line = *"version \""*) ]]
|
||||||
|
then
|
||||||
|
local ver=$(echo $line | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q')
|
||||||
|
# on macOS, sed doesn't support '?'
|
||||||
|
if [[ $ver = "1."* ]]
|
||||||
|
then
|
||||||
|
result=$(echo $ver | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q')
|
||||||
|
else
|
||||||
|
result=$(echo $ver | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q')
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
echo "$result"
|
||||||
|
}
|
||||||
|
v="$(jdk_version)"
|
||||||
|
|
||||||
|
SHAREDPARAMS='-Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$'
|
||||||
cd $(dirname "${0}")
|
cd $(dirname "${0}")
|
||||||
java -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$
|
|
||||||
|
if [[ $v -ge 17 ]]
|
||||||
|
then
|
||||||
|
java --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED $SHAREDPARAMS
|
||||||
|
elif [[ $v -ge 11 ]]
|
||||||
|
then
|
||||||
|
java --illegal-access=permit $SHAREDPARAMS
|
||||||
|
else
|
||||||
|
java $SHAREDPARAMS
|
||||||
|
fi
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
|||||||
@Override
|
@Override
|
||||||
public void deckTypeSelected(final DecksComboBoxEvent ev) {
|
public void deckTypeSelected(final DecksComboBoxEvent ev) {
|
||||||
if (ev.getDeckType() == DeckType.NET_ARCHIVE_STANDARD_DECK && !refreshingDeckType) {
|
if (ev.getDeckType() == DeckType.NET_ARCHIVE_STANDARD_DECK && !refreshingDeckType) {
|
||||||
if(lstDecks.getGameType() != GameType.Constructed)
|
if (lstDecks.getGameType() != GameType.Constructed)
|
||||||
return;
|
return;
|
||||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||||
@Override
|
@Override
|
||||||
@@ -398,7 +398,7 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_PIONEER_DECK && !refreshingDeckType) {
|
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_PIONEER_DECK && !refreshingDeckType) {
|
||||||
if(lstDecks.getGameType() != GameType.Constructed)
|
if (lstDecks.getGameType() != GameType.Constructed)
|
||||||
return;
|
return;
|
||||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||||
@Override
|
@Override
|
||||||
@@ -424,7 +424,7 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_MODERN_DECK && !refreshingDeckType) {
|
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_MODERN_DECK && !refreshingDeckType) {
|
||||||
if(lstDecks.getGameType() != GameType.Constructed)
|
if (lstDecks.getGameType() != GameType.Constructed)
|
||||||
return;
|
return;
|
||||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||||
@Override
|
@Override
|
||||||
@@ -450,7 +450,7 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_PAUPER_DECK && !refreshingDeckType) {
|
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_PAUPER_DECK && !refreshingDeckType) {
|
||||||
if(lstDecks.getGameType() != GameType.Constructed)
|
if (lstDecks.getGameType() != GameType.Constructed)
|
||||||
return;
|
return;
|
||||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||||
@Override
|
@Override
|
||||||
@@ -476,7 +476,7 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_LEGACY_DECK && !refreshingDeckType) {
|
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_LEGACY_DECK && !refreshingDeckType) {
|
||||||
if(lstDecks.getGameType() != GameType.Constructed)
|
if (lstDecks.getGameType() != GameType.Constructed)
|
||||||
return;
|
return;
|
||||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||||
@Override
|
@Override
|
||||||
@@ -502,7 +502,7 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_VINTAGE_DECK && !refreshingDeckType) {
|
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_VINTAGE_DECK && !refreshingDeckType) {
|
||||||
if(lstDecks.getGameType() != GameType.Constructed)
|
if (lstDecks.getGameType() != GameType.Constructed)
|
||||||
return;
|
return;
|
||||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||||
@Override
|
@Override
|
||||||
@@ -528,7 +528,7 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_BLOCK_DECK && !refreshingDeckType) {
|
} else if (ev.getDeckType() == DeckType.NET_ARCHIVE_BLOCK_DECK && !refreshingDeckType) {
|
||||||
if(lstDecks.getGameType() != GameType.Constructed)
|
if (lstDecks.getGameType() != GameType.Constructed)
|
||||||
return;
|
return;
|
||||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||||
@Override
|
@Override
|
||||||
@@ -712,7 +712,6 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
|||||||
prefs.save();
|
prefs.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String getState() {
|
private String getState() {
|
||||||
final StringBuilder state = new StringBuilder();
|
final StringBuilder state = new StringBuilder();
|
||||||
DeckType selectedDeckType = this.selectedDeckType; // decksComboBox.getDeckType()
|
DeckType selectedDeckType = this.selectedDeckType; // decksComboBox.getDeckType()
|
||||||
@@ -827,7 +826,6 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<String> getSelectedDecksFromSavedState(final String savedState) {
|
private List<String> getSelectedDecksFromSavedState(final String savedState) {
|
||||||
try {
|
try {
|
||||||
if (StringUtils.isBlank(savedState)) {
|
if (StringUtils.isBlank(savedState)) {
|
||||||
|
|||||||
@@ -216,7 +216,6 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final Entry<TItem, Integer> itemEntry : itemsToAdd) {
|
for (final Entry<TItem, Integer> itemEntry : itemsToAdd) {
|
||||||
|
|
||||||
final TItem item = itemEntry.getKey();
|
final TItem item = itemEntry.getKey();
|
||||||
final PaperCard card = item instanceof PaperCard ? (PaperCard)item : null;
|
final PaperCard card = item instanceof PaperCard ? (PaperCard)item : null;
|
||||||
int qty = itemEntry.getValue();
|
int qty = itemEntry.getValue();
|
||||||
@@ -224,8 +223,7 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
|
|||||||
int max;
|
int max;
|
||||||
if (deck == null || card == null || limit == CardLimit.None || DeckFormat.canHaveAnyNumberOf(card)) {
|
if (deck == null || card == null || limit == CardLimit.None || DeckFormat.canHaveAnyNumberOf(card)) {
|
||||||
max = Integer.MAX_VALUE;
|
max = Integer.MAX_VALUE;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
max = (limit == CardLimit.Singleton ? 1 : FModel.getPreferences().getPrefInt(FPref.DECK_DEFAULT_CARD_LIMIT));
|
max = (limit == CardLimit.Singleton ? 1 : FModel.getPreferences().getPrefInt(FPref.DECK_DEFAULT_CARD_LIMIT));
|
||||||
|
|
||||||
Integer cardCopies = DeckFormat.canHaveSpecificNumberInDeck(card);
|
Integer cardCopies = DeckFormat.canHaveSpecificNumberInDeck(card);
|
||||||
@@ -538,16 +536,16 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
|
|||||||
CardManager cardManager = (CardManager) CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().getDeckManager();
|
CardManager cardManager = (CardManager) CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().getDeckManager();
|
||||||
PaperCard existingCard = cardManager.getSelectedItem();
|
PaperCard existingCard = cardManager.getSelectedItem();
|
||||||
// make a foiled version based on the original
|
// make a foiled version based on the original
|
||||||
PaperCard foiledCard = existingCard.getFoiled();
|
PaperCard foiledCard = existingCard.isFoil() ? existingCard.getUnFoiled() : existingCard.getFoiled();
|
||||||
// remove *quantity* instances of existing card
|
// remove *quantity* instances of existing card
|
||||||
CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(false, quantity);
|
CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(false, quantity);
|
||||||
// add *quantity* into the deck and set them as selected
|
// add *quantity* into the deck and set them as selected
|
||||||
cardManager.addItem(foiledCard, quantity);
|
cardManager.addItem(foiledCard, quantity);
|
||||||
cardManager.setSelectedItem(foiledCard);
|
cardManager.setSelectedItem(foiledCard);
|
||||||
}
|
}
|
||||||
}, true, true);
|
}, true, true);
|
||||||
}
|
}
|
||||||
//TODO: need to translate getItemDisplayString
|
//TODO: need to translate getItemDisplayString
|
||||||
private void addItem(final String verb, final String dest, final boolean toAlternate, final int qty, final int shortcutModifiers) {
|
private void addItem(final String verb, final String dest, final boolean toAlternate, final int qty, final int shortcutModifiers) {
|
||||||
String label = verb + " " + SItemManagerUtil.getItemDisplayString(getItemManager().getSelectedItems(), qty, false);
|
String label = verb + " " + SItemManagerUtil.getItemDisplayString(getItemManager().getSelectedItems(), qty, false);
|
||||||
if (dest != null && !dest.isEmpty()) {
|
if (dest != null && !dest.isEmpty()) {
|
||||||
@@ -563,8 +561,7 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
|
|||||||
}
|
}
|
||||||
if (isAddContextMenu) {
|
if (isAddContextMenu) {
|
||||||
CDeckEditorUI.SINGLETON_INSTANCE.addSelectedCards(toAlternate, quantity);
|
CDeckEditorUI.SINGLETON_INSTANCE.addSelectedCards(toAlternate, quantity);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(toAlternate, quantity);
|
CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(toAlternate, quantity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import forge.gui.framework.FScreen;
|
|||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.itemmanager.CardManager;
|
import forge.itemmanager.CardManager;
|
||||||
import forge.itemmanager.ItemManagerConfig;
|
import forge.itemmanager.ItemManagerConfig;
|
||||||
import forge.itemmanager.filters.DeckSetFilter;
|
|
||||||
import forge.localinstance.properties.ForgePreferences.FPref;
|
import forge.localinstance.properties.ForgePreferences.FPref;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.screens.deckeditor.AddBasicLandsDialog;
|
import forge.screens.deckeditor.AddBasicLandsDialog;
|
||||||
|
|||||||
@@ -86,10 +86,9 @@ public class DeckController<T extends DeckBase> {
|
|||||||
/**
|
/**
|
||||||
* Load deck from file or clipboard
|
* Load deck from file or clipboard
|
||||||
*/
|
*/
|
||||||
public void loadDeck(Deck deck){
|
public void loadDeck(Deck deck) {
|
||||||
this.loadDeck(deck, true);
|
this.loadDeck(deck, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadDeck(Deck deck, boolean substituteCurrentDeck) {
|
public void loadDeck(Deck deck, boolean substituteCurrentDeck) {
|
||||||
boolean isStored;
|
boolean isStored;
|
||||||
if (view.getCatalogManager().isInfinite()) {
|
if (view.getCatalogManager().isInfinite()) {
|
||||||
@@ -159,7 +158,6 @@ public class DeckController<T extends DeckBase> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void pickFromCatalog(Map<String, Integer> countByName, CardPool catalog, CardPool targetSection) {
|
private void pickFromCatalog(Map<String, Integer> countByName, CardPool catalog, CardPool targetSection) {
|
||||||
|
|
||||||
CardPool catalogClone = new CardPool(catalog); // clone to iterate modified collection
|
CardPool catalogClone = new CardPool(catalog); // clone to iterate modified collection
|
||||||
for (Map.Entry<PaperCard, Integer> entry : catalogClone) {
|
for (Map.Entry<PaperCard, Integer> entry : catalogClone) {
|
||||||
PaperCard availableCard = entry.getKey();
|
PaperCard availableCard = entry.getKey();
|
||||||
@@ -218,7 +216,6 @@ public class DeckController<T extends DeckBase> {
|
|||||||
public void setModel(final T document) {
|
public void setModel(final T document) {
|
||||||
setModel(document, false);
|
setModel(document, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setModel(final T document, final boolean isStored) {
|
private void setModel(final T document, final boolean isStored) {
|
||||||
model = document;
|
model = document;
|
||||||
onModelChanged(isStored);
|
onModelChanged(isStored);
|
||||||
@@ -234,8 +231,7 @@ public class DeckController<T extends DeckBase> {
|
|||||||
if (isStored) {
|
if (isStored) {
|
||||||
if (isModelInSyncWithFolder()) {
|
if (isModelInSyncWithFolder()) {
|
||||||
setSaved(true);
|
setSaved(true);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
notifyModelChanged();
|
notifyModelChanged();
|
||||||
}
|
}
|
||||||
} else { //TODO: Make this smarter
|
} else { //TODO: Make this smarter
|
||||||
@@ -317,8 +313,7 @@ public class DeckController<T extends DeckBase> {
|
|||||||
final T newModel = currentFolder.get(name);
|
final T newModel = currentFolder.get(name);
|
||||||
if (newModel != null) {
|
if (newModel != null) {
|
||||||
setModel((T) newModel.copyTo(name), true);
|
setModel((T) newModel.copyTo(name), true);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
setSaved(true);
|
setSaved(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import java.awt.datatransfer.StringSelection;
|
|||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
@@ -96,7 +95,6 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
pnlContent.setOpaque(false);
|
pnlContent.setOpaque(false);
|
||||||
|
|
||||||
if (javaRecentEnough()) {
|
if (javaRecentEnough()) {
|
||||||
|
|
||||||
// With Blacksmith we would upload the releases and the /latest would redirect to the right URL
|
// With Blacksmith we would upload the releases and the /latest would redirect to the right URL
|
||||||
// That currently doesn't happen so lets comment out this button for now
|
// That currently doesn't happen so lets comment out this button for now
|
||||||
// pnlContent.add(btnCheckForUpdates, constraintsBTN);
|
// pnlContent.add(btnCheckForUpdates, constraintsBTN);
|
||||||
@@ -122,9 +120,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
|
|
||||||
pnlContent.add(btnDownloadSkins, constraintsBTN);
|
pnlContent.add(btnDownloadSkins, constraintsBTN);
|
||||||
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadSkins")), constraintsLBL);
|
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadSkins")), constraintsLBL);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
String text = localizer.getMessage("lblYourVersionOfJavaIsTooOld");
|
String text = localizer.getMessage("lblYourVersionOfJavaIsTooOld");
|
||||||
FLabel label = new FLabel.Builder().fontAlign(SwingConstants.CENTER).text(text).fontStyle(Font.BOLD).fontSize(18).build();
|
FLabel label = new FLabel.Builder().fontAlign(SwingConstants.CENTER).text(text).fontStyle(Font.BOLD).fontSize(18).build();
|
||||||
pnlContent.add(label, "w 90%!, h 25px!, center, gap 0 0 30px 3px");
|
pnlContent.add(label, "w 90%!, h 25px!, center, gap 0 0 30px 3px");
|
||||||
@@ -137,7 +133,6 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
text = text + " . " + localizer.getMessage("lblYouNeedAtLeastJavaVersion") ;
|
text = text + " . " + localizer.getMessage("lblYouNeedAtLeastJavaVersion") ;
|
||||||
label = new FLabel.Builder().fontAlign(SwingConstants.CENTER).text(text).fontStyle(Font.BOLD).fontSize(18).build();
|
label = new FLabel.Builder().fontAlign(SwingConstants.CENTER).text(text).fontStyle(Font.BOLD).fontSize(18).build();
|
||||||
pnlContent.add(label, "w 90%!, h 25px!, center, gap 0 0 0 36px");
|
pnlContent.add(label, "w 90%!, h 25px!, center, gap 0 0 0 36px");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pnlContent.add(btnListImageData, constraintsBTN);
|
pnlContent.add(btnListImageData, constraintsBTN);
|
||||||
@@ -154,15 +149,12 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
|
|
||||||
pnlContent.add(btnLicensing, constraintsBTN);
|
pnlContent.add(btnLicensing, constraintsBTN);
|
||||||
pnlContent.add(_makeLabel(localizer.getMessage("lblLicensing")), constraintsLBL);
|
pnlContent.add(_makeLabel(localizer.getMessage("lblLicensing")), constraintsLBL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean javaRecentEnough() {
|
private boolean javaRecentEnough() {
|
||||||
|
|
||||||
RuntimeVersion javaVersion = RuntimeVersion.of(System.getProperty("java.version"));
|
RuntimeVersion javaVersion = RuntimeVersion.of(System.getProperty("java.version"));
|
||||||
|
|
||||||
return javaVersion.getMajor() >= 9 || (javaVersion.getMajor() >= 1 && (javaVersion.getMinor() > 8 || (javaVersion.getMinor() == 8 && javaVersion.getUpdate() >= 101)));
|
return javaVersion.getMajor() >= 9 || (javaVersion.getMajor() >= 1 && (javaVersion.getMinor() > 8 || (javaVersion.getMinor() == 8 && javaVersion.getUpdate() >= 101)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
@@ -199,7 +191,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
public void setHowToPlayCommand(UiCommand command) { btnHowToPlay.setCommand(command); }
|
public void setHowToPlayCommand(UiCommand command) { btnHowToPlay.setCommand(command); }
|
||||||
public void setDownloadPricesCommand(UiCommand command) { btnDownloadPrices.setCommand(command); }
|
public void setDownloadPricesCommand(UiCommand command) { btnDownloadPrices.setCommand(command); }
|
||||||
public void setLicensingCommand(UiCommand command) { btnLicensing.setCommand(command); }
|
public void setLicensingCommand(UiCommand command) { btnLicensing.setCommand(command); }
|
||||||
public void setDownloadSkinsCommand(UiCommand command) { btnDownloadSkins.setCommand(command); }
|
public void setDownloadSkinsCommand(UiCommand command) { btnDownloadSkins.setCommand(command); }
|
||||||
|
|
||||||
public void focusTopButton() {
|
public void focusTopButton() {
|
||||||
btnDownloadPics.requestFocusInWindow();
|
btnDownloadPics.requestFocusInWindow();
|
||||||
@@ -269,7 +261,6 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
|
|
||||||
String imagePath;
|
String imagePath;
|
||||||
int artIndex = 1;
|
int artIndex = 1;
|
||||||
ArrayList<String> cis = new ArrayList<>();
|
|
||||||
|
|
||||||
HashMap<String, Pair<Boolean, Integer>> cardCount = new HashMap<>();
|
HashMap<String, Pair<Boolean, Integer>> cardCount = new HashMap<>();
|
||||||
for (CardInSet c : e.getAllCardsInSet()) {
|
for (CardInSet c : e.getAllCardsInSet()) {
|
||||||
@@ -302,10 +293,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// check the front image
|
// check the front image
|
||||||
//
|
|
||||||
imagePath = ImageUtil.getImageRelativePath(cp, false, true, false);
|
imagePath = ImageUtil.getImageRelativePath(cp, false, true, false);
|
||||||
if (imagePath != null) {
|
if (imagePath != null) {
|
||||||
File file = ImageKeys.getImageFile(imagePath);
|
File file = ImageKeys.getImageFile(imagePath);
|
||||||
@@ -319,9 +307,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// check the back face
|
// check the back face
|
||||||
//
|
|
||||||
if (cp.hasBackFace()) {
|
if (cp.hasBackFace()) {
|
||||||
imagePath = ImageUtil.getImageRelativePath(cp, true, true, false);
|
imagePath = ImageUtil.getImageRelativePath(cp, true, true, false);
|
||||||
if (imagePath != null) {
|
if (imagePath != null) {
|
||||||
@@ -372,7 +358,6 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
nifSB.append("\n");
|
nifSB.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String totalStats = "Missing images: " + missingCount + "\nUnimplemented cards: " + notImplementedCount + "\n";
|
String totalStats = "Missing images: " + missingCount + "\nUnimplemented cards: " + notImplementedCount + "\n";
|
||||||
cniSB.append("\n-----------\n");
|
cniSB.append("\n-----------\n");
|
||||||
cniSB.append(totalStats);
|
cniSB.append(totalStats);
|
||||||
@@ -425,7 +410,6 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void showLicensing() {
|
public void showLicensing() {
|
||||||
String license = "<html>Forge License Information<br><br>"
|
String license = "<html>Forge License Information<br><br>"
|
||||||
+ "This program is free software : you can redistribute it and/or modify "
|
+ "This program is free software : you can redistribute it and/or modify "
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class IntegerConstraint {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if( min == max ) {
|
if (min == max) {
|
||||||
return String.valueOf( min );
|
return String.valueOf( min );
|
||||||
}
|
}
|
||||||
return "between " + min + " and " + max;
|
return "between " + min + " and " + max;
|
||||||
|
|||||||
@@ -339,17 +339,14 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
//hide deck header on while drafting
|
//hide deck header on while drafting
|
||||||
setDeck(new Deck());
|
setDeck(new Deck());
|
||||||
deckHeader.setVisible(false);
|
deckHeader.setVisible(false);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (newDeck == null) {
|
if (newDeck == null) {
|
||||||
editorType.getController().newModel();
|
editorType.getController().newModel();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
editorType.getController().setDeck(newDeck);
|
editorType.getController().setDeck(newDeck);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (editorType == EditorType.Draft || editorType == EditorType.QuestDraft) {
|
if (editorType == EditorType.Draft || editorType == EditorType.QuestDraft) {
|
||||||
tabPages[0].hideTab(); //hide Draft Pack page if editing existing draft deck
|
tabPages[0].hideTab(); //hide Draft Pack page if editing existing draft deck
|
||||||
}
|
}
|
||||||
@@ -897,8 +894,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
public void handleEvent(FEvent e) {
|
public void handleEvent(FEvent e) {
|
||||||
if (max == 1) {
|
if (max == 1) {
|
||||||
callback.run(max);
|
callback.run(max);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
final Localizer localizer = Localizer.getInstance();
|
final Localizer localizer = Localizer.getInstance();
|
||||||
GuiChoose.getInteger(cardManager.getSelectedItem() + " - " + verb + " " + localizer.getMessage("lblHowMany"), 1, max, 20, callback);
|
GuiChoose.getInteger(cardManager.getSelectedItem() + " - " + verb + " " + localizer.getMessage("lblHowMany"), 1, max, 20, callback);
|
||||||
}
|
}
|
||||||
@@ -1150,8 +1146,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
default:
|
default:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
//if a commander has been set, only show cards that match its color identity
|
//if a commander has been set, only show cards that match its color identity
|
||||||
switch (editorType) {
|
switch (editorType) {
|
||||||
case Commander:
|
case Commander:
|
||||||
@@ -1176,8 +1171,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
default:
|
default:
|
||||||
if (cardManager.getWantUnique()) {
|
if (cardManager.getWantUnique()) {
|
||||||
cardManager.setPool(editorType.applyCardFilter(FModel.getUniqueCardsNoAlt(), additionalFilter), true);
|
cardManager.setPool(editorType.applyCardFilter(FModel.getUniqueCardsNoAlt(), additionalFilter), true);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
cardManager.setPool(editorType.applyCardFilter(FModel.getAllCardsNoAlt(), additionalFilter), true);
|
cardManager.setPool(editorType.applyCardFilter(FModel.getAllCardsNoAlt(), additionalFilter), true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1250,8 +1244,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
CardPreferences.save();
|
CardPreferences.save();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
menu.addItem(new FMenuItem(localizer.getMessage("lblRemoveFavorites"), Forge.hdbuttons ? FSkinImage.HDSTAR_OUTLINE : FSkinImage.STAR_OUTLINE, new FEventHandler() {
|
menu.addItem(new FMenuItem(localizer.getMessage("lblRemoveFavorites"), Forge.hdbuttons ? FSkinImage.HDSTAR_OUTLINE : FSkinImage.STAR_OUTLINE, new FEventHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void handleEvent(FEvent e) {
|
public void handleEvent(FEvent e) {
|
||||||
@@ -1376,8 +1369,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
protected void updateCaption() {
|
protected void updateCaption() {
|
||||||
if (deckSection == DeckSection.Commander) {
|
if (deckSection == DeckSection.Commander) {
|
||||||
caption = captionPrefix; //don't display count for commander section since it won't be more than 1
|
caption = captionPrefix; //don't display count for commander section since it won't be more than 1
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
caption = captionPrefix + " (" + parentScreen.getDeck().get(deckSection).countAll() + ")";
|
caption = captionPrefix + " (" + parentScreen.getDeck().get(deckSection).countAll() + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1767,8 +1759,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
if (isStored) {
|
if (isStored) {
|
||||||
if (isModelInSyncWithFolder()) {
|
if (isModelInSyncWithFolder()) {
|
||||||
setSaved(true);
|
setSaved(true);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
notifyModelChanged();
|
notifyModelChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1779,8 +1770,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
}
|
}
|
||||||
if (model != null) {
|
if (model != null) {
|
||||||
editor.setDeck(model.getHumanDeck());
|
editor.setDeck(model.getHumanDeck());
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
editor.setDeck(null);
|
editor.setDeck(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -525,6 +525,9 @@ public abstract class ItemManager<T extends InventoryItem> extends FContainer im
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addItem(final T item, int qty) {
|
public void addItem(final T item, int qty) {
|
||||||
|
if (pool == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
pool.add(item, qty);
|
pool.add(item, qty);
|
||||||
if (isUnfiltered()) {
|
if (isUnfiltered()) {
|
||||||
model.addItem(item, qty);
|
model.addItem(item, qty);
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ SVar:TrigExile:DB$ ChangeZone | Defined$ TriggeredCard | Origin$ Graveyard | Des
|
|||||||
A:AB$ Draw | Cost$ 2 T | NumCards$ 1 | SpellDescription$ Draw a card, then discard a card. | SubAbility$ DBDiscard
|
A:AB$ Draw | Cost$ 2 T | NumCards$ 1 | SpellDescription$ Draw a card, then discard a card. | SubAbility$ DBDiscard
|
||||||
SVar:DBDiscard:DB$ Discard | Defined$ You | NumCards$ 1 | Mode$ TgtChoose
|
SVar:DBDiscard:DB$ Discard | Defined$ You | NumCards$ 1 | Mode$ TgtChoose
|
||||||
AI:RemoveDeck:All
|
AI:RemoveDeck:All
|
||||||
A:AB$ ChangeZoneAll | Cost$ 4 T Sac<1/CARDNAME> | ChangeType$ Card.ExiledWithSource | Origin$ Exile | Destination$ Hand | AILogic$ DiscardAllAndRetExiled.minAdv2 | SpellDescription$ Return all cards exiled with CARDNAME to their owner's hand.
|
A:AB$ ChangeZoneAll | Cost$ 4 T Sac<1/CARDNAME> | ChangeType$ Card.ExiledWithSource | Origin$ Exile | Destination$ Hand | AILogic$ DiscardAllAndRetExiled.noDiscard.minAdv2 | SpellDescription$ Return all cards exiled with CARDNAME to their owner's hand.
|
||||||
AI:RemoveDeck:Random
|
AI:RemoveDeck:Random
|
||||||
Oracle:Whenever you discard a card, exile that card from your graveyard.\n{2}, {T}: Draw a card, then discard a card.\n{4}, {T}, Sacrifice Bag of Holding: Return all cards exiled with Bag of Holding to their owner's hand.
|
Oracle:Whenever you discard a card, exile that card from your graveyard.\n{2}, {T}: Draw a card, then discard a card.\n{4}, {T}, Sacrifice Bag of Holding: Return all cards exiled with Bag of Holding to their owner's hand.
|
||||||
|
|||||||
6
forge-gui/res/cardsfolder/b/blacker_lotus.txt
Normal file
6
forge-gui/res/cardsfolder/b/blacker_lotus.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Name:Blacker Lotus
|
||||||
|
ManaCost:0
|
||||||
|
Types:Artifact
|
||||||
|
A:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 4 | AILogic$ BlackLotus | SubAbility$ DBTearUpAndRemove | SpellDescription$ Tear CARDNAME into pieces. Add four mana of any one color. Remove the pieces from the game.
|
||||||
|
SVar:DBTearUpAndRemove:DB$ RemoveFromMatch | Defined$ Self | LogMessage$ Torn to pieces and removed
|
||||||
|
Oracle:{T}: Tear Blacker Lotus into pieces. Add four mana of any one color. Remove the pieces from the game.
|
||||||
8
forge-gui/res/cardsfolder/c/chaos_orb.txt
Normal file
8
forge-gui/res/cardsfolder/c/chaos_orb.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Chaos Orb
|
||||||
|
ManaCost:2
|
||||||
|
Types:Artifact
|
||||||
|
A:AB$ FlipOntoBattlefield | Cost$ 1 T | SubAbility$ DBDestroyTouched | ActivationZone$ Battlefield | SpellDescription$ If CARDNAME is on the battlefield, flip CARDNAME onto the battlefield from a height of at least one foot. If CARDNAME turns over completely at least once during the flip, destroy all nontoken permanents it touches. Then destroy CARDNAME. | StackDescription$ SpellDescription
|
||||||
|
SVar:DBDestroyTouched:DB$ DestroyAll | ValidCards$ Card.IsRemembered+nonToken | SubAbility$ DBDestroyChaosOrb | AILogic$ Always | StackDescription$ None
|
||||||
|
SVar:DBDestroyChaosOrb:DB$ Destroy | Defined$ Self | SubAbility$ DBCleanup | AILogic$ Always | StackDescription$ None
|
||||||
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
|
Oracle:{1}, {T}: If Chaos Orb is on the battlefield, flip Chaos Orb onto the battlefield from a height of at least one foot. If Chaos Orb turns over completely at least once during the flip, destroy all nontoken permanents it touches. Then destroy Chaos Orb.
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
Name:Fact or Fiction
|
Name:Fact or Fiction
|
||||||
ManaCost:3 U
|
ManaCost:3 U
|
||||||
Types:Instant
|
Types:Instant
|
||||||
A:SP$ Dig | Cost$ 3 U | DigNum$ 5 | Reveal$ True | RememberRevealed$ True | NoMove$ True | SubAbility$ DBTwoPiles | SpellDescription$ Reveal the top five cards of your library. An opponent separates those cards into two piles. Put one pile into your hand and the other into your graveyard.
|
A:SP$ Dig | DigNum$ 5 | Reveal$ True | RememberRevealed$ True | NoMove$ True | SubAbility$ DBTwoPiles | SpellDescription$ Reveal the top five cards of your library. An opponent separates those cards into two piles. Put one pile into your hand and the other into your graveyard.
|
||||||
SVar:DBTwoPiles:DB$ TwoPiles | Defined$ You | DefinedCards$ Remembered | Separator$ Opponent | ChosenPile$ DBHand | UnchosenPile$ DBGrave
|
SVar:DBTwoPiles:DB$ TwoPiles | Defined$ You | DefinedCards$ Remembered | Separator$ Opponent | ChosenPile$ DBHand | UnchosenPile$ DBGrave | StackDescription$ An opponent separates those cards into two piles. {p:You} puts one pile into their hand and the other into their graveyard.
|
||||||
SVar:DBHand:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Hand | SubAbility$ DBCleanup
|
SVar:DBHand:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Hand | SubAbility$ DBCleanup
|
||||||
SVar:DBGrave:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Graveyard | SubAbility$ DBCleanup
|
SVar:DBGrave:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Graveyard | SubAbility$ DBCleanup
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/fact_or_fiction.jpg
|
|
||||||
Oracle:Reveal the top five cards of your library. An opponent separates those cards into two piles. Put one pile into your hand and the other into your graveyard.
|
Oracle:Reveal the top five cards of your library. An opponent separates those cards into two piles. Put one pile into your hand and the other into your graveyard.
|
||||||
|
|||||||
7
forge-gui/res/cardsfolder/f/falling_star.txt
Normal file
7
forge-gui/res/cardsfolder/f/falling_star.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Falling Star
|
||||||
|
ManaCost:2 R
|
||||||
|
Types:Sorcery
|
||||||
|
A:SP$ FlipOntoBattlefield | SubAbility$ DBDamageTouched | AILogic$ DamageCreatures | SpellDescription$ Flip CARDNAME onto the playing area from a height of at least one foot. CARDNAME deals 3 damage to each creature it lands on. Tap all creatures dealt damage by CARDNAME. If CARDNAME doesn't turn completely over at least once during the flip, it has no effect. | StackDescription$ SpellDescription
|
||||||
|
SVar:DBDamageTouched:DB$ DamageAll | ValidCards$ Creature.IsRemembered | ValidDescription$ each creature touched. | NumDmg$ 3 | SubAbility$ DBCleanup | StackDescription$ None
|
||||||
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
|
Oracle:Flip Falling Star onto the playing area from a height of at least one foot. Falling Star deals 3 damage to each creature it lands on. Tap all creatures dealt damage by Falling Star. If Falling Star doesn't turn completely over at least once during the flip, it has no effect.
|
||||||
@@ -5,5 +5,5 @@ PT:3/3
|
|||||||
K:Double Strike
|
K:Double Strike
|
||||||
K:Evoke:ExileFromHand<1/Card.Red+Other/red card>
|
K:Evoke:ExileFromHand<1/Card.Red+Other/red card>
|
||||||
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDamage | TriggerDescription$ When CARDNAME enters the battlefield, it deals 4 damage divided as you choose among any number of target creatures and/or planeswalkers.
|
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDamage | TriggerDescription$ When CARDNAME enters the battlefield, it deals 4 damage divided as you choose among any number of target creatures and/or planeswalkers.
|
||||||
SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker to distribute damage to | NumDmg$ 4 | TargetMin$ 1 | TargetMax$ 4 | DividedAsYouChoose$ 4
|
SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker to distribute damage to | NumDmg$ 4 | TargetMin$ 0 | TargetMax$ 4 | DividedAsYouChoose$ 4
|
||||||
Oracle:Double strike\nWhen Fury enters the battlefield, it deals 4 damage divided as you choose among any number of target creatures and/or planeswalkers.\nEvoke—Exile a red card from your hand.
|
Oracle:Double strike\nWhen Fury enters the battlefield, it deals 4 damage divided as you choose among any number of target creatures and/or planeswalkers.\nEvoke—Exile a red card from your hand.
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.S
|
|||||||
SVar:TrigEffect:DB$ Effect | Triggers$ TrigDamageDone
|
SVar:TrigEffect:DB$ Effect | Triggers$ TrigDamageDone
|
||||||
SVar:TrigDamageDone:Mode$ DamageDone | ValidTarget$ Creature.OppCtrl | Execute$ TrigDestroy | TriggerDescription$ Poison Breath — Until end of turn, whenever a creature an opponent controls is dealt damage, destroy it.
|
SVar:TrigDamageDone:Mode$ DamageDone | ValidTarget$ Creature.OppCtrl | Execute$ TrigDestroy | TriggerDescription$ Poison Breath — Until end of turn, whenever a creature an opponent controls is dealt damage, destroy it.
|
||||||
SVar:TrigDestroy:DB$ Destroy | Defined$ TriggeredTarget
|
SVar:TrigDestroy:DB$ Destroy | Defined$ TriggeredTarget
|
||||||
|
SVar:PlayMain1:TRUE
|
||||||
Oracle:Flying\nPoison Breath — When Green Dragon enters the battlefield, until end of turn, whenever a creature an opponent controls is dealt damage, destroy it.
|
Oracle:Flying\nPoison Breath — When Green Dragon enters the battlefield, until end of turn, whenever a creature an opponent controls is dealt damage, destroy it.
|
||||||
|
|||||||
@@ -14,5 +14,5 @@ ManaCost:1 G
|
|||||||
Types:Legendary Artifact
|
Types:Legendary Artifact
|
||||||
K:ETBReplacement:Other:ChooseCT
|
K:ETBReplacement:Other:ChooseCT
|
||||||
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type.
|
SVar:ChooseCT:DB$ ChooseType | Defined$ You | Type$ Creature | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a creature type.
|
||||||
A:AB$ Mana | Cost$ T | Produced$ G | RestrictValid$ Creature.ChosenType,Creature.Legendary | SpellDescription$ {T}: Add {G}. Spend this mana only to cast a creature spell of the chosen type or a legendary creature spell.
|
A:AB$ Mana | Cost$ T | Produced$ G | RestrictValid$ Creature.ChosenType,Creature.Legendary | SpellDescription$ Add {G}. Spend this mana only to cast a creature spell of the chosen type or a legendary creature spell.
|
||||||
Oracle:As The Ringhart Crest enters the battlefield, choose a creature type.\n{T}: Add {G}. Spend this mana only to cast a creature spell of the chosen type or a legendary creature spell.
|
Oracle:As The Ringhart Crest enters the battlefield, choose a creature type.\n{T}: Add {G}. Spend this mana only to cast a creature spell of the chosen type or a legendary creature spell.
|
||||||
|
|||||||
6
forge-gui/res/cardsfolder/l/look_at_me_im_the_dci.txt
Normal file
6
forge-gui/res/cardsfolder/l/look_at_me_im_the_dci.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Name:Look at Me, I'm the DCI
|
||||||
|
ManaCost:5 W W
|
||||||
|
Types:Sorcery
|
||||||
|
A:SP$ NameCard | Defined$ You | ValidCards$ Card.nonBasic | SelectPrompt$ Choose a card other than a basic land card to ban | SubAbility$ DBRemove | AILogic$ MostProminentInHumanDeck | StackDescription$ None | SpellDescription$ Ban a card other than a basic land card for the rest of the match. (All cards with that name in any zone or sideboard are removed from the match.)
|
||||||
|
SVar:DBRemove:DB$ RemoveFromMatch | RemoveType$ Card.NamedCard | IncludeSideboard$ True | StackDescription$ Ban a card other than a basic land card for the rest of the match. (All cards with that name in any zone or sideboard are removed from the match.)
|
||||||
|
Oracle:Ban a card other than a basic land card for the rest of the match. (All cards with that name in any zone or sideboard are removed from the match.)
|
||||||
@@ -3,6 +3,6 @@ ManaCost:1 U R
|
|||||||
Types:Legendary Creature Human Wizard
|
Types:Legendary Creature Human Wizard
|
||||||
PT:1/4
|
PT:1/4
|
||||||
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ Player | Execute$ DrawDamageOther | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of each player's end step, that player may draw a card if a player other than you lost life this turn.
|
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ Player | Execute$ DrawDamageOther | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of each player's end step, that player may draw a card if a player other than you lost life this turn.
|
||||||
SVar:DrawDamageOther:DB$ Draw | Defined$ TriggeredPlayer | NumCards$ 1 | ConditionPlayerDefined$ Player.Other | ConditionPlayerContains$ Player.wasDealtDamageThisTurn | OptionalDecider$ True
|
SVar:DrawDamageOther:DB$ Draw | Defined$ TriggeredPlayer | NumCards$ 1 | ConditionPlayerDefined$ Player.Other | ConditionPlayerContains$ Player.LostLifeThisTurn | OptionalDecider$ True
|
||||||
K:Partner
|
K:Partner
|
||||||
Oracle:At the beginning of each player's end step, that player may draw a card if a player other than you lost life this turn.\nPartner (You can have two commanders if both have partner.)
|
Oracle:At the beginning of each player's end step, that player may draw a card if a player other than you lost life this turn.\nPartner (You can have two commanders if both have partner.)
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ Name:Sorin, Lord of Innistrad
|
|||||||
ManaCost:2 W B
|
ManaCost:2 W B
|
||||||
Types:Legendary Planeswalker Sorin
|
Types:Legendary Planeswalker Sorin
|
||||||
Loyalty:3
|
Loyalty:3
|
||||||
A:AB$ Token | Cost$ AddCounter<1/LOYALTY> | TokenAmount$ 1 | TokenScript$ b_1_1_vampire_lifelink | TokenOwner$ You | LegacyImage$ b 1 1 vampire lifelink dka | Planeswalker$ True | SpellDescription$ Create a 1/1 black Vampire creature token with lifelink.
|
A:AB$ Token | Cost$ AddCounter<1/LOYALTY> | TokenAmount$ 1 | TokenScript$ b_1_1_vampire_lifelink | Planeswalker$ True | SpellDescription$ Create a 1/1 black Vampire creature token with lifelink.
|
||||||
A:AB$ Effect | Cost$ SubCounter<2/LOYALTY> | Name$ Emblem - Sorin, Lord of Innistrad | Image$ emblem_sorin_lord_of_innistrad | StaticAbilities$ STPump | Planeswalker$ True | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Creatures you control get +1/+0."
|
A:AB$ Effect | Cost$ SubCounter<2/LOYALTY> | Name$ Emblem - Sorin, Lord of Innistrad | Image$ emblem_sorin_lord_of_innistrad | StaticAbilities$ STPump | Planeswalker$ True | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Creatures you control get +1/+0."
|
||||||
SVar:STPump:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature.YouCtrl | AddPower$ 1
|
SVar:STPump:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature.YouCtrl | AddPower$ 1
|
||||||
A:AB$ Destroy | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Creature,Planeswalker.Other | TargetMin$ 0 | TargetMax$ 3 | TgtPrompt$ Select target creatures or other planeswalkers | RememberTargets$ True | ForgetOtherTargets$ True | SubAbility$ DBChangeZoneAll | SpellDescription$ Destroy up to 3 target creatures and/or other planeswalkers. Return each card put into a graveyard this way to the battlefield under your control.
|
A:AB$ Destroy | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Creature,Planeswalker.Other | TargetMin$ 0 | TargetMax$ 3 | TgtPrompt$ Select target creatures or other planeswalkers | RememberTargets$ True | ForgetOtherTargets$ True | SubAbility$ DBChangeZoneAll | SpellDescription$ Destroy up to three target creatures and/or other planeswalkers. Return each card put into a graveyard this way to the battlefield under your control.
|
||||||
SVar:DBChangeZoneAll:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | SubAbility$ DBCleanup
|
SVar:DBChangeZoneAll:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | SubAbility$ DBCleanup
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/sorin_lord_of_innistrad.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/sorin_lord_of_innistrad.jpg
|
||||||
|
|||||||
113
forge-gui/res/cardsfolder/u/urza_academy_headmaster.txt
Normal file
113
forge-gui/res/cardsfolder/u/urza_academy_headmaster.txt
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
Name:Urza, Academy Headmaster
|
||||||
|
ManaCost:W U B R G
|
||||||
|
Types:Legendary Planeswalker Urza
|
||||||
|
Loyalty:4
|
||||||
|
A:AB$ GenericChoice | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | AtRandom$ Urza | ShowChoice$ Description | Choices$ Pump1,PutCounter2,Destroy3,Token4,Token5,Token6,Dig7,MustAttack8,PutCounter9,Effect10,Exile11,Dig12,Animate13,Draw14,Animate15,PumpAll16,Dig17,DealDamage18,Animate19,Mana20 | ShowChoice$ Description | StackDescription$ SpellDescription | SpellDescription$ Head to AskUrza.com and click +1.
|
||||||
|
SVar:Pump1:DB$ Pump | TargetMin$ 0 | TargetMax$ 1 | KW$ First Strike & Vigilance & Lifelink | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +1 | NumDef$ +1 | KW$ First Strike & Vigilance & Lifelink | SpellDescription$ Until end of turn, up to one target creature gets +1/+1 and gains first strike, vigilance, and lifelink.
|
||||||
|
SVar:PutCounter2:DB$ PutCounter | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control to distribute counters to | CounterType$ P1P1 | CounterNum$ 3 | TargetMin$ 1 | TargetMax$ 3 | DividedAsYouChoose$ 3 | SpellDescription$ Distribute three +1/+1 counters among one, two, or three target creatures you control.
|
||||||
|
SVar:Destroy3:DB$ Destroy | ValidTgts$ Permanent.nonCreature | TgtPrompt$ Select a noncreature permanent | SpellDescription$ Destroy target noncreature permanent.
|
||||||
|
SVar:Token4:DB$ Token | TokenAmount$ 2 | TokenScript$ r_3_1_elemental_haste | AtEOT$ Exile | SpellDescription$ Create two 3/1 red Elemental creature tokens with haste. Exile them at the beginning of the next end step.
|
||||||
|
SVar:Token5:DB$ Token | TokenAmount$ 3 | TokenScript$ w_1_1_soldier | SpellDescription$ Create three 1/1 white Soldier creature tokens.
|
||||||
|
SVar:Token6:DB$ Token | TokenScript$ b_3_3_beast_deathtouch | SpellDescription$ Create a 3/3 black Beast creature token with deathtouch.
|
||||||
|
SVar:Dig7:DB$ Dig | DigNum$ 5 | Reveal$ True | ChangeNum$ All | ChangeValid$ Creature | SpellDescription$ Reveal the top five cards of your library. Put all creature cards revealed this way into your hand and the rest on the bottom of your library in any order.
|
||||||
|
SVar:MustAttack8:DB$ MustAttack | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | Defender$ Self | SpellDescription$ During target opponent's next turn, creatures that player controls attack NICKNAME if able.
|
||||||
|
SVar:PutCounter9:DB$ PutCounter | Defined$ Self | CounterType$ LOYALTY | CounterNum$ X9 | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | StackDescription$ SpellDescription | SpellDescription$ Put a loyalty counter on NICKNAME for each creature target opponent controls.
|
||||||
|
SVar:X9:TargetedPlayer$CreaturesInPlay
|
||||||
|
SVar:Effect10:DB$ Effect | Triggers$ TrigAttack10 | Duration$ UntilYourNextTurn | SpellDescription$ Until your next turn, whenever a creature an opponent controls attacks, it gets -1/-0 until end of turn.
|
||||||
|
SVar:TrigAttack10:Mode$ Attacks | ValidCard$ Creature.OppCtrl | TriggerZones$ Command | Execute$ DebuffAttacker10 | TriggerDescription$ Whenever a creature an opponent controls attacks, it gets -1/-0 until end of turn.
|
||||||
|
SVar:DebuffAttacker10:DB$ Pump | Defined$ TriggeredAttacker | NumAtt$ -1
|
||||||
|
SVar:Exile11:DB$ ChangeZone | ValidTgts$ Player | TgtPrompt$ Select target player | Origin$ Hand | Destination$ Exile | ChangeType$ Card | ChangeNum$ 1 | Chooser$ Targeted | Hidden$ True | IsCurse$ True | Mandatory$ True | SpellDescription$ Target player exiles a card from their hand.
|
||||||
|
SVar:Dig12:DB$ Dig | DigNum$ 1 | Reveal$ True | ChangeNum$ All | ChangeValid$ Land | DestinationZone$ Battlefield | DestinationZone2$ Hand | SpellDescription$ Reveal the top card of your library. If it's a land card, put it onto the battlefield. Otherwise, put it into your hand.
|
||||||
|
SVar:Animate13:DB$ Animate | ValidTgts$ Land.YouCtrl | TgtPrompt$ Select target land you control | Power$ 4 | Toughness$ 4 | Types$ Creature,Elemental | Duration$ Permanent | Keywords$ Trample | SpellDescription$ Target land you control becomes a 4/4 Elemental creature with trample. It's still a land.
|
||||||
|
SVar:Draw14:DB$ Draw | Defined$ You | SubAbility$ DBMana14 | SpellDescription$ Draw a card, then add one mana of any color.
|
||||||
|
SVar:DBMana14:DB$ Mana | Produced$ Any | AILogic$ MostProminentInComputerHand
|
||||||
|
SVar:Animate15:DB$ Animate | Power$ 4 | Toughness$ 4 | Types$ Creature,Legendary,Dragon | Colors$ Red | OverwriteColors$ True | RemoveCardTypes$ True | Keywords$ Flying & Indestructible & Haste | SpellDescription$ Until end of turn, NICKNAME becomes a legendary 4/4 red Dragon creature with flying, indestructible, and haste. (He doesn't lose loyalty while he's not a planeswalker.)
|
||||||
|
SVar:PumpAll16:DB$ PumpAll | ValidCards$ Creature.YouCtrl | NumAtt$ +1 | KW$ Lifelink | Duration$ UntilYourNextTurn | SpellDescription$ Until your next turn, creatures you control get +1/+0 and gain lifelink.
|
||||||
|
SVar:Dig17:DB$ Dig | DigNum$ 5 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Artifact | SpellDescription$ Look at the top five cards of your library. You may reveal an artifact card from among them and put it into your hand. Put the rest on the bottom of your library in any order.
|
||||||
|
SVar:DealDamage18:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 3 | SpellDescription$ NICKNAME deals 3 damage to any target.
|
||||||
|
SVar:Animate19:DB$ Animate | Defined$ Self | Triggers$ DamageTrig19 | Duration$ UntilYourNextTurn | SpellDescription$ Until your next turn, whenever a creature deals combat damage to NICKNAME, destroy that creature. | StackDescription$ SpellDescription
|
||||||
|
SVar:DamageTrig19:Mode$ DamageDone | ValidSource$ Creature | ValidTarget$ Card.Self | TriggerZones$ Battlefield | CombatDamage$ True | Execute$ TrigDestroy19 | TriggerDescription$ Whenever a creature deals combat damage to NICKNAME, destroy that creature.
|
||||||
|
SVar:TrigDestroy19:DB$ Destroy | Defined$ TriggeredSourceLKICopy
|
||||||
|
SVar:Mana20:DB$ Mana | Produced$ Combo Any | Amount$ X20 | SpellDescription$ Add X mana in any combination of colors, where X is the number of creatures you control.
|
||||||
|
SVar:X20:Count$Valid Creature.YouCtrl
|
||||||
|
A:AB$ GenericChoice | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | AtRandom$ Urza | ShowChoice$ Description | Choices$ DamageAll1M,GainControl2M,DealDamage3M,Destroy4M,Effect5M,ChangeZone6M,Draw7M,Mill8M,Dig9M,Exile10M,Reveal11M,Tutor12M,Sacrifice13M,Token14M,Token15M,SetLife16M,Destroy17M,Return18M,Token19M,Draw20M | ShowChoice$ Description | StackDescription$ SpellDescription | SpellDescription$ Head to AskUrza.com and click -1.
|
||||||
|
SVar:DamageAll1M:DB$ DamageAll | NumDmg$ 3 | ValidCards$ Creature | SpellDescription$ NICKNAME deals 3 damage to each creature.
|
||||||
|
SVar:GainControl2M:DB$ GainControl | ValidTgts$ Creature | TgtPrompt$ Select target creature | SpellDescription$ Gain control of target creature.
|
||||||
|
SVar:DealDamage3M:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 4 | SubAbility$ DBGainLife3M | SpellDescription$ NICKNAME deals 4 damage to any target and you gain 4 life.
|
||||||
|
SVar:DBGainLife3M:DB$ GainLife | Defined$ You | LifeAmount$ 4
|
||||||
|
SVar:Destroy4M:DB$ Destroy | ValidTgts$ Creature | TgtPrompt$ Select target creature | SubAbility$ DBGainLife4M | SpellDescription$ Destroy target creature. You gain life equal to its toughness.
|
||||||
|
SVar:DBGainLife4M:DB$ GainLife | Defined$ You | LifeAmount$ X4M
|
||||||
|
SVar:X4M:TargetedLKI$CardToughness
|
||||||
|
SVar:Effect5M:DB$ Effect | Name$ Emblem - Urza, Academy Headmaster (5M) | StaticAbilities$ STPump5M | Duration$ Permanent | SpellDescription$ You get an emblem with "Creatures you control get +1/+1."
|
||||||
|
SVar:STPump5M:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature.YouCtrl | AddPower$ 1 | AddToughness$ 1 | Description$ Creatures you control get +1/+1.
|
||||||
|
SVar:ChangeZone6M:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature | ChangeNum$ 1 | SpellDescription$ You may put a creature card from your hand onto the battlefield.
|
||||||
|
SVar:Draw7M:DB$ Draw | NumCards$ 3 | SubAbility$ DBChangeZone7M | SpellDescription$ Draw three cards, then put a card from your hand on top of your library.
|
||||||
|
SVar:DBChangeZone7M:DB$ ChangeZone | Origin$ Hand | Destination$ Library | ChangeType$ Card | ChangeNum$ 1 | Mandatory$ True | SelectPrompt$ Select a card from your hand to put on top of your library
|
||||||
|
SVar:Mill8M:DB$ Mill | ValidTgts$ Player | TgtPrompt$ Select target player | NumCards$ 10 | SpellDescription$ Target player puts the top ten cards of their library into their graveyard.
|
||||||
|
SVar:Dig9M:DB$ Dig | DigNum$ 5 | Reveal$ True | RememberRevealed$ True | NoMove$ True | SubAbility$ DBTwoPiles9M | SpellDescription$ Reveal the top five cards of your library. An opponent separates them into two piles. Put one pile into your hand and the other on the bottom of your library in any order.
|
||||||
|
SVar:DBTwoPiles9M:DB$ TwoPiles | Defined$ You | DefinedCards$ Remembered | Separator$ Opponent | ChosenPile$ DBHand9M | UnchosenPile$ DBLibraryBottom9M
|
||||||
|
SVar:DBHand9M:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Hand
|
||||||
|
SVar:DBLibraryBottom9M:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Library | Destination$ Library | LibraryPosition$ -1 | SubAbility$ DBCleanup
|
||||||
|
SVar:Exile10M:DB$ ChangeZone | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | Origin$ Battlefield | Destination$ Exile | SpellDescription$ Exile target permanent.
|
||||||
|
SVar:Reveal11M:DB$ Dig | DigNum$ 5 | Reveal$ True | RememberRevealed$ True | NoMove$ True | SubAbility$ DBChangeCreatures11M | SpellDescription$ Reveal the top five cards of your library. You may put all creature cards and/or land cards from among them into your hand. Put the rest into your graveyard.
|
||||||
|
SVar:DBChangeCreatures11M:DB$ ChangeZoneAll | ChangeType$ Card.Creature+IsRemembered | Origin$ Library | Destination$ Hand | Optional$ True | OptionQuestion$ Put all creature cards into your hand? | ForgetChanged$ True | SubAbility$ DBChangeLands11M
|
||||||
|
SVar:DBChangeLands11M:DB$ ChangeZoneAll | ChangeType$ Card.Land+IsRemembered | Origin$ Library | Destination$ Hand | Optional$ True | OptionQuestion$ Put all land cards into your hand? | ForgetChanged$ True | SubAbility$ DBChangeRest11M
|
||||||
|
SVar:DBChangeRest11M:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Library | Destination$ Graveyard | ForgetChanged$ True
|
||||||
|
SVar:Tutor12M:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Card | ChangeNum$ 1 | Mandatory$ True | SpellDescription$ Search your library for a card and put that card into your hand. Then shuffle your library.
|
||||||
|
SVar:Sacrifice13M:DB$ Sacrifice | ValidTgts$ Player | Amount$ 2 | SacValid$ Creature | SpellDescription$ Target player sacrifices two creatures.
|
||||||
|
SVar:Token14M:DB$ Token | TokenScript$ b_5_5_demon_flying | SubAbility$ DBLoselife14M | SpellDescription$ Create a 5/5 black Demon creature token with flying. You lose 2 life.
|
||||||
|
SVar:DBLoselife14M:DB$ LoseLife | LifeAmount$ 2
|
||||||
|
SVar:Token15M:DB$ Token | TokenScript$ c_4_4_dragon_flying | SpellDescription$ Create a 4/4 gold Dragon creature token with flying.
|
||||||
|
SVar:SetLife16M:DB$ SetLife | ValidTgts$ Player | TgtPrompt$ Select target player | LifeAmount$ 10 | SpellDescription$ Target player's life total becomes 10.
|
||||||
|
SVar:Destroy17M:DB$ Destroy | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select a nonland permanent | SpellDescription$ Destroy target nonland permanent.
|
||||||
|
SVar:Return18M:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | TgtPrompt$ Select target permanent in a graveyard | ValidTgts$ Permanent | SpellDescription$ Return target permanent from a graveyard to the battlefield under your control.
|
||||||
|
SVar:Token19M:DB$ Token | TokenAmount$ 2 | TokenScript$ g_3_3_beast | SpellDescription$ Create two 3/3 green Beast creature tokens.
|
||||||
|
SVar:Draw20M:DB$ Draw | NumCards$ 4 | SubAbility$ DBDiscard20M | SpellDescription$ Draw four cards, then discard two cards.
|
||||||
|
SVar:DBDiscard20M:DB$ Discard | Defined$ You | NumCards$ 2 | Mode$ TgtChoose
|
||||||
|
A:AB$ GenericChoice | Cost$ SubCounter<6/LOYALTY> | AtRandom$ Urza | ShowChoice$ Description | Choices$ DealDamage1U,Effect2U,DestroyAll3U,Token4U,LifeGain5U,Damage6U,Effect7U,Effect8U,Token9U,Shuffle10U,Destroy11U,Effect12U,Effect13U,ControlPlayer14U,ExileLibrary15U,Token16U,Raise17U,LifeDraw18U,FlipTurns19U | Planeswalker$ True | Ultimate$ True | ShowChoice$ Description | StackDescription$ SpellDescription | SpellDescription$ Head to AskUrza.com and click -6.
|
||||||
|
SVar:DealDamage1U:DB$ DealDamage | ValidTgts$ Player,Planeswalker | SubAbility$ DBDiscard1U | SpellDescription$ NICKNAME deals 7 damage to target player or planeswalker. That player or that planeswalker's controller discards seven cards, then sacrifices seven permanents.
|
||||||
|
SVar:DBDiscard1U:DB$ Discard | Defined$ TargetedOrController | NumCards$ 7 | Mode$ TgtChoose | SubAbility$ DBSac1U
|
||||||
|
SVar:DBSac1U:DB$Sacrifice | Defined$ TargetedOrController | SacValid$ Permanent | Amount$ 7
|
||||||
|
SVar:Effect2U:DB$ Effect | Name$ Emblem - Urza, Academy Headmaster (2U) | ReplacementEffects$ RPreventDamage | Stackable$ False | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "If a source would deal damage to you or a planeswalker you control, prevent all but 1 of that damage."
|
||||||
|
SVar:RPreventDamage:Event$ DamageDone | ValidTarget$ You,Planeswalker.YouCtrl | ReplaceWith$ PreventDmg | PreventionEffect$ True | Description$ If a source would deal damage to you or a planeswalker you control, prevent all but 1 of that damage.
|
||||||
|
SVar:PreventDmg:DB$ ReplaceDamage | Amount$ ShieldAmount
|
||||||
|
SVar:ShieldAmount:ReplaceCount$DamageAmount/Minus.1
|
||||||
|
SVar:DestroyAll3U:DB$ DestroyAll | ValidTgts$ Player | TgtPrompt$ Select target player | ValidCards$ Land | SpellDescription$ Destroy all lands target player controls.
|
||||||
|
SVar:Token4U:DB$ Token | TokenAmount$ X4U | TokenScript$ w_2_2_cat | SpellDescription$ Create X 2/2 white Cat creature tokens, where X is your life total.
|
||||||
|
SVar:X4U:Count$YourLifeTotal
|
||||||
|
SVar:LifeGain5U:DB$ GainLife | LifeAmount$ 100 | SpellDescription$ You gain 100 life.
|
||||||
|
SVar:Damage6U:DB$ DealDamage | ValidTgts$ Player,Planeswalker | TgtPrompt$ Select a player or planeswalker | NumDmg$ 10 | SubAbility$ DmgAll6U | DamageMap$ True | SpellDescription$ NICKNAME deals 10 damage to target player or planeswalker and each creature that player or that planeswalker's controller controls.
|
||||||
|
SVar:DmgAll6U:DB$ DamageAll | NumDmg$ 10 | ValidCards$ Creature.ControlledBy TargetedOrController | SubAbility$ DBDamageResolve6U
|
||||||
|
SVar:DBDamageResolve6U:DB$ DamageResolve
|
||||||
|
SVar:Effect7U:DB$ Effect | Name$ Emblem - Urza, Academy Headmaster (7U) | StaticAbilities$ ST7U | Stackable$ False | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Creatures you control have double strike, trample, hexproof and haste."
|
||||||
|
SVar:ST7U:Mode$ Continuous | EffectZone$ Command | Affected$ Creature.YouCtrl | AffectedZone$ Battlefield | AddKeyword$ Double Strike & Trample & Hexproof & Haste | Description$ Creatures you control have double strike, trample, hexproof and haste.
|
||||||
|
SVar:Effect8U:DB$ Effect | Name$ Emblem - Urza, Academy Headmaster (8U) | StaticAbilities$ STIndestructible8U | Stackable$ False | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Artifacts, creatures, enchantments, and lands you control have indestructible."
|
||||||
|
SVar:STIndestructible8U:Mode$ Continuous | EffectZone$ Command | Affected$ Artifact.YouCtrl,Creature.YouCtrl,Enchantment.YouCtrl,Land.YouCtrl | AffectedZone$ Battlefield | AddKeyword$ Indestructible | Description$ Artifacts, creatures, enchantments, and lands you control are indestructible.
|
||||||
|
SVar:Token9U:DB$ Token | TokenAmount$ Lands | TokenScript$ g_6_6_wurm | SpellDescription$ Create a 6/6 green Wurm creature token for each land you control.
|
||||||
|
SVar:Lands:Count$Valid Land.YouCtrl
|
||||||
|
SVar:Shuffle10U:DB$ ChangeZoneAll | ChangeType$ Card | Origin$ Hand,Graveyard | Destination$ Library | Shuffle$ True | SubAbility$ DBDraw10U | UseAllOriginZones$ True | SpellDescription$ Each player shuffles their hand and graveyard into their library. You draw seven cards.
|
||||||
|
SVar:DBDraw10U:DB$ Draw | Defined$ You | NumCards$ 7
|
||||||
|
SVar:Destroy11U:DB$ Destroy | ValidTgts$ Creature,Planeswalker.Other | TargetMin$ 0 | TargetMax$ 3 | TgtPrompt$ Select up to three target creatures and/or other planeswalkers | RememberTargets$ True | SubAbility$ DBChangeZoneAll11U | SpellDescription$ Destroy up to three target creatures and/or other planeswalkers. Return each card put into a graveyard this way to the battlefield under your control.
|
||||||
|
SVar:DBChangeZoneAll11U:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | SubAbility$ DBCleanup
|
||||||
|
SVar:Effect12U:DB$ Effect | Name$ Emblem - Urza, Academy Headmaster (12U) | Triggers$ TrigSpellCast12U | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Whenever you cast a spell, exile target permanent."
|
||||||
|
SVar:TrigSpellCast12U:Mode$ SpellCast | ValidActivatingPlayer$ You | Execute$ EffSpellCast12U | TriggerDescription$ Whenever you cast a spell, exile target permanent.
|
||||||
|
SVar:EffSpellCast12U:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Permanent
|
||||||
|
SVar:Effect13U:DB$ Effect | Name$ Emblem - Urza, Academy Headmaster (13U) | Triggers$ TrigFight13U | Duration$ Permanent | AILogic$ Always | SubAbility$ DBToken13U | SpellDescription$ You get an emblem with "Whenever a creature enters the battlefield under your control, you may have it fight target creature." Then create three 8/8 blue Octopus creature tokens.
|
||||||
|
SVar:TrigFight13U:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.YouCtrl | Execute$ DBFight13U | OptionalDecider$ You | TriggerZones$ Command | TriggerDescription$ Whenever a creature enters the battlefield under your control, you may have it fight target creature.
|
||||||
|
SVar:DBFight13U:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature | TgtPrompt$ Choose target creature
|
||||||
|
SVar:DBToken13U:DB$ Token | TokenAmount$ 3 | TokenScript$ u_8_8_octopus
|
||||||
|
SVar:ControlPlayer14U:DB$ ControlPlayer | ValidTgts$ Player | TgtPrompt$ Select target player | SpellDescription$ You control target player during that player's next turn.
|
||||||
|
SVar:ExileLibrary15U:DB$ ChangeZoneAll | Origin$ Library | Destination$ Exile | ValidTgts$ Player | TgtPrompt$ Select target player | SubAbility$ DBChangeZone15U | Planeswalker$ True | Ultimate$ True | SpellDescription$ Exile all cards from target player's library, then that player shuffles their hand into their library.
|
||||||
|
SVar:DBChangeZone15U:DB$ ChangeZoneAll | Origin$ Hand | Destination$ Library | Defined$ Targeted | ChangeType$ Card | Shuffle$ True
|
||||||
|
SVar:Token16U:DB$ Token | TokenAmount$ 3 | TokenScript$ b_1_1_assassin_lose_con | SpellDescription$ Create three 1/1 black Assassin creature tokens with "Whenever this creature deals combat damage to a player, that player loses the game."
|
||||||
|
SVar:Raise17U:DB$ ChangeZoneAll | ChangeType$ Creature | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | SpellDescription$ Put all creature cards in all graveyards onto the battlefield under your control.
|
||||||
|
SVar:LifeDraw18U:DB$ GainLife | LifeAmount$ Lands | SubAbility$ DBDraw18U | SpellDescription$ You gain X life and draw X cards, where X is the number of lands you control.
|
||||||
|
SVar:DBDraw18U:DB$ Draw | NumCards$ Lands
|
||||||
|
SVar:FlipTurns19U:DB$ FlipACoin | Amount$ 5 | NoCall$ True | HeadsSubAbility$ DBAddTurn19U | StackDescription$ SpellDescription | SpellDescription$ Flip 5 coins. Take an extra turn after this one for each coin that comes up heads.
|
||||||
|
SVar:DBAddTurn19U:DB$ AddTurn | Defined$ You | NumTurns$ 1
|
||||||
|
SVar:LifeDrawPut20U:DB$ GainLife | LifeAmount$ 7 | SubAbility$ DBDraw20U | SpellDescription$ You gain 7 life, draw seven cards, then put up to seven permanent cards from your hand onto the battlefield.
|
||||||
|
SVar:DBDraw20U:DB$ Draw | NumCards$ 7 | SubAbility$ DBChangeZone20U
|
||||||
|
SVar:DBChangeZone20U:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Permanent | ChangeNum$ 7
|
||||||
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True
|
||||||
|
DeckHas:Ability$Counters & Ability$Token & Ability$LifeGain & Ability$Discard
|
||||||
|
Oracle:[+1]: Head to AskUrza.com and click +1.\n[-1]: Head to AskUrza.com and click -1.\n[-6]: Head to AskUrza.com and click -6.
|
||||||
@@ -244,7 +244,7 @@ Eternal Warrior|LEG
|
|||||||
Eureka|LEG
|
Eureka|LEG
|
||||||
Evil Eye of Orms-by-Gore|LEG
|
Evil Eye of Orms-by-Gore|LEG
|
||||||
Fallen Angel|LEG
|
Fallen Angel|LEG
|
||||||
#Falling Star|LEG
|
Falling Star|LEG
|
||||||
Feint|LEG
|
Feint|LEG
|
||||||
Field of Dreams|LEG
|
Field of Dreams|LEG
|
||||||
Fire Sprites|LEG
|
Fire Sprites|LEG
|
||||||
@@ -504,7 +504,7 @@ Camouflage|LEB
|
|||||||
Castle|LEB
|
Castle|LEB
|
||||||
Celestial Prism|LEB
|
Celestial Prism|LEB
|
||||||
Channel|LEB
|
Channel|LEB
|
||||||
#Chaos Orb|LEB
|
Chaos Orb|LEB
|
||||||
Chaoslace|LEB
|
Chaoslace|LEB
|
||||||
Circle of Protection: Black|LEB
|
Circle of Protection: Black|LEB
|
||||||
Circle of Protection: Blue|LEB
|
Circle of Protection: Blue|LEB
|
||||||
|
|||||||
14
forge-gui/res/editions/Innistrad Crimson Vow Commander.txt
Normal file
14
forge-gui/res/editions/Innistrad Crimson Vow Commander.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[metadata]
|
||||||
|
Code=VOC
|
||||||
|
Date=2021-11-19
|
||||||
|
Name=Innistrad: Crimson Vow Commander
|
||||||
|
Type=Commander
|
||||||
|
ScryfallCode=VOC
|
||||||
|
|
||||||
|
[cards]
|
||||||
|
1 M Millicent, Restless Revenant @
|
||||||
|
2 M Strefan, Maurer Progenitor @
|
||||||
|
32 M Wedding Ring @
|
||||||
|
39 M Millicent, Restless Revenant @
|
||||||
|
40 M Strefan, Maurer Progenitor @
|
||||||
|
70 M Wedding Ring @
|
||||||
90
forge-gui/res/editions/Innistrad Crimson Vow.txt
Normal file
90
forge-gui/res/editions/Innistrad Crimson Vow.txt
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
[metadata]
|
||||||
|
Code=VOW
|
||||||
|
Date=2021-11-19
|
||||||
|
Name=Innistrad: Crimson Vow
|
||||||
|
Code2=VOW
|
||||||
|
MciCode=vow
|
||||||
|
Type=Expansion
|
||||||
|
ScryfallCode=VOW
|
||||||
|
|
||||||
|
[cards]
|
||||||
|
5 R By Invitation Only @
|
||||||
|
10 C Drogskol Infantry @
|
||||||
|
15 C Gryff Rider @
|
||||||
|
34 M Savior of Ollenbock @
|
||||||
|
36 R Sigarda's Summons @
|
||||||
|
38 R Thalia, Guardian of Thraben @
|
||||||
|
45 R Wedding Announcement @
|
||||||
|
60 U Geistlight Snare @
|
||||||
|
71 R Overcharged Amalgam @
|
||||||
|
103 R Demonic Bargain @
|
||||||
|
112 U Fell Stinger @
|
||||||
|
114 C Gluttonous Guest @
|
||||||
|
129 C Rot-Tide Gargantua @
|
||||||
|
131 M Sorin the Mirthless @
|
||||||
|
137 R Voldaren Bloodcaster @
|
||||||
|
154 R Dominating Vampire @
|
||||||
|
184 C Weary Prisoner @
|
||||||
|
185 C Apprentice Sharpshooter @
|
||||||
|
197 R Dig Up @
|
||||||
|
208 C Massive Might @
|
||||||
|
235 R Dorothea, Vengeful Victim @
|
||||||
|
238 R Grolnok, the Omnivore @
|
||||||
|
245 M Olivia, Crimson Bride @
|
||||||
|
260 C Wedding Invitation @
|
||||||
|
261 R Deathcap Glade @
|
||||||
|
262 R Dreamroot Cascade @
|
||||||
|
264 R Shattered Sanctum @
|
||||||
|
265 R Stormcarved Coast @
|
||||||
|
266 R Sundown Pass @
|
||||||
|
267 R Voldaren Estate @
|
||||||
|
268 L Plains @
|
||||||
|
269 L Plains @
|
||||||
|
270 L Island @
|
||||||
|
271 L Island @
|
||||||
|
272 L Swamp @
|
||||||
|
273 L Swamp @
|
||||||
|
274 L Mountain @
|
||||||
|
275 L Mountain @
|
||||||
|
276 L Forest @
|
||||||
|
277 L Forest @
|
||||||
|
278 M Sorin the Mirthless @
|
||||||
|
281 R Deathcap Glade @
|
||||||
|
282 R Dreamroot Cascade @
|
||||||
|
283 R Shattered Sanctum @
|
||||||
|
284 R Stormcarved Coast @
|
||||||
|
285 R Sundown Pass @
|
||||||
|
292 C Gluttonous Guest @
|
||||||
|
297 M Sorin the Mirthless @
|
||||||
|
298 R Voldaren Bloodcaster @
|
||||||
|
305 R Dominating Vampire @
|
||||||
|
315 M Olivia, Crimson Bride @
|
||||||
|
318 R Thalia, Guardian of Thraben @
|
||||||
|
322 R Dorothea, Vengeful Victim @
|
||||||
|
324 R Grolnok, the Omnivore @
|
||||||
|
330 M Savior of Ollenbock @
|
||||||
|
331 R Thalia, Guardian of Thraben @
|
||||||
|
337 M Sorin the Mirthless @
|
||||||
|
338 R Voldaren Bloodcaster @
|
||||||
|
343 M Olivia, Crimson Bride @
|
||||||
|
346 R By Invitation Only @
|
||||||
|
352 M Savior of Ollenbock @
|
||||||
|
353 R Sigarda's Summons @
|
||||||
|
355 R Wedding Announcement @
|
||||||
|
363 R Overcharged Amalgam @
|
||||||
|
368 R Demonic Bargain @
|
||||||
|
387 R Dig Up @
|
||||||
|
397 R Voldaren Estate @
|
||||||
|
398 L Plains @
|
||||||
|
399 L Island @
|
||||||
|
400 L Swamp @
|
||||||
|
401 L Mountain @
|
||||||
|
402 L Forest @
|
||||||
|
403 R Voldaren Estate @
|
||||||
|
404 R Sigarda's Summons @
|
||||||
|
405 U Geistlight Snare @
|
||||||
|
406 U Fell Stinger @
|
||||||
|
407 R Dominating Vampire @
|
||||||
|
|
||||||
|
[tokens]
|
||||||
|
c_a_blood_draw
|
||||||
@@ -1938,6 +1938,13 @@ lblTails=Zahl
|
|||||||
lblCallCoinFlip=Kopf oder Zahl
|
lblCallCoinFlip=Kopf oder Zahl
|
||||||
lblWin=Gewonnen
|
lblWin=Gewonnen
|
||||||
lblLose=Verloren
|
lblLose=Verloren
|
||||||
|
#FlipOntoBattlefieldEffect.java
|
||||||
|
lblChooseDesiredLocation=Wähle eine Karte als Mittelpunkt der gewünschten Landezone.
|
||||||
|
lblDidNotFlipOver=Die Karte hat sich NICHT überschlagen.
|
||||||
|
lblFlippedOver=Die Karte überschlug sich {0} mal.
|
||||||
|
lblDidNotLandOnCards=Die Karte landete auf keiner Karte.
|
||||||
|
lblLandedOnOneCard=Die Karte landete auf {0}.
|
||||||
|
lblLandedOnTwoCards=Die Karte landete auf {0} und {1}.
|
||||||
#InvestigateEffect.java
|
#InvestigateEffect.java
|
||||||
lblWouldYouLikeInvestigate=Möchtest du Nachforschungen anstellen?
|
lblWouldYouLikeInvestigate=Möchtest du Nachforschungen anstellen?
|
||||||
#LifeSetEffect.java
|
#LifeSetEffect.java
|
||||||
|
|||||||
@@ -1939,6 +1939,13 @@ lblTails=tails
|
|||||||
lblCallCoinFlip=Call coin flip
|
lblCallCoinFlip=Call coin flip
|
||||||
lblWin=win
|
lblWin=win
|
||||||
lblLose=lose
|
lblLose=lose
|
||||||
|
#FlipOntoBattlefieldEffect.java
|
||||||
|
lblChooseDesiredLocation=Choose a card to represent the center of the desired card landing location.
|
||||||
|
lblDidNotFlipOver=The card did not flip over.
|
||||||
|
lblFlippedOver=The card flipped over {0} time(s).
|
||||||
|
lblDidNotLandOnCards=The card did not land on any cards.
|
||||||
|
lblLandedOnOneCard=The card landed on {0}.
|
||||||
|
lblLandedOnTwoCards=The card landed on {0} and {1}.
|
||||||
#InvestigateEffect.java
|
#InvestigateEffect.java
|
||||||
lblWouldYouLikeInvestigate=Do you want to investigate?
|
lblWouldYouLikeInvestigate=Do you want to investigate?
|
||||||
#LifeSetEffect.java
|
#LifeSetEffect.java
|
||||||
|
|||||||
@@ -1937,6 +1937,13 @@ lblTails=cruz
|
|||||||
lblCallCoinFlip=Llamar al lanzamiento de la moneda
|
lblCallCoinFlip=Llamar al lanzamiento de la moneda
|
||||||
lblWin=gana
|
lblWin=gana
|
||||||
lblLose=pierde
|
lblLose=pierde
|
||||||
|
#FlipOntoBattlefieldEffect.java
|
||||||
|
lblChooseDesiredLocation=Choose a card to represent the center of the desired card landing location.
|
||||||
|
lblDidNotFlipOver=The card did not flip over.
|
||||||
|
lblFlippedOver=The card flipped over {0} time(s).
|
||||||
|
lblDidNotLandOnCards=The card did not land on any cards.
|
||||||
|
lblLandedOnOneCard=The card landed on {0}.
|
||||||
|
lblLandedOnTwoCards=The card landed on {0} and {1}.
|
||||||
#InvestigateEffect.java
|
#InvestigateEffect.java
|
||||||
lblWouldYouLikeInvestigate=¿Quieres investigar?
|
lblWouldYouLikeInvestigate=¿Quieres investigar?
|
||||||
#LifeSetEffect.java
|
#LifeSetEffect.java
|
||||||
|
|||||||
@@ -1936,6 +1936,13 @@ lblTails=croce
|
|||||||
lblCallCoinFlip=Scegli testa o croce
|
lblCallCoinFlip=Scegli testa o croce
|
||||||
lblWin=hai vinto
|
lblWin=hai vinto
|
||||||
lblLose=hai perso
|
lblLose=hai perso
|
||||||
|
#FlipOntoBattlefieldEffect.java
|
||||||
|
lblChooseDesiredLocation=Choose a card to represent the center of the desired card landing location.
|
||||||
|
lblDidNotFlipOver=The card did not flip over.
|
||||||
|
lblFlippedOver=The card flipped over {0} time(s).
|
||||||
|
lblDidNotLandOnCards=The card did not land on any cards.
|
||||||
|
lblLandedOnOneCard=The card landed on {0}.
|
||||||
|
lblLandedOnTwoCards=The card landed on {0} and {1}.
|
||||||
#InvestigateEffect.java
|
#InvestigateEffect.java
|
||||||
lblWouldYouLikeInvestigate=Do you want to investigate?
|
lblWouldYouLikeInvestigate=Do you want to investigate?
|
||||||
#LifeSetEffect.java
|
#LifeSetEffect.java
|
||||||
|
|||||||
@@ -1936,6 +1936,13 @@ lblTails=裏
|
|||||||
lblCallCoinFlip=コイン投げを予想
|
lblCallCoinFlip=コイン投げを予想
|
||||||
lblWin=勝ち
|
lblWin=勝ち
|
||||||
lblLose=負け
|
lblLose=負け
|
||||||
|
#FlipOntoBattlefieldEffect.java
|
||||||
|
lblChooseDesiredLocation=Choose a card to represent the center of the desired card landing location.
|
||||||
|
lblDidNotFlipOver=The card did not flip over.
|
||||||
|
lblFlippedOver=The card flipped over {0} time(s).
|
||||||
|
lblDidNotLandOnCards=The card did not land on any cards.
|
||||||
|
lblLandedOnOneCard=The card landed on {0}.
|
||||||
|
lblLandedOnTwoCards=The card landed on {0} and {1}.
|
||||||
#InvestigateEffect.java
|
#InvestigateEffect.java
|
||||||
lblWouldYouLikeInvestigate=Do you want to investigate?
|
lblWouldYouLikeInvestigate=Do you want to investigate?
|
||||||
#LifeSetEffect.java
|
#LifeSetEffect.java
|
||||||
|
|||||||
@@ -1940,6 +1940,13 @@ lblTails=背面
|
|||||||
lblCallCoinFlip=掷骰子
|
lblCallCoinFlip=掷骰子
|
||||||
lblWin=赢
|
lblWin=赢
|
||||||
lblLose=输
|
lblLose=输
|
||||||
|
#FlipOntoBattlefieldEffect.java
|
||||||
|
lblChooseDesiredLocation=Choose a card to represent the center of the desired card landing location.
|
||||||
|
lblDidNotFlipOver=The card did not flip over.
|
||||||
|
lblFlippedOver=The card flipped over {0} time(s).
|
||||||
|
lblDidNotLandOnCards=The card did not land on any cards.
|
||||||
|
lblLandedOnOneCard=The card landed on {0}.
|
||||||
|
lblLandedOnTwoCards=The card landed on {0} and {1}.
|
||||||
#InvestigateEffect.java
|
#InvestigateEffect.java
|
||||||
lblWouldYouLikeInvestigate=你想要探查吗?
|
lblWouldYouLikeInvestigate=你想要探查吗?
|
||||||
#LifeSetEffect.java
|
#LifeSetEffect.java
|
||||||
|
|||||||
@@ -374,6 +374,7 @@ Tezzeret
|
|||||||
Tibalt
|
Tibalt
|
||||||
Tyvar
|
Tyvar
|
||||||
Ugin
|
Ugin
|
||||||
|
Urza
|
||||||
Venser
|
Venser
|
||||||
Vivien
|
Vivien
|
||||||
Vraska
|
Vraska
|
||||||
|
|||||||
@@ -2130,3 +2130,11 @@
|
|||||||
2021-10-11 Legacy Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-11-legacy-challenge.zip
|
2021-10-11 Legacy Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-11-legacy-challenge.zip
|
||||||
2021-10-12 Legacy Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-12-legacy-preliminary.zip
|
2021-10-12 Legacy Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-12-legacy-preliminary.zip
|
||||||
2021-10-16 Legacy League (49 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-16-legacy-league.zip
|
2021-10-16 Legacy League (49 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-16-legacy-league.zip
|
||||||
|
2021-10-18 Legacy Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-18-legacy-challenge.zip
|
||||||
|
2021-10-20 Legacy Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-20-legacy-preliminary.zip
|
||||||
|
2021-10-22 Legacy Preliminary (5 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-22-legacy-preliminary.zip
|
||||||
|
2021-10-23 Legacy League (49 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-23-legacy-league.zip
|
||||||
|
2021-10-23 Legacy Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-23-legacy-preliminary.zip
|
||||||
|
2021-10-24 Legacy Premier (16 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-24-legacy-premier.zip
|
||||||
|
2021-10-25 Legacy Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-25-legacy-challenge.zip
|
||||||
|
2021-10-26 Legacy Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-10-26-legacy-preliminary.zip
|
||||||
|
|||||||
@@ -2798,3 +2798,17 @@
|
|||||||
2021-10-16 Modern Preliminary (6 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-16-modern-preliminary.zip
|
2021-10-16 Modern Preliminary (6 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-16-modern-preliminary.zip
|
||||||
2021-10-16 Modern Premier (16 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-16-modern-premier.zip
|
2021-10-16 Modern Premier (16 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-16-modern-premier.zip
|
||||||
2021-10-17 Modern Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-17-modern-challenge.zip
|
2021-10-17 Modern Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-17-modern-challenge.zip
|
||||||
|
2021-10-18 Modern Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-18-modern-challenge.zip
|
||||||
|
2021-10-18 Modern Premier (16 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-18-modern-premier.zip
|
||||||
|
2021-10-19 Modern League (56 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-19-modern-league.zip
|
||||||
|
2021-10-19 Modern Preliminary (7 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-19-modern-preliminary.zip
|
||||||
|
2021-10-20 Modern Preliminary (5 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-20-modern-preliminary.zip
|
||||||
|
2021-10-21 Modern Preliminary (10 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-21-modern-preliminary.zip
|
||||||
|
2021-10-22 Modern League (56 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-22-modern-league.zip
|
||||||
|
2021-10-22 Modern Preliminary (5 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-22-modern-preliminary.zip
|
||||||
|
2021-10-23 Modern Preliminary (7 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-23-modern-preliminary.zip
|
||||||
|
2021-10-24 Modern Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-24-modern-challenge.zip
|
||||||
|
2021-10-25 Modern Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-25-modern-challenge.zip
|
||||||
|
2021-10-25 Modern Premier (16 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-25-modern-premier.zip
|
||||||
|
2021-10-26 Modern League (65 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-26-modern-league.zip
|
||||||
|
2021-10-26 Modern Preliminary (7 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-10-26-modern-preliminary.zip
|
||||||
|
|||||||
@@ -1815,3 +1815,8 @@
|
|||||||
2021-10-11 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-10-11-pauper-challenge.zip
|
2021-10-11 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-10-11-pauper-challenge.zip
|
||||||
2021-10-13 Pauper League (30 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-10-13-pauper-league.zip
|
2021-10-13 Pauper League (30 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-10-13-pauper-league.zip
|
||||||
2021-10-17 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-10-17-pauper-challenge.zip
|
2021-10-17 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-10-17-pauper-challenge.zip
|
||||||
|
2021-10-18 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-10-18-pauper-challenge.zip
|
||||||
|
2021-10-20 Pauper League (25 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-10-20-pauper-league.zip
|
||||||
|
2021-10-24 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-10-24-pauper-challenge.zip
|
||||||
|
2021-10-25 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-10-25-pauper-challenge.zip
|
||||||
|
Pauper League (20 decks) | https://downloads.cardforge.org/decks/archive/pauper/pauper-league.zip
|
||||||
|
|||||||
@@ -755,3 +755,10 @@
|
|||||||
2021-10-11 Pioneer League (18 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-11-pioneer-league.zip
|
2021-10-11 Pioneer League (18 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-11-pioneer-league.zip
|
||||||
2021-10-14 Pioneer League (15 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-14-pioneer-league.zip
|
2021-10-14 Pioneer League (15 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-14-pioneer-league.zip
|
||||||
2021-10-17 Pioneer Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-17-pioneer-challenge.zip
|
2021-10-17 Pioneer Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-17-pioneer-challenge.zip
|
||||||
|
2021-10-18 Pioneer Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-18-pioneer-challenge.zip
|
||||||
|
2021-10-18 Pioneer League (14 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-18-pioneer-league.zip
|
||||||
|
2021-10-21 Pioneer League (17 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-21-pioneer-league.zip
|
||||||
|
2021-10-23 Pioneer Preliminary (6 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-23-pioneer-preliminary.zip
|
||||||
|
2021-10-24 Pioneer Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-24-pioneer-challenge.zip
|
||||||
|
2021-10-25 Pioneer Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-25-pioneer-challenge.zip
|
||||||
|
2021-10-25 Pioneer League (19 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-10-25-pioneer-league.zip
|
||||||
|
|||||||
@@ -2515,3 +2515,10 @@
|
|||||||
2021-10-14 Standard League (12 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-14-standard-league.zip
|
2021-10-14 Standard League (12 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-14-standard-league.zip
|
||||||
2021-10-15 Standard Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-15-standard-preliminary.zip
|
2021-10-15 Standard Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-15-standard-preliminary.zip
|
||||||
2021-10-17 Standard Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-17-standard-challenge.zip
|
2021-10-17 Standard Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-17-standard-challenge.zip
|
||||||
|
2021-10-18 Standard Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-18-standard-challenge.zip
|
||||||
|
2021-10-18 Standard League (15 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-18-standard-league.zip
|
||||||
|
2021-10-20 Standard Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-20-standard-preliminary.zip
|
||||||
|
2021-10-21 Standard League (5 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-21-standard-league.zip
|
||||||
|
2021-10-24 Standard Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-24-standard-challenge.zip
|
||||||
|
2021-10-25 Standard Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-25-standard-challenge.zip
|
||||||
|
2021-10-25 Standard League (8 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-10-25-standard-league.zip
|
||||||
|
|||||||
@@ -1535,3 +1535,8 @@
|
|||||||
2021-10-11 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-10-11-vintage-challenge.zip
|
2021-10-11 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-10-11-vintage-challenge.zip
|
||||||
2021-10-17 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-10-17-vintage-challenge.zip
|
2021-10-17 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-10-17-vintage-challenge.zip
|
||||||
2021-10-17 Vintage League (12 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-10-17-vintage-league.zip
|
2021-10-17 Vintage League (12 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-10-17-vintage-league.zip
|
||||||
|
2021-10-18 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-10-18-vintage-challenge.zip
|
||||||
|
2021-10-23 Vintage Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-10-23-vintage-preliminary.zip
|
||||||
|
2021-10-24 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-10-24-vintage-challenge.zip
|
||||||
|
2021-10-24 Vintage League (9 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-10-24-vintage-league.zip
|
||||||
|
2021-10-25 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-10-25-vintage-challenge.zip
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import forge.card.mana.ManaCost;
|
|||||||
import forge.card.mana.ManaCostShard;
|
import forge.card.mana.ManaCostShard;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
import forge.game.mana.ManaCostBeingPaid;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -74,7 +73,7 @@ public final class InputSelectCardsForConvokeOrImprovise extends InputSelectMany
|
|||||||
if (improvise) {
|
if (improvise) {
|
||||||
chosenColor = ManaCostShard.COLORLESS.getColorMask();
|
chosenColor = ManaCostShard.COLORLESS.getColorMask();
|
||||||
} else {
|
} else {
|
||||||
ColorSet colors = CardUtil.getColors(card);
|
ColorSet colors = card.determineColor();
|
||||||
if (colors.isMulticolor()) {
|
if (colors.isMulticolor()) {
|
||||||
//if card is multicolor, strip out any colors which can't be paid towards remaining cost
|
//if card is multicolor, strip out any colors which can't be paid towards remaining cost
|
||||||
colors = ColorSet.fromMask(colors.getColor() & remainingCost.getUnpaidColors());
|
colors = ColorSet.fromMask(colors.getColor() & remainingCost.getUnpaidColors());
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ public class FThreads {
|
|||||||
public static void invokeInEdtNowOrLater(final Runnable proc) {
|
public static void invokeInEdtNowOrLater(final Runnable proc) {
|
||||||
if (isGuiThread()) {
|
if (isGuiThread()) {
|
||||||
GuiBase.getInterface().invokeInEdtNow(proc);
|
GuiBase.getInterface().invokeInEdtNow(proc);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
GuiBase.getInterface().invokeInEdtLater(proc);
|
GuiBase.getInterface().invokeInEdtLater(proc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,8 +80,7 @@ public final class ItemManagerModel<T extends InventoryItem> {
|
|||||||
if (data.count(item0) > 0) {
|
if (data.count(item0) > 0) {
|
||||||
if (isInfinite()) {
|
if (isInfinite()) {
|
||||||
data.removeAll(item0);
|
data.removeAll(item0);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
data.remove(item0, qty);
|
data.remove(item0, qty);
|
||||||
}
|
}
|
||||||
isListInSync = false;
|
isListInSync = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user